|
@@ -38,16 +38,23 @@ from searx.engines import (
|
38
|
38
|
search as do_search, categories, engines, get_engines_stats,
|
39
|
39
|
engine_shortcuts
|
40
|
40
|
)
|
41
|
|
-from searx.utils import UnicodeWriter, highlight_content, html_to_text
|
|
41
|
+from searx.utils import (
|
|
42
|
+ UnicodeWriter, highlight_content, html_to_text, get_themes
|
|
43
|
+)
|
42
|
44
|
from searx.languages import language_codes
|
43
|
45
|
from searx.search import Search
|
44
|
46
|
from searx.autocomplete import backends as autocomplete_backends
|
45
|
47
|
|
46
|
48
|
|
|
49
|
+static_path, templates_path, themes = get_themes(settings['themes_path'] if \
|
|
50
|
+ settings.get('themes_path', None) else searx_dir)
|
|
51
|
+default_theme = settings['default_theme'] if \
|
|
52
|
+ settings.get('default_theme', None) else 'default'
|
|
53
|
+
|
47
|
54
|
app = Flask(
|
48
|
55
|
__name__,
|
49
|
|
- static_folder=os.path.join(searx_dir, 'static'),
|
50
|
|
- template_folder=os.path.join(searx_dir, 'templates')
|
|
56
|
+ static_folder=static_path,
|
|
57
|
+ template_folder=templates_path
|
51
|
58
|
)
|
52
|
59
|
|
53
|
60
|
app.secret_key = settings['server']['secret_key']
|
|
@@ -90,7 +97,30 @@ def get_base_url():
|
90
|
97
|
return hostname
|
91
|
98
|
|
92
|
99
|
|
93
|
|
-def render(template_name, **kwargs):
|
|
100
|
+def get_current_theme_name(override=None):
|
|
101
|
+ """Returns theme name.
|
|
102
|
+
|
|
103
|
+ Checks in this order:
|
|
104
|
+ 1. override
|
|
105
|
+ 2. cookies
|
|
106
|
+ 3. settings"""
|
|
107
|
+
|
|
108
|
+ if override and override in themes:
|
|
109
|
+ return override
|
|
110
|
+ theme_name = request.cookies.get('theme', default_theme)
|
|
111
|
+ if theme_name not in themes:
|
|
112
|
+ theme_name = default_theme
|
|
113
|
+ return theme_name
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+def url_for_theme(endpoint, override_theme=None, **values):
|
|
117
|
+ if endpoint == 'static' and values.get('filename', None):
|
|
118
|
+ theme_name = get_current_theme_name(override=override_theme)
|
|
119
|
+ values['filename'] = "{}/{}".format(theme_name, values['filename'])
|
|
120
|
+ return url_for(endpoint, **values)
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+def render(template_name, override_theme=None, **kwargs):
|
94
|
124
|
blocked_engines = request.cookies.get('blocked_engines', '').split(',')
|
95
|
125
|
|
96
|
126
|
autocomplete = request.cookies.get('autocomplete')
|
|
@@ -125,7 +155,13 @@ def render(template_name, **kwargs):
|
125
|
155
|
|
126
|
156
|
kwargs['method'] = request.cookies.get('method', 'POST')
|
127
|
157
|
|
128
|
|
- return render_template(template_name, **kwargs)
|
|
158
|
+ # override url_for function in templates
|
|
159
|
+ kwargs['url_for'] = url_for_theme
|
|
160
|
+
|
|
161
|
+ kwargs['theme'] = get_current_theme_name(override=override_theme)
|
|
162
|
+
|
|
163
|
+ return render_template(
|
|
164
|
+ '{}/{}'.format(kwargs['theme'], template_name), **kwargs)
|
129
|
165
|
|
130
|
166
|
|
131
|
167
|
@app.route('/search', methods=['GET', 'POST'])
|
|
@@ -232,7 +268,8 @@ def index():
|
232
|
268
|
paging=search.paging,
|
233
|
269
|
pageno=search.pageno,
|
234
|
270
|
base_url=get_base_url(),
|
235
|
|
- suggestions=search.suggestions
|
|
271
|
+ suggestions=search.suggestions,
|
|
272
|
+ theme=get_current_theme_name()
|
236
|
273
|
)
|
237
|
274
|
|
238
|
275
|
|
|
@@ -290,7 +327,7 @@ def preferences():
|
290
|
327
|
|
291
|
328
|
if request.method == 'GET':
|
292
|
329
|
blocked_engines = request.cookies.get('blocked_engines', '').split(',')
|
293
|
|
- else:
|
|
330
|
+ else: # on save
|
294
|
331
|
selected_categories = []
|
295
|
332
|
locale = None
|
296
|
333
|
autocomplete = ''
|
|
@@ -315,6 +352,8 @@ def preferences():
|
315
|
352
|
engine_name = pd_name.replace('engine_', '', 1)
|
316
|
353
|
if engine_name in engines:
|
317
|
354
|
blocked_engines.append(engine_name)
|
|
355
|
+ elif pd_name == 'theme':
|
|
356
|
+ theme = pd if pd in themes else default_theme
|
318
|
357
|
|
319
|
358
|
resp = make_response(redirect(url_for('index')))
|
320
|
359
|
|
|
@@ -352,6 +391,9 @@ def preferences():
|
352
|
391
|
|
353
|
392
|
resp.set_cookie('method', method, max_age=cookie_max_age)
|
354
|
393
|
|
|
394
|
+ resp.set_cookie(
|
|
395
|
+ 'theme', theme, max_age=cookie_max_age)
|
|
396
|
+
|
355
|
397
|
return resp
|
356
|
398
|
return render('preferences.html',
|
357
|
399
|
locales=settings['locales'],
|
|
@@ -361,7 +403,9 @@ def preferences():
|
361
|
403
|
categs=categories.items(),
|
362
|
404
|
blocked_engines=blocked_engines,
|
363
|
405
|
autocomplete_backends=autocomplete_backends,
|
364
|
|
- shortcuts={y: x for x, y in engine_shortcuts.items()})
|
|
406
|
+ shortcuts={y: x for x, y in engine_shortcuts.items()},
|
|
407
|
+ themes=themes,
|
|
408
|
+ theme=get_current_theme_name())
|
365
|
409
|
|
366
|
410
|
|
367
|
411
|
@app.route('/stats', methods=['GET'])
|
|
@@ -404,7 +448,10 @@ def opensearch():
|
404
|
448
|
|
405
|
449
|
@app.route('/favicon.ico')
|
406
|
450
|
def favicon():
|
407
|
|
- return send_from_directory(os.path.join(app.root_path, 'static/img'),
|
|
451
|
+ return send_from_directory(os.path.join(app.root_path,
|
|
452
|
+ 'static',
|
|
453
|
+ get_current_theme_name(),
|
|
454
|
+ 'img'),
|
408
|
455
|
'favicon.png',
|
409
|
456
|
mimetype='image/vnd.microsoft.icon')
|
410
|
457
|
|