Merge branch 'master' into patch-2

This commit is contained in:
Adam Tauber 2018-08-19 13:22:22 +02:00 committed by GitHub
commit b75f1b6cc3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
123 changed files with 3067 additions and 1016 deletions

View File

@ -1,4 +1,4 @@
FROM alpine:3.6 FROM alpine:3.7
LABEL maintainer="searx <https://github.com/asciimoo/searx>" LABEL maintainer="searx <https://github.com/asciimoo/searx>"
LABEL description="A privacy-respecting, hackable metasearch engine." LABEL description="A privacy-respecting, hackable metasearch engine."

View File

@ -4,6 +4,8 @@ searx
A privacy-respecting, hackable `metasearch A privacy-respecting, hackable `metasearch
engine <https://en.wikipedia.org/wiki/Metasearch_engine>`__. engine <https://en.wikipedia.org/wiki/Metasearch_engine>`__.
Pronunciation: səːks
List of `running List of `running
instances <https://github.com/asciimoo/searx/wiki/Searx-instances>`__. instances <https://github.com/asciimoo/searx/wiki/Searx-instances>`__.

View File

@ -1,15 +1,17 @@
#!/bin/sh #!/bin/sh
BASE_DIR="$(dirname -- "`readlink -f -- "$0"`")" BASE_DIR="$(dirname -- "`readlink -f -- "$0"`")"
export PATH="$BASE_DIR/node_modules/.bin":$PATH
cd -- "$BASE_DIR"
set -e
export PATH="$(npm bin)":$PATH
# subshell # subshell
PYTHONPATH="$BASE_DIR" PYTHONPATH="$BASE_DIR"
SEARX_DIR="$BASE_DIR/searx" SEARX_DIR="$BASE_DIR/searx"
ACTION="$1" ACTION="$1"
cd -- "$BASE_DIR"
set -e
# #
# Python # Python

View File

@ -1,10 +1,10 @@
certifi==2017.11.5 certifi==2017.11.5
flask==0.12.2 flask==1.0.2
flask-babel==0.11.2 flask-babel==0.11.2
lxml==4.1.1 lxml==4.2.3
idna==2.5 idna==2.7
pygments==2.1.3 pygments==2.1.3
pyopenssl==17.4.0 pyopenssl==18.0.0
python-dateutil==2.6.1 python-dateutil==2.7.3
pyyaml==3.12 pyyaml==3.13
requests[socks]==2.18.4 requests[socks]==2.19.1

View File

@ -6163,9 +6163,21 @@
], ],
"scellino keniota": [ "scellino keniota": [
"KES" "KES"
],
"bitcoin": [
"XBT"
] ]
}, },
"iso4217": { "iso4217": {
"XBT":{
"fr": "Bitcoin",
"en": "Bitcoin",
"nl": "Bitcoin",
"de": "Bitcoin",
"it": "Bitcoin",
"hu": "Bitcoin",
"es": "Bitcoin"
},
"DZD": { "DZD": {
"fr": "Dinar alg\u00e9rien", "fr": "Dinar alg\u00e9rien",
"en": "Algerian dinar", "en": "Algerian dinar",

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,14 @@
{
"ua": "Mozilla/5.0 ({os}; rv:{version}) Gecko/20100101 Firefox/{version}",
"versions": [
"61.0.1",
"61.0",
"60.0.2",
"60.0.1",
"60.0"
],
"os": [
"Windows NT 10; WOW64",
"X11; Linux x86_64"
]
}

View File

@ -20,13 +20,14 @@ import sys
import threading import threading
from os.path import realpath, dirname from os.path import realpath, dirname
from io import open from io import open
from babel.localedata import locale_identifiers
from flask_babel import gettext from flask_babel import gettext
from operator import itemgetter from operator import itemgetter
from json import loads from json import loads
from requests import get from requests import get
from searx import settings from searx import settings
from searx import logger from searx import logger
from searx.utils import load_module from searx.utils import load_module, match_language
logger = logger.getChild('engines') logger = logger.getChild('engines')
@ -38,6 +39,8 @@ engines = {}
categories = {'general': []} categories = {'general': []}
languages = loads(open(engine_dir + '/../data/engines_languages.json', 'r', encoding='utf-8').read()) languages = loads(open(engine_dir + '/../data/engines_languages.json', 'r', encoding='utf-8').read())
babel_langs = [lang_parts[0] + '-' + lang_parts[-1] if len(lang_parts) > 1 else lang_parts[0]
for lang_parts in (lang_code.split('_') for lang_code in locale_identifiers())]
engine_shortcuts = {} engine_shortcuts = {}
engine_default_args = {'paging': False, engine_default_args = {'paging': False,
@ -97,6 +100,22 @@ def load_engine(engine_data):
if engine_data['name'] in languages: if engine_data['name'] in languages:
setattr(engine, 'supported_languages', languages[engine_data['name']]) setattr(engine, 'supported_languages', languages[engine_data['name']])
# find custom aliases for non standard language codes
if hasattr(engine, 'supported_languages'):
if hasattr(engine, 'language_aliases'):
language_aliases = getattr(engine, 'language_aliases')
else:
language_aliases = {}
for engine_lang in getattr(engine, 'supported_languages'):
iso_lang = match_language(engine_lang, babel_langs, fallback=None)
if iso_lang and iso_lang != engine_lang and not engine_lang.startswith(iso_lang) and \
iso_lang not in getattr(engine, 'supported_languages'):
language_aliases[iso_lang] = engine_lang
if language_aliases:
setattr(engine, 'language_aliases', language_aliases)
# assign language fetching method if auxiliary method exists # assign language fetching method if auxiliary method exists
if hasattr(engine, '_fetch_supported_languages'): if hasattr(engine, '_fetch_supported_languages'):
setattr(engine, 'fetch_supported_languages', setattr(engine, 'fetch_supported_languages',

75
searx/engines/acgsou.py Normal file
View File

@ -0,0 +1,75 @@
"""
Acgsou (Japanese Animation/Music/Comics Bittorrent tracker)
@website https://www.acgsou.com/
@provide-api no
@using-api no
@results HTML
@stable no (HTML can change)
@parse url, title, content, seed, leech, torrentfile
"""
from lxml import html
from searx.engines.xpath import extract_text
from searx.url_utils import urlencode
from searx.utils import get_torrent_size, int_or_zero
# engine dependent config
categories = ['files', 'images', 'videos', 'music']
paging = True
# search-url
base_url = 'http://www.acgsou.com/'
search_url = base_url + 'search.php?{query}&page={offset}'
# xpath queries
xpath_results = '//table[contains(@class, "list_style table_fixed")]//tr[not(th)]'
xpath_category = './/td[2]/a[1]'
xpath_title = './/td[3]/a[last()]'
xpath_torrent_links = './/td[3]/a'
xpath_filesize = './/td[4]/text()'
def request(query, params):
query = urlencode({'keyword': query})
params['url'] = search_url.format(query=query, offset=params['pageno'])
return params
def response(resp):
results = []
dom = html.fromstring(resp.text)
for result in dom.xpath(xpath_results):
# defaults
filesize = 0
magnet_link = "magnet:?xt=urn:btih:{}&tr=http://tracker.acgsou.com:2710/announce"
torrent_link = ""
try:
category = extract_text(result.xpath(xpath_category)[0])
except:
pass
page_a = result.xpath(xpath_title)[0]
title = extract_text(page_a)
href = base_url + page_a.attrib.get('href')
magnet_link = magnet_link.format(page_a.attrib.get('href')[5:-5])
try:
filesize_info = result.xpath(xpath_filesize)[0]
filesize = filesize_info[:-2]
filesize_multiplier = filesize_info[-2:]
filesize = get_torrent_size(filesize, filesize_multiplier)
except:
pass
# I didn't add download/seed/leech count since as I figured out they are generated randomly everytime
content = u'Category: "{category}".'
content = content.format(category=category)
results.append({'url': href,
'title': title,
'content': content,
'filesize': filesize,
'magnetlink': magnet_link,
'template': 'torrent.html'})
return results

View File

@ -99,13 +99,13 @@ supported_languages = dict(lang_urls, **main_langs)
# do search-request # do search-request
def request(query, params): def request(query, params):
# translate the locale (e.g. 'en_US') to language code ('en') # translate the locale (e.g. 'en-US') to language code ('en')
language = locale_to_lang_code(params['language']) language = locale_to_lang_code(params['language'])
# if our language is hosted on the main site, we need to add its name # if our language is hosted on the main site, we need to add its name
# to the query in order to narrow the results to that language # to the query in order to narrow the results to that language
if language in main_langs: if language in main_langs:
query += '(' + main_langs[language] + ')' query += b' (' + main_langs[language] + b')'
# prepare the request parameters # prepare the request parameters
query = urlencode({'search': query}) query = urlencode({'search': query})

View File

@ -55,7 +55,7 @@ shorcut_dict = {
def request(query, params): def request(query, params):
# replace shortcuts with API advanced search keywords # replace shortcuts with API advanced search keywords
for key in shorcut_dict.keys(): for key in shorcut_dict.keys():
query = re.sub(str(key), str(shorcut_dict[key]), query) query = re.sub(key, shorcut_dict[key], str(query))
# basic search # basic search
offset = (params['pageno'] - 1) * number_of_results offset = (params['pageno'] - 1) * number_of_results

View File

@ -16,12 +16,14 @@
from lxml import html from lxml import html
from searx.engines.xpath import extract_text from searx.engines.xpath import extract_text
from searx.url_utils import urlencode from searx.url_utils import urlencode
from searx.utils import match_language, gen_useragent
# engine dependent config # engine dependent config
categories = ['general'] categories = ['general']
paging = True paging = True
language_support = True language_support = True
supported_languages_url = 'https://www.bing.com/account/general' supported_languages_url = 'https://www.bing.com/account/general'
language_aliases = {'zh-CN': 'zh-CHS', 'zh-TW': 'zh-CHT', 'zh-HK': 'zh-CHT'}
# search-url # search-url
base_url = 'https://www.bing.com/' base_url = 'https://www.bing.com/'
@ -32,15 +34,18 @@ search_string = 'search?{query}&first={offset}'
def request(query, params): def request(query, params):
offset = (params['pageno'] - 1) * 10 + 1 offset = (params['pageno'] - 1) * 10 + 1
lang = params['language'].split('-')[0].upper() lang = match_language(params['language'], supported_languages, language_aliases)
query = u'language:{} {}'.format(lang, query.decode('utf-8')).encode('utf-8') query = u'language:{} {}'.format(lang.split('-')[0].upper(), query.decode('utf-8')).encode('utf-8')
search_path = search_string.format( search_path = search_string.format(
query=urlencode({'q': query}), query=urlencode({'q': query}),
offset=offset) offset=offset)
params['url'] = base_url + search_path params['url'] = base_url + search_path
params['headers']['User-Agent'] = gen_useragent('Windows NT 6.3; WOW64')
return params return params

View File

@ -19,6 +19,7 @@ from lxml import html
from json import loads from json import loads
import re import re
from searx.url_utils import urlencode from searx.url_utils import urlencode
from searx.utils import match_language
# engine dependent config # engine dependent config
categories = ['images'] categories = ['images']
@ -46,26 +47,6 @@ safesearch_types = {2: 'STRICT',
_quote_keys_regex = re.compile('({|,)([a-z][a-z0-9]*):(")', re.I | re.U) _quote_keys_regex = re.compile('({|,)([a-z][a-z0-9]*):(")', re.I | re.U)
# get supported region code
def get_region_code(lang, lang_list=None):
region = None
if lang in (lang_list or supported_languages):
region = lang
elif lang.startswith('no'):
region = 'nb-NO'
else:
# try to get a supported country code with language
lang = lang.split('-')[0]
for lc in (lang_list or supported_languages):
if lang == lc.split('-')[0]:
region = lc
break
if region:
return region.lower()
else:
return 'en-us'
# do search-request # do search-request
def request(query, params): def request(query, params):
offset = (params['pageno'] - 1) * 10 + 1 offset = (params['pageno'] - 1) * 10 + 1
@ -74,7 +55,7 @@ def request(query, params):
query=urlencode({'q': query}), query=urlencode({'q': query}),
offset=offset) offset=offset)
language = get_region_code(params['language']) language = match_language(params['language'], supported_languages).lower()
params['cookies']['SRCHHPGUSR'] = \ params['cookies']['SRCHHPGUSR'] = \
'ADLT=' + safesearch_types.get(params['safesearch'], 'DEMOTE') 'ADLT=' + safesearch_types.get(params['safesearch'], 'DEMOTE')

View File

@ -14,8 +14,8 @@
from datetime import datetime from datetime import datetime
from dateutil import parser from dateutil import parser
from lxml import etree from lxml import etree
from searx.utils import list_get from searx.utils import list_get, match_language
from searx.engines.bing import _fetch_supported_languages, supported_languages_url from searx.engines.bing import _fetch_supported_languages, supported_languages_url, language_aliases
from searx.url_utils import urlencode, urlparse, parse_qsl from searx.url_utils import urlencode, urlparse, parse_qsl
# engine dependent config # engine dependent config
@ -71,7 +71,7 @@ def request(query, params):
offset = (params['pageno'] - 1) * 10 + 1 offset = (params['pageno'] - 1) * 10 + 1
language = params['language'] language = match_language(params['language'], supported_languages, language_aliases)
params['url'] = _get_url(query, language, offset, params['time_range']) params['url'] = _get_url(query, language, offset, params['time_range'])

View File

@ -12,9 +12,10 @@
from json import loads from json import loads
from lxml import html from lxml import html
from searx.engines.bing_images import _fetch_supported_languages, supported_languages_url, get_region_code from searx.engines.bing_images import _fetch_supported_languages, supported_languages_url
from searx.engines.xpath import extract_text from searx.engines.xpath import extract_text
from searx.url_utils import urlencode from searx.url_utils import urlencode
from searx.utils import match_language
categories = ['videos'] categories = ['videos']
@ -47,8 +48,8 @@ def request(query, params):
'ADLT=' + safesearch_types.get(params['safesearch'], 'DEMOTE') 'ADLT=' + safesearch_types.get(params['safesearch'], 'DEMOTE')
# language cookie # language cookie
region = get_region_code(params['language'], lang_list=supported_languages) language = match_language(params['language'], supported_languages).lower()
params['cookies']['_EDGE_S'] = 'mkt=' + region + '&F=1' params['cookies']['_EDGE_S'] = 'mkt=' + language + '&F=1'
# query and paging # query and paging
params['url'] = search_url.format(query=urlencode({'q': query}), params['url'] = search_url.format(query=urlencode({'q': query}),

View File

@ -11,7 +11,7 @@ if sys.version_info[0] == 3:
unicode = str unicode = str
categories = [] categories = []
url = 'https://finance.google.com/finance/converter?a=1&from={0}&to={1}' url = 'https://duckduckgo.com/js/spice/currency/1/{0}/{1}'
weight = 100 weight = 100
parser_re = re.compile(b'.*?(\\d+(?:\\.\\d+)?) ([^.0-9]+) (?:in|to) ([^.0-9]+)', re.I) parser_re = re.compile(b'.*?(\\d+(?:\\.\\d+)?) ([^.0-9]+) (?:in|to) ([^.0-9]+)', re.I)
@ -44,7 +44,6 @@ def request(query, params):
if not m: if not m:
# wrong query # wrong query
return params return params
amount, from_currency, to_currency = m.groups() amount, from_currency, to_currency = m.groups()
amount = float(amount) amount = float(amount)
from_currency = name_to_iso4217(from_currency.strip()) from_currency = name_to_iso4217(from_currency.strip())
@ -63,16 +62,13 @@ def request(query, params):
def response(resp): def response(resp):
"""remove first and last lines to get only json"""
json_resp = resp.text[resp.text.find('\n') + 1:resp.text.rfind('\n') - 2]
results = [] results = []
pat = '<span class=bld>(.+) {0}</span>'.format(
resp.search_params['to'].upper())
try: try:
conversion_rate = re.findall(pat, resp.text)[0] conversion_rate = float(json.loads(json_resp)['conversion']['converted-amount'])
conversion_rate = float(conversion_rate)
except: except:
return results return results
answer = '{0} {1} = {2} {3}, 1 {1} ({5}) = {4} {3} ({6})'.format( answer = '{0} {1} = {2} {3}, 1 {1} ({5}) = {4} {3} ({6})'.format(
resp.search_params['amount'], resp.search_params['amount'],
resp.search_params['from'], resp.search_params['from'],
@ -83,7 +79,7 @@ def response(resp):
resp.search_params['to_name'], resp.search_params['to_name'],
) )
url = 'https://finance.google.com/finance?q={0}{1}'.format( url = 'https://duckduckgo.com/js/spice/currency/1/{0}/{1}'.format(
resp.search_params['from'].upper(), resp.search_params['to']) resp.search_params['from'].upper(), resp.search_params['to'])
results.append({'answer': answer, 'url': url}) results.append({'answer': answer, 'url': url})

View File

@ -15,6 +15,7 @@
from json import loads from json import loads
from datetime import datetime from datetime import datetime
from searx.url_utils import urlencode from searx.url_utils import urlencode
from searx.utils import match_language
# engine dependent config # engine dependent config
categories = ['videos'] categories = ['videos']
@ -32,7 +33,7 @@ supported_languages_url = 'https://api.dailymotion.com/languages'
# do search-request # do search-request
def request(query, params): def request(query, params):
locale = params['language'] locale = match_language(params['language'], supported_languages)
params['url'] = search_url.format( params['url'] = search_url.format(
query=urlencode({'search': query, 'localization': locale}), query=urlencode({'search': query, 'localization': locale}),

View File

@ -18,16 +18,27 @@ from json import loads
from searx.engines.xpath import extract_text from searx.engines.xpath import extract_text
from searx.poolrequests import get from searx.poolrequests import get
from searx.url_utils import urlencode from searx.url_utils import urlencode
from searx.utils import match_language
# engine dependent config # engine dependent config
categories = ['general'] categories = ['general']
paging = True paging = True
language_support = True language_support = True
supported_languages_url = 'https://duckduckgo.com/d2030.js' supported_languages_url = 'https://duckduckgo.com/util/u172.js'
time_range_support = True time_range_support = True
language_aliases = {
'ar-SA': 'ar-XA',
'es-419': 'es-XL',
'ja': 'jp-JP',
'ko': 'kr-KR',
'sl-SI': 'sl-SL',
'zh-TW': 'tzh-TW',
'zh-HK': 'tzh-HK'
}
# search-url # search-url
url = 'https://duckduckgo.com/html?{query}&s={offset}&api=/d.js&o=json&dc={dc_param}' url = 'https://duckduckgo.com/html?{query}&s={offset}&dc={dc_param}'
time_range_url = '&df={range}' time_range_url = '&df={range}'
time_range_dict = {'day': 'd', time_range_dict = {'day': 'd',
@ -42,34 +53,12 @@ content_xpath = './/a[@class="result__snippet"]'
# match query's language to a region code that duckduckgo will accept # match query's language to a region code that duckduckgo will accept
def get_region_code(lang, lang_list=None): def get_region_code(lang, lang_list=[]):
# custom fixes for languages lang_code = match_language(lang, lang_list, language_aliases, 'wt-WT')
if lang[:2] == 'ja': lang_parts = lang_code.split('-')
region_code = 'jp-jp'
elif lang[:2] == 'sl':
region_code = 'sl-sl'
elif lang == 'zh-TW':
region_code = 'tw-tzh'
elif lang == 'zh-HK':
region_code = 'hk-tzh'
elif lang[-2:] == 'SA':
region_code = 'xa-' + lang.split('-')[0]
elif lang[-2:] == 'GB':
region_code = 'uk-' + lang.split('-')[0]
else:
region_code = lang.split('-')
if len(region_code) == 2:
# country code goes first # country code goes first
region_code = region_code[1].lower() + '-' + region_code[0].lower() return lang_parts[1].lower() + '-' + lang_parts[0].lower()
else:
# tries to get a country code from language
region_code = region_code[0].lower()
for lc in (lang_list or supported_languages):
lc = lc.split('-')
if region_code == lc[0]:
region_code = lc[1].lower() + '-' + lc[0].lower()
break
return region_code
# do search-request # do search-request
@ -79,7 +68,7 @@ def request(query, params):
offset = (params['pageno'] - 1) * 30 offset = (params['pageno'] - 1) * 30
region_code = get_region_code(params['language']) region_code = get_region_code(params['language'], supported_languages)
params['url'] = url.format( params['url'] = url.format(
query=urlencode({'q': query, 'kl': region_code}), offset=offset, dc_param=offset) query=urlencode({'q': query, 'kl': region_code}), offset=offset, dc_param=offset)

View File

@ -2,9 +2,9 @@ import json
from lxml import html from lxml import html
from re import compile from re import compile
from searx.engines.xpath import extract_text from searx.engines.xpath import extract_text
from searx.engines.duckduckgo import _fetch_supported_languages, supported_languages_url from searx.engines.duckduckgo import _fetch_supported_languages, supported_languages_url, language_aliases
from searx.url_utils import urlencode from searx.url_utils import urlencode
from searx.utils import html_to_text from searx.utils import html_to_text, match_language
url = 'https://api.duckduckgo.com/'\ url = 'https://api.duckduckgo.com/'\
+ '?{query}&format=json&pretty=0&no_redirect=1&d=1' + '?{query}&format=json&pretty=0&no_redirect=1&d=1'
@ -24,7 +24,8 @@ def result_to_text(url, text, htmlResult):
def request(query, params): def request(query, params):
params['url'] = url.format(query=urlencode({'q': query})) params['url'] = url.format(query=urlencode({'q': query}))
params['headers']['Accept-Language'] = params['language'].split('-')[0] language = match_language(params['language'], supported_languages, language_aliases)
params['headers']['Accept-Language'] = language.split('-')[0]
return params return params

View File

@ -15,7 +15,10 @@
from json import loads from json import loads
from searx.engines.xpath import extract_text from searx.engines.xpath import extract_text
from searx.engines.duckduckgo import _fetch_supported_languages, supported_languages_url, get_region_code from searx.engines.duckduckgo import (
_fetch_supported_languages, supported_languages_url,
get_region_code, language_aliases
)
from searx.poolrequests import get from searx.poolrequests import get
from searx.url_utils import urlencode from searx.url_utils import urlencode

115
searx/engines/findx.py Normal file
View File

@ -0,0 +1,115 @@
"""
FindX (General, Images, Videos)
@website https://www.findx.com
@provide-api no
@using-api no
@results HTML
@stable no
@parse url, title, content, embedded, img_src, thumbnail_src
"""
from dateutil import parser
from json import loads
import re
from lxml import html
from searx import logger
from searx.engines.xpath import extract_text
from searx.engines.youtube_noapi import base_youtube_url, embedded_url
from searx.url_utils import urlencode
paging = True
results_xpath = '//script[@id="initial-state"]'
search_url = 'https://www.findx.com/{category}?{q}'
type_map = {
'none': 'web',
'general': 'web',
'images': 'images',
'videos': 'videos',
}
def request(query, params):
params['url'] = search_url.format(
category=type_map[params['category']],
q=urlencode({
'q': query,
'page': params['pageno']
})
)
return params
def response(resp):
dom = html.fromstring(resp.text)
results_raw_json = dom.xpath(results_xpath)
results_json = loads(extract_text(results_raw_json))
if len(results_json['web']['results']) > 0:
return _general_results(results_json['web']['results']['webSearch']['results'])
if len(results_json['images']['results']) > 0:
return _images_results(results_json['images']['results'])
if len(results_json['video']['results']) > 0:
return _videos_results(results_json['video']['results'])
return []
def _general_results(general_results):
results = []
for result in general_results:
results.append({
'url': result['url'],
'title': result['title'],
'content': result['sum'],
})
return results
def _images_results(image_results):
results = []
for result in image_results:
results.append({
'url': result['sourceURL'],
'title': result['title'],
'content': result['source'],
'thumbnail_src': _extract_url(result['assets']['thumb']['url']),
'img_src': _extract_url(result['assets']['file']['url']),
'template': 'images.html',
})
return results
def _videos_results(video_results):
results = []
for result in video_results:
if not result['kind'].startswith('youtube'):
logger.warn('Unknown video kind in findx: {}'.format(result['kind']))
continue
description = result['snippet']['description']
if len(description) > 300:
description = description[:300] + '...'
results.append({
'url': base_youtube_url + result['id'],
'title': result['snippet']['title'],
'content': description,
'thumbnail': _extract_url(result['snippet']['thumbnails']['default']['url']),
'publishedDate': parser.parse(result['snippet']['publishedAt']),
'embedded': embedded_url.format(videoid=result['id']),
'template': 'videos.html',
})
return results
def _extract_url(url):
matching = re.search('(/https?://[^)]+)', url)
if matching:
return matching.group(0)[1:]
return ''

View File

@ -34,6 +34,7 @@ search_string = 'search?{query}'\
'&qlang={lang}'\ '&qlang={lang}'\
'&ff={safesearch}'\ '&ff={safesearch}'\
'&rxiec={rxieu}'\ '&rxiec={rxieu}'\
'&ulse={ulse}'\
'&rand={rxikd}' # current unix timestamp '&rand={rxikd}' # current unix timestamp
# specific xpath variables # specific xpath variables
@ -64,6 +65,7 @@ def request(query, params):
number_of_results=number_of_results, number_of_results=number_of_results,
rxikd=int(time() * 1000), rxikd=int(time() * 1000),
rxieu=random.randint(1000000000, 9999999999), rxieu=random.randint(1000000000, 9999999999),
ulse=random.randint(100000000, 999999999),
lang=language, lang=language,
safesearch=safesearch) safesearch=safesearch)

View File

@ -14,6 +14,7 @@ from lxml import html, etree
from searx.engines.xpath import extract_text, extract_url from searx.engines.xpath import extract_text, extract_url
from searx import logger from searx import logger
from searx.url_utils import urlencode, urlparse, parse_qsl from searx.url_utils import urlencode, urlparse, parse_qsl
from searx.utils import match_language
logger = logger.getChild('google engine') logger = logger.getChild('google engine')
@ -72,7 +73,7 @@ country_to_hostname = {
'RO': 'www.google.ro', # Romania 'RO': 'www.google.ro', # Romania
'RU': 'www.google.ru', # Russia 'RU': 'www.google.ru', # Russia
'SK': 'www.google.sk', # Slovakia 'SK': 'www.google.sk', # Slovakia
'SL': 'www.google.si', # Slovenia (SL -> si) 'SI': 'www.google.si', # Slovenia
'SE': 'www.google.se', # Sweden 'SE': 'www.google.se', # Sweden
'TH': 'www.google.co.th', # Thailand 'TH': 'www.google.co.th', # Thailand
'TR': 'www.google.com.tr', # Turkey 'TR': 'www.google.com.tr', # Turkey
@ -90,7 +91,7 @@ url_map = 'https://www.openstreetmap.org/'\
search_path = '/search' search_path = '/search'
search_url = ('https://{hostname}' + search_url = ('https://{hostname}' +
search_path + search_path +
'?{query}&start={offset}&gws_rd=cr&gbv=1&lr={lang}&ei=x') '?{query}&start={offset}&gws_rd=cr&gbv=1&lr={lang}&hl={lang_short}&ei=x')
time_range_search = "&tbs=qdr:{range}" time_range_search = "&tbs=qdr:{range}"
time_range_dict = {'day': 'd', time_range_dict = {'day': 'd',
@ -165,22 +166,16 @@ def extract_text_from_dom(result, xpath):
def request(query, params): def request(query, params):
offset = (params['pageno'] - 1) * 10 offset = (params['pageno'] - 1) * 10
# temporary fix until a way of supporting en-US is found language = match_language(params['language'], supported_languages)
if params['language'] == 'en-US': language_array = language.split('-')
params['language'] = 'en-GB' if params['language'].find('-') > 0:
country = params['language'].split('-')[1]
if params['language'][:2] == 'jv': elif len(language_array) == 2:
language = 'jw'
country = 'ID'
url_lang = 'lang_jw'
else:
language_array = params['language'].lower().split('-')
if len(language_array) == 2:
country = language_array[1] country = language_array[1]
else: else:
country = 'US' country = 'US'
language = language_array[0] + ',' + language_array[0] + '-' + country
url_lang = 'lang_' + language_array[0] url_lang = 'lang_' + language
if use_locale_domain: if use_locale_domain:
google_hostname = country_to_hostname.get(country.upper(), default_hostname) google_hostname = country_to_hostname.get(country.upper(), default_hostname)
@ -192,11 +187,12 @@ def request(query, params):
params['url'] = search_url.format(offset=offset, params['url'] = search_url.format(offset=offset,
query=urlencode({'q': query}), query=urlencode({'q': query}),
hostname=google_hostname, hostname=google_hostname,
lang=url_lang) lang=url_lang,
lang_short=language)
if params['time_range'] in time_range_dict: if params['time_range'] in time_range_dict:
params['url'] += time_range_search.format(range=time_range_dict[params['time_range']]) params['url'] += time_range_search.format(range=time_range_dict[params['time_range']])
params['headers']['Accept-Language'] = language params['headers']['Accept-Language'] = language + ',' + language + '-' + country
params['headers']['Accept'] = 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8' params['headers']['Accept'] = 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8'
params['google_hostname'] = google_hostname params['google_hostname'] = google_hostname

View File

@ -13,7 +13,7 @@
from datetime import date, timedelta from datetime import date, timedelta
from json import loads from json import loads
from lxml import html from lxml import html
from searx.url_utils import urlencode from searx.url_utils import urlencode, urlparse, parse_qs
# engine dependent config # engine dependent config
@ -25,10 +25,9 @@ number_of_results = 100
search_url = 'https://www.google.com/search'\ search_url = 'https://www.google.com/search'\
'?{query}'\ '?{query}'\
'&asearch=ichunk'\
'&async=_id:rg_s,_pms:s'\
'&tbm=isch'\ '&tbm=isch'\
'&yv=2'\ '&gbv=1'\
'&sa=G'\
'&{search_options}' '&{search_options}'
time_range_attr = "qdr:{range}" time_range_attr = "qdr:{range}"
time_range_custom_attr = "cdr:1,cd_min:{start},cd_max{end}" time_range_custom_attr = "cdr:1,cd_min:{start},cd_max{end}"
@ -66,30 +65,22 @@ def request(query, params):
def response(resp): def response(resp):
results = [] results = []
g_result = loads(resp.text) dom = html.fromstring(resp.text)
dom = html.fromstring(g_result[1][1])
# parse results # parse results
for result in dom.xpath('//div[@data-ved]'): for img in dom.xpath('//a'):
r = {
try: 'title': u' '.join(img.xpath('.//div[class="rg_ilmbg"]//text()')),
metadata = loads(''.join(result.xpath('./div[contains(@class, "rg_meta")]/text()'))) 'content': '',
except: 'template': 'images.html',
continue }
url = urlparse(img.xpath('.//@href')[0])
thumbnail_src = metadata['tu'] query = parse_qs(url.query)
r['url'] = query['imgrefurl'][0]
# http to https r['img_src'] = query['imgurl'][0]
thumbnail_src = thumbnail_src.replace("http://", "https://") r['thumbnail_src'] = r['img_src']
# append result # append result
results.append({'url': metadata['ru'], results.append(r)
'title': metadata['pt'],
'content': metadata['s'],
'thumbnail_src': thumbnail_src,
'img_src': metadata['ou'],
'template': 'images.html'})
# return results # return results
return results return results

View File

@ -13,6 +13,7 @@
from lxml import html from lxml import html
from searx.engines.google import _fetch_supported_languages, supported_languages_url from searx.engines.google import _fetch_supported_languages, supported_languages_url
from searx.url_utils import urlencode from searx.url_utils import urlencode
from searx.utils import match_language
# search-url # search-url
categories = ['news'] categories = ['news']
@ -50,8 +51,9 @@ def request(query, params):
params['url'] = search_url.format(query=urlencode({'q': query}), params['url'] = search_url.format(query=urlencode({'q': query}),
search_options=urlencode(search_options)) search_options=urlencode(search_options))
language_array = params['language'].lower().split('-') language = match_language(params['language'], supported_languages).split('-')[0]
params['url'] += '&lr=lang_' + language_array[0] if language:
params['url'] += '&lr=lang_' + language
return params return params
@ -66,8 +68,8 @@ def response(resp):
for result in dom.xpath('//div[@class="g"]|//div[@class="g _cy"]'): for result in dom.xpath('//div[@class="g"]|//div[@class="g _cy"]'):
try: try:
r = { r = {
'url': result.xpath('.//a[@class="l _PMs"]')[0].attrib.get("href"), 'url': result.xpath('.//a[@class="l lLrAF"]')[0].attrib.get("href"),
'title': ''.join(result.xpath('.//a[@class="l _PMs"]//text()')), 'title': ''.join(result.xpath('.//a[@class="l lLrAF"]//text()')),
'content': ''.join(result.xpath('.//div[@class="st"]//text()')), 'content': ''.join(result.xpath('.//div[@class="st"]//text()')),
} }
except: except:

View File

@ -1,7 +1,7 @@
""" """
Nyaa.si (Anime Bittorrent tracker) Nyaa.si (Anime Bittorrent tracker)
@website http://www.nyaa.si/ @website https://nyaa.si/
@provide-api no @provide-api no
@using-api no @using-api no
@results HTML @results HTML
@ -19,7 +19,7 @@ categories = ['files', 'images', 'videos', 'music']
paging = True paging = True
# search-url # search-url
base_url = 'http://www.nyaa.si/' base_url = 'https://nyaa.si/'
search_url = base_url + '?page=search&{query}&offset={offset}' search_url = base_url + '?page=search&{query}&offset={offset}'
# xpath queries # xpath queries

View File

@ -18,7 +18,7 @@ categories = ['videos', 'music', 'files']
paging = True paging = True
# search-url # search-url
url = 'https://thepiratebay.se/' url = 'https://thepiratebay.org/'
search_url = url + 'search/{search_term}/{pageno}/99/{search_type}' search_url = url + 'search/{search_term}/{pageno}/99/{search_type}'
# piratebay specific type-definitions # piratebay specific type-definitions

View File

@ -14,6 +14,7 @@ from datetime import datetime
from json import loads from json import loads
from searx.utils import html_to_text from searx.utils import html_to_text
from searx.url_utils import urlencode from searx.url_utils import urlencode
from searx.utils import match_language
# engine dependent config # engine dependent config
categories = None categories = None
@ -27,7 +28,7 @@ category_to_keyword = {'general': 'web',
'social media': 'social'} 'social media': 'social'}
# search-url # search-url
url = 'https://api.qwant.com/api/search/{keyword}?count=10&offset={offset}&f=&{query}' url = 'https://api.qwant.com/api/search/{keyword}?count=10&offset={offset}&f=&{query}&t={keyword}&uiv=4'
# do search-request # do search-request
@ -45,16 +46,8 @@ def request(query, params):
offset=offset) offset=offset)
# add language tag # add language tag
if params['language'] == 'no' or params['language'].startswith('no-'): language = match_language(params['language'], supported_languages)
params['language'] = params['language'].replace('no', 'nb', 1) params['url'] += '&locale=' + language.replace('-', '_').lower()
if params['language'].find('-') < 0:
# tries to get a country code from language
for lang in supported_languages:
lc = lang.split('-')
if params['language'] == lc[0]:
params['language'] = lang
break
params['url'] += '&locale=' + params['language'].replace('-', '_').lower()
return params return params

View File

@ -14,6 +14,7 @@ from json import loads
import re import re
from lxml.html import fromstring from lxml.html import fromstring
from searx.url_utils import unquote, urlencode from searx.url_utils import unquote, urlencode
from searx.utils import match_language
# engine dependent config # engine dependent config
categories = ['general', 'images'] categories = ['general', 'images']
@ -35,11 +36,8 @@ regex_img_url_remove_start = re.compile(b'^https?://i\.swisscows\.ch/\?link=')
# do search-request # do search-request
def request(query, params): def request(query, params):
if params['language'].split('-')[0] == 'no': region = match_language(params['language'], supported_languages)
region = 'nb-NO' ui_language = region.split('-')[0]
else:
region = params['language']
ui_language = params['language'].split('-')[0]
search_path = search_string.format( search_path = search_string.format(
query=urlencode({'query': query, 'uiLanguage': ui_language, 'region': region}), query=urlencode({'query': query, 'uiLanguage': ui_language, 'region': region}),

View File

@ -16,6 +16,7 @@ from searx.poolrequests import get
from searx.engines.xpath import extract_text from searx.engines.xpath import extract_text
from searx.engines.wikipedia import _fetch_supported_languages, supported_languages_url from searx.engines.wikipedia import _fetch_supported_languages, supported_languages_url
from searx.url_utils import urlencode from searx.url_utils import urlencode
from searx.utils import match_language
from json import loads from json import loads
from lxml.html import fromstring from lxml.html import fromstring
@ -26,7 +27,7 @@ result_count = 1
# urls # urls
wikidata_host = 'https://www.wikidata.org' wikidata_host = 'https://www.wikidata.org'
url_search = wikidata_host \ url_search = wikidata_host \
+ '/wiki/Special:ItemDisambiguation?{query}' + '/w/index.php?{query}'
wikidata_api = wikidata_host + '/w/api.php' wikidata_api = wikidata_host + '/w/api.php'
url_detail = wikidata_api\ url_detail = wikidata_api\
@ -39,7 +40,7 @@ url_map = 'https://www.openstreetmap.org/'\
url_image = 'https://commons.wikimedia.org/wiki/Special:FilePath/{filename}?width=500&height=400' url_image = 'https://commons.wikimedia.org/wiki/Special:FilePath/{filename}?width=500&height=400'
# xpaths # xpaths
wikidata_ids_xpath = '//div/ul[@class="wikibase-disambiguation"]/li/a/@title' wikidata_ids_xpath = '//ul[@class="mw-search-results"]/li//a/@href'
title_xpath = '//*[contains(@class,"wikibase-title-label")]' title_xpath = '//*[contains(@class,"wikibase-title-label")]'
description_xpath = '//div[contains(@class,"wikibase-entitytermsview-heading-description")]' description_xpath = '//div[contains(@class,"wikibase-entitytermsview-heading-description")]'
property_xpath = '//div[@id="{propertyid}"]' property_xpath = '//div[@id="{propertyid}"]'
@ -53,25 +54,25 @@ value_xpath = './/div[contains(@class,"wikibase-statementview-mainsnak")]'\
+ '/*/div[contains(@class,"wikibase-snakview-value")]' + '/*/div[contains(@class,"wikibase-snakview-value")]'
language_fallback_xpath = '//sup[contains(@class,"wb-language-fallback-indicator")]' language_fallback_xpath = '//sup[contains(@class,"wb-language-fallback-indicator")]'
calendar_name_xpath = './/sup[contains(@class,"wb-calendar-name")]' calendar_name_xpath = './/sup[contains(@class,"wb-calendar-name")]'
media_xpath = value_xpath + '//div[contains(@class,"commons-media-caption")]//a'
def request(query, params): def request(query, params):
language = params['language'].split('-')[0]
params['url'] = url_search.format( params['url'] = url_search.format(
query=urlencode({'label': query, 'language': language})) query=urlencode({'search': query}))
return params return params
def response(resp): def response(resp):
results = [] results = []
html = fromstring(resp.text) html = fromstring(resp.text)
wikidata_ids = html.xpath(wikidata_ids_xpath) search_results = html.xpath(wikidata_ids_xpath)
language = resp.search_params['language'].split('-')[0] language = match_language(resp.search_params['language'], supported_languages).split('-')[0]
# TODO: make requests asynchronous to avoid timeout when result_count > 1 # TODO: make requests asynchronous to avoid timeout when result_count > 1
for wikidata_id in wikidata_ids[:result_count]: for search_result in search_results[:result_count]:
wikidata_id = search_result.split('/')[-1]
url = url_detail.format(query=urlencode({'page': wikidata_id, 'uselang': language})) url = url_detail.format(query=urlencode({'page': wikidata_id, 'uselang': language}))
htmlresponse = get(url) htmlresponse = get(url)
jsonresponse = loads(htmlresponse.text) jsonresponse = loads(htmlresponse.text)
@ -313,7 +314,7 @@ def add_image(result):
for property_id in property_ids: for property_id in property_ids:
image = result.xpath(property_xpath.replace('{propertyid}', property_id)) image = result.xpath(property_xpath.replace('{propertyid}', property_id))
if image: if image:
image_name = image[0].xpath(value_xpath) image_name = image[0].xpath(media_xpath)
image_src = url_image.replace('{filename}', extract_text(image_name[0])) image_src = url_image.replace('{filename}', extract_text(image_name[0]))
return image_src return image_src

View File

@ -13,6 +13,7 @@
from json import loads from json import loads
from lxml.html import fromstring from lxml.html import fromstring
from searx.url_utils import quote, urlencode from searx.url_utils import quote, urlencode
from searx.utils import match_language
# search-url # search-url
base_url = u'https://{language}.wikipedia.org/' base_url = u'https://{language}.wikipedia.org/'
@ -30,13 +31,7 @@ supported_languages_url = 'https://meta.wikimedia.org/wiki/List_of_Wikipedias'
# set language in base_url # set language in base_url
def url_lang(lang): def url_lang(lang):
lang = lang.split('-')[0] return match_language(lang, supported_languages).split('-')[0]
if lang not in supported_languages:
language = 'en'
else:
language = lang
return language
# do search-request # do search-request

View File

@ -53,7 +53,7 @@ def extract_url(xpath_results, search_url):
if url.startswith('//'): if url.startswith('//'):
# add http or https to this kind of url //example.com/ # add http or https to this kind of url //example.com/
parsed_search_url = urlparse(search_url) parsed_search_url = urlparse(search_url)
url = u'{0}:{1}'.format(parsed_search_url.scheme, url) url = u'{0}:{1}'.format(parsed_search_url.scheme or 'http', url)
elif url.startswith('/'): elif url.startswith('/'):
# fix relative url to the search engine # fix relative url to the search engine
url = urljoin(search_url, url) url = urljoin(search_url, url)

View File

@ -14,6 +14,7 @@
from lxml import html from lxml import html
from searx.engines.xpath import extract_text, extract_url from searx.engines.xpath import extract_text, extract_url
from searx.url_utils import unquote, urlencode from searx.url_utils import unquote, urlencode
from searx.utils import match_language
# engine dependent config # engine dependent config
categories = ['general'] categories = ['general']
@ -39,6 +40,8 @@ time_range_dict = {'day': ['1d', 'd'],
'week': ['1w', 'w'], 'week': ['1w', 'w'],
'month': ['1m', 'm']} 'month': ['1m', 'm']}
language_aliases = {'zh-CN': 'zh-CHS', 'zh-TW': 'zh-CHT', 'zh-HK': 'zh-CHT'}
# remove yahoo-specific tracking-url # remove yahoo-specific tracking-url
def parse_url(url_string): def parse_url(url_string):
@ -70,23 +73,16 @@ def _get_url(query, offset, language, time_range):
lang=language) lang=language)
def _get_language(params):
if params['language'][:2] == 'zh':
if params['language'] == 'zh' or params['language'] == 'zh-CH':
return 'szh'
else:
return 'tzh'
else:
return params['language'].split('-')[0]
# do search-request # do search-request
def request(query, params): def request(query, params):
if params['time_range'] and params['time_range'] not in time_range_dict: if params['time_range'] and params['time_range'] not in time_range_dict:
return params return params
offset = (params['pageno'] - 1) * 10 + 1 offset = (params['pageno'] - 1) * 10 + 1
language = _get_language(params) language = match_language(params['language'], supported_languages, language_aliases)
if language not in language_aliases.values():
language = language.split('-')[0]
language = language.replace('-', '_').lower()
params['url'] = _get_url(query, offset, language, params['time_range']) params['url'] = _get_url(query, offset, language, params['time_range'])
@ -145,7 +141,11 @@ def _fetch_supported_languages(resp):
dom = html.fromstring(resp.text) dom = html.fromstring(resp.text)
options = dom.xpath('//div[@id="yschlang"]/span/label/input') options = dom.xpath('//div[@id="yschlang"]/span/label/input')
for option in options: for option in options:
code = option.xpath('./@value')[0][5:].replace('_', '-') code_parts = option.xpath('./@value')[0][5:].split('_')
if len(code_parts) == 2:
code = code_parts[0] + '-' + code_parts[1].upper()
else:
code = code_parts[0]
supported_languages.append(code) supported_languages.append(code)
return supported_languages return supported_languages

View File

@ -13,9 +13,12 @@ import re
from datetime import datetime, timedelta from datetime import datetime, timedelta
from lxml import html from lxml import html
from searx.engines.xpath import extract_text, extract_url from searx.engines.xpath import extract_text, extract_url
from searx.engines.yahoo import parse_url, _fetch_supported_languages, supported_languages_url from searx.engines.yahoo import (
parse_url, _fetch_supported_languages, supported_languages_url, language_aliases
)
from dateutil import parser from dateutil import parser
from searx.url_utils import urlencode from searx.url_utils import urlencode
from searx.utils import match_language
# engine dependent config # engine dependent config
categories = ['news'] categories = ['news']
@ -38,7 +41,7 @@ suggestion_xpath = '//div[contains(@class,"VerALSOTRY")]//a'
def request(query, params): def request(query, params):
offset = (params['pageno'] - 1) * 10 + 1 offset = (params['pageno'] - 1) * 10 + 1
language = params['language'].split('-')[0] language = match_language(params['language'], supported_languages, language_aliases).split('-')[0]
params['url'] = search_url.format(offset=offset, params['url'] = search_url.format(offset=offset,
query=urlencode({'p': query}), query=urlencode({'p': query}),

View File

@ -5,11 +5,7 @@
language_codes = ( language_codes = (
(u"ar-SA", u"العربية", u"", u"Arabic"), (u"ar-SA", u"العربية", u"", u"Arabic"),
(u"bg-BG", u"Български", u"", u"Bulgarian"), (u"bg-BG", u"Български", u"", u"Bulgarian"),
(u"ca", u"Català", u"", u"Catalan"), (u"ca-ES", u"Català", u"", u"Catalan"),
(u"ca-AD", u"Català", u"Andorra", u"Catalan"),
(u"ca-CT", u"Català", u"", u"Catalan"),
(u"ca-ES", u"Català", u"Espanya", u"Catalan"),
(u"ca-FR", u"Català", u"França", u"Catalan"),
(u"cs-CZ", u"Čeština", u"", u"Czech"), (u"cs-CZ", u"Čeština", u"", u"Czech"),
(u"da-DK", u"Dansk", u"", u"Danish"), (u"da-DK", u"Dansk", u"", u"Danish"),
(u"de", u"Deutsch", u"", u"German"), (u"de", u"Deutsch", u"", u"German"),
@ -21,55 +17,51 @@ language_codes = (
(u"en-AU", u"English", u"Australia", u"English"), (u"en-AU", u"English", u"Australia", u"English"),
(u"en-CA", u"English", u"Canada", u"English"), (u"en-CA", u"English", u"Canada", u"English"),
(u"en-GB", u"English", u"United Kingdom", u"English"), (u"en-GB", u"English", u"United Kingdom", u"English"),
(u"en-ID", u"English", u"Indonesia", u"English"),
(u"en-IE", u"English", u"Ireland", u"English"),
(u"en-IN", u"English", u"India", u"English"), (u"en-IN", u"English", u"India", u"English"),
(u"en-MY", u"English", u"Malaysia", u"English"), (u"en-MY", u"English", u"Malaysia", u"English"),
(u"en-NZ", u"English", u"New Zealand", u"English"),
(u"en-PH", u"English", u"Philippines", u"English"),
(u"en-SG", u"English", u"Singapore", u"English"),
(u"en-US", u"English", u"United States", u"English"), (u"en-US", u"English", u"United States", u"English"),
(u"en-ZA", u"English", u"South Africa", u"English"),
(u"es", u"Español", u"", u"Spanish"), (u"es", u"Español", u"", u"Spanish"),
(u"es-AD", u"Español", u"Andorra", u"Spanish"),
(u"es-AR", u"Español", u"Argentina", u"Spanish"), (u"es-AR", u"Español", u"Argentina", u"Spanish"),
(u"es-CL", u"Español", u"Chile", u"Spanish"),
(u"es-CO", u"Español", u"Colombia", u"Spanish"),
(u"es-ES", u"Español", u"España", u"Spanish"), (u"es-ES", u"Español", u"España", u"Spanish"),
(u"es-MX", u"Español", u"México", u"Spanish"), (u"es-MX", u"Español", u"México", u"Spanish"),
(u"es-PE", u"Español", u"Perú", u"Spanish"),
(u"es-US", u"Español", u"Estados Unidos", u"Spanish"),
(u"et-EE", u"Eesti", u"", u"Estonian"), (u"et-EE", u"Eesti", u"", u"Estonian"),
(u"fa-IR", u"فارسی", u"", u"Persian"),
(u"fi-FI", u"Suomi", u"", u"Finnish"), (u"fi-FI", u"Suomi", u"", u"Finnish"),
(u"fr", u"Français", u"", u"French"), (u"fr", u"Français", u"", u"French"),
(u"fr-AD", u"Français", u"Andorre", u"French"),
(u"fr-BE", u"Français", u"Belgique", u"French"), (u"fr-BE", u"Français", u"Belgique", u"French"),
(u"fr-CA", u"Français", u"Canada", u"French"), (u"fr-CA", u"Français", u"Canada", u"French"),
(u"fr-CH", u"Français", u"Suisse", u"French"), (u"fr-CH", u"Français", u"Suisse", u"French"),
(u"fr-FR", u"Français", u"France", u"French"), (u"fr-FR", u"Français", u"France", u"French"),
(u"he-IL", u"עברית", u"", u"Hebrew"), (u"he-IL", u"עברית", u"", u"Hebrew"),
(u"hr-HR", u"Hrvatski", u"", u"Croatian"),
(u"hu-HU", u"Magyar", u"", u"Hungarian"), (u"hu-HU", u"Magyar", u"", u"Hungarian"),
(u"it", u"Italiano", u"", u"Italian"), (u"id-ID", u"Indonesia", u"", u"Indonesian"),
(u"it-CH", u"Italiano", u"Svizzera", u"Italian"), (u"is-IS", u"Íslenska", u"", u"Icelandic"),
(u"it-IT", u"Italiano", u"Italia", u"Italian"), (u"it-IT", u"Italiano", u"", u"Italian"),
(u"ja-JP", u"日本語", u"", u"Japanese"), (u"ja-JP", u"日本語", u"", u"Japanese"),
(u"ko-KR", u"한국어", u"", u"Korean"), (u"ko-KR", u"한국어", u"", u"Korean"),
(u"lt-LT", u"Lietuvių", u"", u"Lithuanian"),
(u"lv-LV", u"Latviešu", u"", u"Latvian"),
(u"ms-MY", u"Bahasa Melayu", u"", u"Malay"),
(u"nb-NO", u"Norsk Bokmål", u"", u"Norwegian Bokmål"),
(u"nl", u"Nederlands", u"", u"Dutch"), (u"nl", u"Nederlands", u"", u"Dutch"),
(u"nl-BE", u"Nederlands", u"België", u"Dutch"), (u"nl-BE", u"Nederlands", u"België", u"Dutch"),
(u"nl-NL", u"Nederlands", u"Nederland", u"Dutch"), (u"nl-NL", u"Nederlands", u"Nederland", u"Dutch"),
(u"no-NO", u"Norsk", u"", u"Norwegian"),
(u"pl-PL", u"Polski", u"", u"Polish"), (u"pl-PL", u"Polski", u"", u"Polish"),
(u"pt", u"Português", u"", u"Portuguese"), (u"pt", u"Português", u"", u"Portuguese"),
(u"pt-AD", u"Português", u"Andorra", u"Portuguese"),
(u"pt-BR", u"Português", u"Brasil", u"Portuguese"), (u"pt-BR", u"Português", u"Brasil", u"Portuguese"),
(u"pt-PT", u"Português", u"Portugal", u"Portuguese"), (u"pt-PT", u"Português", u"Portugal", u"Portuguese"),
(u"ro-RO", u"Română", u"", u"Romanian"), (u"ro-RO", u"Română", u"", u"Romanian"),
(u"ru-RU", u"Русский", u"", u"Russian"), (u"ru-RU", u"Русский", u"", u"Russian"),
(u"sk-SK", u"Slovenčina", u"", u"Slovak"),
(u"sl-SI", u"Slovenščina", u"", u"Slovenian"),
(u"sr-RS", u"Српски", u"", u"Serbian"),
(u"sv-SE", u"Svenska", u"", u"Swedish"), (u"sv-SE", u"Svenska", u"", u"Swedish"),
(u"th-TH", u"ไทย", u"", u"Thai"), (u"th-TH", u"ไทย", u"", u"Thai"),
(u"tr-TR", u"Türkçe", u"", u"Turkish"), (u"tr-TR", u"Türkçe", u"", u"Turkish"),
(u"uk-UA", u"Українська", u"", u"Ukrainian"),
(u"vi-VN", u"Tiếng Việt", u"", u"Vietnamese"),
(u"zh", u"中文", u"", u"Chinese"), (u"zh", u"中文", u"", u"Chinese"),
(u"zh-CN", u"中文", u"中国", u"Chinese"), (u"zh-CN", u"中文", u"中国", u"Chinese"),
(u"zh-HK", u"中文", u"香港", u"Chinese"), (u"zh-TW", u"中文", u"台灣", u"Chinese")
(u"zh-TW", u"中文", u"台湾", u"Chinese")
) )

View File

@ -9,7 +9,7 @@ regex = re.compile(r'10\.\d{4,9}/[^\s]+')
name = gettext('Open Access DOI rewrite') name = gettext('Open Access DOI rewrite')
description = gettext('Avoid paywalls by redirecting to open-access versions of publications when available') description = gettext('Avoid paywalls by redirecting to open-access versions of publications when available')
default_on = False default_on = False
preference_section = 'privacy' preference_section = 'general'
doi_resolvers = settings['doi_resolvers'] doi_resolvers = settings['doi_resolvers']
@ -30,7 +30,8 @@ def get_doi_resolver(args, preference_doi_resolver):
doi_resolver = args.get('doi_resolver', preference_doi_resolver)[0] doi_resolver = args.get('doi_resolver', preference_doi_resolver)[0]
if doi_resolver not in doi_resolvers: if doi_resolver not in doi_resolvers:
doi_resolvers = settings['default_doi_resolver'] doi_resolvers = settings['default_doi_resolver']
return doi_resolver doi_resolver_url = doi_resolvers[doi_resolver]
return doi_resolver_url
def on_result(request, search, result): def on_result(request, search, result):

View File

@ -115,10 +115,6 @@ class SearchLanguageSetting(EnumStringSetting):
pass pass
elif lang in self.choices: elif lang in self.choices:
data = lang data = lang
elif data == 'nb-NO':
data = 'no-NO'
elif data == 'ar-XA':
data = 'ar-SA'
else: else:
data = self.value data = self.value
self.value = data self.value = data

View File

@ -96,7 +96,11 @@ class RawTextQuery(object):
break break
# user may set a valid, yet not selectable language # user may set a valid, yet not selectable language
if not self.languages and VALID_LANGUAGE_CODE.match(lang): if VALID_LANGUAGE_CODE.match(lang):
lang_parts = lang.split('-')
if len(lang_parts) > 1:
lang = lang_parts[0].lower() + '-' + lang_parts[1].upper()
if lang not in self.languages:
self.languages.append(lang) self.languages.append(lang)
parse_next = True parse_next = True
@ -107,14 +111,21 @@ class RawTextQuery(object):
# check if prefix is equal with engine shortcut # check if prefix is equal with engine shortcut
if prefix in engine_shortcuts: if prefix in engine_shortcuts:
parse_next = True parse_next = True
self.engines.append({'category': 'none', engine_name = engine_shortcuts[prefix]
'name': engine_shortcuts[prefix]}) if engine_name in engines:
for engine_category in engines[engine_name].categories:
self.engines.append({'category': engine_category,
'name': engine_name,
'from_bang': True})
# check if prefix is equal with engine name # check if prefix is equal with engine name
elif prefix in engines: elif prefix in engines:
parse_next = True parse_next = True
self.engines.append({'category': 'none', if prefix in engines:
'name': prefix}) for engine_category in engines[prefix].categories:
self.engines.append({'category': engine_category,
'name': prefix,
'from_bang': True})
# check if prefix is equal with categorie name # check if prefix is equal with categorie name
elif prefix in categories: elif prefix in categories:

View File

@ -258,8 +258,13 @@ def get_search_query_from_webapp(preferences, form):
# if engines are calculated from query, # if engines are calculated from query,
# set categories by using that informations # set categories by using that informations
if query_engines and raw_text_query.specific: if query_engines and raw_text_query.specific:
query_categories = list(set(engine['category'] additional_categories = set()
for engine in query_engines)) for engine in query_engines:
if 'from_bang' in engine and engine['from_bang']:
additional_categories.add('none')
else:
additional_categories.add(engine['category'])
query_categories = list(additional_categories)
# otherwise, using defined categories to # otherwise, using defined categories to
# calculate which engines should be used # calculate which engines should be used

View File

@ -174,6 +174,7 @@ engines:
- name : wikidata - name : wikidata
engine : wikidata engine : wikidata
shortcut : wd shortcut : wd
timeout : 3.0
weight : 2 weight : 2
- name : duckduckgo - name : duckduckgo
@ -191,10 +192,9 @@ engines:
engine : xpath engine : xpath
paging : True paging : True
search_url : http://etymonline.com/?search={query}&p={pageno} search_url : http://etymonline.com/?search={query}&p={pageno}
url_xpath : //dt/a[1]/@href url_xpath : //a[contains(@class, "word--")]/@href
title_xpath : //dt title_xpath : //p[contains(@class, "word__name--")]/text()
content_xpath : //dd content_xpath : //section[contains(@class, "word__defination")]/object
suggestion_xpath : //a[@class="crossreference"]
first_page_num : 0 first_page_num : 0
shortcut : et shortcut : et
disabled : True disabled : True
@ -218,6 +218,24 @@ engines:
shortcut : fd shortcut : fd
disabled : True disabled : True
- name : findx
engine : findx
shortcut : fx
categories : general
disabled : True
- name : findx images
engine : findx
shortcut : fxi
categories : images
disabled : True
- name : findx videos
engine : findx
shortcut : fxv
categories : videos
disabled : True
- name : flickr - name : flickr
categories : images categories : images
shortcut : fl shortcut : fl
@ -292,7 +310,7 @@ engines:
engine : xpath engine : xpath
paging : True paging : True
search_url : https://scholar.google.com/scholar?start={pageno}&q={query}&hl=en&as_sdt=0,5&as_vis=1 search_url : https://scholar.google.com/scholar?start={pageno}&q={query}&hl=en&as_sdt=0,5&as_vis=1
results_xpath : //div[@class="gs_r"]/div[@class="gs_ri"] results_xpath : //div[contains(@class, "gs_r")]/div[@class="gs_ri"]
url_xpath : .//h3/a/@href url_xpath : .//h3/a/@href
title_xpath : .//h3/a title_xpath : .//h3/a
content_xpath : .//div[@class="gs_rs"] content_xpath : .//div[@class="gs_rs"]
@ -415,6 +433,12 @@ engines:
shortcut : nt shortcut : nt
disabled : True disabled : True
- name : acgsou
engine : acgsou
shortcut : acg
disabled : True
timeout: 5.0
- name : openairedatasets - name : openairedatasets
engine : json_engine engine : json_engine
paging : True paging : True
@ -723,6 +747,7 @@ locales:
it : Italiano (Italian) it : Italiano (Italian)
ja : 日本語 (Japanese) ja : 日本語 (Japanese)
nl : Nederlands (Dutch) nl : Nederlands (Dutch)
pl : Polski (Polish)
pt : Português (Portuguese) pt : Português (Portuguese)
pt_BR : Português (Portuguese_Brazil) pt_BR : Português (Portuguese_Brazil)
ro : Română (Romanian) ro : Română (Romanian)
@ -740,5 +765,6 @@ doi_resolvers :
oadoi.org : 'https://oadoi.org/' oadoi.org : 'https://oadoi.org/'
doi.org : 'https://doi.org/' doi.org : 'https://doi.org/'
doai.io : 'http://doai.io/' doai.io : 'http://doai.io/'
sci-hub.tw : 'http://sci-hub.tw/'
default_doi_resolver : 'oadoi.org' default_doi_resolver : 'oadoi.org'

View File

@ -14,3 +14,6 @@
border-radius: 50% !important; border-radius: 50% !important;
margin: 0 auto; margin: 0 auto;
} }
#pagination button {
visibility: hidden;
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.0 KiB

After

Width:  |  Height:  |  Size: 587 B

View File

@ -18,6 +18,7 @@
padding-bottom: 0.4rem; padding-bottom: 0.4rem;
padding-top: 0.4rem; padding-top: 0.4rem;
text-align: center; text-align: center;
min-width: 50px;
} }
label:last-child, .input-group-addon:last-child { label:last-child, .input-group-addon:last-child {
border-right: @mild-gray 1px solid; border-right: @mild-gray 1px solid;

View File

@ -18,6 +18,7 @@
padding-bottom: 0.8rem; padding-bottom: 0.8rem;
padding-top: 0.8rem; padding-top: 0.8rem;
text-align: center; text-align: center;
min-width: 50px;
} }
label:last-child, .input-group-addon:last-child { label:last-child, .input-group-addon:last-child {

View File

@ -1,44 +1,30 @@
/*! searx | 03-12-2017 | https://github.com/asciimoo/searx */ /*! searx | 14-08-2018 | https://github.com/asciimoo/searx */
/* /*
* searx, A privacy-respecting, hackable metasearch engine * searx, A privacy-respecting, hackable metasearch engine
* *
* To convert "style.less" to "style.css" run: $make styles * To convert "style.less" to "style.css" run: $make styles
*/ */
/*! normalize.css v7.0.0 | MIT License | github.com/necolas/normalize.css */ /*! normalize.css v8.0.0 | MIT License | github.com/necolas/normalize.css */
/* Document /* Document
========================================================================== */ ========================================================================== */
/** /**
* 1. Correct the line height in all browsers. * 1. Correct the line height in all browsers.
* 2. Prevent adjustments of font size after orientation changes in * 2. Prevent adjustments of font size after orientation changes in iOS.
* IE on Windows Phone and in iOS.
*/ */
html { html {
line-height: 1.15; line-height: 1.15;
/* 1 */ /* 1 */
-ms-text-size-adjust: 100%;
/* 2 */
-webkit-text-size-adjust: 100%; -webkit-text-size-adjust: 100%;
/* 2 */ /* 2 */
} }
/* Sections /* Sections
========================================================================== */ ========================================================================== */
/** /**
* Remove the margin in all browsers (opinionated). * Remove the margin in all browsers.
*/ */
body { body {
margin: 0; margin: 0;
} }
/**
* Add the correct display in IE 9-.
*/
article,
aside,
footer,
header,
nav,
section {
display: block;
}
/** /**
* Correct the font size and margin on `h1` elements within `section` and * Correct the font size and margin on `h1` elements within `section` and
* `article` contexts in Chrome, Firefox, and Safari. * `article` contexts in Chrome, Firefox, and Safari.
@ -49,22 +35,6 @@ h1 {
} }
/* Grouping content /* Grouping content
========================================================================== */ ========================================================================== */
/**
* Add the correct display in IE 9-.
* 1. Add the correct display in IE.
*/
figcaption,
figure,
main {
/* 1 */
display: block;
}
/**
* Add the correct margin in IE 8.
*/
figure {
margin: 1em 40px;
}
/** /**
* 1. Add the correct box sizing in Firefox. * 1. Add the correct box sizing in Firefox.
* 2. Show the overflow in Edge and IE. * 2. Show the overflow in Edge and IE.
@ -90,17 +60,13 @@ pre {
/* Text-level semantics /* Text-level semantics
========================================================================== */ ========================================================================== */
/** /**
* 1. Remove the gray background on active links in IE 10. * Remove the gray background on active links in IE 10.
* 2. Remove gaps in links underline in iOS 8+ and Safari 8+.
*/ */
a { a {
background-color: transparent; background-color: transparent;
/* 1 */
-webkit-text-decoration-skip: objects;
/* 2 */
} }
/** /**
* 1. Remove the bottom border in Chrome 57- and Firefox 39-. * 1. Remove the bottom border in Chrome 57-
* 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari. * 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari.
*/ */
abbr[title] { abbr[title] {
@ -111,13 +77,6 @@ abbr[title] {
text-decoration: underline dotted; text-decoration: underline dotted;
/* 2 */ /* 2 */
} }
/**
* Prevent the duplicate application of `bolder` by the next rule in Safari 6.
*/
b,
strong {
font-weight: inherit;
}
/** /**
* Add the correct font weight in Chrome, Edge, and Safari. * Add the correct font weight in Chrome, Edge, and Safari.
*/ */
@ -137,19 +96,6 @@ samp {
font-size: 1em; font-size: 1em;
/* 2 */ /* 2 */
} }
/**
* Add the correct font style in Android 4.3-.
*/
dfn {
font-style: italic;
}
/**
* Add the correct background and color in IE 9-.
*/
mark {
background-color: #ff0;
color: #000;
}
/** /**
* Add the correct font size in all browsers. * Add the correct font size in all browsers.
*/ */
@ -176,35 +122,15 @@ sup {
/* Embedded content /* Embedded content
========================================================================== */ ========================================================================== */
/** /**
* Add the correct display in IE 9-. * Remove the border on images inside links in IE 10.
*/
audio,
video {
display: inline-block;
}
/**
* Add the correct display in iOS 4-7.
*/
audio:not([controls]) {
display: none;
height: 0;
}
/**
* Remove the border on images inside links in IE 10-.
*/ */
img { img {
border-style: none; border-style: none;
} }
/**
* Hide the overflow in IE.
*/
svg:not(:root) {
overflow: hidden;
}
/* Forms /* Forms
========================================================================== */ ========================================================================== */
/** /**
* 1. Change the font styles in all browsers (opinionated). * 1. Change the font styles in all browsers.
* 2. Remove the margin in Firefox and Safari. * 2. Remove the margin in Firefox and Safari.
*/ */
button, button,
@ -212,7 +138,7 @@ input,
optgroup, optgroup,
select, select,
textarea { textarea {
font-family: sans-serif; font-family: inherit;
/* 1 */ /* 1 */
font-size: 100%; font-size: 100%;
/* 1 */ /* 1 */
@ -240,16 +166,13 @@ select {
text-transform: none; text-transform: none;
} }
/** /**
* 1. Prevent a WebKit bug where (2) destroys native `audio` and `video` * Correct the inability to style clickable types in iOS and Safari.
* controls in Android 4.
* 2. Correct the inability to style clickable types in iOS and Safari.
*/ */
button, button,
html [type="button"], [type="button"],
[type="reset"], [type="reset"],
[type="submit"] { [type="submit"] {
-webkit-appearance: button; -webkit-appearance: button;
/* 2 */
} }
/** /**
* Remove the inner border and padding in Firefox. * Remove the inner border and padding in Firefox.
@ -297,24 +220,20 @@ legend {
/* 1 */ /* 1 */
} }
/** /**
* 1. Add the correct display in IE 9-. * Add the correct vertical alignment in Chrome, Firefox, and Opera.
* 2. Add the correct vertical alignment in Chrome, Firefox, and Opera.
*/ */
progress { progress {
display: inline-block;
/* 1 */
vertical-align: baseline; vertical-align: baseline;
/* 2 */
} }
/** /**
* Remove the default vertical scrollbar in IE. * Remove the default vertical scrollbar in IE 10+.
*/ */
textarea { textarea {
overflow: auto; overflow: auto;
} }
/** /**
* 1. Add the correct box sizing in IE 10-. * 1. Add the correct box sizing in IE 10.
* 2. Remove the padding in IE 10-. * 2. Remove the padding in IE 10.
*/ */
[type="checkbox"], [type="checkbox"],
[type="radio"] { [type="radio"] {
@ -341,9 +260,8 @@ textarea {
/* 2 */ /* 2 */
} }
/** /**
* Remove the inner padding and cancel buttons in Chrome and Safari on macOS. * Remove the inner padding in Chrome and Safari on macOS.
*/ */
[type="search"]::-webkit-search-cancel-button,
[type="search"]::-webkit-search-decoration { [type="search"]::-webkit-search-decoration {
-webkit-appearance: none; -webkit-appearance: none;
} }
@ -360,11 +278,9 @@ textarea {
/* Interactive /* Interactive
========================================================================== */ ========================================================================== */
/* /*
* Add the correct display in IE 9-. * Add the correct display in Edge, IE 10+, and Firefox.
* 1. Add the correct display in Edge, IE, and Firefox.
*/ */
details, details {
menu {
display: block; display: block;
} }
/* /*
@ -373,24 +289,16 @@ menu {
summary { summary {
display: list-item; display: list-item;
} }
/* Scripting /* Misc
========================================================================== */ ========================================================================== */
/** /**
* Add the correct display in IE 9-. * Add the correct display in IE 10+.
*/
canvas {
display: inline-block;
}
/**
* Add the correct display in IE.
*/ */
template { template {
display: none; display: none;
} }
/* Hidden
========================================================================== */
/** /**
* Add the correct display in IE 10-. * Add the correct display in IE 10.
*/ */
[hidden] { [hidden] {
display: none; display: none;
@ -706,7 +614,14 @@ html.js .show_if_nojs {
float: left; float: left;
} }
.invisible { .invisible {
display: none; display: none !important;
}
.list-unstyled {
list-style-type: none;
}
.list-unstyled li {
margin-top: 4px;
margin-bottom: 4px;
} }
.danger { .danger {
background-color: #fae1e1; background-color: #fae1e1;
@ -722,6 +637,13 @@ html.js .show_if_nojs {
padding: 1px 5px; padding: 1px 5px;
border-radius: 5px; border-radius: 5px;
} }
kbd {
padding: 2px 4px;
margin: 1px;
font-size: 90%;
color: white;
background: black;
}
table { table {
width: 100%; width: 100%;
} }
@ -737,6 +659,27 @@ td {
tr:hover { tr:hover {
background: #ececec; background: #ececec;
} }
div.selectable_url {
border: 1px solid #888;
padding: 4px;
color: #444;
width: 100%;
display: block;
margin: 0.1em;
overflow: hidden;
height: 1.2em;
line-height: 1.2em;
}
div.selectable_url pre {
display: block;
font-size: 0.8em;
word-break: break-all;
margin: 0.1em;
-webkit-user-select: all;
-moz-user-select: all;
-ms-user-select: element;
user-select: all;
}
.dialog-error { .dialog-error {
position: relative; position: relative;
width: 70%; width: 70%;
@ -768,6 +711,22 @@ tr:hover {
.dialog-error p { .dialog-error p {
margin: 1px 0 0 0; margin: 1px 0 0 0;
} }
.dialog-error table {
width: auto;
}
.dialog-error tr {
vertical-align: text-top;
}
.dialog-error tr:hover {
background: transparent;
}
.dialog-error td {
padding: 0 1em 0 0;
}
.dialog-error h4 {
margin-top: 0.3em;
margin-bottom: 0.3em;
}
.dialog-error:before { .dialog-error:before {
content: "\f110"; content: "\f110";
} }
@ -802,9 +761,78 @@ tr:hover {
.dialog-warning p { .dialog-warning p {
margin: 1px 0 0 0; margin: 1px 0 0 0;
} }
.dialog-warning table {
width: auto;
}
.dialog-warning tr {
vertical-align: text-top;
}
.dialog-warning tr:hover {
background: transparent;
}
.dialog-warning td {
padding: 0 1em 0 0;
}
.dialog-warning h4 {
margin-top: 0.3em;
margin-bottom: 0.3em;
}
.dialog-warning:before { .dialog-warning:before {
content: "\f10f"; content: "\f10f";
} }
.dialog-modal {
position: relative;
width: 70%;
padding: 1em 1em 1em 2.7em;
margin: 0em 8% 1em 8%;
border: 1px solid black;
border-radius: 4px;
text-align: left;
background: white;
position: fixed;
top: 50%;
left: 50%;
/* bring your own prefixes */
transform: translate(-50%, -50%);
z-index: 100000;
margin: 0 50% 0 0;
box-shadow: 0 0 1em;
}
.dialog-modal:before {
position: absolute;
top: 0.5em;
left: 0.5em;
font-family: "ion";
font-size: 1.5em;
}
.dialog-modal .close {
float: right;
position: relative;
top: -3px;
color: inherit;
font-size: 1.5em;
}
.dialog-modal ul,
.dialog-modal ol,
.dialog-modal p {
margin: 1px 0 0 0;
}
.dialog-modal table {
width: auto;
}
.dialog-modal tr {
vertical-align: text-top;
}
.dialog-modal tr:hover {
background: transparent;
}
.dialog-modal td {
padding: 0 1em 0 0;
}
.dialog-modal h4 {
margin-top: 0.3em;
margin-bottom: 0.3em;
}
.btn-collapse { .btn-collapse {
cursor: pointer; cursor: pointer;
} }
@ -816,6 +844,7 @@ tr:hover {
margin: 0; margin: 0;
border: none; border: none;
} }
/* -- tabs --*/
.tabs .tabs > label { .tabs .tabs > label {
font-size: 90%; font-size: 90%;
} }
@ -894,6 +923,7 @@ html body .tabs > input:checked + label {
html body .tabs > input:checked + label + section { html body .tabs > input:checked + label + section {
display: block; display: block;
} }
/* -- select -- */
select { select {
height: 28px; height: 28px;
margin: 0 1em 0 0; margin: 0 1em 0 0;
@ -924,6 +954,7 @@ select:focus {
border-bottom: 1px solid #3498DB; border-bottom: 1px solid #3498DB;
} }
} }
/* -- checkbox-onoff -- */
@supports (border-radius: 50px) { @supports (border-radius: 50px) {
.checkbox-onoff { .checkbox-onoff {
display: inline-block; display: inline-block;
@ -955,6 +986,7 @@ select:focus {
background: #dcdcdc; background: #dcdcdc;
} }
} }
/* -- checkbox --*/
@supports (transform: rotate(-45deg)) { @supports (transform: rotate(-45deg)) {
.checkbox { .checkbox {
width: 20px; width: 20px;
@ -1007,6 +1039,48 @@ select:focus {
width: 100%; width: 100%;
} }
} }
/* -- loader -- */
.loader,
.loader:after {
border-radius: 50%;
width: 2em;
height: 2em;
}
.loader {
margin: 1em auto;
font-size: 10px;
position: relative;
text-indent: -9999em;
border-top: 0.5em solid rgba(0, 0, 0, 0.2);
border-right: 0.5em solid rgba(0, 0, 0, 0.2);
border-bottom: 0.5em solid rgba(0, 0, 0, 0.2);
border-left: 0.5em solid rgba(255, 255, 255, 0);
-webkit-transform: translateZ(0);
-ms-transform: translateZ(0);
transform: translateZ(0);
-webkit-animation: load8 1.2s infinite linear;
animation: load8 1.2s infinite linear;
}
@-webkit-keyframes load8 {
0% {
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
}
100% {
-webkit-transform: rotate(360deg);
transform: rotate(360deg);
}
}
@keyframes load8 {
0% {
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
}
100% {
-webkit-transform: rotate(360deg);
transform: rotate(360deg);
}
}
/*! Autocomplete.js v2.6.3 | license MIT | (c) 2017, Baptiste Donaux | http://autocomplete-js.com */ /*! Autocomplete.js v2.6.3 | license MIT | (c) 2017, Baptiste Donaux | http://autocomplete-js.com */
.autocomplete { .autocomplete {
position: absolute; position: absolute;
@ -1073,8 +1147,8 @@ select:focus {
} }
@font-face { @font-face {
font-family: "ion"; font-family: "ion";
src: url("../fonts/ion.eot?94af7082ea096aefe3a7b6642834716e"); src: url("../fonts/ion.eot?ce7a0ead692560b4405a96d5b8471f51");
src: url("../fonts/ion.eot?#iefix") format("embedded-opentype"), url("../fonts/ion.woff2?94af7082ea096aefe3a7b6642834716e") format("woff2"), url("../fonts/ion.woff?94af7082ea096aefe3a7b6642834716e") format("woff"), url("../fonts/ion.ttf?94af7082ea096aefe3a7b6642834716e") format("truetype"), url("../fonts/ion.svg?94af7082ea096aefe3a7b6642834716e#ion") format("svg"); src: url("../fonts/ion.eot?#iefix") format("embedded-opentype"), url("../fonts/ion.woff2?ce7a0ead692560b4405a96d5b8471f51") format("woff2"), url("../fonts/ion.woff?ce7a0ead692560b4405a96d5b8471f51") format("woff"), url("../fonts/ion.ttf?ce7a0ead692560b4405a96d5b8471f51") format("truetype"), url("../fonts/ion.svg?ce7a0ead692560b4405a96d5b8471f51#ion") format("svg");
font-weight: normal; font-weight: normal;
font-style: normal; font-style: normal;
} }
@ -1154,6 +1228,9 @@ select:focus {
.ion-magnet:before { .ion-magnet:before {
content: "\f114"; content: "\f114";
} }
.ion-close:before {
content: "\f115";
}
.ion-icon-big { .ion-icon-big {
display: inline-block; display: inline-block;
vertical-align: middle; vertical-align: middle;
@ -1240,6 +1317,22 @@ select:focus {
#main_preferences table td { #main_preferences table td {
text-align: center; text-align: center;
} }
#main_preferences table.cookies {
width: auto;
}
#main_preferences table.cookies th,
#main_preferences table.cookies td {
text-align: left;
padding: 0.25em;
}
#main_preferences table.cookies th:first-child,
#main_preferences table.cookies td:first-child {
padding-right: 4em;
}
#main_preferences table.cookies > tbody > tr:nth-child(even) > th,
#main_preferences table.cookies > tbody > tr:nth-child(even) > td {
background-color: #ececec;
}
#main_preferences .name, #main_preferences .name,
#main_preferences .shortcut { #main_preferences .shortcut {
text-align: left; text-align: left;
@ -1263,6 +1356,9 @@ select:focus {
#main_preferences .preferences_back a::first-letter { #main_preferences .preferences_back a::first-letter {
text-transform: uppercase; text-transform: uppercase;
} }
#main_preferences div.selectable_url pre {
width: 100%;
}
@media screen and (max-width: 75em) { @media screen and (max-width: 75em) {
.preferences_back { .preferences_back {
clear: both; clear: both;
@ -1291,12 +1387,40 @@ select:focus {
} }
*/ */
} }
#clear_search {
display: block;
border-collapse: separate;
box-sizing: border-box;
width: 1.8em;
margin: 0;
padding: 2px;
height: 2.2em;
background: none repeat scroll 0 0 #FFF;
border-top: 1px solid #3498DB;
border-bottom: 1px solid #3498DB;
border-right: none;
border-left: none;
border-radius: 0px;
outline: none;
color: #222;
font-size: 16px;
z-index: 10000;
}
#clear_search:hover {
color: #3498DB;
}
#clear_search.empty * {
display: none;
}
#q::-ms-clear,
#q::-webkit-search-cancel-button {
display: none;
}
#q, #q,
#send_search { #send_search {
display: block !important; display: block !important;
border-collapse: separate; border-collapse: separate;
box-sizing: border-box; box-sizing: border-box;
position: relative;
margin: 0; margin: 0;
padding: 2px; padding: 2px;
height: 2.2em; height: 2.2em;
@ -1857,27 +1981,8 @@ article.result-images[data-vim-selected]::before {
#search_url { #search_url {
margin-top: 8px; margin-top: 8px;
} }
#search_url div { #search_url div.selectable_url pre {
border: 1px solid #888;
padding: 4px;
color: #444;
width: 100%;
display: block;
margin: 0.1em;
overflow: hidden;
height: 1.2em;
line-height: 1.2em;
}
#search_url div pre {
display: block;
width: 200em; width: 200em;
font-size: 0.8em;
word-break: break-all;
margin: 0.1em;
-webkit-user-select: all;
-moz-user-select: all;
-ms-user-select: all;
user-select: all;
} }
#linkto_preferences { #linkto_preferences {
position: absolute; position: absolute;
@ -2001,6 +2106,28 @@ article.result-images[data-vim-selected]::before {
max-width: 98%; max-width: 98%;
} }
} }
#main_results div#results.only_template_images {
flex-direction: column;
width: auto;
display: flex;
}
#main_results div#results.only_template_images #sidebar {
position: relative;
top: auto;
order: 2;
}
#main_results div#results.only_template_images #urls {
position: relative;
order: 1;
}
#main_results div#results.only_template_images #backToTop {
right: 0.5em;
left: auto;
}
#main_results div#results.only_template_images #pagination {
position: relative;
order: 3;
}
@media screen and (max-width: 50em) { @media screen and (max-width: 50em) {
article[data-vim-selected]::before { article[data-vim-selected]::before {
display: none; display: none;

Binary file not shown.

View File

@ -1,44 +1,30 @@
/*! searx | 03-12-2017 | https://github.com/asciimoo/searx */ /*! searx | 14-08-2018 | https://github.com/asciimoo/searx */
/* /*
* searx, A privacy-respecting, hackable metasearch engine * searx, A privacy-respecting, hackable metasearch engine
* *
* To convert "style.less" to "style.css" run: $make styles * To convert "style.less" to "style.css" run: $make styles
*/ */
/*! normalize.css v7.0.0 | MIT License | github.com/necolas/normalize.css */ /*! normalize.css v8.0.0 | MIT License | github.com/necolas/normalize.css */
/* Document /* Document
========================================================================== */ ========================================================================== */
/** /**
* 1. Correct the line height in all browsers. * 1. Correct the line height in all browsers.
* 2. Prevent adjustments of font size after orientation changes in * 2. Prevent adjustments of font size after orientation changes in iOS.
* IE on Windows Phone and in iOS.
*/ */
html { html {
line-height: 1.15; line-height: 1.15;
/* 1 */ /* 1 */
-ms-text-size-adjust: 100%;
/* 2 */
-webkit-text-size-adjust: 100%; -webkit-text-size-adjust: 100%;
/* 2 */ /* 2 */
} }
/* Sections /* Sections
========================================================================== */ ========================================================================== */
/** /**
* Remove the margin in all browsers (opinionated). * Remove the margin in all browsers.
*/ */
body { body {
margin: 0; margin: 0;
} }
/**
* Add the correct display in IE 9-.
*/
article,
aside,
footer,
header,
nav,
section {
display: block;
}
/** /**
* Correct the font size and margin on `h1` elements within `section` and * Correct the font size and margin on `h1` elements within `section` and
* `article` contexts in Chrome, Firefox, and Safari. * `article` contexts in Chrome, Firefox, and Safari.
@ -49,22 +35,6 @@ h1 {
} }
/* Grouping content /* Grouping content
========================================================================== */ ========================================================================== */
/**
* Add the correct display in IE 9-.
* 1. Add the correct display in IE.
*/
figcaption,
figure,
main {
/* 1 */
display: block;
}
/**
* Add the correct margin in IE 8.
*/
figure {
margin: 1em 40px;
}
/** /**
* 1. Add the correct box sizing in Firefox. * 1. Add the correct box sizing in Firefox.
* 2. Show the overflow in Edge and IE. * 2. Show the overflow in Edge and IE.
@ -90,17 +60,13 @@ pre {
/* Text-level semantics /* Text-level semantics
========================================================================== */ ========================================================================== */
/** /**
* 1. Remove the gray background on active links in IE 10. * Remove the gray background on active links in IE 10.
* 2. Remove gaps in links underline in iOS 8+ and Safari 8+.
*/ */
a { a {
background-color: transparent; background-color: transparent;
/* 1 */
-webkit-text-decoration-skip: objects;
/* 2 */
} }
/** /**
* 1. Remove the bottom border in Chrome 57- and Firefox 39-. * 1. Remove the bottom border in Chrome 57-
* 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari. * 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari.
*/ */
abbr[title] { abbr[title] {
@ -111,13 +77,6 @@ abbr[title] {
text-decoration: underline dotted; text-decoration: underline dotted;
/* 2 */ /* 2 */
} }
/**
* Prevent the duplicate application of `bolder` by the next rule in Safari 6.
*/
b,
strong {
font-weight: inherit;
}
/** /**
* Add the correct font weight in Chrome, Edge, and Safari. * Add the correct font weight in Chrome, Edge, and Safari.
*/ */
@ -137,19 +96,6 @@ samp {
font-size: 1em; font-size: 1em;
/* 2 */ /* 2 */
} }
/**
* Add the correct font style in Android 4.3-.
*/
dfn {
font-style: italic;
}
/**
* Add the correct background and color in IE 9-.
*/
mark {
background-color: #ff0;
color: #000;
}
/** /**
* Add the correct font size in all browsers. * Add the correct font size in all browsers.
*/ */
@ -176,35 +122,15 @@ sup {
/* Embedded content /* Embedded content
========================================================================== */ ========================================================================== */
/** /**
* Add the correct display in IE 9-. * Remove the border on images inside links in IE 10.
*/
audio,
video {
display: inline-block;
}
/**
* Add the correct display in iOS 4-7.
*/
audio:not([controls]) {
display: none;
height: 0;
}
/**
* Remove the border on images inside links in IE 10-.
*/ */
img { img {
border-style: none; border-style: none;
} }
/**
* Hide the overflow in IE.
*/
svg:not(:root) {
overflow: hidden;
}
/* Forms /* Forms
========================================================================== */ ========================================================================== */
/** /**
* 1. Change the font styles in all browsers (opinionated). * 1. Change the font styles in all browsers.
* 2. Remove the margin in Firefox and Safari. * 2. Remove the margin in Firefox and Safari.
*/ */
button, button,
@ -212,7 +138,7 @@ input,
optgroup, optgroup,
select, select,
textarea { textarea {
font-family: sans-serif; font-family: inherit;
/* 1 */ /* 1 */
font-size: 100%; font-size: 100%;
/* 1 */ /* 1 */
@ -240,16 +166,13 @@ select {
text-transform: none; text-transform: none;
} }
/** /**
* 1. Prevent a WebKit bug where (2) destroys native `audio` and `video` * Correct the inability to style clickable types in iOS and Safari.
* controls in Android 4.
* 2. Correct the inability to style clickable types in iOS and Safari.
*/ */
button, button,
html [type="button"], [type="button"],
[type="reset"], [type="reset"],
[type="submit"] { [type="submit"] {
-webkit-appearance: button; -webkit-appearance: button;
/* 2 */
} }
/** /**
* Remove the inner border and padding in Firefox. * Remove the inner border and padding in Firefox.
@ -297,24 +220,20 @@ legend {
/* 1 */ /* 1 */
} }
/** /**
* 1. Add the correct display in IE 9-. * Add the correct vertical alignment in Chrome, Firefox, and Opera.
* 2. Add the correct vertical alignment in Chrome, Firefox, and Opera.
*/ */
progress { progress {
display: inline-block;
/* 1 */
vertical-align: baseline; vertical-align: baseline;
/* 2 */
} }
/** /**
* Remove the default vertical scrollbar in IE. * Remove the default vertical scrollbar in IE 10+.
*/ */
textarea { textarea {
overflow: auto; overflow: auto;
} }
/** /**
* 1. Add the correct box sizing in IE 10-. * 1. Add the correct box sizing in IE 10.
* 2. Remove the padding in IE 10-. * 2. Remove the padding in IE 10.
*/ */
[type="checkbox"], [type="checkbox"],
[type="radio"] { [type="radio"] {
@ -341,9 +260,8 @@ textarea {
/* 2 */ /* 2 */
} }
/** /**
* Remove the inner padding and cancel buttons in Chrome and Safari on macOS. * Remove the inner padding in Chrome and Safari on macOS.
*/ */
[type="search"]::-webkit-search-cancel-button,
[type="search"]::-webkit-search-decoration { [type="search"]::-webkit-search-decoration {
-webkit-appearance: none; -webkit-appearance: none;
} }
@ -360,11 +278,9 @@ textarea {
/* Interactive /* Interactive
========================================================================== */ ========================================================================== */
/* /*
* Add the correct display in IE 9-. * Add the correct display in Edge, IE 10+, and Firefox.
* 1. Add the correct display in Edge, IE, and Firefox.
*/ */
details, details {
menu {
display: block; display: block;
} }
/* /*
@ -373,24 +289,16 @@ menu {
summary { summary {
display: list-item; display: list-item;
} }
/* Scripting /* Misc
========================================================================== */ ========================================================================== */
/** /**
* Add the correct display in IE 9-. * Add the correct display in IE 10+.
*/
canvas {
display: inline-block;
}
/**
* Add the correct display in IE.
*/ */
template { template {
display: none; display: none;
} }
/* Hidden
========================================================================== */
/** /**
* Add the correct display in IE 10-. * Add the correct display in IE 10.
*/ */
[hidden] { [hidden] {
display: none; display: none;
@ -706,7 +614,14 @@ html.js .show_if_nojs {
float: left; float: left;
} }
.invisible { .invisible {
display: none; display: none !important;
}
.list-unstyled {
list-style-type: none;
}
.list-unstyled li {
margin-top: 4px;
margin-bottom: 4px;
} }
.danger { .danger {
background-color: #fae1e1; background-color: #fae1e1;
@ -722,6 +637,13 @@ html.js .show_if_nojs {
padding: 1px 5px; padding: 1px 5px;
border-radius: 5px; border-radius: 5px;
} }
kbd {
padding: 2px 4px;
margin: 1px;
font-size: 90%;
color: white;
background: black;
}
table { table {
width: 100%; width: 100%;
} }
@ -737,6 +659,27 @@ td {
tr:hover { tr:hover {
background: #ececec; background: #ececec;
} }
div.selectable_url {
border: 1px solid #888;
padding: 4px;
color: #444;
width: 100%;
display: block;
margin: 0.1em;
overflow: hidden;
height: 1.2em;
line-height: 1.2em;
}
div.selectable_url pre {
display: block;
font-size: 0.8em;
word-break: break-all;
margin: 0.1em;
-webkit-user-select: all;
-moz-user-select: all;
-ms-user-select: element;
user-select: all;
}
.dialog-error { .dialog-error {
position: relative; position: relative;
width: 70%; width: 70%;
@ -768,6 +711,22 @@ tr:hover {
.dialog-error p { .dialog-error p {
margin: 1px 0 0 0; margin: 1px 0 0 0;
} }
.dialog-error table {
width: auto;
}
.dialog-error tr {
vertical-align: text-top;
}
.dialog-error tr:hover {
background: transparent;
}
.dialog-error td {
padding: 0 1em 0 0;
}
.dialog-error h4 {
margin-top: 0.3em;
margin-bottom: 0.3em;
}
.dialog-error:before { .dialog-error:before {
content: "\f110"; content: "\f110";
} }
@ -802,9 +761,78 @@ tr:hover {
.dialog-warning p { .dialog-warning p {
margin: 1px 0 0 0; margin: 1px 0 0 0;
} }
.dialog-warning table {
width: auto;
}
.dialog-warning tr {
vertical-align: text-top;
}
.dialog-warning tr:hover {
background: transparent;
}
.dialog-warning td {
padding: 0 1em 0 0;
}
.dialog-warning h4 {
margin-top: 0.3em;
margin-bottom: 0.3em;
}
.dialog-warning:before { .dialog-warning:before {
content: "\f10f"; content: "\f10f";
} }
.dialog-modal {
position: relative;
width: 70%;
padding: 1em 1em 1em 2.7em;
margin: 0em 8% 1em 8%;
border: 1px solid black;
border-radius: 4px;
text-align: left;
background: white;
position: fixed;
top: 50%;
left: 50%;
/* bring your own prefixes */
transform: translate(-50%, -50%);
z-index: 100000;
margin: 0 50% 0 0;
box-shadow: 0 0 1em;
}
.dialog-modal:before {
position: absolute;
top: 0.5em;
left: 0.5em;
font-family: "ion";
font-size: 1.5em;
}
.dialog-modal .close {
float: right;
position: relative;
top: -3px;
color: inherit;
font-size: 1.5em;
}
.dialog-modal ul,
.dialog-modal ol,
.dialog-modal p {
margin: 1px 0 0 0;
}
.dialog-modal table {
width: auto;
}
.dialog-modal tr {
vertical-align: text-top;
}
.dialog-modal tr:hover {
background: transparent;
}
.dialog-modal td {
padding: 0 1em 0 0;
}
.dialog-modal h4 {
margin-top: 0.3em;
margin-bottom: 0.3em;
}
.btn-collapse { .btn-collapse {
cursor: pointer; cursor: pointer;
} }
@ -816,6 +844,7 @@ tr:hover {
margin: 0; margin: 0;
border: none; border: none;
} }
/* -- tabs --*/
.tabs .tabs > label { .tabs .tabs > label {
font-size: 90%; font-size: 90%;
} }
@ -894,6 +923,7 @@ html body .tabs > input:checked + label {
html body .tabs > input:checked + label + section { html body .tabs > input:checked + label + section {
display: block; display: block;
} }
/* -- select -- */
select { select {
height: 28px; height: 28px;
margin: 0 1em 0 0; margin: 0 1em 0 0;
@ -924,6 +954,7 @@ select:focus {
border-bottom: 1px solid #3498DB; border-bottom: 1px solid #3498DB;
} }
} }
/* -- checkbox-onoff -- */
@supports (border-radius: 50px) { @supports (border-radius: 50px) {
.checkbox-onoff { .checkbox-onoff {
display: inline-block; display: inline-block;
@ -955,6 +986,7 @@ select:focus {
background: #dcdcdc; background: #dcdcdc;
} }
} }
/* -- checkbox --*/
@supports (transform: rotate(-45deg)) { @supports (transform: rotate(-45deg)) {
.checkbox { .checkbox {
width: 20px; width: 20px;
@ -1007,6 +1039,48 @@ select:focus {
width: 100%; width: 100%;
} }
} }
/* -- loader -- */
.loader,
.loader:after {
border-radius: 50%;
width: 2em;
height: 2em;
}
.loader {
margin: 1em auto;
font-size: 10px;
position: relative;
text-indent: -9999em;
border-top: 0.5em solid rgba(0, 0, 0, 0.2);
border-right: 0.5em solid rgba(0, 0, 0, 0.2);
border-bottom: 0.5em solid rgba(0, 0, 0, 0.2);
border-left: 0.5em solid rgba(255, 255, 255, 0);
-webkit-transform: translateZ(0);
-ms-transform: translateZ(0);
transform: translateZ(0);
-webkit-animation: load8 1.2s infinite linear;
animation: load8 1.2s infinite linear;
}
@-webkit-keyframes load8 {
0% {
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
}
100% {
-webkit-transform: rotate(360deg);
transform: rotate(360deg);
}
}
@keyframes load8 {
0% {
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
}
100% {
-webkit-transform: rotate(360deg);
transform: rotate(360deg);
}
}
/*! Autocomplete.js v2.6.3 | license MIT | (c) 2017, Baptiste Donaux | http://autocomplete-js.com */ /*! Autocomplete.js v2.6.3 | license MIT | (c) 2017, Baptiste Donaux | http://autocomplete-js.com */
.autocomplete { .autocomplete {
position: absolute; position: absolute;
@ -1073,8 +1147,8 @@ select:focus {
} }
@font-face { @font-face {
font-family: "ion"; font-family: "ion";
src: url("../fonts/ion.eot?94af7082ea096aefe3a7b6642834716e"); src: url("../fonts/ion.eot?ce7a0ead692560b4405a96d5b8471f51");
src: url("../fonts/ion.eot?#iefix") format("embedded-opentype"), url("../fonts/ion.woff2?94af7082ea096aefe3a7b6642834716e") format("woff2"), url("../fonts/ion.woff?94af7082ea096aefe3a7b6642834716e") format("woff"), url("../fonts/ion.ttf?94af7082ea096aefe3a7b6642834716e") format("truetype"), url("../fonts/ion.svg?94af7082ea096aefe3a7b6642834716e#ion") format("svg"); src: url("../fonts/ion.eot?#iefix") format("embedded-opentype"), url("../fonts/ion.woff2?ce7a0ead692560b4405a96d5b8471f51") format("woff2"), url("../fonts/ion.woff?ce7a0ead692560b4405a96d5b8471f51") format("woff"), url("../fonts/ion.ttf?ce7a0ead692560b4405a96d5b8471f51") format("truetype"), url("../fonts/ion.svg?ce7a0ead692560b4405a96d5b8471f51#ion") format("svg");
font-weight: normal; font-weight: normal;
font-style: normal; font-style: normal;
} }
@ -1154,6 +1228,9 @@ select:focus {
.ion-magnet:before { .ion-magnet:before {
content: "\f114"; content: "\f114";
} }
.ion-close:before {
content: "\f115";
}
.ion-icon-big { .ion-icon-big {
display: inline-block; display: inline-block;
vertical-align: middle; vertical-align: middle;
@ -1240,6 +1317,22 @@ select:focus {
#main_preferences table td { #main_preferences table td {
text-align: center; text-align: center;
} }
#main_preferences table.cookies {
width: auto;
}
#main_preferences table.cookies th,
#main_preferences table.cookies td {
text-align: left;
padding: 0.25em;
}
#main_preferences table.cookies th:first-child,
#main_preferences table.cookies td:first-child {
padding-right: 4em;
}
#main_preferences table.cookies > tbody > tr:nth-child(even) > th,
#main_preferences table.cookies > tbody > tr:nth-child(even) > td {
background-color: #ececec;
}
#main_preferences .name, #main_preferences .name,
#main_preferences .shortcut { #main_preferences .shortcut {
text-align: left; text-align: left;
@ -1263,6 +1356,9 @@ select:focus {
#main_preferences .preferences_back a::first-letter { #main_preferences .preferences_back a::first-letter {
text-transform: uppercase; text-transform: uppercase;
} }
#main_preferences div.selectable_url pre {
width: 100%;
}
@media screen and (max-width: 75em) { @media screen and (max-width: 75em) {
.preferences_back { .preferences_back {
clear: both; clear: both;
@ -1291,12 +1387,40 @@ select:focus {
} }
*/ */
} }
#clear_search {
display: block;
border-collapse: separate;
box-sizing: border-box;
width: 1.8em;
margin: 0;
padding: 2px;
height: 2.2em;
background: none repeat scroll 0 0 #FFF;
border-top: 1px solid #3498DB;
border-bottom: 1px solid #3498DB;
border-right: none;
border-left: none;
border-radius: 0px;
outline: none;
color: #222;
font-size: 16px;
z-index: 10000;
}
#clear_search:hover {
color: #3498DB;
}
#clear_search.empty * {
display: none;
}
#q::-ms-clear,
#q::-webkit-search-cancel-button {
display: none;
}
#q, #q,
#send_search { #send_search {
display: block !important; display: block !important;
border-collapse: separate; border-collapse: separate;
box-sizing: border-box; box-sizing: border-box;
position: relative;
margin: 0; margin: 0;
padding: 2px; padding: 2px;
height: 2.2em; height: 2.2em;
@ -1857,27 +1981,8 @@ article.result-images[data-vim-selected]::before {
#search_url { #search_url {
margin-top: 8px; margin-top: 8px;
} }
#search_url div { #search_url div.selectable_url pre {
border: 1px solid #888;
padding: 4px;
color: #444;
width: 100%;
display: block;
margin: 0.1em;
overflow: hidden;
height: 1.2em;
line-height: 1.2em;
}
#search_url div pre {
display: block;
width: 200em; width: 200em;
font-size: 0.8em;
word-break: break-all;
margin: 0.1em;
-webkit-user-select: all;
-moz-user-select: all;
-ms-user-select: all;
user-select: all;
} }
#linkto_preferences { #linkto_preferences {
position: absolute; position: absolute;
@ -2001,6 +2106,28 @@ article.result-images[data-vim-selected]::before {
max-width: 98%; max-width: 98%;
} }
} }
#main_results div#results.only_template_images {
flex-direction: column;
width: auto;
display: flex;
}
#main_results div#results.only_template_images #sidebar {
position: relative;
top: auto;
order: 2;
}
#main_results div#results.only_template_images #urls {
position: relative;
order: 1;
}
#main_results div#results.only_template_images #backToTop {
right: 0.5em;
left: auto;
}
#main_results div#results.only_template_images #pagination {
position: relative;
order: 3;
}
@media screen and (max-width: 50em) { @media screen and (max-width: 50em) {
article[data-vim-selected]::before { article[data-vim-selected]::before {
display: none; display: none;

Binary file not shown.

View File

@ -3,12 +3,12 @@
@font-face { @font-face {
font-family:"ion"; font-family:"ion";
src:url("../fonts/ion.eot?492c5e946f5ae6f02467d64ca0f55cd1"); src:url("../fonts/ion.eot?ce7a0ead692560b4405a96d5b8471f51");
src:url("../fonts/ion.eot?#iefix") format("embedded-opentype"), src:url("../fonts/ion.eot?#iefix") format("embedded-opentype"),
url("../fonts/ion.woff2?492c5e946f5ae6f02467d64ca0f55cd1") format("woff2"), url("../fonts/ion.woff2?ce7a0ead692560b4405a96d5b8471f51") format("woff2"),
url("../fonts/ion.woff?492c5e946f5ae6f02467d64ca0f55cd1") format("woff"), url("../fonts/ion.woff?ce7a0ead692560b4405a96d5b8471f51") format("woff"),
url("../fonts/ion.ttf?492c5e946f5ae6f02467d64ca0f55cd1") format("truetype"), url("../fonts/ion.ttf?ce7a0ead692560b4405a96d5b8471f51") format("truetype"),
url("../fonts/ion.svg?492c5e946f5ae6f02467d64ca0f55cd1#ion") format("svg"); url("../fonts/ion.svg?ce7a0ead692560b4405a96d5b8471f51#ion") format("svg");
font-weight:normal; font-weight:normal;
font-style:normal; font-style:normal;
} }
@ -132,3 +132,8 @@
.ion-magnet:before { .ion-magnet:before {
content:"\f114"; content:"\f114";
} }
.ion-close:before {
content:"\f115";
}

View File

@ -60,12 +60,12 @@
@font-face { @font-face {
font-family:"ion"; font-family:"ion";
src:url("ion.eot?492c5e946f5ae6f02467d64ca0f55cd1"); src:url("ion.eot?ce7a0ead692560b4405a96d5b8471f51");
src:url("ion.eot?#iefix") format("embedded-opentype"), src:url("ion.eot?#iefix") format("embedded-opentype"),
url("ion.woff2?492c5e946f5ae6f02467d64ca0f55cd1") format("woff2"), url("ion.woff2?ce7a0ead692560b4405a96d5b8471f51") format("woff2"),
url("ion.woff?492c5e946f5ae6f02467d64ca0f55cd1") format("woff"), url("ion.woff?ce7a0ead692560b4405a96d5b8471f51") format("woff"),
url("ion.ttf?492c5e946f5ae6f02467d64ca0f55cd1") format("truetype"), url("ion.ttf?ce7a0ead692560b4405a96d5b8471f51") format("truetype"),
url("ion.svg?492c5e946f5ae6f02467d64ca0f55cd1#ion") format("svg"); url("ion.svg?ce7a0ead692560b4405a96d5b8471f51#ion") format("svg");
font-weight:normal; font-weight:normal;
font-style:normal; font-style:normal;
} }
@ -190,6 +190,11 @@
content:"\f114"; content:"\f114";
} }
.ion-close:before {
content:"\f115";
}
</style> </style>
</head> </head>
<body> <body>
@ -237,6 +242,8 @@
<div class="icons__item" data-name="magnet"><i class="ion-icon ion-magnet"></i> ion-magnet</div> <div class="icons__item" data-name="magnet"><i class="ion-icon ion-magnet"></i> ion-magnet</div>
<div class="icons__item" data-name="close"><i class="ion-icon ion-close"></i> ion-close</div>
</div> </div>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 12 KiB

View File

@ -25,6 +25,10 @@ module.exports = function(grunt) {
output: { output: {
comments: 'some' comments: 'some'
}, },
ie8: false,
warnings: true,
compress: false,
mangle: true,
sourceMap: true sourceMap: true
}, },
dist: { dist: {
@ -63,7 +67,7 @@ module.exports = function(grunt) {
plugins: [ plugins: [
new (require('less-plugin-clean-css'))({ new (require('less-plugin-clean-css'))({
advanced: true, advanced: true,
compatibility: 'ie8' compatibility: '*'
}) })
], ],
banner: '/*! searx | <%= grunt.template.today("dd-mm-yyyy") %> | https://github.com/asciimoo/searx */\n' banner: '/*! searx | <%= grunt.template.today("dd-mm-yyyy") %> | https://github.com/asciimoo/searx */\n'
@ -99,7 +103,8 @@ module.exports = function(grunt) {
'node_modules/ionicons-npm/src/music-note.svg', 'node_modules/ionicons-npm/src/music-note.svg',
'node_modules/ionicons-npm/src/ion-close-round.svg', 'node_modules/ionicons-npm/src/ion-close-round.svg',
'node_modules/ionicons-npm/src/android-more-vertical.svg', 'node_modules/ionicons-npm/src/android-more-vertical.svg',
'magnet.svg' 'magnet.svg',
'node_modules/ionicons-npm/src/android-close.svg',
], ],
dest: 'fonts', dest: 'fonts',
destLess: 'less', destLess: 'less',

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.1 KiB

View File

@ -147,10 +147,19 @@
} }
}; };
searx.insertBefore = function (newNode, referenceNode) {
element.parentNode.insertBefore(newNode, referenceNode);
};
searx.insertAfter = function(newNode, referenceNode) {
referenceNode.parentNode.insertBefore(newNode, referenceNode.nextSibling);
};
searx.on('.close', 'click', function(e) { searx.on('.close', 'click', function(e) {
var el = e.target || e.srcElement; var el = e.target || e.srcElement;
this.parentNode.style.display="None"; this.parentNode.classList.add('invisible');
}); });
return searx; return searx;
})(window, document, window.searx); })(window, document, window.searx);
;(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.AutoComplete = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){ ;(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.AutoComplete = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
@ -958,7 +967,7 @@ module.exports = AutoComplete;
} }
}; };
searx.on(document, "keyup", function(e) { searx.on(document, "keydown", function(e) {
// check for modifiers so we don't break browser's hotkeys // 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 (vimKeys.hasOwnProperty(e.keyCode) && !e.ctrlKey && !e.altKey && !e.shiftKey && !e.metaKey) {
var tagName = e.target.tagName.toLowerCase(); var tagName = e.target.tagName.toLowerCase();
@ -968,6 +977,7 @@ module.exports = AutoComplete;
} }
} else { } else {
if (e.target === document.body || tagName === 'a' || tagName === 'button') { if (e.target === document.body || tagName === 'a' || tagName === 'button') {
e.preventDefault();
vimKeys[e.keyCode].fun(); vimKeys[e.keyCode].fun();
} }
} }
@ -1132,13 +1142,7 @@ module.exports = AutoComplete;
}; };
} }
function toggleHelp() { function initHelpContent(divElement) {
var helpPanel = document.querySelector('#vim-hotkeys-help');
if (helpPanel.length) {
helpPanel.classList.toggle('hidden');
return;
}
var categories = {}; var categories = {};
for (var k in vimKeys) { for (var k in vimKeys) {
@ -1155,14 +1159,9 @@ module.exports = AutoComplete;
return; return;
} }
var html = '<div id="vim-hotkeys-help" class="well vim-hotkeys-help">'; var html = '<a href="#" class="close" aria-label="close" title="close">×</a>';
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 += '<h3>How to navigate searx with Vim-like hotkeys</h3>';
html += '</div>'; // col-sm-12 html += '<table>';
html += '</div>'; // row
for (var i = 0; i < sorted.length; i++) { for (var i = 0; i < sorted.length; i++) {
var cat = categories[sorted[i]]; var cat = categories[sorted[i]];
@ -1171,13 +1170,11 @@ module.exports = AutoComplete;
var first = i % 2 === 0; var first = i % 2 === 0;
if (first) { if (first) {
html += '<div class="row dflex">'; html += '<tr>';
} }
html += '<div class="col-sm-' + (first && lastCategory ? 12 : 6) + ' dflex">'; html += '<td>';
html += '<div class="panel panel-default iflex">'; html += '<h4>' + cat[0].cat + '</h4>';
html += '<div class="panel-heading">' + cat[0].cat + '</div>';
html += '<div class="panel-body">';
html += '<ul class="list-unstyled">'; html += '<ul class="list-unstyled">';
for (var cj in cat) { for (var cj in cat) {
@ -1185,20 +1182,38 @@ module.exports = AutoComplete;
} }
html += '</ul>'; html += '</ul>';
html += '</div>'; // panel-body html += '</td>'; // col-sm-*
html += '</div>'; // panel
html += '</div>'; // col-sm-*
if (!first || lastCategory) { if (!first || lastCategory) {
html += '</div>'; // row html += '</tr>'; // row
} }
} }
html += '</div>'; // container-fluid html += '</table>';
html += '</div>'; // vim-hotkeys-help
$('body').append(html); divElement.innerHTML = html;
} }
function toggleHelp() {
var helpPanel = document.querySelector('#vim-hotkeys-help');
console.log(helpPanel);
if (helpPanel === undefined || helpPanel === null) {
// first call
helpPanel = document.createElement('div');
helpPanel.id = 'vim-hotkeys-help';
helpPanel.className='dialog-modal';
helpPanel.style='width: 40%';
initHelpContent(helpPanel);
var body = document.getElementsByTagName('body')[0];
body.appendChild(helpPanel);
} else {
// togggle hidden
helpPanel.classList.toggle('invisible');
return;
}
}
}); });
;/** ;/**
* searx is free software: you can redistribute it and/or modify * searx is free software: you can redistribute it and/or modify
@ -1292,13 +1307,14 @@ module.exports = AutoComplete;
newHtml += "</td></tr>"; newHtml += "</td></tr>";
} }
} }
result_table_loadicon.classList.add('invisible'); result_table_loadicon.parentNode.removeChild(result_table_loadicon);
result_table.classList.remove('invisible'); result_table.classList.remove('invisible');
result_table.querySelector("tbody").innerHTML = newHtml; result_table.querySelector("tbody").innerHTML = newHtml;
} }
}) })
.catch(function() { .catch(function() {
result_table_loadicon.innerHTML = result_table_loadicon.innerHTML + "<p class=\"text-muted\">could not load data!</p>"; result_table_loadicon.classList.remove('invisible');
result_table_loadicon.innerHTML = "could not load data!";
}); });
} }
} }
@ -1473,6 +1489,26 @@ module.exports = AutoComplete;
} }
} }
function createClearButton(qinput) {
var cs = document.getElementById('clear_search');
var updateClearButton = function() {
if (qinput.value.length === 0) {
cs.classList.add("empty");
} else {
cs.classList.remove("empty");
}
};
// update status, event listener
updateClearButton();
cs.addEventListener('click', function() {
qinput.value='';
qinput.focus();
updateClearButton();
});
qinput.addEventListener('keyup', updateClearButton, false);
}
searx.ready(function() { searx.ready(function() {
qinput = d.getElementById(qinput_id); qinput = d.getElementById(qinput_id);
@ -1486,6 +1522,9 @@ module.exports = AutoComplete;
} }
if (qinput !== null) { if (qinput !== null) {
// clear button
createClearButton(qinput);
// autocompleter // autocompleter
if (searx.autocompleter) { if (searx.autocompleter) {
searx.autocomplete = AutoComplete.call(w, { searx.autocomplete = AutoComplete.call(w, {

Binary file not shown.

View File

@ -147,9 +147,18 @@
} }
}; };
searx.insertBefore = function (newNode, referenceNode) {
element.parentNode.insertBefore(newNode, referenceNode);
};
searx.insertAfter = function(newNode, referenceNode) {
referenceNode.parentNode.insertBefore(newNode, referenceNode.nextSibling);
};
searx.on('.close', 'click', function(e) { searx.on('.close', 'click', function(e) {
var el = e.target || e.srcElement; var el = e.target || e.srcElement;
this.parentNode.style.display="None"; this.parentNode.classList.add('invisible');
}); });
return searx; return searx;
})(window, document, window.searx); })(window, document, window.searx);

View File

@ -116,7 +116,7 @@ searx.ready(function() {
} }
}; };
searx.on(document, "keyup", function(e) { searx.on(document, "keydown", function(e) {
// check for modifiers so we don't break browser's hotkeys // 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 (vimKeys.hasOwnProperty(e.keyCode) && !e.ctrlKey && !e.altKey && !e.shiftKey && !e.metaKey) {
var tagName = e.target.tagName.toLowerCase(); var tagName = e.target.tagName.toLowerCase();
@ -126,6 +126,7 @@ searx.ready(function() {
} }
} else { } else {
if (e.target === document.body || tagName === 'a' || tagName === 'button') { if (e.target === document.body || tagName === 'a' || tagName === 'button') {
e.preventDefault();
vimKeys[e.keyCode].fun(); vimKeys[e.keyCode].fun();
} }
} }
@ -290,13 +291,7 @@ searx.ready(function() {
}; };
} }
function toggleHelp() { function initHelpContent(divElement) {
var helpPanel = document.querySelector('#vim-hotkeys-help');
if (helpPanel.length) {
helpPanel.classList.toggle('hidden');
return;
}
var categories = {}; var categories = {};
for (var k in vimKeys) { for (var k in vimKeys) {
@ -313,14 +308,9 @@ searx.ready(function() {
return; return;
} }
var html = '<div id="vim-hotkeys-help" class="well vim-hotkeys-help">'; var html = '<a href="#" class="close" aria-label="close" title="close">×</a>';
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 += '<h3>How to navigate searx with Vim-like hotkeys</h3>';
html += '</div>'; // col-sm-12 html += '<table>';
html += '</div>'; // row
for (var i = 0; i < sorted.length; i++) { for (var i = 0; i < sorted.length; i++) {
var cat = categories[sorted[i]]; var cat = categories[sorted[i]];
@ -329,13 +319,11 @@ searx.ready(function() {
var first = i % 2 === 0; var first = i % 2 === 0;
if (first) { if (first) {
html += '<div class="row dflex">'; html += '<tr>';
} }
html += '<div class="col-sm-' + (first && lastCategory ? 12 : 6) + ' dflex">'; html += '<td>';
html += '<div class="panel panel-default iflex">'; html += '<h4>' + cat[0].cat + '</h4>';
html += '<div class="panel-heading">' + cat[0].cat + '</div>';
html += '<div class="panel-body">';
html += '<ul class="list-unstyled">'; html += '<ul class="list-unstyled">';
for (var cj in cat) { for (var cj in cat) {
@ -343,18 +331,36 @@ searx.ready(function() {
} }
html += '</ul>'; html += '</ul>';
html += '</div>'; // panel-body html += '</td>'; // col-sm-*
html += '</div>'; // panel
html += '</div>'; // col-sm-*
if (!first || lastCategory) { if (!first || lastCategory) {
html += '</div>'; // row html += '</tr>'; // row
} }
} }
html += '</div>'; // container-fluid html += '</table>';
html += '</div>'; // vim-hotkeys-help
$('body').append(html); divElement.innerHTML = html;
} }
function toggleHelp() {
var helpPanel = document.querySelector('#vim-hotkeys-help');
console.log(helpPanel);
if (helpPanel === undefined || helpPanel === null) {
// first call
helpPanel = document.createElement('div');
helpPanel.id = 'vim-hotkeys-help';
helpPanel.className='dialog-modal';
helpPanel.style='width: 40%';
initHelpContent(helpPanel);
var body = document.getElementsByTagName('body')[0];
body.appendChild(helpPanel);
} else {
// togggle hidden
helpPanel.classList.toggle('invisible');
return;
}
}
}); });

View File

@ -90,13 +90,14 @@
newHtml += "</td></tr>"; newHtml += "</td></tr>";
} }
} }
result_table_loadicon.classList.add('invisible'); result_table_loadicon.parentNode.removeChild(result_table_loadicon);
result_table.classList.remove('invisible'); result_table.classList.remove('invisible');
result_table.querySelector("tbody").innerHTML = newHtml; result_table.querySelector("tbody").innerHTML = newHtml;
} }
}) })
.catch(function() { .catch(function() {
result_table_loadicon.innerHTML = result_table_loadicon.innerHTML + "<p class=\"text-muted\">could not load data!</p>"; result_table_loadicon.classList.remove('invisible');
result_table_loadicon.innerHTML = "could not load data!";
}); });
} }
} }

View File

@ -33,6 +33,26 @@
} }
} }
function createClearButton(qinput) {
var cs = document.getElementById('clear_search');
var updateClearButton = function() {
if (qinput.value.length === 0) {
cs.classList.add("empty");
} else {
cs.classList.remove("empty");
}
};
// update status, event listener
updateClearButton();
cs.addEventListener('click', function() {
qinput.value='';
qinput.focus();
updateClearButton();
});
qinput.addEventListener('keyup', updateClearButton, false);
}
searx.ready(function() { searx.ready(function() {
qinput = d.getElementById(qinput_id); qinput = d.getElementById(qinput_id);
@ -46,6 +66,9 @@
} }
if (qinput !== null) { if (qinput !== null) {
// clear button
createClearButton(qinput);
// autocompleter // autocompleter
if (searx.autocompleter) { if (searx.autocompleter) {
searx.autocomplete = AutoComplete.call(w, { searx.autocomplete = AutoComplete.call(w, {

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.5 KiB

After

Width:  |  Height:  |  Size: 2.4 KiB

View File

@ -0,0 +1 @@
alexandre@alf-laptop.2449:1533915028

View File

@ -3,12 +3,12 @@
@font-face { @font-face {
font-family:"ion"; font-family:"ion";
src:url("../fonts/ion.eot?492c5e946f5ae6f02467d64ca0f55cd1"); src:url("../fonts/ion.eot?ce7a0ead692560b4405a96d5b8471f51");
src:url("../fonts/ion.eot?#iefix") format("embedded-opentype"), src:url("../fonts/ion.eot?#iefix") format("embedded-opentype"),
url("../fonts/ion.woff2?492c5e946f5ae6f02467d64ca0f55cd1") format("woff2"), url("../fonts/ion.woff2?ce7a0ead692560b4405a96d5b8471f51") format("woff2"),
url("../fonts/ion.woff?492c5e946f5ae6f02467d64ca0f55cd1") format("woff"), url("../fonts/ion.woff?ce7a0ead692560b4405a96d5b8471f51") format("woff"),
url("../fonts/ion.ttf?492c5e946f5ae6f02467d64ca0f55cd1") format("truetype"), url("../fonts/ion.ttf?ce7a0ead692560b4405a96d5b8471f51") format("truetype"),
url("../fonts/ion.svg?492c5e946f5ae6f02467d64ca0f55cd1#ion") format("svg"); url("../fonts/ion.svg?ce7a0ead692560b4405a96d5b8471f51#ion") format("svg");
font-weight:normal; font-weight:normal;
font-style:normal; font-style:normal;
} }
@ -172,3 +172,10 @@
} }
} }
.ion-close {
&:before {
content:"\f115";
}
}

View File

@ -30,7 +30,7 @@
.select-all-on-focus() { .select-all-on-focus() {
-webkit-user-select: all; -webkit-user-select: all;
-moz-user-select: all; -moz-user-select: all;
-ms-user-select: all; -ms-user-select: element;
user-select: all; user-select: all;
} }

View File

@ -1,17 +1,15 @@
/*! normalize.css v7.0.0 | MIT License | github.com/necolas/normalize.css */ /*! normalize.css v8.0.0 | MIT License | github.com/necolas/normalize.css */
/* Document /* Document
========================================================================== */ ========================================================================== */
/** /**
* 1. Correct the line height in all browsers. * 1. Correct the line height in all browsers.
* 2. Prevent adjustments of font size after orientation changes in * 2. Prevent adjustments of font size after orientation changes in iOS.
* IE on Windows Phone and in iOS.
*/ */
html { html {
line-height: 1.15; /* 1 */ line-height: 1.15; /* 1 */
-ms-text-size-adjust: 100%; /* 2 */
-webkit-text-size-adjust: 100%; /* 2 */ -webkit-text-size-adjust: 100%; /* 2 */
} }
@ -19,26 +17,13 @@ html {
========================================================================== */ ========================================================================== */
/** /**
* Remove the margin in all browsers (opinionated). * Remove the margin in all browsers.
*/ */
body { body {
margin: 0; margin: 0;
} }
/**
* Add the correct display in IE 9-.
*/
article,
aside,
footer,
header,
nav,
section {
display: block;
}
/** /**
* Correct the font size and margin on `h1` elements within `section` and * Correct the font size and margin on `h1` elements within `section` and
* `article` contexts in Chrome, Firefox, and Safari. * `article` contexts in Chrome, Firefox, and Safari.
@ -52,25 +37,6 @@ h1 {
/* Grouping content /* Grouping content
========================================================================== */ ========================================================================== */
/**
* Add the correct display in IE 9-.
* 1. Add the correct display in IE.
*/
figcaption,
figure,
main { /* 1 */
display: block;
}
/**
* Add the correct margin in IE 8.
*/
figure {
margin: 1em 40px;
}
/** /**
* 1. Add the correct box sizing in Firefox. * 1. Add the correct box sizing in Firefox.
* 2. Show the overflow in Edge and IE. * 2. Show the overflow in Edge and IE.
@ -96,17 +62,15 @@ pre {
========================================================================== */ ========================================================================== */
/** /**
* 1. Remove the gray background on active links in IE 10. * Remove the gray background on active links in IE 10.
* 2. Remove gaps in links underline in iOS 8+ and Safari 8+.
*/ */
a { a {
background-color: transparent; /* 1 */ background-color: transparent;
-webkit-text-decoration-skip: objects; /* 2 */
} }
/** /**
* 1. Remove the bottom border in Chrome 57- and Firefox 39-. * 1. Remove the bottom border in Chrome 57-
* 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari. * 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari.
*/ */
@ -116,15 +80,6 @@ abbr[title] {
text-decoration: underline dotted; /* 2 */ text-decoration: underline dotted; /* 2 */
} }
/**
* Prevent the duplicate application of `bolder` by the next rule in Safari 6.
*/
b,
strong {
font-weight: inherit;
}
/** /**
* Add the correct font weight in Chrome, Edge, and Safari. * Add the correct font weight in Chrome, Edge, and Safari.
*/ */
@ -146,23 +101,6 @@ samp {
font-size: 1em; /* 2 */ font-size: 1em; /* 2 */
} }
/**
* Add the correct font style in Android 4.3-.
*/
dfn {
font-style: italic;
}
/**
* Add the correct background and color in IE 9-.
*/
mark {
background-color: #ff0;
color: #000;
}
/** /**
* Add the correct font size in all browsers. * Add the correct font size in all browsers.
*/ */
@ -196,44 +134,18 @@ sup {
========================================================================== */ ========================================================================== */
/** /**
* Add the correct display in IE 9-. * Remove the border on images inside links in IE 10.
*/
audio,
video {
display: inline-block;
}
/**
* Add the correct display in iOS 4-7.
*/
audio:not([controls]) {
display: none;
height: 0;
}
/**
* Remove the border on images inside links in IE 10-.
*/ */
img { img {
border-style: none; border-style: none;
} }
/**
* Hide the overflow in IE.
*/
svg:not(:root) {
overflow: hidden;
}
/* Forms /* Forms
========================================================================== */ ========================================================================== */
/** /**
* 1. Change the font styles in all browsers (opinionated). * 1. Change the font styles in all browsers.
* 2. Remove the margin in Firefox and Safari. * 2. Remove the margin in Firefox and Safari.
*/ */
@ -242,7 +154,7 @@ input,
optgroup, optgroup,
select, select,
textarea { textarea {
font-family: sans-serif; /* 1 */ font-family: inherit; /* 1 */
font-size: 100%; /* 1 */ font-size: 100%; /* 1 */
line-height: 1.15; /* 1 */ line-height: 1.15; /* 1 */
margin: 0; /* 2 */ margin: 0; /* 2 */
@ -269,16 +181,14 @@ select { /* 1 */
} }
/** /**
* 1. Prevent a WebKit bug where (2) destroys native `audio` and `video` * Correct the inability to style clickable types in iOS and Safari.
* controls in Android 4.
* 2. Correct the inability to style clickable types in iOS and Safari.
*/ */
button, button,
html [type="button"], /* 1 */ [type="button"],
[type="reset"], [type="reset"],
[type="submit"] { [type="submit"] {
-webkit-appearance: button; /* 2 */ -webkit-appearance: button;
} }
/** /**
@ -329,17 +239,15 @@ legend {
} }
/** /**
* 1. Add the correct display in IE 9-. * Add the correct vertical alignment in Chrome, Firefox, and Opera.
* 2. Add the correct vertical alignment in Chrome, Firefox, and Opera.
*/ */
progress { progress {
display: inline-block; /* 1 */ vertical-align: baseline;
vertical-align: baseline; /* 2 */
} }
/** /**
* Remove the default vertical scrollbar in IE. * Remove the default vertical scrollbar in IE 10+.
*/ */
textarea { textarea {
@ -347,8 +255,8 @@ textarea {
} }
/** /**
* 1. Add the correct box sizing in IE 10-. * 1. Add the correct box sizing in IE 10.
* 2. Remove the padding in IE 10-. * 2. Remove the padding in IE 10.
*/ */
[type="checkbox"], [type="checkbox"],
@ -377,10 +285,9 @@ textarea {
} }
/** /**
* Remove the inner padding and cancel buttons in Chrome and Safari on macOS. * Remove the inner padding in Chrome and Safari on macOS.
*/ */
[type="search"]::-webkit-search-cancel-button,
[type="search"]::-webkit-search-decoration { [type="search"]::-webkit-search-decoration {
-webkit-appearance: none; -webkit-appearance: none;
} }
@ -399,12 +306,10 @@ textarea {
========================================================================== */ ========================================================================== */
/* /*
* Add the correct display in IE 9-. * Add the correct display in Edge, IE 10+, and Firefox.
* 1. Add the correct display in Edge, IE, and Firefox.
*/ */
details, /* 1 */ details {
menu {
display: block; display: block;
} }
@ -416,30 +321,19 @@ summary {
display: list-item; display: list-item;
} }
/* Scripting /* Misc
========================================================================== */ ========================================================================== */
/** /**
* Add the correct display in IE 9-. * Add the correct display in IE 10+.
*/
canvas {
display: inline-block;
}
/**
* Add the correct display in IE.
*/ */
template { template {
display: none; display: none;
} }
/* Hidden
========================================================================== */
/** /**
* Add the correct display in IE 10-. * Add the correct display in IE 10.
*/ */
[hidden] { [hidden] {

View File

@ -45,6 +45,24 @@
text-align: center; text-align: center;
} }
table.cookies {
width: auto;
th, td {
text-align: left;
padding: 0.25em;
}
th:first-child, td:first-child {
padding-right: 4em;
}
&>tbody>tr:nth-child(even)>th,
&>tbody>tr:nth-child(even)>td {
background-color: @color-settings-tr-hover;
}
}
.name, .shortcut { .name, .shortcut {
text-align: left; text-align: left;
} }
@ -69,6 +87,13 @@
} }
} }
div.selectable_url {
pre {
width: 100%;
}
}
} }
@media screen and (max-width: 75em) { @media screen and (max-width: 75em) {

View File

@ -26,11 +26,43 @@
*/ */
} }
#clear_search {
display: block;
border-collapse: separate;
box-sizing: border-box;
width: 1.8em;
margin: 0;
padding: 2px;
height: 2.2em;
background: none repeat scroll 0 0 @color-search-background;
border-top: 1px solid @color-search-border;
border-bottom: 1px solid @color-search-border;
border-right: none;
border-left: none;
border-radius: 0px;
outline: none;
color: @color-search-font;
font-size: 16px;
z-index: 10000;
&:hover {
color: @color-search-border;
}
&.empty * {
display: none;
}
}
#q::-ms-clear, #q::-webkit-search-cancel-button {
display: none;
}
#q, #send_search { #q, #send_search {
display: block !important; display: block !important;
border-collapse: separate; border-collapse: separate;
box-sizing: border-box; box-sizing: border-box;
position: relative;
margin: 0; margin: 0;
padding: 2px; padding: 2px;

View File

@ -477,25 +477,9 @@ article.result-images[data-vim-selected]::before {
#search_url { #search_url {
margin-top: 8px; margin-top: 8px;
div { div.selectable_url {
display: block;
border: 1px solid @color-result-search-url-border;
padding: 4px;
color: @color-result-search-url-font;
width: 100%;
display: block;
margin: 0.1em;
overflow: hidden;
height: 1.2em;
line-height: 1.2em;
pre { pre {
display: block;
width: 200em; width: 200em;
font-size: 0.8em;
word-break: break-all;
margin: 0.1em;
.select-all-on-focus();
} }
} }
} }
@ -648,6 +632,34 @@ article.result-images[data-vim-selected]::before {
} }
#main_results div#results.only_template_images {
flex-direction: column;
width: auto;
display: flex;
#sidebar {
position: relative;
top: auto;
order: 2;
}
#urls {
position: relative;
order: 1;
}
#backToTop {
right: 0.5em;
left: auto;
}
#pagination {
position: relative;
order: 3;
}
}
@media screen and (max-width: @results-width) { @media screen and (max-width: @results-width) {
article[data-vim-selected]::before { article[data-vim-selected]::before {

View File

@ -20,7 +20,16 @@ html.js .show_if_nojs {
} }
.invisible { .invisible {
display: none; display: none !important;
}
.list-unstyled {
list-style-type: none;
li {
margin-top: 4px;
margin-bottom: 4px;
}
} }
.danger { .danger {
@ -39,6 +48,15 @@ html.js .show_if_nojs {
border-radius: 5px; border-radius: 5px;
} }
// kbd
kbd {
padding: 2px 4px;
margin: 1px;
font-size: 90%;
color: white;
background: black;
}
// table // table
table { table {
@ -65,6 +83,32 @@ tr {
} }
} }
// pre
.pre() {
display: block;
font-size: 0.8em;
word-break: break-all;
margin: 0.1em;
.select-all-on-focus();
}
div.selectable_url {
display: block;
border: 1px solid @color-result-search-url-border;
padding: 4px;
color: @color-result-search-url-font;
width: 100%;
display: block;
margin: 0.1em;
overflow: hidden;
height: 1.2em;
line-height: 1.2em;
pre {
.pre();
}
}
// dialog // dialog
.dialog() { .dialog() {
position: relative; position: relative;
@ -95,6 +139,28 @@ tr {
margin: 1px 0 0 0; margin: 1px 0 0 0;
} }
table {
width: auto;
}
tr {
vertical-align: text-top;
&:hover {
background: transparent;
}
}
td {
padding: 0 1em 0 0;
}
h4 {
margin-top: 0.3em;
margin-bottom: 0.3em;
}
} }
.dialog-error { .dialog-error {
@ -113,6 +179,19 @@ tr {
.ion-warning(); .ion-warning();
} }
.dialog-modal {
.dialog();
background: white;
position: fixed;
top: 50%;
left: 50%;
/* bring your own prefixes */
transform: translate(-50%, -50%);
z-index: 100000;
margin: 0 50% 0 0;
box-shadow: 0 0 1em;
}
// btn-collapse // btn-collapse
.btn-collapse { .btn-collapse {
cursor: pointer; cursor: pointer;
@ -128,7 +207,7 @@ tr {
border: none; border: none;
} }
// tabs /* -- tabs --*/
.tabs .tabs > label { .tabs .tabs > label {
font-size: 90%; font-size: 90%;
} }
@ -215,7 +294,7 @@ html body .tabs > input:checked {
} }
} }
// select /* -- select -- */
select { select {
height: 28px; height: 28px;
margin: 0 1em 0 0; margin: 0 1em 0 0;
@ -251,7 +330,7 @@ select {
} }
// checkbox-onoff /* -- checkbox-onoff -- */
@supports (border-radius: 50px) { @supports (border-radius: 50px) {
.checkbox-onoff { .checkbox-onoff {
display: inline-block; display: inline-block;
@ -285,7 +364,7 @@ select {
} }
} }
// checkbox /* -- checkbox --*/
@supports (transform: rotate(-45deg)) { @supports (transform: rotate(-45deg)) {
.checkbox { .checkbox {
width: 20px; width: 20px;
@ -325,7 +404,7 @@ select {
} }
} }
// disabled : can't be focused, show only the check mark // disabled : can''t be focused, show only the check mark
input[disabled] + label { input[disabled] + label {
background-color: transparent !important; background-color: transparent !important;
box-shadow: none !important; box-shadow: none !important;
@ -344,3 +423,46 @@ select {
width: 100%; width: 100%;
} }
} }
/* -- loader -- */
.loader,
.loader:after {
border-radius: 50%;
width: 2em;
height: 2em;
}
.loader {
margin: 1em auto;
font-size: 10px;
position: relative;
text-indent: -9999em;
border-top: 0.5em solid rgba(0, 0, 0, 0.2);
border-right: 0.5em solid rgba(0, 0, 0, 0.2);
border-bottom: 0.5em solid rgba(0, 0, 0, 0.2);
border-left: 0.5em solid rgba(255, 255, 255, 0);
-webkit-transform: translateZ(0);
-ms-transform: translateZ(0);
transform: translateZ(0);
-webkit-animation: load8 1.2s infinite linear;
animation: load8 1.2s infinite linear;
}
@-webkit-keyframes load8 {
0% {
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
}
100% {
-webkit-transform: rotate(360deg);
transform: rotate(360deg);
}
}
@keyframes load8 {
0% {
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
}
100% {
-webkit-transform: rotate(360deg);
transform: rotate(360deg);
}
}

View File

@ -0,0 +1,41 @@
.loader,
.loader:after {
border-radius: 50%;
width: 10em;
height: 10em;
}
.loader {
margin: 60px auto;
font-size: 10px;
position: relative;
text-indent: -9999em;
border-top: 1.1em solid rgba(255, 255, 255, 0.2);
border-right: 1.1em solid rgba(255, 255, 255, 0.2);
border-bottom: 1.1em solid rgba(255, 255, 255, 0.2);
border-left: 1.1em solid #ffffff;
-webkit-transform: translateZ(0);
-ms-transform: translateZ(0);
transform: translateZ(0);
-webkit-animation: load8 1.1s infinite linear;
animation: load8 1.1s infinite linear;
}
@-webkit-keyframes load8 {
0% {
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
}
100% {
-webkit-transform: rotate(360deg);
transform: rotate(360deg);
}
}
@keyframes load8 {
0% {
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
}
100% {
-webkit-transform: rotate(360deg);
transform: rotate(360deg);
}
}

View File

@ -1,15 +1,15 @@
{ {
"devDependencies": { "devDependencies": {
"grunt": "~1.0.1", "grunt": "~1.0.3",
"grunt-contrib-concat": "~1.0.1", "grunt-contrib-concat": "~1.0.1",
"grunt-contrib-cssmin": "^2.2.1", "grunt-contrib-cssmin": "^2.2.1",
"grunt-contrib-jshint": "~1.1.0", "grunt-contrib-jshint": "~1.1.0",
"grunt-contrib-less": "^1.4.1", "grunt-contrib-less": "^1.4.1",
"grunt-contrib-uglify": "~3.0.1", "grunt-contrib-uglify": "~3.4.0",
"grunt-contrib-watch": "~1.0.0", "grunt-contrib-watch": "~1.1.0",
"grunt-webfont": "^1.6.0", "grunt-webfont": "^1.7.1",
"ionicons-npm": "^2.0.1", "ionicons-npm": "^2.0.1",
"jslint": "^0.10.3", "jslint": "^0.12.0",
"less-plugin-clean-css": "^1.5.1" "less-plugin-clean-css": "^1.5.1"
}, },
"scripts": { "scripts": {

View File

@ -187,7 +187,7 @@
</td> </td>
<th>{{ search_engine.name }}</th> <th>{{ search_engine.name }}</th>
<td class="name">{{ shortcuts[search_engine.name] }}</td> <td class="name">{{ shortcuts[search_engine.name] }}</td>
<td>{{ support_toggle(current_language in search_engine.supported_languages or current_language.split('-')[0] in search_engine.supported_languages) }}</td> <td>{{ support_toggle(stats[search_engine.name].supports_selected_language) }}</td>
<td>{{ support_toggle(search_engine.safesearch==True) }}</td> <td>{{ support_toggle(search_engine.safesearch==True) }}</td>
<td>{{ support_toggle(search_engine.time_range_support==True) }}</td> <td>{{ support_toggle(search_engine.time_range_support==True) }}</td>
<td class="{{ 'danger' if stats[search_engine.name]['warn_time'] else '' }}">{{ 'N/A' if stats[search_engine.name].time==None else stats[search_engine.name].time }}</td> <td class="{{ 'danger' if stats[search_engine.name]['warn_time'] else '' }}">{{ 'N/A' if stats[search_engine.name].time==None else stats[search_engine.name].time }}</td>
@ -197,7 +197,7 @@
<td class="{{ 'danger' if stats[search_engine.name]['warn_time'] else '' }}">{{ 'N/A' if stats[search_engine.name].time==None else stats[search_engine.name].time }}</td> <td class="{{ 'danger' if stats[search_engine.name]['warn_time'] else '' }}">{{ 'N/A' if stats[search_engine.name].time==None else stats[search_engine.name].time }}</td>
<td>{{ support_toggle(search_engine.time_range_support==True) }}</td> <td>{{ support_toggle(search_engine.time_range_support==True) }}</td>
<td>{{ support_toggle(search_engine.safesearch==True) }}</td> <td>{{ support_toggle(search_engine.safesearch==True) }}</td>
<td>{{ support_toggle(current_language in search_engine.supported_languages or current_language.split('-')[0] in search_engine.supported_languages) }}</td> <td>{{ support_toggle(stats[search_engine.name].supports_selected_language) }}</td>
<td>{{ shortcuts[search_engine.name] }}</td> <td>{{ shortcuts[search_engine.name] }}</td>
<th>{{ search_engine.name }}</th> <th>{{ search_engine.name }}</th>
<td class="onoff-checkbox"> <td class="onoff-checkbox">

View File

@ -52,9 +52,9 @@
<p class="value"> <p class="value">
<select name="autocomplete"> <select name="autocomplete">
<option value=""> - </option> <option value=""> - </option>
{% for backend in autocomplete_backends %} {%- for backend in autocomplete_backends -%}
<option value="{{ backend }}" {% if backend == autocomplete %}selected="selected"{% endif %}>{{ backend }}</option> <option value="{{ backend }}" {% if backend == autocomplete %}selected="selected"{% endif %}>{{ backend }}</option>
{% endfor %} {%- endfor -%}
</select> </select>
</p> </p>
<div class="description">{{ _('Find stuff as you type') }}</div> <div class="description">{{ _('Find stuff as you type') }}</div>
@ -71,6 +71,19 @@
<div class="description">{{ _('Filter content') }}</p> <div class="description">{{ _('Filter content') }}</p>
</fieldset> </fieldset>
{{ plugin_preferences('general') }} {{ plugin_preferences('general') }}
<fieldset>
<legend>{{ _('Open Access DOI resolver') }}</legend>
<p class="value">
<select id='doi_resolver' name='doi_resolver'>
{%- for doi_resolver_name,doi_resolver_url in doi_resolvers.items() -%}
<option value="{{ doi_resolver_name }}" {% if doi_resolver_name == current_doi_resolver %}selected="selected"{% endif %}>
{{- doi_resolver_name }} - {{ doi_resolver_url -}}
</option>
{%- endfor -%}
</select>
</p>
<div class="description"><!-- {{ _('Redirect to open-access versions of publications when available (plugin required)') }} --></div>
</fieldset>
{{ tab_footer() }} {{ tab_footer() }}
{{ tab_header('maintab', 'engines', _('Engines')) }} {{ tab_header('maintab', 'engines', _('Engines')) }}
@ -151,6 +164,38 @@
{{ plugin_preferences('ui') }} {{ plugin_preferences('ui') }}
{{ tab_footer() }} {{ tab_footer() }}
{{ tab_header('maintab', 'cookies', _('Cookies')) }}
<p class="text-muted" style="margin:20px 0;">
{{ _('This is the list of cookies and their values searx is storing on your computer.') }}<br />
{{ _('With that list, you can assess searx transparency.') }}<br />
</p>
{% if cookies %}
<table class="cookies">
<tr>
<th>{{ _('Cookie name') }}</th>
<th>{{ _('Value') }}</th>
</tr>
{% for cookie in cookies %}
<tr>
<td>{{ cookie }}</td>
<td>{{ cookies[cookie] }}</td>
</tr>
{% endfor %}
</table>
{% else %}
{% include 'oscar/messages/no_cookies.html' %}
{% endif %}
<h4>{{ _('Search URL of the currently saved preferences') }} :</h4>
<div class="selectable_url">
<pre>{{ url_for('index', _external=True) }}?preferences={{ preferences_url_params|e }}{% raw %}&amp;q=%s{% endraw %}</pre>
</div>
<p class="small_font">{{ _('Note: specifying custom settings in the search URL can reduce privacy by leaking data to the clicked result sites.') }}</p>
{{ tab_footer() }}
{{ tab_header('maintab', 'privacy', _('Privacy')) }} {{ tab_header('maintab', 'privacy', _('Privacy')) }}
<fieldset> <fieldset>
<legend>{{ _('Method') }}</legend> <legend>{{ _('Method') }}</legend>
@ -173,6 +218,7 @@
<div class="description">{{ _('Proxying image results through searx') }}</div> <div class="description">{{ _('Proxying image results through searx') }}</div>
</fieldset> </fieldset>
{{ plugin_preferences('privacy') }} {{ plugin_preferences('privacy') }}
{{ tab_footer() }} {{ tab_footer() }}
{{ tabs_close() }} {{ tabs_close() }}

View File

@ -23,17 +23,17 @@
{%- endif -%} {%- endif -%}
{% if result.address.road -%} {% if result.address.road -%}
<span itemprop="streetAddress"> <span itemprop="streetAddress">
{% if result.address.house_number %}{{ result.address.house_number }}, {% endif %} {%- if result.address.house_number -%}{{- result.address.house_number -}}, {% endif %}
{{ result.address.road }} {{- result.address.road -}}
</span><br/> </span><br/>
{%- endif %} {%- endif %}
{%- if result.address.locality -%} {%- if result.address.locality -%}
<span itemprop="addressLocality">{{ result.address.locality }}</span> <span itemprop="addressLocality">{{- result.address.locality -}}</span>
{% if result.address.postcode %}, <span itemprop="postalCode">{{ result.address.postcode }}</span>{% endif %} {%- if result.address.postcode -%}, <span itemprop="postalCode">{{- result.address.postcode -}}</span>{% endif %}
<br/> <br/>
{%- endif -%} {%- endif -%}
{%- if result.address.country -%} {%- if result.address.country -%}
<span itemprop="addressCountry">{{ result.address.country }}</span> <span itemprop="addressCountry">{{- result.address.country -}}</span>
{%- endif -%} {%- endif -%}
</p> </p>
{%- endif -%} {%- endif -%}
@ -44,11 +44,8 @@
{% if result.osm and (result.osm.type and result.osm.id) -%} {% if result.osm and (result.osm.type and result.osm.id) -%}
<div class="result-content invisible" id="result-overpass-{{ index }}"{% if rtl %} dir="ltr"{% endif %}> <div class="result-content invisible" id="result-overpass-{{ index }}"{% if rtl %} dir="ltr"{% endif %}>
<div id="result-overpass-table-loading-{{ index }}"><img src="{{ url_for('static', filename='img/loader.gif') }}" alt="Loading ..."/></div> <div id="result-overpass-table-loading-{{ index }}"><div class="loader">{{ _('Loading...') }}</div></div>
<table id="result-overpass-table-{{ index }}"> <table id="result-overpass-table-{{ index }}">
<thead>
<tr><th>key</th><th>value</th></tr>
</thead>
<tbody> <tbody>
</tbody> </tbody>
</table> </table>

View File

@ -1,19 +1,26 @@
{% extends "simple/base.html" %} {% extends "simple/base.html" %}
{% from 'simple/macros.html' import icon, icon_small %} {% from 'simple/macros.html' import icon, icon_small %}
{% block title %}{{ q|e }} - {% endblock %} {% block title %}{% if method == 'GET' %}{{- q|e -}} -{% endif %}{% endblock %}
{% block meta %}<link rel="alternate" type="application/rss+xml" title="Searx search: {{ q|e }}" href="{{ url_for('index') }}?q={{ q|urlencode }}&amp;categories={{ selected_categories|join(",") | replace(' ','+') }}&amp;pageno={{ pageno }}&amp;time_range={{ time_range }}&amp;language={{ current_language }}&amp;safesearch={{ safesearch }}&amp;format=rss">{% endblock %} {% block meta %}<link rel="alternate" type="application/rss+xml" title="Searx search: {{ q|e }}" href="{{ url_for('index') }}?q={{ q|urlencode }}&amp;categories={{ selected_categories|join(",") | replace(' ','+') }}&amp;pageno={{ pageno }}&amp;time_range={{ time_range }}&amp;language={{ current_language }}&amp;safesearch={{ safesearch }}&amp;format=rss">{% endblock %}
{% block content %} {% block content %}
<nav id="linkto_preferences"><a href="{{ url_for('preferences') }}">{{ icon('navicon-round') }}</a></nav> <nav id="linkto_preferences"><a href="{{ url_for('preferences') }}">{{ icon('navicon-round') }}</a></nav>
{% include 'simple/search.html' %} {% include 'simple/search.html' %}
<div id="results">
{% if answers %} {% if results and results|map(attribute='template')|unique|list|count == 1 %}
<div id="answers"><h4 class="title">{{ _('Answers') }} : </h4> {% set only_template = 'only_template_' + results[0]['template']|default('default')|replace('.html', '') %}
{% for answer in answers -%} {% else %}
<div class="answer">{{ answer }}</div> {% set unique_template = '' %}
{%- endfor %}
</div>
{% endif %} {% endif %}
<div id="results" class="{{ only_template }}">
{% if answers -%}
<div id="answers"><h4 class="title">{{ _('Answers') }} : </h4>
{%- for answer in answers -%}
<div class="answer">{{- answer -}}</div>
{%- endfor -%}
</div>
{%- endif %}
<div id="sidebar"> <div id="sidebar">
{% if number_of_results != '0' -%} {% if number_of_results != '0' -%}
@ -24,16 +31,16 @@
<div class="dialog-error" role="alert"> <div class="dialog-error" role="alert">
<p><strong>{{ _('Error!') }}</strong> {{ _('Engines cannot retrieve results') }}:</p> <p><strong>{{ _('Error!') }}</strong> {{ _('Engines cannot retrieve results') }}:</p>
<p>{% for engine_name, error_type in unresponsive_engines %} <p>{% for engine_name, error_type in unresponsive_engines %}
{{ engine_name }} ({{ error_type }}){% if not loop.last %}, {% endif %} {{- engine_name }} ({{- error_type -}}){% if not loop.last %}, {% endif %}
{% endfor %}</p> {% endfor %}</p>
</div> </div>
{% endif %} {% endif %}
{% if infoboxes %} {% if infoboxes %}
<div id="infoboxes"> <div id="infoboxes">
{% for infobox in infoboxes %} {% for infobox in infoboxes -%}
{% include 'simple/infobox.html' %} {% include 'simple/infobox.html' %}
{% endfor %} {%- endfor %}
</div> </div>
{% endif %} {% endif %}
@ -56,7 +63,7 @@
<div id="search_url"> <div id="search_url">
<h4 class="title">{{ _('Search URL') }} :</h4> <h4 class="title">{{ _('Search URL') }} :</h4>
<div><pre>{{ base_url }}?q={{ q|urlencode }}&amp;language={{ current_language }}&amp;time_range={{ time_range }}&amp;safesearch={{ safesearch }}{% if pageno > 1 %}&amp;pageno={{ pageno }}{% endif %}{% if selected_categories %}&amp;categories={{ selected_categories|join(",") | replace(' ','+') }}{% endif %}</pre></div> <div class="selectable_url"><pre>{{ base_url }}?q={{ q|urlencode }}&amp;language={{ current_language }}&amp;time_range={{ time_range }}&amp;safesearch={{ safesearch }}{% if pageno > 1 %}&amp;pageno={{ pageno }}{% endif %}{% if selected_categories %}&amp;categories={{ selected_categories|join(",") | replace(' ','+') }}{% endif %}</pre></div>
</div> </div>
<div id="apis"> <div id="apis">
<h4 class="title">{{ _('Download results') }}</h4> <h4 class="title">{{ _('Download results') }}</h4>

View File

@ -2,6 +2,7 @@
<div id="search_wrapper"> <div id="search_wrapper">
<div class="search_box"> <div class="search_box">
<input id="q" name="q" type="text" placeholder="{{ _('Search for...') }}" tabindex="1" autocomplete="off" spellcheck="false" dir="auto" {% if q %}value="{{ q }}"{% endif %} > <input id="q" name="q" type="text" placeholder="{{ _('Search for...') }}" tabindex="1" autocomplete="off" spellcheck="false" dir="auto" {% if q %}value="{{ q }}"{% endif %} >
<button id="clear_search" type="button" tabindex="-1"><span class="hide_if_nojs">{{ icon('close') }}</span><span class="show_if_nojs">{{ _('Clear search') }}</span></button>
<button id="send_search" type="submit" tabindex="-1"><span class="hide_if_nojs">{{ icon('search') }}</span><span class="show_if_nojs">{{ _('Start search') }}</span></button> <button id="send_search" type="submit" tabindex="-1"><span class="hide_if_nojs">{{ icon('search') }}</span><span class="show_if_nojs">{{ _('Start search') }}</span></button>
</div> </div>
<div class="search_filters"> <div class="search_filters">

View File

@ -3,14 +3,14 @@
# This file is distributed under the same license as the PROJECT project. # This file is distributed under the same license as the PROJECT project.
# #
# Translators: # Translators:
# ButterflyOfFire, 2017-2018 # ButterflyOfFire <ButterflyOfFire@protonmail.com>, 2017-2018
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: searx\n" "Project-Id-Version: searx\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
"POT-Creation-Date: 2017-11-01 21:31+0100\n" "POT-Creation-Date: 2017-11-01 21:31+0100\n"
"PO-Revision-Date: 2018-01-23 17:54+0000\n" "PO-Revision-Date: 2018-01-23 17:54+0000\n"
"Last-Translator: ButterflyOfFire\n" "Last-Translator: ButterflyOfFire <ButterflyOfFire@protonmail.com>\n"
"Language-Team: Arabic (http://www.transifex.com/asciimoo/searx/language/ar/)\n" "Language-Team: Arabic (http://www.transifex.com/asciimoo/searx/language/ar/)\n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"

View File

@ -3,14 +3,15 @@
# This file is distributed under the same license as the PROJECT project. # This file is distributed under the same license as the PROJECT project.
# #
# Translators: # Translators:
# Mikkel Kirkgaard Nielsen <memb_transifex@mikini.dk>, 2018
# Morten Krogh Andersen <spam1@krogh.net>, 2017 # Morten Krogh Andersen <spam1@krogh.net>, 2017
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: searx\n" "Project-Id-Version: searx\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
"POT-Creation-Date: 2017-11-01 21:31+0100\n" "POT-Creation-Date: 2017-11-01 21:31+0100\n"
"PO-Revision-Date: 2017-11-01 20:31+0000\n" "PO-Revision-Date: 2018-02-22 01:48+0000\n"
"Last-Translator: Adam Tauber <asciimoo@gmail.com>\n" "Last-Translator: Mikkel Kirkgaard Nielsen <memb_transifex@mikini.dk>\n"
"Language-Team: Danish (http://www.transifex.com/asciimoo/searx/language/da/)\n" "Language-Team: Danish (http://www.transifex.com/asciimoo/searx/language/da/)\n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
@ -21,15 +22,15 @@ msgstr ""
#: searx/search.py:137 searx/search.py:182 #: searx/search.py:137 searx/search.py:182
msgid "timeout" msgid "timeout"
msgstr "" msgstr "tidsudløb"
#: searx/search.py:144 #: searx/search.py:144
msgid "request exception" msgid "request exception"
msgstr "" msgstr "forespørgsels-undtagelse"
#: searx/search.py:151 #: searx/search.py:151
msgid "unexpected crash" msgid "unexpected crash"
msgstr "" msgstr "uventet nedlukning"
#: searx/webapp.py:136 #: searx/webapp.py:136
msgid "files" msgid "files"
@ -77,7 +78,7 @@ msgstr "Ugyldige indstillinger, redigér venligst dine valg"
#: searx/webapp.py:415 #: searx/webapp.py:415
msgid "Invalid settings" msgid "Invalid settings"
msgstr "" msgstr "Ugyldig indstilling"
#: searx/webapp.py:449 searx/webapp.py:493 #: searx/webapp.py:449 searx/webapp.py:493
msgid "search error" msgid "search error"
@ -143,7 +144,7 @@ msgstr "Denne værdi er blevet overskrevet af"
#: searx/engines/pubmed.py:74 #: searx/engines/pubmed.py:74
msgid "No abstract is available for this publication." msgid "No abstract is available for this publication."
msgstr "" msgstr "Intet sammendrag er tilgængelig for denne publikation."
#: searx/plugins/https_rewrite.py:32 #: searx/plugins/https_rewrite.py:32
msgid "Rewrite HTTP links to HTTPS if possible" msgid "Rewrite HTTP links to HTTPS if possible"
@ -159,7 +160,7 @@ msgstr "Indlæs automatisk næste side, når der scrolles til bunden af den nuv
#: searx/plugins/oa_doi_rewrite.py:9 #: searx/plugins/oa_doi_rewrite.py:9
msgid "Open Access DOI rewrite" msgid "Open Access DOI rewrite"
msgstr "" msgstr "Open Access DOI-omskrivning"
#: searx/plugins/oa_doi_rewrite.py:10 #: searx/plugins/oa_doi_rewrite.py:10
msgid "" msgid ""
@ -630,11 +631,11 @@ msgstr "viderestillet"
#: searx/templates/oscar/macros.html:92 #: searx/templates/oscar/macros.html:92
msgid "supported" msgid "supported"
msgstr "" msgstr "understøttet"
#: searx/templates/oscar/macros.html:96 #: searx/templates/oscar/macros.html:96
msgid "not supported" msgid "not supported"
msgstr "" msgstr "ikke-understøttet"
#: searx/templates/oscar/preferences.html:13 #: searx/templates/oscar/preferences.html:13
#: searx/templates/oscar/preferences.html:22 #: searx/templates/oscar/preferences.html:22
@ -712,13 +713,13 @@ msgstr "Stil"
#: searx/templates/oscar/preferences.html:122 #: searx/templates/oscar/preferences.html:122
msgid "Open Access DOI resolver" msgid "Open Access DOI resolver"
msgstr "" msgstr "Open Access DOI-forløser"
#: searx/templates/oscar/preferences.html:123 #: searx/templates/oscar/preferences.html:123
msgid "" msgid ""
"Redirect to open-access versions of publications when available (plugin " "Redirect to open-access versions of publications when available (plugin "
"required)" "required)"
msgstr "" msgstr "Omdiriger til open-access-udgaver af publikationer hvis tilgængelig (plugin påkrævet)"
#: searx/templates/oscar/preferences.html:163 #: searx/templates/oscar/preferences.html:163
#: searx/templates/oscar/preferences.html:175 #: searx/templates/oscar/preferences.html:175
@ -729,7 +730,7 @@ msgstr "Genvej"
#: searx/templates/oscar/preferences.html:164 #: searx/templates/oscar/preferences.html:164
#: searx/templates/oscar/preferences.html:174 #: searx/templates/oscar/preferences.html:174
msgid "Selected language" msgid "Selected language"
msgstr "" msgstr "Valgt sprog"
#: searx/templates/oscar/preferences.html:166 #: searx/templates/oscar/preferences.html:166
#: searx/templates/oscar/preferences.html:172 #: searx/templates/oscar/preferences.html:172
@ -789,13 +790,13 @@ msgstr "Værdi"
#: searx/templates/oscar/preferences.html:301 #: searx/templates/oscar/preferences.html:301
msgid "Search URL of the currently saved preferences" msgid "Search URL of the currently saved preferences"
msgstr "" msgstr "Søge-URL for den nuværende gemte indstilling"
#: searx/templates/oscar/preferences.html:301 #: searx/templates/oscar/preferences.html:301
msgid "" msgid ""
"Note: specifying custom settings in the search URL can reduce privacy by " "Note: specifying custom settings in the search URL can reduce privacy by "
"leaking data to the clicked result sites." "leaking data to the clicked result sites."
msgstr "" msgstr "Bemærk: brugertilpassede indstillinger i søge-URL kan reducere niveauet af beskyttelse ved at lække data til de sider der klikkes på i resultatet."
#: searx/templates/oscar/results.html:17 #: searx/templates/oscar/results.html:17
msgid "Search results" msgid "Search results"
@ -804,12 +805,12 @@ msgstr "Søgereresultater"
#: searx/templates/oscar/results.html:21 #: searx/templates/oscar/results.html:21
#: searx/templates/simple/results.html:84 #: searx/templates/simple/results.html:84
msgid "Try searching for:" msgid "Try searching for:"
msgstr "" msgstr "Prøv at søge efter:"
#: searx/templates/oscar/results.html:100 #: searx/templates/oscar/results.html:100
#: searx/templates/simple/results.html:25 #: searx/templates/simple/results.html:25
msgid "Engines cannot retrieve results" msgid "Engines cannot retrieve results"
msgstr "" msgstr "Søgemotorer kan ikke hente resultater"
#: searx/templates/oscar/results.html:131 #: searx/templates/oscar/results.html:131
msgid "Links" msgid "Links"
@ -874,12 +875,12 @@ msgstr "Der er pt. ingen tilgængelige data"
#: searx/templates/oscar/messages/no_results.html:4 #: searx/templates/oscar/messages/no_results.html:4
#: searx/templates/simple/messages/no_results.html:4 #: searx/templates/simple/messages/no_results.html:4
msgid "Engines cannot retrieve results." msgid "Engines cannot retrieve results."
msgstr "" msgstr "Søgemotorer kan ikke hente resultater."
#: searx/templates/oscar/messages/no_results.html:10 #: searx/templates/oscar/messages/no_results.html:10
#: searx/templates/simple/messages/no_results.html:10 #: searx/templates/simple/messages/no_results.html:10
msgid "Please, try again later or find another searx instance." msgid "Please, try again later or find another searx instance."
msgstr "" msgstr "Vær venlig at prøve igen senere, eller find en anden searx-instans."
#: searx/templates/oscar/messages/no_results.html:14 #: searx/templates/oscar/messages/no_results.html:14
#: searx/templates/simple/messages/no_results.html:14 #: searx/templates/simple/messages/no_results.html:14
@ -998,7 +999,7 @@ msgstr "Indlæs mere..."
#: searx/templates/simple/base.html:31 #: searx/templates/simple/base.html:31
msgid "No item found" msgid "No item found"
msgstr "" msgstr "Intet fundet"
#: searx/templates/simple/preferences.html:89 #: searx/templates/simple/preferences.html:89
msgid "Supports selected language" msgid "Supports selected language"
@ -1006,8 +1007,8 @@ msgstr "Undstøtter valgte sprog"
#: searx/templates/simple/preferences.html:118 #: searx/templates/simple/preferences.html:118
msgid "User interface" msgid "User interface"
msgstr "" msgstr "Brugerinterface"
#: searx/templates/simple/preferences.html:154 #: searx/templates/simple/preferences.html:154
msgid "Privacy" msgid "Privacy"
msgstr "" msgstr "Privatliv"

View File

@ -3,15 +3,15 @@
# This file is distributed under the same license as the PROJECT project. # This file is distributed under the same license as the PROJECT project.
# #
# Translators: # Translators:
# GR01D, 2018 # gr01d, 2018
# GR01D, 2018 # gr01d, 2018
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: searx\n" "Project-Id-Version: searx\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
"POT-Creation-Date: 2017-11-01 21:31+0100\n" "POT-Creation-Date: 2017-11-01 21:31+0100\n"
"PO-Revision-Date: 2018-02-18 04:45+0000\n" "PO-Revision-Date: 2018-02-18 04:45+0000\n"
"Last-Translator: GR01D\n" "Last-Translator: gr01d\n"
"Language-Team: Filipino (http://www.transifex.com/asciimoo/searx/language/fil/)\n" "Language-Team: Filipino (http://www.transifex.com/asciimoo/searx/language/fil/)\n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"

Binary file not shown.

File diff suppressed because it is too large Load Diff

View File

@ -8,14 +8,14 @@
# Guimarães Mello <maeslor@cryptolab.net>, 2017 # Guimarães Mello <maeslor@cryptolab.net>, 2017
# Neton Brício <fervelinux@gmail.com>, 2015 # Neton Brício <fervelinux@gmail.com>, 2015
# pizzaiolo, 2016 # pizzaiolo, 2016
# Shizuka 静香 <deusadaji@gmail.com>, 2018 # shizuka, 2018
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: searx\n" "Project-Id-Version: searx\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
"POT-Creation-Date: 2017-11-01 21:31+0100\n" "POT-Creation-Date: 2017-11-01 21:31+0100\n"
"PO-Revision-Date: 2018-02-04 10:39+0000\n" "PO-Revision-Date: 2018-03-03 12:33+0000\n"
"Last-Translator: Shizuka 静香 <deusadaji@gmail.com>\n" "Last-Translator: shizuka\n"
"Language-Team: Portuguese (Brazil) (http://www.transifex.com/asciimoo/searx/language/pt_BR/)\n" "Language-Team: Portuguese (Brazil) (http://www.transifex.com/asciimoo/searx/language/pt_BR/)\n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
@ -778,7 +778,7 @@ msgstr "Exemplos"
msgid "" msgid ""
"This is the list of cookies and their values searx is storing on your " "This is the list of cookies and their values searx is storing on your "
"computer." "computer."
msgstr "Esta é a lista de cookies que searx está armazenando em seu computador." msgstr "Esta é a lista de cookies que o searx está armazenando em seu computador."
#: searx/templates/oscar/preferences.html:276 #: searx/templates/oscar/preferences.html:276
msgid "With that list, you can assess searx transparency." msgid "With that list, you can assess searx transparency."

View File

@ -7,14 +7,15 @@
# dimqua <dimqua@riseup.net>, 2015 # dimqua <dimqua@riseup.net>, 2015
# dimqua <dimqua@riseup.net>, 2015 # dimqua <dimqua@riseup.net>, 2015
# dimqua <dimqua@riseup.net>, 2017 # dimqua <dimqua@riseup.net>, 2017
# John DOe <is-kir@ya.ru>, 2018
# Дмитрий Михирев, 2016-2017 # Дмитрий Михирев, 2016-2017
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: searx\n" "Project-Id-Version: searx\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
"POT-Creation-Date: 2017-11-01 21:31+0100\n" "POT-Creation-Date: 2017-11-01 21:31+0100\n"
"PO-Revision-Date: 2017-12-27 10:02+0000\n" "PO-Revision-Date: 2018-02-26 16:39+0000\n"
"Last-Translator: Andrey\n" "Last-Translator: John DOe <is-kir@ya.ru>\n"
"Language-Team: Russian (http://www.transifex.com/asciimoo/searx/language/ru/)\n" "Language-Team: Russian (http://www.transifex.com/asciimoo/searx/language/ru/)\n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
@ -29,7 +30,7 @@ msgstr "таймаут"
#: searx/search.py:144 #: searx/search.py:144
msgid "request exception" msgid "request exception"
msgstr "запрос исключен" msgstr "ошибка выполнения запроса"
#: searx/search.py:151 #: searx/search.py:151
msgid "unexpected crash" msgid "unexpected crash"
@ -447,7 +448,7 @@ msgstr "Блокировать"
msgid "" msgid ""
"These settings are stored in your cookies, this allows us not to store this " "These settings are stored in your cookies, this allows us not to store this "
"data about you." "data about you."
msgstr "Настройки хранятся в ваших файлах cookie, что позволяет нам не сохранять эти сведения о вас." msgstr "Настройки сохраняются в ваших файлах cookie, что позволяет нам не хранить никаких сведений о вас."
#: searx/templates/courgette/preferences.html:124 #: searx/templates/courgette/preferences.html:124
#: searx/templates/legacy/preferences.html:121 #: searx/templates/legacy/preferences.html:121
@ -457,7 +458,7 @@ msgstr "Настройки хранятся в ваших файлах cookie,
msgid "" msgid ""
"These cookies serve your sole convenience, we don't use these cookies to " "These cookies serve your sole convenience, we don't use these cookies to "
"track you." "track you."
msgstr "Эти файлы cookie используются для вашего удобства, мы не используем их чтобы отслеживать вас." msgstr "Эти файлы используются исключительно для вашего удобства, мы не отслеживаем вашу активность."
#: searx/templates/courgette/preferences.html:127 #: searx/templates/courgette/preferences.html:127
#: searx/templates/legacy/preferences.html:124 #: searx/templates/legacy/preferences.html:124
@ -685,7 +686,7 @@ msgstr "Поисковые предложения по мере ввода"
#: searx/templates/oscar/preferences.html:69 #: searx/templates/oscar/preferences.html:69
#: searx/templates/simple/preferences.html:173 #: searx/templates/simple/preferences.html:173
msgid "Proxying image results through searx" msgid "Proxying image results through searx"
msgstr "Проксировать найденные изображения с помощью searx" msgstr "Загружать найденные изображения через searx"
#: searx/templates/oscar/preferences.html:78 #: searx/templates/oscar/preferences.html:78
msgid "" msgid ""

View File

@ -4,14 +4,18 @@ import hmac
import os import os
import re import re
from babel.core import get_global
from babel.dates import format_date from babel.dates import format_date
from codecs import getincrementalencoder from codecs import getincrementalencoder
from imp import load_source from imp import load_source
from numbers import Number from numbers import Number
from os.path import splitext, join from os.path import splitext, join
from io import open
from random import choice from random import choice
import sys import sys
import json
from searx import settings
from searx.version import VERSION_STRING from searx.version import VERSION_STRING
from searx.languages import language_codes from searx.languages import language_codes
from searx import settings from searx import settings
@ -31,33 +35,17 @@ if sys.version_info[0] == 3:
unichr = chr unichr = chr
unicode = str unicode = str
IS_PY2 = False IS_PY2 = False
basestring = str
else: else:
IS_PY2 = True IS_PY2 = True
logger = logger.getChild('utils') logger = logger.getChild('utils')
ua_versions = ('40.0',
'41.0',
'42.0',
'43.0',
'44.0',
'45.0',
'46.0',
'47.0')
ua_os = ('Windows NT 6.3; WOW64',
'X11; Linux x86_64',
'X11; Linux x86')
ua = "Mozilla/5.0 ({os}; rv:{version}) Gecko/20100101 Firefox/{version}"
blocked_tags = ('script', blocked_tags = ('script',
'style') 'style')
useragents = json.loads(open(os.path.dirname(os.path.realpath(__file__))
def gen_useragent(): + "/data/useragents.json", 'r', encoding='utf-8').read())
# TODO
return ua.format(os=choice(ua_os), version=choice(ua_versions))
def searx_useragent(): def searx_useragent():
@ -66,6 +54,10 @@ def searx_useragent():
suffix=settings['outgoing'].get('useragent_suffix', '')) suffix=settings['outgoing'].get('useragent_suffix', ''))
def gen_useragent(os=None):
return str(useragents['ua'].format(os=os or choice(useragents['os']), version=choice(useragents['versions'])))
def highlight_content(content, query): def highlight_content(content, query):
if not content: if not content:
@ -322,6 +314,65 @@ def is_valid_lang(lang):
return False return False
# auxiliary function to match lang_code in lang_list
def _match_language(lang_code, lang_list=[], custom_aliases={}):
# replace language code with a custom alias if necessary
if lang_code in custom_aliases:
lang_code = custom_aliases[lang_code]
if lang_code in lang_list:
return lang_code
# try to get the most likely country for this language
subtags = get_global('likely_subtags').get(lang_code)
if subtags:
subtag_parts = subtags.split('_')
new_code = subtag_parts[0] + '-' + subtag_parts[-1]
if new_code in custom_aliases:
new_code = custom_aliases[new_code]
if new_code in lang_list:
return new_code
# try to get the any supported country for this language
for lc in lang_list:
if lang_code == lc.split('-')[0]:
return lc
return None
# get the language code from lang_list that best matches locale_code
def match_language(locale_code, lang_list=[], custom_aliases={}, fallback='en-US'):
# try to get language from given locale_code
language = _match_language(locale_code, lang_list, custom_aliases)
if language:
return language
locale_parts = locale_code.split('-')
lang_code = locale_parts[0]
# try to get language using an equivalent country code
if len(locale_parts) > 1:
country_alias = get_global('territory_aliases').get(locale_parts[-1])
if country_alias:
language = _match_language(lang_code + '-' + country_alias[0], lang_list, custom_aliases)
if language:
return language
# try to get language using an equivalent language code
alias = get_global('language_aliases').get(lang_code)
if alias:
language = _match_language(alias, lang_list, custom_aliases)
if language:
return language
if lang_code != locale_code:
# try to get language from given language without giving the country
language = _match_language(lang_code, lang_list, custom_aliases)
return language or fallback
def load_module(filename, module_dir): def load_module(filename, module_dir):
modname = splitext(filename)[0] modname = splitext(filename)[0]
if modname in sys.modules: if modname in sys.modules:

View File

@ -58,16 +58,16 @@ from searx.engines import (
from searx.utils import ( from searx.utils import (
UnicodeWriter, highlight_content, html_to_text, get_resources_directory, UnicodeWriter, highlight_content, html_to_text, get_resources_directory,
get_static_files, get_result_templates, get_themes, gen_useragent, get_static_files, get_result_templates, get_themes, gen_useragent,
dict_subset, prettify_url dict_subset, prettify_url, match_language
) )
from searx.version import VERSION_STRING from searx.version import VERSION_STRING
from searx.languages import language_codes from searx.languages import language_codes as languages
from searx.search import SearchWithPlugins, get_search_query_from_webapp from searx.search import SearchWithPlugins, get_search_query_from_webapp
from searx.query import RawTextQuery from searx.query import RawTextQuery
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.plugins.oa_doi_rewrite import get_doi_resolver from searx.plugins.oa_doi_rewrite import get_doi_resolver
from searx.preferences import Preferences, ValidationException from searx.preferences import Preferences, ValidationException, LANGUAGE_CODES
from searx.answerers import answerers from searx.answerers import answerers
from searx.url_utils import urlencode, urlparse, urljoin from searx.url_utils import urlencode, urlparse, urljoin
from searx.utils import new_hmac from searx.utils import new_hmac
@ -133,7 +133,7 @@ if not searx_debug \
babel = Babel(app) babel = Babel(app)
rtl_locales = ['ar', 'arc', 'bcc', 'bqi', 'ckb', 'dv', 'fa', 'glk', 'he', rtl_locales = ['ar', 'arc', 'bcc', 'bqi', 'ckb', 'dv', 'fa', 'glk', 'he',
'ku', 'mzn', 'pnb'', ''ps', 'sd', 'ug', 'ur', 'yi'] 'ku', 'mzn', 'pnb', 'ps', 'sd', 'ug', 'ur', 'yi']
# used when translating category names # used when translating category names
_category_names = (gettext('files'), _category_names = (gettext('files'),
@ -352,9 +352,11 @@ def render(template_name, override_theme=None, **kwargs):
kwargs['safesearch'] = str(request.preferences.get_value('safesearch')) kwargs['safesearch'] = str(request.preferences.get_value('safesearch'))
kwargs['language_codes'] = language_codes kwargs['language_codes'] = languages
if 'current_language' not in kwargs: if 'current_language' not in kwargs:
kwargs['current_language'] = request.preferences.get_value('language') kwargs['current_language'] = match_language(request.preferences.get_value('language'),
LANGUAGE_CODES,
fallback=settings['search']['language'])
# override url_for function in templates # override url_for function in templates
kwargs['url_for'] = url_for_theme kwargs['url_for'] = url_for_theme
@ -590,7 +592,9 @@ def index():
infoboxes=result_container.infoboxes, infoboxes=result_container.infoboxes,
paging=result_container.paging, paging=result_container.paging,
unresponsive_engines=result_container.unresponsive_engines, unresponsive_engines=result_container.unresponsive_engines,
current_language=search_query.lang, current_language=match_language(search_query.lang,
LANGUAGE_CODES,
fallback=settings['search']['language']),
base_url=get_base_url(), base_url=get_base_url(),
theme=get_current_theme_name(), theme=get_current_theme_name(),
favicons=global_favicons[themes.index(get_current_theme_name())] favicons=global_favicons[themes.index(get_current_theme_name())]
@ -687,6 +691,10 @@ def preferences():
'warn_time': False} 'warn_time': False}
if e.timeout > settings['outgoing']['request_timeout']: if e.timeout > settings['outgoing']['request_timeout']:
stats[e.name]['warn_timeout'] = True stats[e.name]['warn_timeout'] = True
if match_language(request.preferences.get_value('language'),
getattr(e, 'supported_languages', []),
getattr(e, 'language_aliases', {}), None):
stats[e.name]['supports_selected_language'] = True
# get first element [0], the engine time, # get first element [0], the engine time,
# and then the second element [1] : the time (the first one is the label) # and then the second element [1] : the time (the first one is the label)
@ -855,7 +863,7 @@ def config():
'safe_search': settings['search']['safe_search'], 'safe_search': settings['search']['safe_search'],
'default_theme': settings['ui']['default_theme'], 'default_theme': settings['ui']['default_theme'],
'version': VERSION_STRING, 'version': VERSION_STRING,
'doi_resolvers': [r for r in search['doi_resolvers']], 'doi_resolvers': [r for r in settings['doi_resolvers']],
'default_doi_resolver': settings['default_doi_resolver'], 'default_doi_resolver': settings['default_doi_resolver'],
}) })

Some files were not shown because too many files have changed in this diff Show More