[fix] remove js_dependencies & css_dependencies

Previously plugins could declare js_dependencies and css_dependencies
which in theory would then be embedded in the page by themes.

Practically this does not make sense when you have multiple themes
since the JS & CSS needs to be written with a specific theme in mind
in order to support it.

Which is also why js_dependencies and css_dependencies was actually only
used by the Oscar theme and ignored by the Simple theme because the
Simple theme doesn't bundle jQuery and has a slightly different page
markup.

This commit removes this broken feature and also moves the *.js files in
searx/static/plugins/js/ to searx/static/themes/oscar/src/js/plugins
(where they actually belong).

The oscar-specific CSS is now simply injected via the oscar-specific JS.

Fixes #769.
This commit is contained in:
Martin Fischer 2022-01-20 09:55:53 +01:00
parent 96a1f79c6d
commit 132917ff42
17 changed files with 78 additions and 105 deletions

View file

@ -33,7 +33,4 @@ Configuration defaults (at built time):
- {{(plgin.default_on and "y") or ""}}
- {{plgin.description}}
{% for dep in (plgin.js_dependencies + plgin.css_dependencies) %}
| ``{{dep}}`` {% endfor %}
{% endfor %}

View file

@ -19,9 +19,6 @@ Example plugin
description = 'This plugin extends the suggestions with the word "example"'
default_on = False # disabled by default
js_dependencies = tuple() # optional, list of static js files
css_dependencies = tuple() # optional, list of static css files
# attach callback to the post search hook
# request: flask request object

View file

@ -22,8 +22,6 @@ class Plugin: # pylint: disable=too-few-public-methods
name: str
description: str
default_on: bool
js_dependencies: Tuple[str]
css_dependencies: Tuple[str]
preference_section: str
@ -39,8 +37,6 @@ required_attrs = (
optional_attrs = (
# fmt: off
("js_dependencies", tuple),
("css_dependencies", tuple),
("preference_section", str),
# fmt: on
)
@ -71,9 +67,7 @@ def sync_resource(base_path, resource_path, name, target_dir, plugin_dir):
return join("plugins/external_plugins", plugin_dir, file_name)
def prepare_package_resources(plugin, plugin_module_name):
plugin_base_path = dirname(abspath(plugin.__file__))
def prepare_package_resources(plugin_module_name):
plugin_dir = plugin_module_name
target_dir = join(settings["ui"]["static_path"], "plugins/external_plugins", plugin_dir)
try:
@ -84,20 +78,6 @@ def prepare_package_resources(plugin, plugin_module_name):
resources = []
if hasattr(plugin, "js_dependencies"):
resources.extend(map(basename, plugin.js_dependencies))
plugin.js_dependencies = [
sync_resource(plugin_base_path, x, plugin_module_name, target_dir, plugin_dir)
for x in plugin.js_dependencies
]
if hasattr(plugin, "css_dependencies"):
resources.extend(map(basename, plugin.css_dependencies))
plugin.css_dependencies = [
sync_resource(plugin_base_path, x, plugin_module_name, target_dir, plugin_dir)
for x in plugin.css_dependencies
]
for f in listdir(target_dir):
if basename(f) not in resources:
resource_path = join(target_dir, basename(f))
@ -168,7 +148,7 @@ def load_plugin(plugin_module_name, external):
# copy ressources if this is an external plugin
if external:
prepare_package_resources(plugin, plugin_module_name)
prepare_package_resources(plugin_module_name)
logger.debug("%s: loaded", plugin_module_name)

View file

@ -5,5 +5,4 @@ description = gettext('Automatically load next page when scrolling to bottom of
default_on = False
preference_section = 'ui'
js_dependencies = ('plugins/js/infinite_scroll.js',)
css_dependencies = ('plugins/css/infinite_scroll.css',)
# this plugin is implemented in the themes via JavaScript

View file

@ -23,4 +23,4 @@ description = gettext(
default_on = True
preference_section = 'ui'
js_dependencies = ('plugins/js/search_on_category_select.js',)
# this plugin is implemented in the themes via JavaScript

View file

@ -9,5 +9,4 @@ description = gettext(
default_on = False
preference_section = 'ui'
js_dependencies = ('plugins/js/vim_hotkeys.js',)
css_dependencies = ('plugins/css/vim_hotkeys.css',)
# this plugin is implemented in the themes via JavaScript

View file

@ -1,19 +0,0 @@
@keyframes rotate-forever {
0% { transform: rotate(0deg) }
100% { transform: rotate(360deg) }
}
.loading-spinner {
animation-duration: 0.75s;
animation-iteration-count: infinite;
animation-name: rotate-forever;
animation-timing-function: linear;
height: 30px;
width: 30px;
border: 8px solid #666;
border-right-color: transparent;
border-radius: 50% !important;
margin: 0 auto;
}
#pagination button {
visibility: hidden;
}

View file

@ -1,26 +0,0 @@
.vim-hotkeys-help {
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
z-index: 9999999;
overflow-y: auto;
max-height: 80%;
box-shadow: 0 0 1em;
}
.dflex {
display: -webkit-box; /* OLD - iOS 6-, Safari 3.1-6 */
display: -moz-box; /* OLD - Firefox 19- (buggy but mostly works) */
display: -ms-flexbox; /* TWEENER - IE 10 */
display: -webkit-flex; /* NEW - Chrome */
display: flex; /* NEW, Spec - Opera 12.1, Firefox 20+ */
}
.iflex {
-webkit-box-flex: 1; /* OLD - iOS 6-, Safari 3.1-6 */
-moz-box-flex: 1; /* OLD - Firefox 19- */
-webkit-flex: 1; /* Chrome */
-ms-flex: 1; /* IE 10 */
flex: 1; /* NEW, Spec - Opera 12.1, Firefox 20+ */
}

View file

@ -60,7 +60,7 @@ module.exports = function(grunt) {
separator: ';'
},
dist: {
src: ['src/js/*.js', '../__common__/js/image_layout.js'],
src: ['src/js/*.js', '../__common__/js/image_layout.js', 'src/js/plugins/*.js'],
dest: 'js/searxng.js'
}
},

View file

@ -20,6 +20,7 @@ window.searxng = (function(d) {
return {
autocompleter: script.getAttribute('data-autocompleter') === 'true',
method: script.getAttribute('data-method'),
translations: JSON.parse(script.getAttribute('data-translations'))
translations: JSON.parse(script.getAttribute('data-translations')),
plugins: JSON.parse(script.getAttribute('data-plugins'))
};
})(document);

View file

@ -1,3 +1,4 @@
if (searxng.plugins['searx.plugins.infinite_scroll']) {
function hasScrollbar() {
var root = document.compatMode=='BackCompat'? document.body : document.documentElement;
return root.scrollHeight>root.clientHeight;
@ -38,3 +39,28 @@ $(document).ready(function() {
}
});
});
const style = document.createElement('style');
style.textContent = `
@keyframes rotate-forever {
0% { transform: rotate(0deg) }
100% { transform: rotate(360deg) }
}
.loading-spinner {
animation-duration: 0.75s;
animation-iteration-count: infinite;
animation-name: rotate-forever;
animation-timing-function: linear;
height: 30px;
width: 30px;
border: 8px solid #666;
border-right-color: transparent;
border-radius: 50% !important;
margin: 0 auto;
}
#pagination button {
visibility: hidden;
}
`;
document.head.append(style);
}

View file

@ -1,3 +1,4 @@
if (searxng.plugins['searx.plugins.search_on_category_select']) {
$(document).ready(function() {
if($('#q').length) {
$('#categories label').click(function(e) {
@ -40,3 +41,4 @@ function getHttpRequest() {
}
return httpRequest;
}
}

View file

@ -1,3 +1,4 @@
if (searxng.plugins['searx.plugins.vim_hotkeys']) {
$(document).ready(function() {
highlightResult('top')();
@ -343,3 +344,35 @@ $(document).ready(function() {
$('body').append(html);
}
});
const style = document.createElement('style');
style.textContent = `
.vim-hotkeys-help {
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
z-index: 9999999;
overflow-y: auto;
max-height: 80%;
box-shadow: 0 0 1em;
}
.dflex {
display: -webkit-box; /* OLD - iOS 6-, Safari 3.1-6 */
display: -moz-box; /* OLD - Firefox 19- (buggy but mostly works) */
display: -ms-flexbox; /* TWEENER - IE 10 */
display: -webkit-flex; /* NEW - Chrome */
display: flex; /* NEW, Spec - Opera 12.1, Firefox 20+ */
}
.iflex {
-webkit-box-flex: 1; /* OLD - iOS 6-, Safari 3.1-6 */
-moz-box-flex: 1; /* OLD - Firefox 19- */
-webkit-flex: 1; /* Chrome */
-ms-flex: 1; /* IE 10 */
flex: 1; /* NEW, Spec - Opera 12.1, Firefox 20+ */
}
`;
document.head.append(style);
}

View file

@ -14,14 +14,16 @@
return scripts[scripts.length - 1];
})();
const enabledPluginIds = JSON.parse(script.getAttribute('data-plugins'));
// try to detect touch screen
w.searxng = {
touch: (("ontouchstart" in w) || w.DocumentTouch && document instanceof DocumentTouch) || false,
method: script.getAttribute('data-method'),
autocompleter: script.getAttribute('data-autocompleter') === 'true',
search_on_category_select: script.getAttribute('data-search-on-category-select') === 'true',
infinite_scroll: script.getAttribute('data-infinite-scroll') === 'true',
hotkeys: script.getAttribute('data-hotkeys') === 'true',
search_on_category_select: enabledPluginIds['searx.plugins.search_on_category_select'] == true,
infinite_scroll: enabledPluginIds['searx.plugins.infinite_scroll'] == true,
hotkeys: enabledPluginIds['searx.plugins.vim_hotkeys'] == true,
static_path: script.getAttribute('data-static-path'),
translations: JSON.parse(script.getAttribute('data-translations')),
theme: {

View file

@ -23,10 +23,6 @@
{{' '}}<link rel="stylesheet" href="{{ url_for('static', filename='css/leaflet.min.css') }}" type="text/css" />
{%- endif %}
{%- for css in styles %}
<link rel="stylesheet" href="{{ url_for('static', filename=css) }}" type="text/css" />
{% endfor %}
<link rel="shortcut icon" href="{{ url_for('static', filename='img/favicon.png') }}" />
{% block styles %}
@ -100,10 +96,8 @@
<script src="{{ url_for('static', filename='js/searxng.min.js') }}"
data-method="{{ method or 'POST' }}"
data-autocompleter="{% if autocomplete %}true{% else %}false{% endif %}"
data-plugins="{{enabled_plugin_ids_json}}"
data-translations="{{ translations }}"></script>
{% for script in scripts %}
{{""}}<script src="{{ url_for('static', filename=script) }}"></script>
{% endfor %}
<noscript>
<style>
.glyphicon { display: none; }

View file

@ -22,9 +22,7 @@
<script src="{{ url_for('static', filename='js/searxng.head.min.js') }}"
data-method="{{ method or 'POST' }}"
data-autocompleter="{% if autocomplete %}true{% else %}false{% endif %}"
data-search-on-category-select="{{ 'true' if 'plugins/js/search_on_category_select.js' in scripts else 'false'}}"
data-infinite-scroll="{{ 'true' if 'plugins/js/infinite_scroll.js' in scripts else 'false' }}"
data-hotkeys="{{ 'true' if 'plugins/js/vim_hotkeys.js' in scripts else 'false' }}"
data-plugins="{{enabled_plugin_ids_json}}"
data-static-path="{{ url_for('static', filename='themes/simple') }}/"
data-translations="{{ translations }}"></script>
<!--<![endif]-->

View file

@ -493,17 +493,7 @@ def render(template_name: str, override_theme: str = None, **kwargs):
url_for('opensearch') + '?' + urlencode({'method': kwargs['method'], 'autocomplete': kwargs['autocomplete']})
)
# scripts from plugins
kwargs['scripts'] = set()
for plugin in request.user_plugins:
for script in plugin.js_dependencies:
kwargs['scripts'].add(script)
# styles from plugins
kwargs['styles'] = set()
for plugin in request.user_plugins:
for css in plugin.css_dependencies:
kwargs['styles'].add(css)
kwargs['enabled_plugin_ids_json'] = json.dumps({plugin.id: True for plugin in request.user_plugins})
start_time = default_timer()
result = render_template('{}/{}'.format(kwargs['theme'], template_name), **kwargs)