Update upstream sources to 0.9
This commit is contained in:
parent
88e17d06a8
commit
9c7a55e0c0
|
@ -0,0 +1,20 @@
|
||||||
|
[run]
|
||||||
|
branch = True
|
||||||
|
source =
|
||||||
|
searx/engines
|
||||||
|
searx/__init__.py
|
||||||
|
searx/autocomplete.py
|
||||||
|
searx/https_rewrite.py
|
||||||
|
searx/languages.py
|
||||||
|
searx/search.py
|
||||||
|
searx/testing.py
|
||||||
|
searx/utils.py
|
||||||
|
searx/webapp.py
|
||||||
|
|
||||||
|
[report]
|
||||||
|
show_missing = True
|
||||||
|
exclude_lines =
|
||||||
|
if __name__ == .__main__.:
|
||||||
|
|
||||||
|
[html]
|
||||||
|
directory = coverage
|
|
@ -0,0 +1,17 @@
|
||||||
|
.coverage
|
||||||
|
.installed.cfg
|
||||||
|
engines.cfg
|
||||||
|
env
|
||||||
|
robot_log.html
|
||||||
|
robot_output.xml
|
||||||
|
robot_report.html
|
||||||
|
test_basic/
|
||||||
|
setup.cfg
|
||||||
|
|
||||||
|
*.pyc
|
||||||
|
*/*.pyc
|
||||||
|
*~
|
||||||
|
|
||||||
|
node_modules/
|
||||||
|
|
||||||
|
.tx/
|
|
@ -0,0 +1,3 @@
|
||||||
|
strictness: high
|
||||||
|
ignore-paths:
|
||||||
|
- bootstrap.py
|
|
@ -0,0 +1,32 @@
|
||||||
|
sudo: false
|
||||||
|
cache:
|
||||||
|
- pip
|
||||||
|
- npm
|
||||||
|
- directories:
|
||||||
|
- $HOME/.cache/pip
|
||||||
|
language: python
|
||||||
|
python:
|
||||||
|
- "2.7"
|
||||||
|
before_install:
|
||||||
|
- "export DISPLAY=:99.0"
|
||||||
|
- "sh -e /etc/init.d/xvfb start"
|
||||||
|
- npm install less grunt-cli
|
||||||
|
- ( cd searx/static/themes/oscar;npm install; cd - )
|
||||||
|
install:
|
||||||
|
- ./manage.sh update_dev_packages
|
||||||
|
- pip install coveralls
|
||||||
|
script:
|
||||||
|
- ./manage.sh pep8_check
|
||||||
|
- ./manage.sh styles
|
||||||
|
- ./manage.sh grunt_build
|
||||||
|
- ./manage.sh py_test_coverage
|
||||||
|
- ./manage.sh robot_tests
|
||||||
|
after_success:
|
||||||
|
coveralls
|
||||||
|
notifications:
|
||||||
|
irc:
|
||||||
|
channels:
|
||||||
|
- "irc.freenode.org#searx"
|
||||||
|
template:
|
||||||
|
- "%{repository}/#%{build_number}/%{branch} (%{author}): %{message} %{build_url}"
|
||||||
|
on_success: change
|
|
@ -44,3 +44,10 @@ generally made searx better:
|
||||||
- Kirill Isakov
|
- Kirill Isakov
|
||||||
- Guilhem Bonnefille
|
- Guilhem Bonnefille
|
||||||
- Marc Abonce Seguin
|
- Marc Abonce Seguin
|
||||||
|
|
||||||
|
- @jibe-b
|
||||||
|
- Christian Pietsch @pietsch
|
||||||
|
- @Maxqia
|
||||||
|
- Ashutosh Das @pyprism
|
||||||
|
- YuLun Shih @imZack
|
||||||
|
- Dmitry Mikhirev @mikhirev
|
||||||
|
|
|
@ -1,3 +1,41 @@
|
||||||
|
0.9.0 2016.05.24
|
||||||
|
================
|
||||||
|
|
||||||
|
- New search category: science
|
||||||
|
- New engines
|
||||||
|
|
||||||
|
- Wolframalpha (science)
|
||||||
|
- Frinkiac (images)
|
||||||
|
- Arch Linux (it)
|
||||||
|
- BASE - Bielefeld Academic Search Engine (science)
|
||||||
|
- Dokuwiki (general)
|
||||||
|
- Nyaa.se (files, images, music, video)
|
||||||
|
- Reddit (general, images, news, social media)
|
||||||
|
- Torrentz.eu (files, music, video)
|
||||||
|
- Tokyo Toshokan (files, music, video)
|
||||||
|
- F-Droid (files)
|
||||||
|
- Erowid (general)
|
||||||
|
- Bitbucket (it)
|
||||||
|
- GitLab (it)
|
||||||
|
- Geektimes (it)
|
||||||
|
- Habrahabr (it)
|
||||||
|
- New plugins
|
||||||
|
|
||||||
|
- Open links in new tab
|
||||||
|
- Vim hotkeys for better navigation
|
||||||
|
- Wikipedia/Mediawiki engine improvements
|
||||||
|
- Configurable instance name
|
||||||
|
- Configurable connection pool size
|
||||||
|
- Fixed broken google engine
|
||||||
|
- Better docker image
|
||||||
|
- Images in standard results
|
||||||
|
- Fixed and refactored user settings (Warning: backward incompatibility - you have to reset your custom engine preferences)
|
||||||
|
- Suspending engines on errors
|
||||||
|
- Simplified development/deployment tooling
|
||||||
|
- Translation updates
|
||||||
|
- Multilingual autocompleter
|
||||||
|
- Qwant autocompleter backend
|
||||||
|
|
||||||
0.8.1 2015.12.22
|
0.8.1 2015.12.22
|
||||||
================
|
================
|
||||||
|
|
||||||
|
|
|
@ -18,7 +18,7 @@ Installation
|
||||||
``git clone git@github.com:asciimoo/searx.git && cd searx``
|
``git clone git@github.com:asciimoo/searx.git && cd searx``
|
||||||
- install dependencies: ``./manage.sh update_packages``
|
- install dependencies: ``./manage.sh update_packages``
|
||||||
- edit your
|
- edit your
|
||||||
`settings.yml <https://github.com/asciimoo/searx/blob/master/settings.yml>`__
|
`settings.yml <https://github.com/asciimoo/searx/blob/master/searx/settings.yml>`__
|
||||||
(set your ``secret_key``!)
|
(set your ``secret_key``!)
|
||||||
- run ``python searx/webapp.py`` to start the application
|
- run ``python searx/webapp.py`` to start the application
|
||||||
|
|
||||||
|
|
|
@ -54,6 +54,12 @@ def response(resp):
|
||||||
|
|
||||||
dom = html.fromstring(resp.text)
|
dom = html.fromstring(resp.text)
|
||||||
|
|
||||||
|
try:
|
||||||
|
results.append({'number_of_results': int(dom.xpath('//span[@class="sb_count"]/text()')[0]
|
||||||
|
.split()[0].replace(',', ''))})
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
# parse results
|
# parse results
|
||||||
for result in dom.xpath('//div[@class="sa_cc"]'):
|
for result in dom.xpath('//div[@class="sa_cc"]'):
|
||||||
link = result.xpath('.//h3/a')[0]
|
link = result.xpath('.//h3/a')[0]
|
||||||
|
@ -66,10 +72,6 @@ def response(resp):
|
||||||
'title': title,
|
'title': title,
|
||||||
'content': content})
|
'content': content})
|
||||||
|
|
||||||
# return results if something is found
|
|
||||||
if results:
|
|
||||||
return results
|
|
||||||
|
|
||||||
# parse results again if nothing is found yet
|
# parse results again if nothing is found yet
|
||||||
for result in dom.xpath('//li[@class="b_algo"]'):
|
for result in dom.xpath('//li[@class="b_algo"]'):
|
||||||
link = result.xpath('.//h2/a')[0]
|
link = result.xpath('.//h2/a')[0]
|
||||||
|
|
|
@ -9,13 +9,13 @@ categories = []
|
||||||
url = 'https://download.finance.yahoo.com/d/quotes.csv?e=.csv&f=sl1d1t1&s={query}=X'
|
url = 'https://download.finance.yahoo.com/d/quotes.csv?e=.csv&f=sl1d1t1&s={query}=X'
|
||||||
weight = 100
|
weight = 100
|
||||||
|
|
||||||
parser_re = re.compile(u'^\W*(\d+(?:\.\d+)?)\W*([^.0-9].+)\W+in?\W+([^\.]+)\W*$', re.I) # noqa
|
parser_re = re.compile(u'.*?(\d+(?:\.\d+)?) ([^.0-9]+) (?:in|to) ([^.0-9]+)', re.I) # noqa
|
||||||
|
|
||||||
db = 1
|
db = 1
|
||||||
|
|
||||||
|
|
||||||
def normalize_name(name):
|
def normalize_name(name):
|
||||||
name = name.lower().replace('-', ' ')
|
name = name.lower().replace('-', ' ').rstrip('s')
|
||||||
name = re.sub(' +', ' ', name)
|
name = re.sub(' +', ' ', name)
|
||||||
return unicodedata.normalize('NFKD', name).lower()
|
return unicodedata.normalize('NFKD', name).lower()
|
||||||
|
|
||||||
|
|
|
@ -31,9 +31,9 @@ search_string = 'search?{query}'\
|
||||||
'&s={offset}'\
|
'&s={offset}'\
|
||||||
'&format=json'\
|
'&format=json'\
|
||||||
'&qh=0'\
|
'&qh=0'\
|
||||||
'&rxiwd={rxiwd}'\
|
|
||||||
'&qlang={lang}'\
|
'&qlang={lang}'\
|
||||||
'&ff={safesearch}'
|
'&ff={safesearch}'\
|
||||||
|
'&rxikd={rxikd}' # random number - 9 digits
|
||||||
|
|
||||||
# specific xpath variables
|
# specific xpath variables
|
||||||
results_xpath = '//response//result'
|
results_xpath = '//response//result'
|
||||||
|
@ -59,8 +59,7 @@ def request(query, params):
|
||||||
search_path = search_string.format(query=urlencode({'q': query}),
|
search_path = search_string.format(query=urlencode({'q': query}),
|
||||||
offset=offset,
|
offset=offset,
|
||||||
number_of_results=number_of_results,
|
number_of_results=number_of_results,
|
||||||
rxiwd=1,
|
rxikd=str(time())[:9],
|
||||||
# rand=int(time()),
|
|
||||||
lang=language,
|
lang=language,
|
||||||
safesearch=safesearch)
|
safesearch=safesearch)
|
||||||
|
|
||||||
|
|
|
@ -77,6 +77,13 @@ def response(resp):
|
||||||
|
|
||||||
dom = html.fromstring(resp.text)
|
dom = html.fromstring(resp.text)
|
||||||
|
|
||||||
|
try:
|
||||||
|
results_num = int(dom.xpath('//div[@class="compPagination"]/span[last()]/text()')[0]
|
||||||
|
.split()[0].replace(',', ''))
|
||||||
|
results.append({'number_of_results': results_num})
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
# parse results
|
# parse results
|
||||||
for result in dom.xpath(results_xpath):
|
for result in dom.xpath(results_xpath):
|
||||||
try:
|
try:
|
||||||
|
|
|
@ -23,7 +23,8 @@ from searx.plugins import (https_rewrite,
|
||||||
open_results_on_new_tab,
|
open_results_on_new_tab,
|
||||||
self_info,
|
self_info,
|
||||||
search_on_category_select,
|
search_on_category_select,
|
||||||
tracker_url_remover)
|
tracker_url_remover,
|
||||||
|
vim_hotkeys)
|
||||||
|
|
||||||
required_attrs = (('name', str),
|
required_attrs = (('name', str),
|
||||||
('description', str),
|
('description', str),
|
||||||
|
@ -77,3 +78,4 @@ plugins.register(open_results_on_new_tab)
|
||||||
plugins.register(self_info)
|
plugins.register(self_info)
|
||||||
plugins.register(search_on_category_select)
|
plugins.register(search_on_category_select)
|
||||||
plugins.register(tracker_url_remover)
|
plugins.register(tracker_url_remover)
|
||||||
|
plugins.register(vim_hotkeys)
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
from flask.ext.babel import gettext
|
||||||
|
|
||||||
|
name = gettext('Vim-like hotkeys')
|
||||||
|
description = gettext('Navigate search results with Vim-like hotkeys '
|
||||||
|
'(JavaScript required). '
|
||||||
|
'Press "h" key on main or result page to get help.')
|
||||||
|
default_on = False
|
||||||
|
|
||||||
|
js_dependencies = ('plugins/js/vim_hotkeys.js',)
|
||||||
|
css_dependencies = ('plugins/css/vim_hotkeys.css',)
|
|
@ -41,14 +41,18 @@ class HTTPAdapterWithConnParams(requests.adapters.HTTPAdapter):
|
||||||
block=self._pool_block, **self._conn_params)
|
block=self._pool_block, **self._conn_params)
|
||||||
|
|
||||||
|
|
||||||
|
connect = settings['outgoing'].get('pool_connections', 100) # Magic number kept from previous code
|
||||||
|
maxsize = settings['outgoing'].get('pool_maxsize', requests.adapters.DEFAULT_POOLSIZE) # Picked from constructor
|
||||||
if settings['outgoing'].get('source_ips'):
|
if settings['outgoing'].get('source_ips'):
|
||||||
http_adapters = cycle(HTTPAdapterWithConnParams(pool_connections=100, source_address=(source_ip, 0))
|
http_adapters = cycle(HTTPAdapterWithConnParams(pool_connections=connect, pool_maxsize=maxsize,
|
||||||
|
source_address=(source_ip, 0))
|
||||||
for source_ip in settings['outgoing']['source_ips'])
|
for source_ip in settings['outgoing']['source_ips'])
|
||||||
https_adapters = cycle(HTTPAdapterWithConnParams(pool_connections=100, source_address=(source_ip, 0))
|
https_adapters = cycle(HTTPAdapterWithConnParams(pool_connections=connect, pool_maxsize=maxsize,
|
||||||
|
source_address=(source_ip, 0))
|
||||||
for source_ip in settings['outgoing']['source_ips'])
|
for source_ip in settings['outgoing']['source_ips'])
|
||||||
else:
|
else:
|
||||||
http_adapters = cycle((HTTPAdapterWithConnParams(pool_connections=100), ))
|
http_adapters = cycle((HTTPAdapterWithConnParams(pool_connections=connect, pool_maxsize=maxsize), ))
|
||||||
https_adapters = cycle((HTTPAdapterWithConnParams(pool_connections=100), ))
|
https_adapters = cycle((HTTPAdapterWithConnParams(pool_connections=connect, pool_maxsize=maxsize), ))
|
||||||
|
|
||||||
|
|
||||||
class SessionSinglePool(requests.Session):
|
class SessionSinglePool(requests.Session):
|
||||||
|
|
|
@ -181,7 +181,7 @@ class EnginesSetting(SwitchableSetting):
|
||||||
return [item[len('engine_'):].replace('_', ' ').replace(' ', '__') for item in items]
|
return [item[len('engine_'):].replace('_', ' ').replace(' ', '__') for item in items]
|
||||||
|
|
||||||
def transform_values(self, values):
|
def transform_values(self, values):
|
||||||
if len(values) == 1 and values[0] == '':
|
if len(values) == 1 and next(iter(values)) == '':
|
||||||
return list()
|
return list()
|
||||||
transformed_values = []
|
transformed_values = []
|
||||||
for value in values:
|
for value in values:
|
||||||
|
@ -229,6 +229,7 @@ class Preferences(object):
|
||||||
|
|
||||||
self.engines = EnginesSetting('engines', choices=engines)
|
self.engines = EnginesSetting('engines', choices=engines)
|
||||||
self.plugins = PluginsSetting('plugins', choices=plugins)
|
self.plugins = PluginsSetting('plugins', choices=plugins)
|
||||||
|
self.unknown_params = {}
|
||||||
|
|
||||||
def parse_cookies(self, input_data):
|
def parse_cookies(self, input_data):
|
||||||
for user_setting_name, user_setting in input_data.iteritems():
|
for user_setting_name, user_setting in input_data.iteritems():
|
||||||
|
@ -254,6 +255,8 @@ class Preferences(object):
|
||||||
enabled_categories.append(user_setting_name[len('category_'):])
|
enabled_categories.append(user_setting_name[len('category_'):])
|
||||||
elif user_setting_name.startswith('plugin_'):
|
elif user_setting_name.startswith('plugin_'):
|
||||||
disabled_plugins.append(user_setting_name)
|
disabled_plugins.append(user_setting_name)
|
||||||
|
else:
|
||||||
|
self.unknown_params[user_setting_name] = user_setting
|
||||||
self.key_value_settings['categories'].parse_form(enabled_categories)
|
self.key_value_settings['categories'].parse_form(enabled_categories)
|
||||||
self.engines.parse_form(disabled_engines)
|
self.engines.parse_form(disabled_engines)
|
||||||
self.plugins.parse_form(disabled_plugins)
|
self.plugins.parse_form(disabled_plugins)
|
||||||
|
@ -268,4 +271,6 @@ class Preferences(object):
|
||||||
user_setting.save(user_setting_name, resp)
|
user_setting.save(user_setting_name, resp)
|
||||||
self.engines.save(resp)
|
self.engines.save(resp)
|
||||||
self.plugins.save(resp)
|
self.plugins.save(resp)
|
||||||
|
for k, v in self.unknown_params.items():
|
||||||
|
resp.set_cookie(k, v, max_age=COOKIE_MAX_AGE)
|
||||||
return resp
|
return resp
|
||||||
|
|
|
@ -99,6 +99,7 @@ class ResultContainer(object):
|
||||||
self._infobox_ids = {}
|
self._infobox_ids = {}
|
||||||
self.suggestions = set()
|
self.suggestions = set()
|
||||||
self.answers = set()
|
self.answers = set()
|
||||||
|
self.number_of_results = 0
|
||||||
|
|
||||||
def extend(self, engine_name, results):
|
def extend(self, engine_name, results):
|
||||||
for result in list(results):
|
for result in list(results):
|
||||||
|
@ -111,6 +112,9 @@ class ResultContainer(object):
|
||||||
elif 'infobox' in result:
|
elif 'infobox' in result:
|
||||||
self._merge_infobox(result)
|
self._merge_infobox(result)
|
||||||
results.remove(result)
|
results.remove(result)
|
||||||
|
elif 'number_of_results' in result:
|
||||||
|
self.number_of_results = max(self.number_of_results, result['number_of_results'])
|
||||||
|
results.remove(result)
|
||||||
|
|
||||||
with RLock():
|
with RLock():
|
||||||
engines[engine_name].stats['search_count'] += 1
|
engines[engine_name].stats['search_count'] += 1
|
||||||
|
|
|
@ -21,6 +21,8 @@ ui:
|
||||||
outgoing: # communication with search engines
|
outgoing: # communication with search engines
|
||||||
request_timeout : 2.0 # seconds
|
request_timeout : 2.0 # seconds
|
||||||
useragent_suffix : "" # suffix of searx_useragent, could contain informations like an email address to the administrator
|
useragent_suffix : "" # suffix of searx_useragent, could contain informations like an email address to the administrator
|
||||||
|
pool_connections : 100 # Number of different hosts
|
||||||
|
pool_maxsize : 10 # Number of simultaneous requests by host
|
||||||
# uncomment below section if you want to use a proxy
|
# uncomment below section if you want to use a proxy
|
||||||
# see http://docs.python-requests.org/en/latest/user/advanced/#proxies
|
# see http://docs.python-requests.org/en/latest/user/advanced/#proxies
|
||||||
# SOCKS proxies are not supported : see https://github.com/kennethreitz/requests/pull/478
|
# SOCKS proxies are not supported : see https://github.com/kennethreitz/requests/pull/478
|
||||||
|
@ -38,6 +40,17 @@ engines:
|
||||||
engine : archlinux
|
engine : archlinux
|
||||||
shortcut : al
|
shortcut : al
|
||||||
|
|
||||||
|
- name : archive is
|
||||||
|
engine : xpath
|
||||||
|
search_url : https://archive.is/{query}
|
||||||
|
url_xpath : (//div[@class="TEXT-BLOCK"]/a)/@href
|
||||||
|
title_xpath : (//div[@class="TEXT-BLOCK"]/a)
|
||||||
|
content_xpath : //div[@class="TEXT-BLOCK"]/ul/li
|
||||||
|
categories : general
|
||||||
|
timeout : 7.0
|
||||||
|
disabled : True
|
||||||
|
shortcut : ai
|
||||||
|
|
||||||
- name : base
|
- name : base
|
||||||
engine : base
|
engine : base
|
||||||
shortcut : bs
|
shortcut : bs
|
||||||
|
@ -221,8 +234,8 @@ engines:
|
||||||
engine : xpath
|
engine : xpath
|
||||||
paging : True
|
paging : True
|
||||||
search_url : https://geektimes.ru/search/page{pageno}/?q={query}
|
search_url : https://geektimes.ru/search/page{pageno}/?q={query}
|
||||||
url_xpath : //div[@class="search_results"]//a[@class="post_title"]/@href
|
url_xpath : //div[@class="search_results"]//a[@class="post__title_link"]/@href
|
||||||
title_xpath : //div[@class="search_results"]//a[@class="post_title"]
|
title_xpath : //div[@class="search_results"]//a[@class="post__title_link"]
|
||||||
content_xpath : //div[@class="search_results"]//div[contains(@class, "content")]
|
content_xpath : //div[@class="search_results"]//div[contains(@class, "content")]
|
||||||
categories : it
|
categories : it
|
||||||
timeout : 4.0
|
timeout : 4.0
|
||||||
|
|
|
@ -0,0 +1,26 @@
|
||||||
|
.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+ */
|
||||||
|
}
|
|
@ -0,0 +1,336 @@
|
||||||
|
$(document).ready(function() {
|
||||||
|
highlightResult('top')();
|
||||||
|
|
||||||
|
$('.result').on('click', function() {
|
||||||
|
highlightResult($(this))();
|
||||||
|
});
|
||||||
|
|
||||||
|
var vimKeys = {
|
||||||
|
27: {
|
||||||
|
key: 'Escape',
|
||||||
|
fun: removeFocus,
|
||||||
|
des: 'remove focus from the focused input',
|
||||||
|
cat: 'Control'
|
||||||
|
},
|
||||||
|
73: {
|
||||||
|
key: 'i',
|
||||||
|
fun: searchInputFocus,
|
||||||
|
des: 'focus on the search input',
|
||||||
|
cat: 'Control'
|
||||||
|
},
|
||||||
|
66: {
|
||||||
|
key: 'b',
|
||||||
|
fun: scrollPage(-window.innerHeight),
|
||||||
|
des: 'scroll one page up',
|
||||||
|
cat: 'Navigation'
|
||||||
|
},
|
||||||
|
70: {
|
||||||
|
key: 'f',
|
||||||
|
fun: scrollPage(window.innerHeight),
|
||||||
|
des: 'scroll one page down',
|
||||||
|
cat: 'Navigation'
|
||||||
|
},
|
||||||
|
85: {
|
||||||
|
key: 'u',
|
||||||
|
fun: scrollPage(-window.innerHeight / 2),
|
||||||
|
des: 'scroll half a page up',
|
||||||
|
cat: 'Navigation'
|
||||||
|
},
|
||||||
|
68: {
|
||||||
|
key: 'd',
|
||||||
|
fun: scrollPage(window.innerHeight / 2),
|
||||||
|
des: 'scroll half a page down',
|
||||||
|
cat: 'Navigation'
|
||||||
|
},
|
||||||
|
71: {
|
||||||
|
key: 'g',
|
||||||
|
fun: scrollPageTo(-document.body.scrollHeight, 'top'),
|
||||||
|
des: 'scroll to the top of the page',
|
||||||
|
cat: 'Navigation'
|
||||||
|
},
|
||||||
|
86: {
|
||||||
|
key: 'v',
|
||||||
|
fun: scrollPageTo(document.body.scrollHeight, 'bottom'),
|
||||||
|
des: 'scroll to the bottom of the page',
|
||||||
|
cat: 'Navigation'
|
||||||
|
},
|
||||||
|
75: {
|
||||||
|
key: 'k',
|
||||||
|
fun: highlightResult('up'),
|
||||||
|
des: 'select previous search result',
|
||||||
|
cat: 'Results'
|
||||||
|
},
|
||||||
|
74: {
|
||||||
|
key: 'j',
|
||||||
|
fun: highlightResult('down'),
|
||||||
|
des: 'select next search result',
|
||||||
|
cat: 'Results'
|
||||||
|
},
|
||||||
|
80: {
|
||||||
|
key: 'p',
|
||||||
|
fun: pageButtonClick(0),
|
||||||
|
des: 'go to previous page',
|
||||||
|
cat: 'Results'
|
||||||
|
},
|
||||||
|
78: {
|
||||||
|
key: 'n',
|
||||||
|
fun: pageButtonClick(1),
|
||||||
|
des: 'go to next page',
|
||||||
|
cat: 'Results'
|
||||||
|
},
|
||||||
|
79: {
|
||||||
|
key: 'o',
|
||||||
|
fun: openResult(false),
|
||||||
|
des: 'open search result',
|
||||||
|
cat: 'Results'
|
||||||
|
},
|
||||||
|
84: {
|
||||||
|
key: 't',
|
||||||
|
fun: openResult(true),
|
||||||
|
des: 'open the result in a new tab',
|
||||||
|
cat: 'Results'
|
||||||
|
},
|
||||||
|
82: {
|
||||||
|
key: 'r',
|
||||||
|
fun: reloadPage,
|
||||||
|
des: 'reload page from the server',
|
||||||
|
cat: 'Control'
|
||||||
|
},
|
||||||
|
72: {
|
||||||
|
key: 'h',
|
||||||
|
fun: toggleHelp,
|
||||||
|
des: 'toggle help window',
|
||||||
|
cat: 'Other'
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
$(document).keyup(function(e) {
|
||||||
|
// check for modifiers so we don't break browser's hotkeys
|
||||||
|
if (vimKeys.hasOwnProperty(e.keyCode)
|
||||||
|
&& !e.ctrlKey
|
||||||
|
&& !e.altKey
|
||||||
|
&& !e.shiftKey
|
||||||
|
&& !e.metaKey)
|
||||||
|
{
|
||||||
|
if (e.keyCode === 27) {
|
||||||
|
if (e.target.tagName.toLowerCase() === 'input') {
|
||||||
|
vimKeys[e.keyCode].fun();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (e.target === document.body) {
|
||||||
|
vimKeys[e.keyCode].fun();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
function highlightResult(which) {
|
||||||
|
return function() {
|
||||||
|
var current = $('.result[data-vim-selected]');
|
||||||
|
if (current.length === 0) {
|
||||||
|
current = $('.result:first');
|
||||||
|
if (current.length === 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var next;
|
||||||
|
|
||||||
|
if (typeof which !== 'string') {
|
||||||
|
next = which;
|
||||||
|
} else {
|
||||||
|
switch (which) {
|
||||||
|
case 'visible':
|
||||||
|
var top = $(window).scrollTop();
|
||||||
|
var bot = top + $(window).height();
|
||||||
|
var results = $('.result');
|
||||||
|
|
||||||
|
for (var i = 0; i < results.length; i++) {
|
||||||
|
next = $(results[i]);
|
||||||
|
var etop = next.offset().top;
|
||||||
|
var ebot = etop + next.height();
|
||||||
|
|
||||||
|
if ((ebot <= bot) && (etop > top)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'down':
|
||||||
|
next = current.next('.result');
|
||||||
|
if (next.length === 0) {
|
||||||
|
next = $('.result:first');
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'up':
|
||||||
|
next = current.prev('.result');
|
||||||
|
if (next.length === 0) {
|
||||||
|
next = $('.result:last');
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'bottom':
|
||||||
|
next = $('.result:last');
|
||||||
|
break;
|
||||||
|
case 'top':
|
||||||
|
default:
|
||||||
|
next = $('.result:first');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (next) {
|
||||||
|
current.removeAttr('data-vim-selected').removeClass('well well-sm');
|
||||||
|
next.attr('data-vim-selected', 'true').addClass('well well-sm');
|
||||||
|
scrollPageToSelected();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function reloadPage() {
|
||||||
|
document.location.reload(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
function removeFocus() {
|
||||||
|
if (document.activeElement) {
|
||||||
|
document.activeElement.blur();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function pageButtonClick(num) {
|
||||||
|
return function() {
|
||||||
|
var buttons = $('div#pagination button[type="submit"]');
|
||||||
|
if (buttons.length !== 2) {
|
||||||
|
console.log('page navigation with this theme is not supported');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (num >= 0 && num < buttons.length) {
|
||||||
|
buttons[num].click();
|
||||||
|
} else {
|
||||||
|
console.log('pageButtonClick(): invalid argument');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function scrollPageToSelected() {
|
||||||
|
var sel = $('.result[data-vim-selected]');
|
||||||
|
if (sel.length !== 1) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var wnd = $(window);
|
||||||
|
|
||||||
|
var wtop = wnd.scrollTop();
|
||||||
|
var etop = sel.offset().top;
|
||||||
|
|
||||||
|
var offset = 30;
|
||||||
|
|
||||||
|
if (wtop > etop) {
|
||||||
|
wnd.scrollTop(etop - offset);
|
||||||
|
} else {
|
||||||
|
var ebot = etop + sel.height();
|
||||||
|
var wbot = wtop + wnd.height();
|
||||||
|
|
||||||
|
if (wbot < ebot) {
|
||||||
|
wnd.scrollTop(ebot - wnd.height() + offset);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function scrollPage(amount) {
|
||||||
|
return function() {
|
||||||
|
window.scrollBy(0, amount);
|
||||||
|
highlightResult('visible')();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function scrollPageTo(position, nav) {
|
||||||
|
return function() {
|
||||||
|
window.scrollTo(0, position);
|
||||||
|
highlightResult(nav)();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function searchInputFocus() {
|
||||||
|
$('input#q').focus();
|
||||||
|
}
|
||||||
|
|
||||||
|
function openResult(newTab) {
|
||||||
|
return function() {
|
||||||
|
var link = $('.result[data-vim-selected] .result_header a');
|
||||||
|
if (link.length) {
|
||||||
|
var url = link.attr('href');
|
||||||
|
if (newTab) {
|
||||||
|
window.open(url);
|
||||||
|
} else {
|
||||||
|
window.location.href = url;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function toggleHelp() {
|
||||||
|
var helpPanel = $('#vim-hotkeys-help');
|
||||||
|
if (helpPanel.length) {
|
||||||
|
helpPanel.toggleClass('hidden');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var categories = {};
|
||||||
|
|
||||||
|
for (var k in vimKeys) {
|
||||||
|
var key = vimKeys[k];
|
||||||
|
categories[key.cat] = categories[key.cat] || [];
|
||||||
|
categories[key.cat].push(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
var sorted = Object.keys(categories).sort(function(a, b) {
|
||||||
|
return categories[b].length - categories[a].length;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (sorted.length === 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var html = '<div id="vim-hotkeys-help" class="well vim-hotkeys-help">';
|
||||||
|
html += '<div class="container-fluid">';
|
||||||
|
|
||||||
|
html += '<div class="row">';
|
||||||
|
html += '<div class="col-sm-12">';
|
||||||
|
html += '<h3>How to navigate searx with Vim-like hotkeys</h3>';
|
||||||
|
html += '</div>'; // col-sm-12
|
||||||
|
html += '</div>'; // row
|
||||||
|
|
||||||
|
for (var i = 0; i < sorted.length; i++) {
|
||||||
|
var cat = categories[sorted[i]];
|
||||||
|
|
||||||
|
var lastCategory = i === (sorted.length - 1);
|
||||||
|
var first = i % 2 === 0;
|
||||||
|
|
||||||
|
if (first) {
|
||||||
|
html += '<div class="row dflex">';
|
||||||
|
}
|
||||||
|
html += '<div class="col-sm-' + (first && lastCategory ? 12 : 6) + ' dflex">';
|
||||||
|
|
||||||
|
html += '<div class="panel panel-default iflex">';
|
||||||
|
html += '<div class="panel-heading">' + cat[0].cat + '</div>';
|
||||||
|
html += '<div class="panel-body">';
|
||||||
|
html += '<ul class="list-unstyled">';
|
||||||
|
|
||||||
|
for (var cj in cat) {
|
||||||
|
html += '<li><kbd>' + cat[cj].key + '</kbd> ' + cat[cj].des + '</li>';
|
||||||
|
}
|
||||||
|
|
||||||
|
html += '</ul>';
|
||||||
|
html += '</div>'; // panel-body
|
||||||
|
html += '</div>'; // panel
|
||||||
|
html += '</div>'; // col-sm-*
|
||||||
|
|
||||||
|
if (!first || lastCategory) {
|
||||||
|
html += '</div>'; // row
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
html += '</div>'; // container-fluid
|
||||||
|
html += '</div>'; // vim-hotkeys-help
|
||||||
|
|
||||||
|
$('body').append(html);
|
||||||
|
}
|
||||||
|
});
|
File diff suppressed because one or more lines are too long
|
@ -1,88 +0,0 @@
|
||||||
html{position:relative;min-height:100%}
|
|
||||||
body{margin-bottom:80px}
|
|
||||||
.footer{position:absolute;bottom:0;width:100%;height:60px}
|
|
||||||
input[type=checkbox]:checked+.label_hide_if_checked,input[type=checkbox]:checked+.label_hide_if_not_checked+.label_hide_if_checked{display:none}
|
|
||||||
input[type=checkbox]:not(:checked)+.label_hide_if_not_checked,input[type=checkbox]:not(:checked)+.label_hide_if_checked+.label_hide_if_not_checked{display:none}
|
|
||||||
.result_header{margin-bottom:5px;margin-top:20px}.result_header .favicon{margin-bottom:-3px}
|
|
||||||
.result_header a{vertical-align:bottom}.result_header a .highlight{font-weight:bold}
|
|
||||||
.result-content{margin-top:5px;word-wrap:break-word}.result-content .highlight{font-weight:bold}
|
|
||||||
.result-default{clear:both}
|
|
||||||
.result-images{float:left !important}
|
|
||||||
.img-thumbnail{margin:5px;max-height:128px;min-height:128px}
|
|
||||||
.result-videos{clear:both}
|
|
||||||
.result-torrents{clear:both}
|
|
||||||
.result-map{clear:both}
|
|
||||||
.result-code{clear:both}
|
|
||||||
.suggestion_item{margin:2px 5px}
|
|
||||||
.result_download{margin-right:5px}
|
|
||||||
#pagination{margin-top:30px;padding-bottom:50px}
|
|
||||||
.label-default{color:#aaa;background:#fff}
|
|
||||||
.infobox .infobox_part{margin-bottom:20px;word-wrap:break-word;table-layout:fixed}
|
|
||||||
.infobox .infobox_part:last-child{margin-bottom:0}
|
|
||||||
.search_categories{margin:10px 0;text-transform:capitalize}
|
|
||||||
.cursor-text{cursor:text !important}
|
|
||||||
.cursor-pointer{cursor:pointer !important}
|
|
||||||
.highlight .hll{background-color:#ffc}
|
|
||||||
.highlight{background:#f8f8f8}
|
|
||||||
.highlight .c{color:#408080;font-style:italic}
|
|
||||||
.highlight .err{border:1px solid #f00}
|
|
||||||
.highlight .k{color:#008000;font-weight:bold}
|
|
||||||
.highlight .o{color:#666}
|
|
||||||
.highlight .cm{color:#408080;font-style:italic}
|
|
||||||
.highlight .cp{color:#bc7a00}
|
|
||||||
.highlight .c1{color:#408080;font-style:italic}
|
|
||||||
.highlight .cs{color:#408080;font-style:italic}
|
|
||||||
.highlight .gd{color:#a00000}
|
|
||||||
.highlight .ge{font-style:italic}
|
|
||||||
.highlight .gr{color:#f00}
|
|
||||||
.highlight .gh{color:#000080;font-weight:bold}
|
|
||||||
.highlight .gi{color:#00a000}
|
|
||||||
.highlight .go{color:#888}
|
|
||||||
.highlight .gp{color:#000080;font-weight:bold}
|
|
||||||
.highlight .gs{font-weight:bold}
|
|
||||||
.highlight .gu{color:#800080;font-weight:bold}
|
|
||||||
.highlight .gt{color:#04d}
|
|
||||||
.highlight .kc{color:#008000;font-weight:bold}
|
|
||||||
.highlight .kd{color:#008000;font-weight:bold}
|
|
||||||
.highlight .kn{color:#008000;font-weight:bold}
|
|
||||||
.highlight .kp{color:#008000}
|
|
||||||
.highlight .kr{color:#008000;font-weight:bold}
|
|
||||||
.highlight .kt{color:#b00040}
|
|
||||||
.highlight .m{color:#666}
|
|
||||||
.highlight .s{color:#ba2121}
|
|
||||||
.highlight .na{color:#7d9029}
|
|
||||||
.highlight .nb{color:#008000}
|
|
||||||
.highlight .nc{color:#00f;font-weight:bold}
|
|
||||||
.highlight .no{color:#800}
|
|
||||||
.highlight .nd{color:#a2f}
|
|
||||||
.highlight .ni{color:#999;font-weight:bold}
|
|
||||||
.highlight .ne{color:#d2413a;font-weight:bold}
|
|
||||||
.highlight .nf{color:#00f}
|
|
||||||
.highlight .nl{color:#a0a000}
|
|
||||||
.highlight .nn{color:#00f;font-weight:bold}
|
|
||||||
.highlight .nt{color:#008000;font-weight:bold}
|
|
||||||
.highlight .nv{color:#19177c}
|
|
||||||
.highlight .ow{color:#a2f;font-weight:bold}
|
|
||||||
.highlight .w{color:#bbb}
|
|
||||||
.highlight .mf{color:#666}
|
|
||||||
.highlight .mh{color:#666}
|
|
||||||
.highlight .mi{color:#666}
|
|
||||||
.highlight .mo{color:#666}
|
|
||||||
.highlight .sb{color:#ba2121}
|
|
||||||
.highlight .sc{color:#ba2121}
|
|
||||||
.highlight .sd{color:#ba2121;font-style:italic}
|
|
||||||
.highlight .s2{color:#ba2121}
|
|
||||||
.highlight .se{color:#b62;font-weight:bold}
|
|
||||||
.highlight .sh{color:#ba2121}
|
|
||||||
.highlight .si{color:#b68;font-weight:bold}
|
|
||||||
.highlight .sx{color:#008000}
|
|
||||||
.highlight .sr{color:#b68}
|
|
||||||
.highlight .s1{color:#ba2121}
|
|
||||||
.highlight .ss{color:#19177c}
|
|
||||||
.highlight .bp{color:#008000}
|
|
||||||
.highlight .vc{color:#19177c}
|
|
||||||
.highlight .vg{color:#19177c}
|
|
||||||
.highlight .vi{color:#19177c}
|
|
||||||
.highlight .il{color:#666}
|
|
||||||
.highlight .lineno{-webkit-touch-callout:none;-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;cursor:default}.highlight .lineno::selection{background:transparent;}
|
|
||||||
.highlight .lineno::-moz-selection{background:transparent;}
|
|
|
@ -0,0 +1 @@
|
||||||
|
html{position:relative;min-height:100%}body{margin-bottom:80px}.footer{position:absolute;bottom:0;width:100%;height:60px}input[type=checkbox]:checked+.label_hide_if_checked,input[type=checkbox]:checked+.label_hide_if_not_checked+.label_hide_if_checked{display:none}input[type=checkbox]:not(:checked)+.label_hide_if_not_checked,input[type=checkbox]:not(:checked)+.label_hide_if_checked+.label_hide_if_not_checked{display:none}.result_header{margin-bottom:5px;margin-top:20px}.result_header .favicon{margin-bottom:-3px}.result_header a{vertical-align:bottom}.result_header a .highlight{font-weight:700}.result-content{margin-top:5px;word-wrap:break-word}.result-content .highlight{font-weight:700}.result-default{clear:both}.result-images{float:left!important}.img-thumbnail{margin:5px;max-height:128px;min-height:128px}.result-videos{clear:both}.result-torrents{clear:both}.result-map{clear:both}.result-code{clear:both}.suggestion_item{margin:2px 5px}.result_download{margin-right:5px}#pagination{margin-top:30px;padding-bottom:50px}.label-default{color:#AAA;background:#FFF}.infobox .infobox_part{margin-bottom:20px;word-wrap:break-word;table-layout:fixed}.infobox .infobox_part:last-child{margin-bottom:0}.search_categories{margin:10px 0;text-transform:capitalize}.cursor-text{cursor:text!important}.cursor-pointer{cursor:pointer!important}.highlight .hll{background-color:#ffc}.highlight{background:#f8f8f8}.highlight .c{color:#408080;font-style:italic}.highlight .err{border:1px solid red}.highlight .k{color:green;font-weight:700}.highlight .o{color:#666}.highlight .cm{color:#408080;font-style:italic}.highlight .cp{color:#bc7a00}.highlight .c1{color:#408080;font-style:italic}.highlight .cs{color:#408080;font-style:italic}.highlight .gd{color:#a00000}.highlight .ge{font-style:italic}.highlight .gr{color:red}.highlight .gh{color:navy;font-weight:700}.highlight .gi{color:#00a000}.highlight .go{color:#888}.highlight .gp{color:navy;font-weight:700}.highlight .gs{font-weight:700}.highlight .gu{color:purple;font-weight:700}.highlight .gt{color:#04d}.highlight .kc{color:green;font-weight:700}.highlight .kd{color:green;font-weight:700}.highlight .kn{color:green;font-weight:700}.highlight .kp{color:green}.highlight .kr{color:green;font-weight:700}.highlight .kt{color:#b00040}.highlight .m{color:#666}.highlight .s{color:#ba2121}.highlight .na{color:#7d9029}.highlight .nb{color:green}.highlight .nc{color:#00F;font-weight:700}.highlight .no{color:#800}.highlight .nd{color:#a2f}.highlight .ni{color:#999;font-weight:700}.highlight .ne{color:#D2413A;font-weight:700}.highlight .nf{color:#00f}.highlight .nl{color:#a0a000}.highlight .nn{color:#00F;font-weight:700}.highlight .nt{color:green;font-weight:700}.highlight .nv{color:#19177c}.highlight .ow{color:#A2F;font-weight:700}.highlight .w{color:#bbb}.highlight .mf{color:#666}.highlight .mh{color:#666}.highlight .mi{color:#666}.highlight .mo{color:#666}.highlight .sb{color:#ba2121}.highlight .sc{color:#ba2121}.highlight .sd{color:#BA2121;font-style:italic}.highlight .s2{color:#ba2121}.highlight .se{color:#B62;font-weight:700}.highlight .sh{color:#ba2121}.highlight .si{color:#B68;font-weight:700}.highlight .sx{color:green}.highlight .sr{color:#b68}.highlight .s1{color:#ba2121}.highlight .ss{color:#19177c}.highlight .bp{color:green}.highlight .vc{color:#19177c}.highlight .vg{color:#19177c}.highlight .vi{color:#19177c}.highlight .il{color:#666}.highlight .lineno{-webkit-touch-callout:none;-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;cursor:default}.highlight .lineno::selection{background:0 0}.highlight .lineno::-moz-selection{background:0 0}
|
|
@ -36,18 +36,20 @@ module.exports = function(grunt) {
|
||||||
less: {
|
less: {
|
||||||
development: {
|
development: {
|
||||||
options: {
|
options: {
|
||||||
paths: ["less/oscar"]
|
paths: ["less/pointhi", "less/logicodev"]
|
||||||
//banner: '/*! less/oscar/oscar.css | <%= grunt.template.today("dd-mm-yyyy") %> | https://github.com/asciimoo/searx */\n'
|
//banner: '/*! less/oscar/oscar.css | <%= grunt.template.today("dd-mm-yyyy") %> | https://github.com/asciimoo/searx */\n'
|
||||||
},
|
},
|
||||||
files: {"css/oscar.css": "less/oscar/oscar.less"}
|
files: {"css/pointhi.css": "less/pointhi/oscar.less",
|
||||||
|
"css/logicodev.css": "less/logicodev/oscar.less"}
|
||||||
},
|
},
|
||||||
production: {
|
production: {
|
||||||
options: {
|
options: {
|
||||||
paths: ["less/oscar"],
|
paths: ["less/pointhi", "less/logicodev"],
|
||||||
//banner: '/*! less/oscar/oscar.css | <%= grunt.template.today("dd-mm-yyyy") %> | https://github.com/asciimoo/searx */\n',
|
//banner: '/*! less/oscar/oscar.css | <%= grunt.template.today("dd-mm-yyyy") %> | https://github.com/asciimoo/searx */\n',
|
||||||
cleancss: true
|
cleancss: true
|
||||||
},
|
},
|
||||||
files: {"css/oscar.min.css": "less/oscar/oscar.less"}
|
files: {"css/pointhi.min.css": "less/pointhi/oscar.less",
|
||||||
|
"css/logicodev.min.css": "less/logicodev/oscar.less"}
|
||||||
},
|
},
|
||||||
bootstrap: {
|
bootstrap: {
|
||||||
options: {
|
options: {
|
||||||
|
@ -63,7 +65,7 @@ module.exports = function(grunt) {
|
||||||
tasks: ['jshint', 'concat', 'uglify']
|
tasks: ['jshint', 'concat', 'uglify']
|
||||||
},
|
},
|
||||||
oscar_styles: {
|
oscar_styles: {
|
||||||
files: ['less/oscar/**/*.less'],
|
files: ['less/pointhi/**/*.less'],
|
||||||
tasks: ['less:development', 'less:production']
|
tasks: ['less:development', 'less:production']
|
||||||
},
|
},
|
||||||
bootstrap_styles: {
|
bootstrap_styles: {
|
||||||
|
|
Binary file not shown.
After Width: | Height: | Size: 33 KiB |
Binary file not shown.
After Width: | Height: | Size: 32 KiB |
|
@ -0,0 +1,103 @@
|
||||||
|
pre, code{
|
||||||
|
font-family: 'Ubuntu Mono', 'Courier New', 'Lucida Console', monospace !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.lineno{
|
||||||
|
margin-right: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.highlight .hll { background-color: #ffffcc }
|
||||||
|
.highlight { background: #f8f8f8; }
|
||||||
|
.highlight .c { color: #556366; font-style: italic } /* Comment */
|
||||||
|
.highlight .err { border: 1px solid @orange } /* Error */
|
||||||
|
.highlight .k { color: #BE74D5; font-weight: bold } /* Keyword */
|
||||||
|
.highlight .o { color: #D19A66 } /* Operator */
|
||||||
|
.highlight .cm { color: #556366; font-style: italic } /* Comment.Multiline */
|
||||||
|
.highlight .cp { color: #BC7A00 } /* Comment.Preproc */
|
||||||
|
.highlight .c1 { color: #556366; font-style: italic } /* Comment.Single */
|
||||||
|
.highlight .cs { color: #556366; font-style: italic } /* Comment.Special */
|
||||||
|
.highlight .gd { color: #A00000 } /* Generic.Deleted */
|
||||||
|
.highlight .ge { font-style: italic } /* Generic.Emph */
|
||||||
|
.highlight .gr { color: #FF0000 } /* Generic.Error */
|
||||||
|
.highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */
|
||||||
|
.highlight .gi { color: #00A000 } /* Generic.Inserted */
|
||||||
|
.highlight .go { color: #888888 } /* Generic.Output */
|
||||||
|
.highlight .gp { color: #000080; font-weight: bold } /* Generic.Prompt */
|
||||||
|
.highlight .gs { font-weight: bold } /* Generic.Strong */
|
||||||
|
.highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */
|
||||||
|
.highlight .gt { color: #0044DD } /* Generic.Traceback */
|
||||||
|
.highlight .kc { color: #BE74D5; font-weight: bold } /* Keyword.Constant */
|
||||||
|
.highlight .kd { color: #BE74D5; font-weight: bold } /* Keyword.Declaration */
|
||||||
|
.highlight .kn { color: #BE74D5; font-weight: bold } /* Keyword.Namespace */
|
||||||
|
.highlight .kp { color: #BE74D5 } /* Keyword.Pseudo */
|
||||||
|
.highlight .kr { color: #BE74D5; font-weight: bold } /* Keyword.Reserved */
|
||||||
|
.highlight .kt { color: #D46C72 } /* Keyword.Type */
|
||||||
|
.highlight .m { color: #D19A66 } /* Literal.Number */
|
||||||
|
.highlight .s { color: #86C372 } /* Literal.String */
|
||||||
|
.highlight .na { color: #7D9029 } /* Name.Attribute */
|
||||||
|
.highlight .nb { color: #BE74D5 } /* Name.Builtin */
|
||||||
|
.highlight .nc { color: #61AFEF; font-weight: bold } /* Name.Class */
|
||||||
|
.highlight .no { color: #D19A66 } /* Name.Constant */
|
||||||
|
.highlight .nd { color: #AA22FF } /* Name.Decorator */
|
||||||
|
.highlight .ni { color: #999999; font-weight: bold } /* Name.Entity */
|
||||||
|
.highlight .ne { color: #D2413A; font-weight: bold } /* Name.Exception */
|
||||||
|
.highlight .nf { color: #61AFEF } /* Name.Function */
|
||||||
|
.highlight .nl { color: #A0A000 } /* Name.Label */
|
||||||
|
.highlight .nn { color: #61AFEF; font-weight: bold } /* Name.Namespace */
|
||||||
|
.highlight .nt { color: #BE74D5; font-weight: bold } /* Name.Tag */
|
||||||
|
.highlight .nv { color: #DFC06F } /* Name.Variable */
|
||||||
|
.highlight .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */
|
||||||
|
.highlight .w { color: #D7DAE0 } /* Text.Whitespace */
|
||||||
|
.highlight .mf { color: #D19A66 } /* Literal.Number.Float */
|
||||||
|
.highlight .mh { color: #D19A66 } /* Literal.Number.Hex */
|
||||||
|
.highlight .mi { color: #D19A66 } /* Literal.Number.Integer */
|
||||||
|
.highlight .mo { color: #D19A66 } /* Literal.Number.Oct */
|
||||||
|
.highlight .sb { color: #86C372 } /* Literal.String.Backtick */
|
||||||
|
.highlight .sc { color: #86C372 } /* Literal.String.Char */
|
||||||
|
.highlight .sd { color: #86C372; font-style: italic } /* Literal.String.Doc */
|
||||||
|
.highlight .s2 { color: #86C372 } /* Literal.String.Double */
|
||||||
|
.highlight .se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */
|
||||||
|
.highlight .sh { color: #86C372 } /* Literal.String.Heredoc */
|
||||||
|
.highlight .si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */
|
||||||
|
.highlight .sx { color: #BE74D5 } /* Literal.String.Other */
|
||||||
|
.highlight .sr { color: #BB6688 } /* Literal.String.Regex */
|
||||||
|
.highlight .s1 { color: #86C372 } /* Literal.String.Single */
|
||||||
|
.highlight .ss { color: #DFC06F } /* Literal.String.Symbol */
|
||||||
|
.highlight .bp { color: #BE74D5 } /* Name.Builtin.Pseudo */
|
||||||
|
.highlight .vc { color: #DFC06F } /* Name.Variable.Class */
|
||||||
|
.highlight .vg { color: #DFC06F } /* Name.Variable.Global */
|
||||||
|
.highlight .vi { color: #DFC06F } /* Name.Variable.Instance */
|
||||||
|
.highlight .il { color: #D19A66 } /* Literal.Number.Integer.Long */
|
||||||
|
|
||||||
|
.highlight .lineno {
|
||||||
|
-webkit-touch-callout: none;
|
||||||
|
-webkit-user-select: none;
|
||||||
|
-khtml-user-select: none;
|
||||||
|
-moz-user-select: none;
|
||||||
|
-ms-user-select: none;
|
||||||
|
user-select: none;
|
||||||
|
cursor: default;
|
||||||
|
color: #556366;
|
||||||
|
|
||||||
|
&::selection {
|
||||||
|
background: transparent; /* WebKit/Blink Browsers */
|
||||||
|
}
|
||||||
|
&::-moz-selection {
|
||||||
|
background: transparent; /* Gecko Browsers */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.highlight pre {
|
||||||
|
background-color: #282C34;
|
||||||
|
color: #D7DAE0;
|
||||||
|
border: none;
|
||||||
|
margin-bottom: 25px;
|
||||||
|
font-size: 15px;
|
||||||
|
padding: 20px 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.highlight {
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,30 @@
|
||||||
|
// Sticky footer styles
|
||||||
|
*{
|
||||||
|
border-radius: 0 !important;
|
||||||
|
}
|
||||||
|
html {
|
||||||
|
position: relative;
|
||||||
|
min-height: 100%;
|
||||||
|
color: @black;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
/* Margin bottom by footer height */
|
||||||
|
font-family: 'Roboto', Helvetica, Arial, sans-serif;
|
||||||
|
margin-bottom: 80px;
|
||||||
|
background-color: white;
|
||||||
|
|
||||||
|
a{
|
||||||
|
color: @blue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer {
|
||||||
|
position: absolute;
|
||||||
|
bottom: 0;
|
||||||
|
width: 100%;
|
||||||
|
/* Set the fixed height of the footer here */
|
||||||
|
height: 60px;
|
||||||
|
text-align: center;
|
||||||
|
color: #999;
|
||||||
|
}
|
|
@ -0,0 +1,37 @@
|
||||||
|
.infobox {
|
||||||
|
|
||||||
|
.panel-heading{
|
||||||
|
background-color: @dim-gray;
|
||||||
|
|
||||||
|
.panel-title{
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
p{
|
||||||
|
font-family: "DejaVu Serif", Georgia, Cambria, "Times New Roman", Times, serif !important;
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn{
|
||||||
|
background-color: @green;
|
||||||
|
border: none;
|
||||||
|
|
||||||
|
a{
|
||||||
|
color: white;
|
||||||
|
margin: 5px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.infobox_part {
|
||||||
|
margin-bottom: 20px;
|
||||||
|
word-wrap: break-word;
|
||||||
|
table-layout: fixed;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
.infobox_part:last-child {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,54 @@
|
||||||
|
.navbar-default .navbar-nav > .active > a, .navbar-default .navbar-nav > .active > a:hover, .navbar-default .navbar-nav > .active > a:focus{
|
||||||
|
background: @black;
|
||||||
|
color: @light-green;
|
||||||
|
}
|
||||||
|
|
||||||
|
.navbar > li > a {
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.navbar-nav > li > a {
|
||||||
|
background: @black;
|
||||||
|
padding: 0 8px;
|
||||||
|
margin: 0;
|
||||||
|
line-height: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.navbar, .navbar-default{
|
||||||
|
background-color: @black;
|
||||||
|
border: none;
|
||||||
|
border-top: 4px solid @light-green;
|
||||||
|
padding-top: 5px;
|
||||||
|
color: @dim-gray !important;
|
||||||
|
font-weight: 700;
|
||||||
|
font-size: 1.1em;
|
||||||
|
text-transform: lowercase;
|
||||||
|
margin-bottom: 24px;
|
||||||
|
height: 30px;
|
||||||
|
line-height: 30px;
|
||||||
|
|
||||||
|
.navbar-nav > li > a{
|
||||||
|
color: @dim-gray;
|
||||||
|
}
|
||||||
|
|
||||||
|
.navbar-brand{
|
||||||
|
font-weight: 700;
|
||||||
|
color: @light-green;
|
||||||
|
line-height: 30px;
|
||||||
|
padding: 0 30px;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Hover color
|
||||||
|
// http://stackoverflow.com/users/114029/leniel-macaferi
|
||||||
|
.navbar-default .navbar-nav > li > a:hover, .navbar-default .navbar-nav > li > a:focus {
|
||||||
|
color: @light-green;
|
||||||
|
background: @black;
|
||||||
|
}
|
||||||
|
|
||||||
|
.navbar-toggle {
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
|
@ -0,0 +1,17 @@
|
||||||
|
@import "variables.less";
|
||||||
|
|
||||||
|
@import "navbar.less";
|
||||||
|
|
||||||
|
@import "footer.less";
|
||||||
|
|
||||||
|
@import "checkbox.less";
|
||||||
|
|
||||||
|
@import "results.less";
|
||||||
|
|
||||||
|
@import "infobox.less";
|
||||||
|
|
||||||
|
@import "search.less";
|
||||||
|
|
||||||
|
@import "cursor.less";
|
||||||
|
|
||||||
|
@import "code.less";
|
|
@ -0,0 +1,150 @@
|
||||||
|
.result_header {
|
||||||
|
margin-top: 6px;
|
||||||
|
margin-bottom: 4px;
|
||||||
|
font-size: 16px;
|
||||||
|
|
||||||
|
.favicon {
|
||||||
|
margin-bottom:-3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
color: @black;
|
||||||
|
text-decoration: none;
|
||||||
|
|
||||||
|
&:hover{
|
||||||
|
color: @blue;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:visited{
|
||||||
|
color: @violet;
|
||||||
|
}
|
||||||
|
|
||||||
|
.highlight {
|
||||||
|
background-color: @dim-gray;
|
||||||
|
// Chrome hack: bold is different size than normal
|
||||||
|
// https://stackoverflow.com/questions/20713988/weird-text-alignment-issue-in-css-when-bolded-lucida-sans
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.result-content {
|
||||||
|
margin-top: 2px;
|
||||||
|
margin-bottom: 0;
|
||||||
|
word-wrap: break-word;
|
||||||
|
color: @dark-gray;
|
||||||
|
font-size: 13px;
|
||||||
|
|
||||||
|
|
||||||
|
.highlight {
|
||||||
|
font-weight:bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
.external-link, .external-link a{
|
||||||
|
color: @green;
|
||||||
|
|
||||||
|
a{
|
||||||
|
margin-right: 3px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// default formating of results
|
||||||
|
.result-default, .result-code, .result-torrent, .result-videos, .result-map {
|
||||||
|
clear: both;
|
||||||
|
padding: 2px 4px;
|
||||||
|
&:hover{
|
||||||
|
background-color: @dim-gray;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// image formating of results
|
||||||
|
.result-images {
|
||||||
|
float: left !important;
|
||||||
|
width: 24%;
|
||||||
|
margin: .5%;
|
||||||
|
a{
|
||||||
|
display: block;
|
||||||
|
width: 100%;
|
||||||
|
height: 170px;
|
||||||
|
background-size: cover;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.img-thumbnail {
|
||||||
|
margin: 5px;
|
||||||
|
max-height: 128px;
|
||||||
|
min-height: 128px;
|
||||||
|
}
|
||||||
|
|
||||||
|
// video formating of results
|
||||||
|
.result-videos {
|
||||||
|
clear: both;
|
||||||
|
|
||||||
|
hr{
|
||||||
|
margin: 5px 0 15px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.collapse{
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.in{
|
||||||
|
margin-bottom: 8px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// torrent formating of results
|
||||||
|
.result-torrent {
|
||||||
|
clear: both;
|
||||||
|
|
||||||
|
b{
|
||||||
|
margin-right: 5px;
|
||||||
|
margin-left: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.seeders{
|
||||||
|
color: @green;
|
||||||
|
}
|
||||||
|
|
||||||
|
.leechers{
|
||||||
|
color: @red;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// map formating of results
|
||||||
|
.result-map {
|
||||||
|
clear: both;
|
||||||
|
}
|
||||||
|
|
||||||
|
// code formating of results
|
||||||
|
.result-code {
|
||||||
|
clear: both;
|
||||||
|
|
||||||
|
.code-fork, .code-fork a{
|
||||||
|
color: @dark-gray;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// suggestion
|
||||||
|
.suggestion_item {
|
||||||
|
margin: 2px 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
// download result
|
||||||
|
.result_download {
|
||||||
|
margin-right: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
// page forward, backward
|
||||||
|
#pagination {
|
||||||
|
margin-top: 30px;
|
||||||
|
padding-bottom: 60px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.label-default {
|
||||||
|
color: @gray;
|
||||||
|
background: transparent;
|
||||||
|
}
|
|
@ -0,0 +1,59 @@
|
||||||
|
.search_categories, #categories {
|
||||||
|
margin: 10px 0 4px 0;
|
||||||
|
text-transform: capitalize;
|
||||||
|
|
||||||
|
label{
|
||||||
|
border: none;
|
||||||
|
box-shadow: none;
|
||||||
|
font-size: 13px;
|
||||||
|
padding-bottom: 2px;
|
||||||
|
color: @gray;
|
||||||
|
margin-bottom: 5px;
|
||||||
|
|
||||||
|
&:hover{
|
||||||
|
color: @black;
|
||||||
|
background-color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:active{
|
||||||
|
box-shadow: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.active, .btn-primary{
|
||||||
|
color: @black;
|
||||||
|
font-weight: 700;
|
||||||
|
border-bottom: 5px solid @light-green;
|
||||||
|
background-color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#categories{
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#main-logo{
|
||||||
|
margin-top: 10vh;
|
||||||
|
margin-bottom: 25px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#main-logo > img {
|
||||||
|
max-width: 350px;
|
||||||
|
width: 80%;
|
||||||
|
}
|
||||||
|
|
||||||
|
#q{
|
||||||
|
box-shadow: none;
|
||||||
|
border-right: none;
|
||||||
|
border-color: @gray;
|
||||||
|
}
|
||||||
|
|
||||||
|
#search_form .input-group-btn .btn{
|
||||||
|
border-color: @gray;
|
||||||
|
}
|
||||||
|
|
||||||
|
#search_form .input-group-btn .btn:hover{
|
||||||
|
background-color: @green;
|
||||||
|
color: white;
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
@black: #29314D;
|
||||||
|
@gray: #A4A4A4;
|
||||||
|
@dim-gray: #F6F9FA;
|
||||||
|
@dark-gray: #666;
|
||||||
|
@blue: #0088CC;
|
||||||
|
@red: #F35E77;
|
||||||
|
@violet: #684898;
|
||||||
|
@green: #2ecc71;
|
||||||
|
@light-green: #01D7D4;
|
||||||
|
@orange: #FFA92F;
|
|
@ -0,0 +1,9 @@
|
||||||
|
// Hide element if checkbox is checked
|
||||||
|
input[type=checkbox]:checked + .label_hide_if_checked, input[type=checkbox]:checked + .label_hide_if_not_checked + .label_hide_if_checked {
|
||||||
|
display:none;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Hide element if checkbox is not checked
|
||||||
|
input[type=checkbox]:not(:checked) + .label_hide_if_not_checked, input[type=checkbox]:not(:checked) + .label_hide_if_checked + .label_hide_if_not_checked {
|
||||||
|
display:none;
|
||||||
|
}
|
|
@ -0,0 +1,8 @@
|
||||||
|
// display cursor
|
||||||
|
.cursor-text {
|
||||||
|
cursor: text !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cursor-pointer {
|
||||||
|
cursor: pointer !important;
|
||||||
|
}
|
|
@ -12,7 +12,11 @@
|
||||||
<title>{% block title %}{% endblock %}{{ instance_name }}</title>
|
<title>{% block title %}{% endblock %}{{ instance_name }}</title>
|
||||||
|
|
||||||
<link rel="stylesheet" href="{{ url_for('static', filename='css/bootstrap.min.css') }}" type="text/css" />
|
<link rel="stylesheet" href="{{ url_for('static', filename='css/bootstrap.min.css') }}" type="text/css" />
|
||||||
<link rel="stylesheet" href="{{ url_for('static', filename='css/oscar.min.css') }}" type="text/css" />
|
{% if cookies['oscar-style'] %}
|
||||||
|
<link rel="stylesheet" href="{{ url_for('static', filename='css/'+cookies['oscar-style']+'.min.css') }}" type="text/css" />
|
||||||
|
{% else %}
|
||||||
|
<link rel="stylesheet" href="{{ url_for('static', filename='css/logicodev.min.css') }}" type="text/css" />
|
||||||
|
{% endif %}
|
||||||
<link rel="stylesheet" href="{{ url_for('static', filename='css/leaflet.min.css') }}" type="text/css" />
|
<link rel="stylesheet" href="{{ url_for('static', filename='css/leaflet.min.css') }}" type="text/css" />
|
||||||
{% for css in styles %}
|
{% for css in styles %}
|
||||||
<link rel="stylesheet" href="{{ url_for('static', filename=css) }}" type="text/css" />
|
<link rel="stylesheet" href="{{ url_for('static', filename=css) }}" type="text/css" />
|
||||||
|
@ -48,8 +52,8 @@
|
||||||
</noscript>
|
</noscript>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div class="container">
|
|
||||||
{% include 'oscar/navbar.html' %}
|
{% include 'oscar/navbar.html' %}
|
||||||
|
<div class="container">
|
||||||
|
|
||||||
{% block site_alert_error %}
|
{% block site_alert_error %}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
@ -75,7 +79,7 @@
|
||||||
<div class="container">
|
<div class="container">
|
||||||
{% block footer %}
|
{% block footer %}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
<p class="text-muted">{{ _('Powered by') }} <a href="https://asciimoo.github.io/searx/">searx</a> - {{ searx_version }} - {{ _('a privacy-respecting, hackable metasearch engine') }}</p>
|
<p class="text-muted"><small>{{ _('Powered by') }} <a href="https://asciimoo.github.io/searx/">searx</a> - {{ searx_version }} - {{ _('a privacy-respecting, hackable metasearch engine') }}</small></p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<script src="{{ url_for('static', filename='js/jquery-1.11.1.min.js') }}"></script>
|
<script src="{{ url_for('static', filename='js/jquery-1.11.1.min.js') }}"></script>
|
||||||
|
|
|
@ -3,7 +3,14 @@
|
||||||
<div class="container-fluid">
|
<div class="container-fluid">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="text-center col-sm-12 col-md-12">
|
<div class="text-center col-sm-12 col-md-12">
|
||||||
<h1 class="text-hide center-block"><img class="center-block img-responsive" src="{{ url_for('static', filename='img/searx_logo.png') }}" alt="searx logo"/>searx</h1>
|
{% if cookies['oscar-style'] == 'pointhi' %}
|
||||||
|
<h1 class="text-hide center-block"><img class="center-block img-responsive" src="{{ url_for('static', filename='img/searx_logo.png') }}" alt="searx logo"/>searx</h1>
|
||||||
|
{% else %}
|
||||||
|
<h1 class="text-hide center-block" id="main-logo">
|
||||||
|
<img class="center-block img-responsive" src="{{ url_for('static', filename='img/logo_searx_a.png') }}" alt="searx logo" />
|
||||||
|
searx
|
||||||
|
</h1>
|
||||||
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
|
|
|
@ -17,7 +17,6 @@
|
||||||
<!-- Draw result sub header -->
|
<!-- Draw result sub header -->
|
||||||
{% macro result_sub_header(result) -%}
|
{% macro result_sub_header(result) -%}
|
||||||
{% if result.publishedDate %}<time class="text-muted" datetime="{{ result.pubdate }}" >{{ result.publishedDate }}</time>{% endif %}
|
{% if result.publishedDate %}<time class="text-muted" datetime="{{ result.pubdate }}" >{{ result.publishedDate }}</time>{% endif %}
|
||||||
<small><a class="text-info" href="https://web.archive.org/web/{{ result.url }}" rel="noreferrer">{{ icon('link') }} {{ _('cached') }}</a></small>
|
|
||||||
{% if result.magnetlink %}<small> • <a href="{{ result.magnetlink }}" class="magnetlink">{{ icon('magnet') }} {{ _('magnet link') }}</a></small>{% endif %}
|
{% if result.magnetlink %}<small> • <a href="{{ result.magnetlink }}" class="magnetlink">{{ icon('magnet') }} {{ _('magnet link') }}</a></small>{% endif %}
|
||||||
{% if result.torrentfile %}<small> • <a href="{{ result.torrentfile }}" class="torrentfile" rel="noreferrer">{{ icon('download-alt') }} {{ _('torrent file') }}</a></small>{% endif %}
|
{% if result.torrentfile %}<small> • <a href="{{ result.torrentfile }}" class="torrentfile" rel="noreferrer">{{ icon('download-alt') }} {{ _('torrent file') }}</a></small>{% endif %}
|
||||||
{%- endmacro %}
|
{%- endmacro %}
|
||||||
|
@ -29,15 +28,19 @@
|
||||||
{% for engine in result.engines %}
|
{% for engine in result.engines %}
|
||||||
<span class="label label-default">{{ engine }}</span>
|
<span class="label label-default">{{ engine }}</span>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
<small><a class="text-info" href="https://web.archive.org/web/{{ result.url }}" rel="noreferrer">{{ icon('link') }} {{ _('cached') }}</a></small>
|
||||||
</div>
|
</div>
|
||||||
<p class="text-muted">{{ result.pretty_url }}</p>
|
<div class="text-muted"><small>{{ result.pretty_url }}</small></div>
|
||||||
{%- endmacro %}
|
{%- endmacro %}
|
||||||
|
|
||||||
<!-- Draw result footer -->
|
<!-- Draw result footer -->
|
||||||
{% macro result_footer_rtl(result) -%}
|
{% macro result_footer_rtl(result) -%}
|
||||||
<div class="clearfix"></div>
|
<div class="clearfix"></div>
|
||||||
<span class="label label-default pull-left">{{ result.engine }}</span>
|
{% for engine in result.engines %}
|
||||||
<p class="text-muted">{{ result.pretty_url }}‎</p>
|
<span class="label label-default">{{ engine }}</span>
|
||||||
|
{% endfor %}
|
||||||
|
<small><a class="text-info" href="https://web.archive.org/web/{{ result.url }}" rel="noreferrer">{{ icon('link') }} {{ _('cached') }}</a></small>
|
||||||
|
<div class="text-muted"><small>{{ result.pretty_url }}</small></div>
|
||||||
{%- endmacro %}
|
{%- endmacro %}
|
||||||
|
|
||||||
{% macro preferences_item_header(info, label, rtl) -%}
|
{% macro preferences_item_header(info, label, rtl) -%}
|
||||||
|
|
|
@ -110,6 +110,13 @@
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</select>
|
</select>
|
||||||
{{ preferences_item_footer(theme_info, theme_label, rtl) }}
|
{{ preferences_item_footer(theme_info, theme_label, rtl) }}
|
||||||
|
|
||||||
|
{{ preferences_item_header(_('Choose style for this theme'), _('Style'), rtl) }}
|
||||||
|
<select class="form-control" name='oscar-style'>
|
||||||
|
<option value="logicodev" >Logicodev</option>
|
||||||
|
<option value="pointhi" {% if cookies['oscar-style'] == 'pointhi' %}selected="selected"{% endif %}>Pointhi</option>
|
||||||
|
</select>
|
||||||
|
{{ preferences_item_footer(_('Choose style for this theme'), _('Style'), rtl) }}
|
||||||
</div>
|
</div>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -78,6 +78,16 @@
|
||||||
</div><!-- /#main_results -->
|
</div><!-- /#main_results -->
|
||||||
|
|
||||||
<div class="col-sm-4" id="sidebar_results">
|
<div class="col-sm-4" id="sidebar_results">
|
||||||
|
{% if number_of_results != '0' %}
|
||||||
|
<div class="panel panel-default">
|
||||||
|
<div class="panel-heading">
|
||||||
|
<h4 class="panel-title">{{ _('Number of results') }}</h4>
|
||||||
|
</div>
|
||||||
|
<div class="panel-body">
|
||||||
|
{{ number_of_results }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
{% if infoboxes %}
|
{% if infoboxes %}
|
||||||
{% for infobox in infoboxes %}
|
{% for infobox in infoboxes %}
|
||||||
{% include 'oscar/infobox.html' %}
|
{% include 'oscar/infobox.html' %}
|
||||||
|
|
|
@ -18,8 +18,8 @@ along with searx. If not, see < http://www.gnu.org/licenses/ >.
|
||||||
|
|
||||||
# version of searx
|
# version of searx
|
||||||
VERSION_MAJOR = 0
|
VERSION_MAJOR = 0
|
||||||
VERSION_MINOR = 8
|
VERSION_MINOR = 9
|
||||||
VERSION_BUILD = 1
|
VERSION_BUILD = 0
|
||||||
|
|
||||||
VERSION_STRING = "{0}.{1}.{2}".format(VERSION_MAJOR,
|
VERSION_STRING = "{0}.{1}.{2}".format(VERSION_MAJOR,
|
||||||
VERSION_MINOR,
|
VERSION_MINOR,
|
||||||
|
|
|
@ -48,7 +48,8 @@ from flask import (
|
||||||
Flask, request, render_template, url_for, Response, make_response,
|
Flask, request, render_template, url_for, Response, make_response,
|
||||||
redirect, send_from_directory
|
redirect, send_from_directory
|
||||||
)
|
)
|
||||||
from flask.ext.babel import Babel, gettext, format_date
|
from flask.ext.babel import Babel, gettext, format_date, format_decimal
|
||||||
|
from flask.json import jsonify
|
||||||
from searx import settings, searx_dir
|
from searx import settings, searx_dir
|
||||||
from searx.engines import (
|
from searx.engines import (
|
||||||
categories, engines, get_engines_stats, engine_shortcuts
|
categories, engines, get_engines_stats, engine_shortcuts
|
||||||
|
@ -64,7 +65,7 @@ from searx.search import Search
|
||||||
from searx.query import Query
|
from searx.query import Query
|
||||||
from searx.autocomplete import searx_bang, backends as autocomplete_backends
|
from searx.autocomplete import searx_bang, backends as autocomplete_backends
|
||||||
from searx.plugins import plugins
|
from searx.plugins import plugins
|
||||||
from searx.preferences import Preferences
|
from searx.preferences import Preferences, ValidationException
|
||||||
|
|
||||||
# check if the pyopenssl, ndg-httpsclient, pyasn1 packages are installed.
|
# check if the pyopenssl, ndg-httpsclient, pyasn1 packages are installed.
|
||||||
# They are needed for SSL connection without trouble, see #298
|
# They are needed for SSL connection without trouble, see #298
|
||||||
|
@ -419,6 +420,7 @@ def index():
|
||||||
|
|
||||||
if search.request_data.get('format') == 'json':
|
if search.request_data.get('format') == 'json':
|
||||||
return Response(json.dumps({'query': search.query,
|
return Response(json.dumps({'query': search.query,
|
||||||
|
'number_of_results': search.result_container.number_of_results,
|
||||||
'results': search.result_container.get_ordered_results()}),
|
'results': search.result_container.get_ordered_results()}),
|
||||||
mimetype='application/json')
|
mimetype='application/json')
|
||||||
elif search.request_data.get('format') == 'csv':
|
elif search.request_data.get('format') == 'csv':
|
||||||
|
@ -438,7 +440,7 @@ def index():
|
||||||
'opensearch_response_rss.xml',
|
'opensearch_response_rss.xml',
|
||||||
results=search.result_container.get_ordered_results(),
|
results=search.result_container.get_ordered_results(),
|
||||||
q=search.request_data['q'],
|
q=search.request_data['q'],
|
||||||
number_of_results=search.result_container.results_length(),
|
number_of_results=search.result_container.number_of_results,
|
||||||
base_url=get_base_url()
|
base_url=get_base_url()
|
||||||
)
|
)
|
||||||
return Response(response_rss, mimetype='text/xml')
|
return Response(response_rss, mimetype='text/xml')
|
||||||
|
@ -449,6 +451,7 @@ def index():
|
||||||
q=search.request_data['q'],
|
q=search.request_data['q'],
|
||||||
selected_categories=search.categories,
|
selected_categories=search.categories,
|
||||||
paging=search.paging,
|
paging=search.paging,
|
||||||
|
number_of_results=format_decimal(search.result_container.number_of_results),
|
||||||
pageno=search.pageno,
|
pageno=search.pageno,
|
||||||
base_url=get_base_url(),
|
base_url=get_base_url(),
|
||||||
suggestions=search.result_container.suggestions,
|
suggestions=search.result_container.suggestions,
|
||||||
|
@ -685,6 +688,24 @@ def clear_cookies():
|
||||||
return resp
|
return resp
|
||||||
|
|
||||||
|
|
||||||
|
@app.route('/config')
|
||||||
|
def config():
|
||||||
|
return jsonify({'categories': categories.keys(),
|
||||||
|
'engines': [{'name': engine_name,
|
||||||
|
'categories': engine.categories,
|
||||||
|
'enabled': not engine.disabled}
|
||||||
|
for engine_name, engine in engines.items()],
|
||||||
|
'plugins': [{'name': plugin.name,
|
||||||
|
'enabled': plugin.default_on}
|
||||||
|
for plugin in plugins],
|
||||||
|
'instance_name': settings['general']['instance_name'],
|
||||||
|
'locales': settings['locales'],
|
||||||
|
'default_locale': settings['ui']['default_locale'],
|
||||||
|
'autocomplete': settings['search']['autocomplete'],
|
||||||
|
'safe_search': settings['search']['safe_search'],
|
||||||
|
'default_theme': settings['ui']['default_theme']})
|
||||||
|
|
||||||
|
|
||||||
def run():
|
def run():
|
||||||
app.run(
|
app.run(
|
||||||
debug=settings['general']['debug'],
|
debug=settings['general']['debug'],
|
||||||
|
|
|
@ -53,6 +53,8 @@ setup(
|
||||||
'searx': [
|
'searx': [
|
||||||
'settings.yml',
|
'settings.yml',
|
||||||
'../README.rst',
|
'../README.rst',
|
||||||
|
'../requirements.txt',
|
||||||
|
'../requirements-dev.txt',
|
||||||
'data/*',
|
'data/*',
|
||||||
'plugins/*/*',
|
'plugins/*/*',
|
||||||
'static/*.*',
|
'static/*.*',
|
||||||
|
|
|
@ -14,23 +14,19 @@ class TestCurrencyConvertEngine(SearxTestCase):
|
||||||
params = currency_convert.request(query, dicto)
|
params = currency_convert.request(query, dicto)
|
||||||
self.assertNotIn('url', params)
|
self.assertNotIn('url', params)
|
||||||
|
|
||||||
query = '1.1.1 EUR in USD'
|
query = 'convert 10 Pound Sterlings to United States Dollars'
|
||||||
params = currency_convert.request(query, dicto)
|
|
||||||
self.assertNotIn('url', params)
|
|
||||||
|
|
||||||
query = '10 eur in usd'
|
|
||||||
params = currency_convert.request(query, dicto)
|
params = currency_convert.request(query, dicto)
|
||||||
self.assertIn('url', params)
|
self.assertIn('url', params)
|
||||||
self.assertIn('finance.yahoo.com', params['url'])
|
self.assertIn('finance.yahoo.com', params['url'])
|
||||||
self.assertIn('EUR', params['url'])
|
self.assertIn('GBP', params['url'])
|
||||||
self.assertIn('USD', params['url'])
|
self.assertIn('USD', params['url'])
|
||||||
|
|
||||||
def test_response(self):
|
def test_response(self):
|
||||||
dicto = defaultdict(dict)
|
dicto = defaultdict(dict)
|
||||||
dicto['ammount'] = float(10)
|
dicto['ammount'] = float(10)
|
||||||
dicto['from'] = "EUR"
|
dicto['from'] = "GBP"
|
||||||
dicto['to'] = "USD"
|
dicto['to'] = "USD"
|
||||||
dicto['from_name'] = "euro"
|
dicto['from_name'] = "pound sterling"
|
||||||
dicto['to_name'] = "United States dollar"
|
dicto['to_name'] = "United States dollar"
|
||||||
response = mock.Mock(text='a,b,c,d', search_params=dicto)
|
response = mock.Mock(text='a,b,c,d', search_params=dicto)
|
||||||
self.assertEqual(currency_convert.response(response), [])
|
self.assertEqual(currency_convert.response(response), [])
|
||||||
|
@ -40,7 +36,8 @@ class TestCurrencyConvertEngine(SearxTestCase):
|
||||||
results = currency_convert.response(response)
|
results = currency_convert.response(response)
|
||||||
self.assertEqual(type(results), list)
|
self.assertEqual(type(results), list)
|
||||||
self.assertEqual(len(results), 1)
|
self.assertEqual(len(results), 1)
|
||||||
self.assertEqual(results[0]['answer'], '10.0 EUR = 5.0 USD, 1 EUR (euro) = 0.5 USD (United States dollar)')
|
self.assertEqual(results[0]['answer'], '10.0 GBP = 5.0 USD, 1 GBP (pound sterling)' +
|
||||||
|
' = 0.5 USD (United States dollar)')
|
||||||
now_date = datetime.now().strftime('%Y%m%d')
|
now_date = datetime.now().strftime('%Y%m%d')
|
||||||
self.assertEqual(results[0]['url'], 'https://finance.yahoo.com/currency/converter-results/' +
|
self.assertEqual(results[0]['url'], 'https://finance.yahoo.com/currency/converter-results/' +
|
||||||
now_date + '/10.0-eur-to-usd.html')
|
now_date + '/10.0-gbp-to-usd.html')
|
||||||
|
|
Loading…
Reference in New Issue