[enh] add simple theme (WIP)

This commit is contained in:
Alexandre Flament 2017-02-12 15:06:01 +01:00
parent 4f6586d808
commit 10a24bdc2c
85 changed files with 11902 additions and 6 deletions

10
.gitattributes vendored Normal file
View file

@ -0,0 +1,10 @@
searx/static/css/bootstrap.min.css -diff
searx/static/js/bootstrap.min.js -diff
searx/static/themes/oscar/css/logicodev.min.css -diff
searx/static/themes/oscar/css/leaflet.min.css -diff
searx/static/themes/oscar/css/pointhi.min.css -diff
searx/static/themes/oscar/js/searx.min.js -diff
searx/static/themes/simple/css/searx.min.css -diff
searx/static/themes/simple/css/searx-rtl.min.css -diff
searx/static/themes/simple/js/searx.min.js -diff
searx/static/themes/simple/js/searx.min.js.map -diff

View file

@ -13,10 +13,11 @@ python:
before_install:
- "export DISPLAY=:99.0"
- "sh -e /etc/init.d/xvfb start"
- npm install less grunt-cli
- npm install less less-plugin-clean-css grunt-cli
- ( cd searx/static/themes/oscar;npm install; cd - )
- ( cd searx/static/themes/simple;npm install; cd - )
- mkdir -p ~/drivers; export PATH=~/drivers:$PATH;
- GECKODRIVER_URL="https://github.com/mozilla/geckodriver/releases/download/v0.11.1/geckodriver-v0.11.1-linux64.tar.gz";
- GECKODRIVER_URL="https://github.com/mozilla/geckodriver/releases/download/v0.14.0/geckodriver-v0.14.0-linux64.tar.gz";
- FILE=`mktemp`; wget "$GECKODRIVER_URL" -qO $FILE && tar xz -C ~/drivers -f $FILE geckodriver; rm $FILE; chmod 777 ~/drivers/geckodriver;
install:
- ./manage.sh update_dev_packages

View file

@ -22,7 +22,7 @@ check_geckodriver() {
if [ -z $NOTFOUND ]; then
return
fi
GECKODRIVER_VERSION="v0.11.1"
GECKODRIVER_VERSION="v0.14.0"
PLATFORM=`python -c "import platform; print platform.system().lower(), platform.architecture()[0]"`
case $PLATFORM in
"linux 32bit" | "linux2 32bit") ARCH="linux32";;
@ -49,7 +49,7 @@ pep8_check() {
# ignored rules:
# E402 module level import not at top of file
# W503 line break before binary operator
pep8 --max-line-length=120 --ignore "E402,W503" "$SEARX_DIR" "$BASE_DIR/tests"
pep8 --exclude=searx/static --max-line-length=120 --ignore "E402,W503" "$SEARX_DIR" "$BASE_DIR/tests"
}
unit_tests() {
@ -79,7 +79,8 @@ tests() {
}
build_style() {
lessc -x "$BASE_DIR/searx/static/$1" "$BASE_DIR/searx/static/$2"
# lessc -x "$BASE_DIR/searx/static/$1" "$BASE_DIR/searx/static/$2"
lessc --clean-css="--s1 --advanced --compatibility=ie9" "$BASE_DIR/searx/static/$1" "$BASE_DIR/searx/static/$2"
}
styles() {
@ -92,10 +93,13 @@ styles() {
build_style themes/oscar/less/pointhi/oscar.less themes/oscar/css/pointhi.min.css
build_style themes/oscar/less/logicodev/oscar.less themes/oscar/css/logicodev.min.css
build_style themes/pix-art/less/style.less themes/pix-art/css/style.css
build_style themes/simple/less/style.less themes/simple/css/searx.min.css
build_style themes/simple/less/style-rtl.less themes/simple/css/searx-rtl.min.css
}
grunt_build() {
grunt --gruntfile "$SEARX_DIR/static/themes/oscar/gruntfile.js"
grunt --gruntfile "$SEARX_DIR/static/themes/simple/gruntfile.js"
}
locales() {

View file

@ -7,6 +7,7 @@ regex = re.compile(r'10\.\d{4,9}/[^\s]+')
name = gettext('DOAI rewrite')
description = gettext('Avoid paywalls by redirecting to open-access versions of publications when available')
default_on = False
preference_section = 'privacy'
def extract_doi(url):

View file

@ -31,6 +31,7 @@ if sys.version_info[0] == 3:
name = "HTTPS rewrite"
description = gettext('Rewrite HTTP links to HTTPS if possible')
default_on = True
preference_section = 'privacy'
if 'SEARX_HTTPS_REWRITE_PATH' in environ:
rules_path = environ['SEARX_rules_path']

View file

@ -3,6 +3,7 @@ from flask_babel import gettext
name = gettext('Infinite scroll')
description = gettext('Automatically load next page when scrolling to bottom of current page')
default_on = False
preference_section = 'ui'
js_dependencies = ('plugins/js/infinite_scroll.js',)
css_dependencies = ('plugins/css/infinite_scroll.css',)

View file

@ -19,5 +19,6 @@ name = gettext('Search on category select')
description = gettext('Perform search immediately if a category selected. '
'Disable to select multiple categories. (JavaScript required)')
default_on = True
preference_section = 'ui'
js_dependencies = ('plugins/js/search_on_category_select.js',)

View file

@ -26,6 +26,7 @@ regexes = {re.compile(r'utm_[^&]+&?'),
name = gettext('Tracker URL remover')
description = gettext('Remove trackers arguments from the returned URL')
default_on = True
preference_section = 'privacy'
def on_result(request, search, result):

View file

@ -0,0 +1 @@
js/searx_src/autocomplete.js

File diff suppressed because it is too large Load diff

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load diff

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,134 @@
/* Generated by grunt-webfont */
@font-face {
font-family:"ion";
src:url("../fonts/ion.eot?94af7082ea096aefe3a7b6642834716e");
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");
font-weight:normal;
font-style:normal;
}
.ion-icon {
font-family:"ion";
display:inline-block;
vertical-align:middle;
line-height:1;
font-weight:normal;
font-style:normal;
speak:none;
text-decoration:inherit;
text-transform:none;
text-rendering:auto;
-webkit-font-smoothing:antialiased;
-moz-osx-font-smoothing:grayscale;
}
/* Icons */
.ion-navicon-round:before {
content:"\f101";
}
.ion-search:before {
content:"\f102";
}
.ion-play:before {
content:"\f103";
}
.ion-link:before {
content:"\f104";
}
.ion-chevron-up:before {
content:"\f105";
}
.ion-chevron-left:before {
content:"\f106";
}
.ion-chevron-right:before {
content:"\f107";
}
.ion-arrow-down-a:before {
content:"\f108";
}
.ion-arrow-up-a:before {
content:"\f109";
}
.ion-arrow-swap:before {
content:"\f10a";
}
.ion-arrow-dropdown:before {
content:"\f10b";
}
.ion-globe:before {
content:"\f10c";
}
.ion-time:before {
content:"\f10d";
}
.ion-location:before {
content:"\f10e";
}
.ion-warning:before {
content:"\f10f";
}
.ion-error:before {
content:"\f110";
}
.ion-film-outline:before {
content:"\f111";
}
.ion-music-note:before {
content:"\f112";
}
.ion-more-vertical:before {
content:"\f113";
}
.ion-magnet:before {
content:"\f114";
}

Binary file not shown.

View file

@ -0,0 +1,261 @@
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>ion</title>
<style>
body {
margin:0;
padding:10px 20px;
background:#fff;
color:#222;
}
h1, div, footer {
font-family:"Helvetica Neue", Arial, sans-serif;
}
h1 {
margin:0 0 20px;
font-size:32px;
font-weight:normal;
}
h1 small {
font-size: 0.8em;
padding-left: 2em;
}
.icons {
margin-bottom:40px;
-webkit-column-count:5;
-moz-column-count:5;
column-count:5;
-webkit-column-gap:20px;
-moz-column-gap:20px;
column-gap:20px;
}
.icons__item,
.icons__item i {
line-height:2em;
cursor:pointer;
overflow:hidden;
}
.icons__item:hover {
color:#3c90be;
}
.icons__item i {
display:inline-block;
width:32px;
text-align:center;
}
.icons__item:hover i {
-webkit-transform:scale(1.5);
transform:scale(1.5);
}
footer {
margin-top:40px;
font-size:14px;
color:#999;
}
/* Generated by grunt-webfont */
@font-face {
font-family:"ion";
src:url("ion.eot?94af7082ea096aefe3a7b6642834716e");
src:url("ion.eot?#iefix") format("embedded-opentype"),
url("ion.woff2?94af7082ea096aefe3a7b6642834716e") format("woff2"),
url("ion.woff?94af7082ea096aefe3a7b6642834716e") format("woff"),
url("ion.ttf?94af7082ea096aefe3a7b6642834716e") format("truetype"),
url("ion.svg?94af7082ea096aefe3a7b6642834716e#ion") format("svg");
font-weight:normal;
font-style:normal;
}
.ion-icon {
font-family:"ion";
display:inline-block;
vertical-align:middle;
line-height:1;
font-weight:normal;
font-style:normal;
speak:none;
text-decoration:inherit;
text-transform:none;
text-rendering:auto;
-webkit-font-smoothing:antialiased;
-moz-osx-font-smoothing:grayscale;
}
/* Icons */
.ion-navicon-round:before {
content:"\f101";
}
.ion-search:before {
content:"\f102";
}
.ion-play:before {
content:"\f103";
}
.ion-link:before {
content:"\f104";
}
.ion-chevron-up:before {
content:"\f105";
}
.ion-chevron-left:before {
content:"\f106";
}
.ion-chevron-right:before {
content:"\f107";
}
.ion-arrow-down-a:before {
content:"\f108";
}
.ion-arrow-up-a:before {
content:"\f109";
}
.ion-arrow-swap:before {
content:"\f10a";
}
.ion-arrow-dropdown:before {
content:"\f10b";
}
.ion-globe:before {
content:"\f10c";
}
.ion-time:before {
content:"\f10d";
}
.ion-location:before {
content:"\f10e";
}
.ion-warning:before {
content:"\f10f";
}
.ion-error:before {
content:"\f110";
}
.ion-film-outline:before {
content:"\f111";
}
.ion-music-note:before {
content:"\f112";
}
.ion-more-vertical:before {
content:"\f113";
}
.ion-magnet:before {
content:"\f114";
}
</style>
</head>
<body>
<h1>ion</h1>
<div class="icons" id="icons">
<div class="icons__item" data-name="navicon-round"><i class="ion-icon ion-navicon-round"></i> ion-navicon-round</div>
<div class="icons__item" data-name="search"><i class="ion-icon ion-search"></i> ion-search</div>
<div class="icons__item" data-name="play"><i class="ion-icon ion-play"></i> ion-play</div>
<div class="icons__item" data-name="link"><i class="ion-icon ion-link"></i> ion-link</div>
<div class="icons__item" data-name="chevron-up"><i class="ion-icon ion-chevron-up"></i> ion-chevron-up</div>
<div class="icons__item" data-name="chevron-left"><i class="ion-icon ion-chevron-left"></i> ion-chevron-left</div>
<div class="icons__item" data-name="chevron-right"><i class="ion-icon ion-chevron-right"></i> ion-chevron-right</div>
<div class="icons__item" data-name="arrow-down-a"><i class="ion-icon ion-arrow-down-a"></i> ion-arrow-down-a</div>
<div class="icons__item" data-name="arrow-up-a"><i class="ion-icon ion-arrow-up-a"></i> ion-arrow-up-a</div>
<div class="icons__item" data-name="arrow-swap"><i class="ion-icon ion-arrow-swap"></i> ion-arrow-swap</div>
<div class="icons__item" data-name="arrow-dropdown"><i class="ion-icon ion-arrow-dropdown"></i> ion-arrow-dropdown</div>
<div class="icons__item" data-name="globe"><i class="ion-icon ion-globe"></i> ion-globe</div>
<div class="icons__item" data-name="time"><i class="ion-icon ion-time"></i> ion-time</div>
<div class="icons__item" data-name="location"><i class="ion-icon ion-location"></i> ion-location</div>
<div class="icons__item" data-name="warning"><i class="ion-icon ion-warning"></i> ion-warning</div>
<div class="icons__item" data-name="error"><i class="ion-icon ion-error"></i> ion-error</div>
<div class="icons__item" data-name="film-outline"><i class="ion-icon ion-film-outline"></i> ion-film-outline</div>
<div class="icons__item" data-name="music-note"><i class="ion-icon ion-music-note"></i> ion-music-note</div>
<div class="icons__item" data-name="more-vertical"><i class="ion-icon ion-more-vertical"></i> ion-more-vertical</div>
<div class="icons__item" data-name="magnet"><i class="ion-icon ion-magnet"></i> ion-magnet</div>
</div>
<h1>Usage</h1>
<pre><code>&lt;i class=&quot;ion-icon ion-<span id="name">name</span>&quot;&gt;&lt;/i&gt;</code></pre>
<footer>Generated by <a href="https://github.com/sapegin/grunt-webfont">grunt-webfont</a>.</footer>
<script>
(function() {
document.getElementById('icons').onclick = function(e) {
e = e || window.event;
var name = e.target.getAttribute('data-name') || e.target.parentNode.getAttribute('data-name');
document.getElementById('name').innerHTML = name;
}
})();
</script>
</body>
</html>

View file

@ -0,0 +1,97 @@
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" >
<!--
2017-5-26: Created.
-->
<svg xmlns="http://www.w3.org/2000/svg">
<metadata>
Created by FontForge 20120731 at Fri May 26 22:22:55 2017
By alexandre,,,
</metadata>
<defs>
<font id="ion" horiz-adv-x="512" >
<font-face
font-family="ion"
font-weight="500"
font-stretch="normal"
units-per-em="512"
panose-1="2 0 6 9 0 0 0 0 0 0"
ascent="448"
descent="-64"
bbox="31.9799 -31.9632 479.993 415.9"
underline-thickness="25.6"
underline-position="-51.2"
unicode-range="U+F101-F114"
/>
<missing-glyph />
<glyph glyph-name="arrow-down-a" unicode="&#xf108;"
d="M256.5 -0.5l-192 192h112v192h160v-192h112z" />
<glyph glyph-name="arrow-dropdown" unicode="&#xf10b;"
d="M128 256h256l-128 -128z" />
<glyph glyph-name="arrow-swap" unicode="&#xf10a;"
d="M64 120c0 4.40039 3.59961 7.99999 8 7.99999h248v64l128 -96l-128 -96v64h-248c-4.40039 0 -8 3.59961 -8 8v48zM448 264c0 -4.40039 -3.59961 -8 -8 -8h-248v-64l-128 96l128 96v-64h248c4.40039 0 8 -3.59961 8 -8v-48z" />
<glyph glyph-name="arrow-up-a" unicode="&#xf109;"
d="M256.5 383.5l192 -192h-112v-192h-160v192h-112z" />
<glyph glyph-name="chevron-left" unicode="&#xf106;"
d="M213.7 192l167.2 -174.2c4.19922 -4.2998 4.09961 -11.3994 -0.200195 -15.7998l-29.9004 -30.5996c-4.2998 -4.40039 -11.2998 -4.5 -15.5 -0.200191l-204.2 212.7c-2.09961 2.19922 -3.09961 5.09961 -3 8.09961c-0.199219 2.90039 0.800781 5.90039 3 8.09961
l204.2 212.601c4.2002 4.2998 11.2002 4.2002 15.5 -0.200195l29.9004 -30.5996c4.2998 -4.40039 4.39941 -11.5 0.200195 -15.8008l-167.2 -174.1v0v0z" />
<glyph glyph-name="chevron-right" unicode="&#xf107;"
d="M298.3 192v0v0l-167.2 174.1c-4.19922 4.30078 -4.09961 11.4004 0.200195 15.8008l29.9004 30.5996c4.2998 4.40039 11.2998 4.5 15.5 0.200195l204.2 -212.7c2.19922 -2.2002 3.19922 -5.2002 3 -8.09961c0.0996094 -3 -0.900391 -5.90039 -3 -8.10059l-204.2 -212.6
c-4.2002 -4.29981 -11.2002 -4.2002 -15.5 0.200191l-29.9004 30.5996c-4.2998 4.40039 -4.39941 11.5 -0.200195 15.7998z" />
<glyph glyph-name="chevron-up" unicode="&#xf105;"
d="M256 234.3l-174.2 -167.2c-4.2998 -4.19922 -11.3994 -4.09961 -15.7998 0.200195l-30.5996 29.9004c-4.40039 4.2998 -4.5 11.2998 -0.200195 15.5l212.7 204.2c2.19922 2.09961 5.09961 3.09961 8.09961 3c2.90039 0.199219 5.90039 -0.800781 8.09961 -3l212.7 -204.2
c4.2998 -4.2002 4.20016 -11.2002 -0.200226 -15.5l-30.5996 -29.9004c-4.40039 -4.2998 -11.5 -4.39941 -15.7998 -0.200195l-174.2 167.2v0v0z" />
<glyph glyph-name="error" unicode="&#xf110;"
d="M256 400c114.4 0 208 -93.6006 208 -208c0 -114.399 -93.5996 -208 -208 -208s-208 93.6006 -208 208c0 114.399 93.5996 208 208 208zM280 88v40h-48v-40h48zM280 176v128h-48v-128h48z" />
<glyph glyph-name="film-outline" unicode="&#xf111;"
d="M56 360h400v-336h-400v336zM128 40v48h-56v-48h56zM128 104v48h-56v-48h56zM128 168v48h-56v-48h56zM128 232v48h-56v-48h56zM128 296v48h-56v-48h56zM368 40v144h-224v-144h224zM368 200v144h-224v-144h224zM440 40v48h-56v-48h56zM440 104v48h-56v-48h56zM440 168v48
h-56v-48h56zM440 232v48h-56v-48h56zM440 296v48h-56v-48h56z" />
<glyph glyph-name="globe" unicode="&#xf10c;"
d="M256 400c114.875 0 208 -93.125 208 -208c0 -114.875 -93.125 -208 -208 -208c-114.876 0 -208 93.125 -208 208c0 114.875 93.124 208 208 208zM234.451 15.001c6.04297 15.0449 19.9453 28.6484 7.27342 39.1172c-8.17285 6.75 -15.6123 13.6279 -23.1104 21.125
c-2.47461 2.47363 -9.9082 19.7109 -8.35156 22.3916c5.10254 8.78613 5.76367 14.8613 8.12988 24.7236c2.94336 12.2627 -3.33398 15.4434 -13.3828 21.8389c-15.2256 9.68848 -28.9629 22.4844 -43.3223 33.4941c-7.11621 5.45508 -17.4355 10.0986 -20.0186 18.9521
c-2.64062 9.05078 -3.97363 20.2598 -9.40039 28.0781c-13.9277 20.0752 -11.5791 34.9678 -9.93945 58.7627c0.449219 6.52637 -1.30371 15.6572 -2.01367 24.1748c-27.5654 -32.2354 -42.6016 -72.7891 -42.6016 -115.659c0 -47.6221 18.5439 -92.3926 52.2178 -126.067
c28.541 -28.54 65.0557 -46.2061 104.52 -50.9316zM382.067 65.9326c23.0352 23.0381 38.9873 51.2695 46.7686 82.0527c-8.34668 -1.19141 -18.3838 2.22754 -18.3838 2.22754s-21.7363 23.707 -23.5244 44.5723c-1.85645 21.667 0.498047 38.3945 -2.89551 56.8105
c-2.87988 15.624 -19.2803 31.5 -26.6729 46.3018c-6.92188 13.8555 -13.7334 27.7031 -20.2646 41.7451c2.25098 -0.848633 4.90039 -1.40234 6.96484 -2.62305c4.99902 0.636719 9.43066 1.22949 13.4629 1.59082c-22.5381 15.6758 -48.2725 25.8418 -75.5225 29.7998
v-8.33887l3.55273 -9.27734l-13.7793 -12.9951l-8.6748 2.79492l-9.92383 10.2334l-9.94434 11.8008l-14.084 5.66016c-15.7227 -2.36133 -30.9336 -6.78711 -45.3096 -13.1523c0.360352 -2.30762 0.662109 -4.64453 0.662109 -7.13281
c7.17383 2.98926 15.2764 5.04883 22.4502 8.03906c2.96289 1.23438 12.7529 -7.1748 15.6221 -8.96777c-4.0957 -4.70996 -20.5576 -15.4434 -21.3574 -21.3574c-0.317383 -2.33984 6.50586 -6.06348 6.45117 -9.69141
c-0.0878906 -5.74609 -0.173828 -11.4912 -0.259766 -17.2373c3.24414 2.76172 20.0332 20.3672 21.9404 20.8594c12.7256 3.2832 34.3916 -17.7646 36.249 -25.1934c1.8584 -7.42871 -21.6514 -23.6826 -32.6113 -34.0469
c-8.39941 -7.94434 -24.8086 -12.5137 -19.8037 -24.2285c1.62695 -3.80957 10.0498 -20.0156 5.21191 -24.0586c-5.92188 -4.94824 -14.7686 8.97656 -17.3418 12.0938c-8.1543 9.87695 -25.626 6.02539 -37.9082 6.47852c0 -17.4209 -0.757812 -31.1885 14.9219 -42.9971
c15.1953 -11.4434 29.5977 -24.7061 47.0781 -32.3389c12.7637 -5.57129 35.7158 6.53613 47.0205 -1.41699c15.8672 -11.165 29.3066 -21.624 47.1611 -29.375c7.93359 -3.44531 32.418 -19.8828 25.3525 -30.7812c-4.96582 -7.66211 -9.87305 -14.8848 -13.5771 -23.2168
c-3.70703 -8.34375 -12.5957 -18.876 -19.6924 -24.3525c-8.15918 -6.29199 -16.9551 -17.1455 -21.8955 -29.3623c34.8574 6.5957 66.9229 23.4482 92.5566 49.0811z" />
<glyph glyph-name="link" unicode="&#xf104;"
d="M256.5 240h-0.5v0h0.5zM368.5 288c44.2002 0 79.5 -35.2998 79.5 -79.5v-32c0 -44.2002 -35.2998 -80.5 -79.5 -80.5h-112c-32.7002 0 -61 19.7998 -73.5996 48c-4.40039 10 -6.90039 21 -6.90039 32.5v31.5h48v-31.5c0 -17.5996 14.9004 -32.5 32.5 -32.5h112
c17.5996 0 31.5 14.9004 31.5 32.5v32c0 17.5996 -13.9004 31.5 -31.5 31.5h-0.5h-16.4004c-5.59961 31 -31.5996 48 -31.5996 48h48.5zM329.6 240c4.10059 -9.59961 6.40039 -20.2998 6.40039 -31.5v-32v-0.5h-48v0.5v32c0 17.5996 -13.9004 31.5 -31.5 31.5h-0.5h-111.5
c-17.5996 0 -32.5 -13.9004 -32.5 -31.5v-32c0 -17.5996 14.9004 -32.5 32.5 -32.5h15.4004c6.2998 -31 32.0996 -48 32.0996 -48h-47.5c-44.2002 0 -80.5 36.2998 -80.5 80.5v32c0 44.2002 36.2998 79.5 80.5 79.5h112c33 0 61 -19.7002 73.0996 -48z" />
<glyph glyph-name="location" unicode="&#xf10e;"
d="M256 384c65.9004 0 119.3 -53.7002 119.3 -120c0 -114.6 -119.3 -264 -119.3 -264s-119.3 149.4 -119.3 264c0 66.2998 53.3994 120 119.3 120zM256 205.8c31.2002 0 56.4004 25.4004 56.4004 56.7002c0 31.4004 -25.2002 56.7998 -56.4004 56.7998
c-31.0996 0 -56.4004 -25.5 -56.4004 -56.7998s25.2002 -56.7002 56.4004 -56.7002z" />
<glyph glyph-name="magnet" unicode="&#xf114;"
d="M270.208 177.19h0.0126953v87.8721c0.345703 4.8125 -3.85254 22.8994 -14.0674 35.1738c-10.4697 12.5312 -23.6543 22.3496 -51.3662 22.7588c-27.7246 -0.396484 -40.8955 -10.2275 -51.3789 -22.7588c-10.1895 -12.2744 -14.4131 -30.3486 -14.0674 -35.1738
v-87.8848h-64v87.8848c0.371094 21.8369 7.83398 48.7422 27.8271 74.7773c19.6865 25.7666 55.2188 47.6035 101.645 47.207c46.3877 0.421875 81.9199 -21.415 101.619 -47.1943c19.9941 -26.0352 27.4434 -52.9277 27.8018 -74.7646v-87.8975h-64.0254zM334.233 99.3789
h0.0253906l-64.0508 -0.0126953v65.0244h64.0254v-65.0117zM75.3408 99.3662v65.0244h64v-65.0244h-64z" />
<glyph glyph-name="more-vertical" unicode="&#xf113;"
d="M296 312c0 -22.002 -17.998 -40 -40 -40s-40 17.998 -40 40s17.998 40 40 40s40 -17.998 40 -40zM296 72c0 -22.002 -17.998 -40 -40 -40s-40 17.998 -40 40s17.998 40 40 40s40 -17.998 40 -40zM296 192c0 -22.002 -17.998 -40 -40 -40s-40 17.998 -40 40
s17.998 40 40 40s40 -17.998 40 -40z" />
<glyph glyph-name="music-note" unicode="&#xf112;"
d="M426 415.9c12.0996 0 22 -9.5 22.0996 -21.2002v-302.8c0 -24.7002 -3 -42.9004 -12 -54.9004h-0.199219c-9.10059 -15 -25 -21 -43.2002 -21h-37.2002c-28.2998 0 -51.2002 19.9004 -51.2002 48s22.9004 48 51.2002 48h60.5v192l-208 -38v-232
c0 -8.2998 -3.40039 -27 -13 -41.0996c-1 -1.80078 -2.09961 -3.40039 -3.40039 -5c-0.5 -0.600586 -0.899414 -1.5 -1.5 -2.10059c-0.0996094 -0.0996094 -0.299805 -0.0996103 -0.399414 -0.200196c-9.40039 -10.5996 -23 -17.5 -38.2998 -17.5h-36.2002
c-28.2002 0 -51.2998 20 -51.2998 48s23.0996 48 51.0996 48v-0.0996094h61v286.5c1 14.5 13.5 27.9004 27.2998 31.5996l217.601 33.2002s2.89941 0.600586 5.09961 0.600586z" />
<glyph glyph-name="navicon-round" unicode="&#xf101;"
d="M417.4 224c16.8994 0 30.5996 -14.2998 30.5996 -32s-13.7002 -32 -30.5996 -32h-322.801c-16.8994 0 -30.5996 14.2998 -30.5996 32s13.7002 32 30.5996 32h322.801zM417.4 352c16.8994 0 30.5996 -14.2998 30.5996 -32s-13.7002 -32 -30.5996 -32h-322.801
c-16.8994 0 -30.5996 14.2998 -30.5996 32s13.7002 32 30.5996 32h322.801zM417.4 96c16.8994 0 30.5996 -14.2998 30.5996 -32s-13.7002 -32 -30.5996 -32h-322.801c-16.8994 0 -30.5996 14.2998 -30.5996 32s13.7002 32 30.5996 32h322.801z" />
<glyph glyph-name="play" unicode="&#xf103;"
d="M405.2 215.1c6.59961 -5.59961 10.7998 -13.7998 10.7998 -23.0996s-4.2002 -17.5996 -10.7998 -23.0996l-278.101 -165.5c-3.69922 -2 -7.09962 -3.40039 -11.1992 -3.40039c-10.9004 0 -19.8008 9 -19.8008 20h-0.0996094v344h0.0996094c0 11 8.90039 20 19.8008 20
c4 0 7.49999 -1.2002 10.8994 -3.2002z" />
<glyph glyph-name="search" unicode="&#xf102;"
d="M445 61.2998c4 -4 4 -10.3994 0 -14.5l-43.2998 -43.7998c-1.90039 -2 -4.60059 -3.09961 -7.2998 -3.09961c-2.7002 0 -5.40039 1.19922 -7.30078 3.09961l-84.3994 85.5996c-24.6006 -14.6992 -52.2002 -22.3994 -80.1006 -22.3994
c-87.3994 0 -158.6 71.2998 -158.6 158.899c0 87.6006 71.2002 158.9 158.6 158.9c87.4004 0 158.601 -71.2998 158.601 -158.9c0 -27 -7.2002 -53.7998 -21 -77.8994zM222.6 322.1c-53.3994 0 -96.7998 -43.5 -96.7998 -97s43.4004 -97 96.7998 -97
c53.4004 0 96.8008 43.5 96.8008 97s-43.4004 97 -96.8008 97z" />
<glyph glyph-name="time" unicode="&#xf10d;"
d="M256 405c117.149 0 213 -95.8506 213 -213c0 -117.149 -94.7891 -213 -213 -213s-213 95.8506 -213 213c0 117.149 94.7891 213 213 213zM256 21.5996c93.7178 0 170.4 76.6826 170.4 170.4s-76.6826 170.4 -170.4 170.4s-170.4 -76.6836 -170.4 -170.4
s76.6826 -170.4 170.4 -170.4zM266.65 298.5v-111.824l95.8496 -56.4434l-15.9746 -26.625l-111.825 67.0928v127.8h31.9502z" />
<glyph glyph-name="warning" unicode="&#xf10f;"
d="M476.7 25.7998c2.7998 -4.89941 4.7998 -13 1.7998 -17.8994c-2.90039 -4.90039 -8.20016 -7.90039 -14 -7.90039h-417.1c-5.80078 0 -11.1006 3 -14 7.90039c-2.90039 4.89941 -0.900391 12.8994 1.89941 17.8994l206.601 349.5c2.7998 5 8.1992 8.7002 14.0996 8.7002
c5.7998 0 11.2002 -3.7002 14.0996 -8.7002zM288 48v48h-64v-48h64zM288 128v144h-64v-144h64z" />
</font>
</defs></svg>

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -0,0 +1,150 @@
module.exports = function(grunt) {
const path = require('path');
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
watch: {
scripts: {
files: ['<%= jshint.files %>', 'less/*.less'],
tasks: ['jshint', 'concat', 'uglify', 'webfont', 'less:development', 'less:production']
}
},
concat: {
options: {
separator: ';'
},
dist: {
src: ['js/searx_src/*.js'],
dest: 'js/searx.js'
}
},
uglify: {
options: {
banner: '/*! simple/searx.min.js | <%= grunt.template.today("dd-mm-yyyy") %> | https://github.com/asciimoo/searx */\n',
preserveComments: 'some',
sourceMap: true
},
dist: {
files: {
'js/searx.min.js': ['<%= concat.dist.dest %>']
}
}
},
jshint: {
files: ['js/searx_src/*.js'],
options: {
proto: true,
// options here to override JSHint defaults
globals: {
browser: true,
jQuery: false,
devel: true
}
}
},
less: {
development: {
options: {
paths: ["less"],
banner: '/*! searx | <%= grunt.template.today("dd-mm-yyyy") %> | https://github.com/asciimoo/searx */\n'
},
files: {
"css/searx.css": "less/style.less",
"css/searx-rtl.css": "less/style-rtl.less"
}
},
production: {
options: {
paths: ["less"],
plugins: [
new (require('less-plugin-clean-css'))({
advanced: true,
compatibility: 'ie8'
})
],
banner: '/*! searx | <%= grunt.template.today("dd-mm-yyyy") %> | https://github.com/asciimoo/searx */\n'
},
files: {
"css/searx.min.css": "less/style.less",
"css/searx-rtl.min.css": "less/style-rtl.less"
}
},
},
webfont: {
icons: {
// src: 'node_modules/ionicons-npm/src/*.svg',
src: [
'node_modules/ionicons-npm/src/navicon-round.svg',
'node_modules/ionicons-npm/src/search.svg',
'node_modules/ionicons-npm/src/play.svg',
'node_modules/ionicons-npm/src/link.svg',
'node_modules/ionicons-npm/src/chevron-up.svg',
'node_modules/ionicons-npm/src/chevron-left.svg',
'node_modules/ionicons-npm/src/chevron-right.svg',
'node_modules/ionicons-npm/src/arrow-down-a.svg',
'node_modules/ionicons-npm/src/arrow-up-a.svg',
'node_modules/ionicons-npm/src/arrow-swap.svg',
'node_modules/ionicons-npm/src/telephone.svg',
'node_modules/ionicons-npm/src/android-arrow-dropdown.svg',
'node_modules/ionicons-npm/src/android-globe.svg',
'node_modules/ionicons-npm/src/android-time.svg',
'node_modules/ionicons-npm/src/location.svg',
'node_modules/ionicons-npm/src/alert-circled.svg',
'node_modules/ionicons-npm/src/android-alert.svg',
'node_modules/ionicons-npm/src/ios-film-outline.svg',
'node_modules/ionicons-npm/src/music-note.svg',
'node_modules/ionicons-npm/src/ion-close-round.svg',
'node_modules/ionicons-npm/src/android-more-vertical.svg',
'magnet.svg'
],
dest: 'fonts',
destLess: 'less',
options: {
font: 'ion',
hashes : true,
syntax: 'bem',
styles : 'font,icon',
types : 'eot,woff2,woff,ttf,svg',
order : 'eot,woff2,woff,ttf,svg',
stylesheets : ['css', 'less'],
relativeFontPath : '../fonts/',
autoHint : false,
normalize : false,
// ligatures : true,
optimize : true,
// fontHeight : 400,
rename : function(name) {
basename = path.basename(name);
if (basename === 'android-alert.svg') {
return 'error.svg';
}
if (basename === 'alert-circled.svg') {
return 'warning.svg';
}
if (basename === 'ion-close-round.svg') {
return 'close.svg';
}
return basename.replace(/(ios|md|android)-/i, '');
},
templateOptions: {
baseClass: 'ion-icon',
classPrefix: 'ion-'
}
}
}
}
});
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.loadNpmTasks('grunt-contrib-jshint');
grunt.loadNpmTasks('grunt-contrib-concat');
grunt.loadNpmTasks('grunt-contrib-less');
grunt.loadNpmTasks('grunt-contrib-cssmin');
grunt.loadNpmTasks('grunt-webfont');
grunt.registerTask('test', ['jshint']);
grunt.registerTask('default', ['jshint', 'concat', 'uglify', 'less:development', 'less:production']);
};

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

View file

@ -0,0 +1,203 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="744.09448819"
height="1052.3622047"
id="svg2"
version="1.1"
inkscape:version="0.48.4 r9939"
sodipodi:docname="searx_logo.svg"
inkscape:export-filename="/home/a/magnif.png"
inkscape:export-xdpi="203.1774"
inkscape:export-ydpi="203.1774">
<defs
id="defs4">
<linearGradient
inkscape:collect="always"
id="linearGradient3857">
<stop
style="stop-color:#ffffff;stop-opacity:1;"
offset="0"
id="stop3859" />
<stop
style="stop-color:#ffffff;stop-opacity:0;"
offset="1"
id="stop3861" />
</linearGradient>
<linearGradient
id="linearGradient3790">
<stop
style="stop-color:#a9a9a9;stop-opacity:1;"
offset="0"
id="stop3792" />
<stop
style="stop-color:#000000;stop-opacity:1;"
offset="1"
id="stop3794" />
</linearGradient>
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3790"
id="radialGradient3798"
cx="294.45947"
cy="208.37973"
fx="294.45947"
fy="208.37973"
r="107.58125"
gradientUnits="userSpaceOnUse" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient3857"
id="linearGradient3865"
x1="120.68947"
y1="239.61774"
x2="120.68947"
y2="602.17517"
gradientUnits="userSpaceOnUse" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient3790"
id="linearGradient3912"
x1="186.74416"
y1="354.42426"
x2="255.84358"
y2="254.35953"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.2227304,0,0,0.89945099,-289.31433,113.40259)" />
<filter
inkscape:collect="always"
id="filter4024"
x="-0.12996517"
width="1.2599303"
y="-0.14709377"
height="1.2941875">
<feGaussianBlur
inkscape:collect="always"
stdDeviation="6.4759344"
id="feGaussianBlur4026" />
</filter>
<filter
inkscape:collect="always"
id="filter3983"
x="-1.0608404"
width="3.1216809"
y="-0.31017202"
height="1.620344">
<feGaussianBlur
inkscape:collect="always"
stdDeviation="9.392858"
id="feGaussianBlur3985" />
</filter>
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="1.979899"
inkscape:cx="30.708726"
inkscape:cy="948.08556"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:window-width="1364"
inkscape:window-height="663"
inkscape:window-x="0"
inkscape:window-y="30"
inkscape:window-maximized="0"
showguides="true"
inkscape:guide-bbox="true" />
<metadata
id="metadata7">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1">
<path
style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
d="m 70.523181,34.870671 c -7.11959,15.242893 -10.17798,31.779192 -8.22563,48.814566 5.01677,43.774133 41.675309,79.324503 91.536109,95.162893 -6.62576,-22.40752 -5.34093,-44.9362 2.6395,-65.84431 C 108.73618,98.821131 74.828141,70.195435 70.523181,34.870671 z"
id="path3814-0-7"
inkscape:connector-curvature="0" />
<path
style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
d="m 303.77876,36.21406 c 7.11959,15.242893 10.17798,31.779192 8.22563,48.814566 -5.01677,43.774134 -41.67531,79.324504 -91.53611,95.162894 6.62576,-22.40752 5.34093,-44.9362 -2.6395,-65.84431 47.73698,-14.18269 81.64502,-42.808386 85.94998,-78.13315 z"
id="path3814-0"
inkscape:connector-curvature="0" />
<path
transform="matrix(0.6556593,-0.75505688,0.75505688,0.6556593,0,0)"
style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
d="m -5.0905523,259.06055 18.4167573,0 c 6.220455,0 11.228257,16.68196 11.228257,37.40349 l 0,172.83701 c 0,20.72153 -5.007802,37.40349 -11.228257,37.40349 l -18.4167573,0 c -6.2204547,0 -11.2282577,-16.68196 -11.2282577,-37.40349 l 0,-172.83701 c 0,-20.72153 5.007803,-37.40349 11.2282577,-37.40349 z"
id="rect3804" />
<path
sodipodi:type="arc"
style="fill:url(#radialGradient3798);fill-opacity:1;fill-rule:nonzero;stroke:none"
id="path2987"
sodipodi:cx="294.45947"
sodipodi:cy="208.37973"
sodipodi:rx="107.58125"
sodipodi:ry="107.58125"
d="m 402.04073,208.37973 a 107.58125,107.58125 0 1 1 -215.16251,0 107.58125,107.58125 0 1 1 215.16251,0 z"
transform="translate(-107.07617,-60.609153)" />
<path
sodipodi:type="arc"
style="fill:url(#linearGradient3865);fill-opacity:1;fill-rule:nonzero;stroke:none"
id="path3757"
sodipodi:cx="131.82491"
sodipodi:cy="299.29346"
sodipodi:rx="101.52033"
sodipodi:ry="101.52033"
d="m 233.34524,299.29346 a 101.52033,101.52033 0 1 1 -203.040667,0 101.52033,101.52033 0 1 1 203.040667,0 z"
transform="matrix(0.76865672,0,0,0.76865672,85.80266,-82.535889)" />
<path
sodipodi:type="arc"
style="fill:#1a1a1a;fill-opacity:1;fill-rule:nonzero;stroke:none"
id="path3800"
sodipodi:cx="183.34268"
sodipodi:cy="156.35687"
sodipodi:rx="27.274118"
sodipodi:ry="27.274118"
d="m 210.6168,156.35687 a 27.274118,27.274118 0 1 1 -54.54824,0 27.274118,27.274118 0 1 1 54.54824,0 z"
transform="translate(5,-7.1428572)" />
<path
sodipodi:type="arc"
style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
id="path3802"
sodipodi:cx="197.9899"
sodipodi:cy="203.32896"
sodipodi:rx="5.5558391"
sodipodi:ry="5.5558391"
d="m 203.54574,203.32896 a 5.5558391,5.5558391 0 1 1 -11.11168,0 5.5558391,5.5558391 0 1 1 11.11168,0 z"
transform="translate(1.4847712,-63.564549)" />
<rect
style="fill:#ffffff;fill-opacity:0.82211531000000004;fill-rule:nonzero;stroke:none;filter:url(#filter4024)"
id="rect3916"
width="2.2392972"
height="159.43797"
x="19.525793"
y="337.8396"
rx="2.8666623"
ry="9.0007057"
transform="matrix(0.74466525,-0.84318084,0.84318084,0.74466525,-35.543204,-26.349917)" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 7.1 KiB

File diff suppressed because it is too large Load diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,155 @@
/**
* searx is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* searx is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with searx. If not, see < http://www.gnu.org/licenses/ >.
*
* (C) 2017 by Alexandre Flament, <alex@al-f.net>
*
*/
(function(w, d, searx) {
'use strict';
// not invented here tookit with bugs fixed elsewhere
// purposes : be just good enough and as small as possible
// from https://plainjs.com/javascript/events/live-binding-event-handlers-14/
if (w.Element) {
(function(ElementPrototype) {
ElementPrototype.matches = ElementPrototype.matches ||
ElementPrototype.matchesSelector ||
ElementPrototype.webkitMatchesSelector ||
ElementPrototype.msMatchesSelector ||
function(selector) {
var node = this, nodes = (node.parentNode || node.document).querySelectorAll(selector), i = -1;
while (nodes[++i] && nodes[i] != node);
return !!nodes[i];
};
})(Element.prototype);
}
function callbackSafe(callback, el, e) {
try {
callback.call(el, e);
} catch (exception) {
console.log(exception);
}
}
searx = searx || {};
searx.on = function(obj, eventType, callback, useCapture) {
useCapture = useCapture || false;
if (typeof obj !== 'string') {
// obj HTMLElement, HTMLDocument
obj.addEventListener(eventType, callback, useCapture);
} else {
// obj is a selector
d.addEventListener(eventType, function(e) {
var el = e.target || e.srcElement, found = false;
while (el && el.matches && el !== d && !(found = el.matches(obj))) el = el.parentElement;
if (found) callbackSafe(callback, el, e);
}, useCapture);
}
};
searx.ready = function(callback) {
if (document.readyState != 'loading') {
callback.call(w);
} else {
w.addEventListener('DOMContentLoaded', callback.bind(w));
}
};
searx.http = function(method, url, callback) {
var req = new XMLHttpRequest(),
resolve = function() {},
reject = function() {},
promise = {
then: function(callback) { resolve = callback; return promise; },
catch: function(callback) { reject = callback; return promise; }
};
try {
req.open(method, url, true);
// On load
req.onload = function() {
if (req.status == 200) {
resolve(req.response, req.responseType);
} else {
reject(Error(req.statusText));
}
};
// Handle network errors
req.onerror = function() {
reject(Error("Network Error"));
};
req.onabort = function() {
reject(Error("Transaction is aborted"));
};
// Make the request
req.send();
} catch (ex) {
reject(ex);
}
return promise;
};
searx.loadStyle = function(src) {
var path = searx.staticPath + src,
id = "style_" + src.replace('.', '_'),
s = d.getElementById(id);
if (s === null) {
s = d.createElement('link');
s.setAttribute('id', id);
s.setAttribute('rel', 'stylesheet');
s.setAttribute('type', 'text/css');
s.setAttribute('href', path);
d.body.appendChild(s);
}
};
searx.loadScript = function(src, callback) {
var path = searx.staticPath + src,
id = "script_" + src.replace('.', '_'),
s = d.getElementById(id);
if (s === null) {
s = d.createElement('script');
s.setAttribute('id', id);
s.setAttribute('src', path);
s.onload = callback;
s.onerror = function() {
s.setAttribute('error', '1');
};
d.body.appendChild(s);
} else if (!s.hasAttribute('error')) {
try {
callback.apply(s, []);
} catch (exception) {
console.log(exception);
}
} else {
console.log("callback not executed : script '" + path + "' not loaded.");
}
};
searx.on('.close', 'click', function(e) {
var el = e.target || e.srcElement;
this.parentNode.style.display="None";
});
return searx;
})(window, document, window.searx);

View file

@ -0,0 +1,536 @@
(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){
/*
* @license MIT
*
* Autocomplete.js v2.6.3
* Developed by Baptiste Donaux
* http://autocomplete-js.com
*
* (c) 2017, Baptiste Donaux
*/
"use strict";
var ConditionOperator;
(function (ConditionOperator) {
ConditionOperator[ConditionOperator["AND"] = 0] = "AND";
ConditionOperator[ConditionOperator["OR"] = 1] = "OR";
})(ConditionOperator || (ConditionOperator = {}));
var EventType;
(function (EventType) {
EventType[EventType["KEYDOWN"] = 0] = "KEYDOWN";
EventType[EventType["KEYUP"] = 1] = "KEYUP";
})(EventType || (EventType = {}));
/**
* Core
*
* @class
* @author Baptiste Donaux <baptiste.donaux@gmail.com> @baptistedonaux
*/
var AutoComplete = (function () {
// Constructor
function AutoComplete(params, selector) {
if (params === void 0) { params = {}; }
if (selector === void 0) { selector = "[data-autocomplete]"; }
if (Array.isArray(selector)) {
selector.forEach(function (s) {
new AutoComplete(params, s);
});
}
else if (typeof selector == "string") {
var elements = document.querySelectorAll(selector);
Array.prototype.forEach.call(elements, function (input) {
new AutoComplete(params, input);
});
}
else {
var specificParams = AutoComplete.merge(AutoComplete.defaults, params, {
DOMResults: document.createElement("div")
});
AutoComplete.prototype.create(specificParams, selector);
return specificParams;
}
}
AutoComplete.prototype.create = function (params, element) {
params.Input = element;
if (params.Input.nodeName.match(/^INPUT$/i) && (params.Input.hasAttribute("type") === false || params.Input.getAttribute("type").match(/^TEXT|SEARCH$/i))) {
params.Input.setAttribute("autocomplete", "off");
params._Position(params);
params.Input.parentNode.appendChild(params.DOMResults);
params.$Listeners = {
blur: params._Blur.bind(params),
destroy: AutoComplete.prototype.destroy.bind(null, params),
focus: params._Focus.bind(params),
keyup: AutoComplete.prototype.event.bind(null, params, EventType.KEYUP),
keydown: AutoComplete.prototype.event.bind(null, params, EventType.KEYDOWN),
position: params._Position.bind(params)
};
for (var event in params.$Listeners) {
params.Input.addEventListener(event, params.$Listeners[event]);
}
}
};
AutoComplete.prototype.getEventsByType = function (params, type) {
var mappings = {};
for (var key in params.KeyboardMappings) {
var event = EventType.KEYUP;
if (params.KeyboardMappings[key].Event !== undefined) {
event = params.KeyboardMappings[key].Event;
}
if (event == type) {
mappings[key] = params.KeyboardMappings[key];
}
}
return mappings;
};
AutoComplete.prototype.event = function (params, type, event) {
var eventIdentifier = function (condition) {
if ((match === true && mapping.Operator == ConditionOperator.AND) || (match === false && mapping.Operator == ConditionOperator.OR)) {
condition = AutoComplete.merge({
Not: false
}, condition);
if (condition.hasOwnProperty("Is")) {
if (condition.Is == event.keyCode) {
match = !condition.Not;
}
else {
match = condition.Not;
}
}
else if (condition.hasOwnProperty("From") && condition.hasOwnProperty("To")) {
if (event.keyCode >= condition.From && event.keyCode <= condition.To) {
match = !condition.Not;
}
else {
match = condition.Not;
}
}
}
};
for (var name in AutoComplete.prototype.getEventsByType(params, type)) {
var mapping = AutoComplete.merge({
Operator: ConditionOperator.AND
}, params.KeyboardMappings[name]), match = ConditionOperator.AND == mapping.Operator;
mapping.Conditions.forEach(eventIdentifier);
if (match === true) {
mapping.Callback.call(params, event);
}
}
};
AutoComplete.prototype.makeRequest = function (params, callback) {
var propertyHttpHeaders = Object.getOwnPropertyNames(params.HttpHeaders), request = new XMLHttpRequest(), method = params._HttpMethod(), url = params._Url(), queryParams = params._Pre(), queryParamsStringify = encodeURIComponent(params._QueryArg()) + "=" + encodeURIComponent(queryParams);
if (method.match(/^GET$/i)) {
if (url.indexOf("?") !== -1) {
url += "&" + queryParamsStringify;
}
else {
url += "?" + queryParamsStringify;
}
}
request.open(method, url, true);
for (var i = propertyHttpHeaders.length - 1; i >= 0; i--) {
request.setRequestHeader(propertyHttpHeaders[i], params.HttpHeaders[propertyHttpHeaders[i]]);
}
request.onreadystatechange = function () {
if (request.readyState == 4 && request.status == 200) {
params.$Cache[queryParams] = request.response;
callback(request.response);
}
};
return request;
};
AutoComplete.prototype.ajax = function (params, request, timeout) {
if (timeout === void 0) { timeout = true; }
if (params.$AjaxTimer) {
window.clearTimeout(params.$AjaxTimer);
}
if (timeout === true) {
params.$AjaxTimer = window.setTimeout(AutoComplete.prototype.ajax.bind(null, params, request, false), params.Delay);
}
else {
if (params.Request) {
params.Request.abort();
}
params.Request = request;
params.Request.send(params._QueryArg() + "=" + params._Pre());
}
};
AutoComplete.prototype.cache = function (params, callback) {
var response = params._Cache(params._Pre());
if (response === undefined) {
var request = AutoComplete.prototype.makeRequest(params, callback);
AutoComplete.prototype.ajax(params, request);
}
else {
callback(response);
}
};
AutoComplete.prototype.destroy = function (params) {
for (var event in params.$Listeners) {
params.Input.removeEventListener(event, params.$Listeners[event]);
}
params.DOMResults.parentNode.removeChild(params.DOMResults);
};
return AutoComplete;
}());
AutoComplete.merge = function () {
var merge = {}, tmp;
for (var i = 0; i < arguments.length; i++) {
for (tmp in arguments[i]) {
merge[tmp] = arguments[i][tmp];
}
}
return merge;
};
AutoComplete.defaults = {
Delay: 150,
EmptyMessage: "No result here",
Highlight: {
getRegex: function (value) {
return new RegExp(value, "ig");
},
transform: function (value) {
return "<strong>" + value + "</strong>";
}
},
HttpHeaders: {
"Content-type": "application/x-www-form-urlencoded"
},
Limit: 0,
MinChars: 0,
HttpMethod: "GET",
QueryArg: "q",
Url: null,
KeyboardMappings: {
"Enter": {
Conditions: [{
Is: 13,
Not: false
}],
Callback: function (event) {
if (this.DOMResults.getAttribute("class").indexOf("open") != -1) {
var liActive = this.DOMResults.querySelector("li.active");
if (liActive !== null) {
event.preventDefault();
this._Select(liActive);
this.DOMResults.setAttribute("class", "autocomplete");
}
}
},
Operator: ConditionOperator.AND,
Event: EventType.KEYDOWN
},
"KeyUpAndDown_down": {
Conditions: [{
Is: 38,
Not: false
},
{
Is: 40,
Not: false
}],
Callback: function (event) {
event.preventDefault();
},
Operator: ConditionOperator.OR,
Event: EventType.KEYDOWN
},
"KeyUpAndDown_up": {
Conditions: [{
Is: 38,
Not: false
},
{
Is: 40,
Not: false
}],
Callback: function (event) {
event.preventDefault();
var first = this.DOMResults.querySelector("li:first-child:not(.locked)"), last = this.DOMResults.querySelector("li:last-child:not(.locked)"), active = this.DOMResults.querySelector("li.active");
if (active) {
var currentIndex = Array.prototype.indexOf.call(active.parentNode.children, active), position = currentIndex + (event.keyCode - 39), lisCount = this.DOMResults.getElementsByTagName("li").length;
if (position < 0) {
position = lisCount - 1;
}
else if (position >= lisCount) {
position = 0;
}
active.classList.remove("active");
active.parentElement.children.item(position).classList.add("active");
}
else if (last && event.keyCode == 38) {
last.classList.add("active");
}
else if (first) {
first.classList.add("active");
}
},
Operator: ConditionOperator.OR,
Event: EventType.KEYUP
},
"AlphaNum": {
Conditions: [{
Is: 13,
Not: true
}, {
From: 35,
To: 40,
Not: true
}],
Callback: function () {
var oldValue = this.Input.getAttribute("data-autocomplete-old-value"), currentValue = this._Pre();
if (currentValue !== "" && currentValue.length >= this._MinChars()) {
if (!oldValue || currentValue != oldValue) {
this.DOMResults.setAttribute("class", "autocomplete open");
}
AutoComplete.prototype.cache(this, function (response) {
this._Render(this._Post(response));
this._Open();
}.bind(this));
}
},
Operator: ConditionOperator.AND,
Event: EventType.KEYUP
}
},
DOMResults: null,
Request: null,
Input: null,
/**
* Return the message when no result returns
*/
_EmptyMessage: function () {
var emptyMessage = "";
if (this.Input.hasAttribute("data-autocomplete-empty-message")) {
emptyMessage = this.Input.getAttribute("data-autocomplete-empty-message");
}
else if (this.EmptyMessage !== false) {
emptyMessage = this.EmptyMessage;
}
else {
emptyMessage = "";
}
return emptyMessage;
},
/**
* Returns the maximum number of results
*/
_Limit: function () {
var limit = this.Input.getAttribute("data-autocomplete-limit");
if (isNaN(limit) || limit === null) {
return this.Limit;
}
return parseInt(limit, 10);
},
/**
* Returns the minimum number of characters entered before firing ajax
*/
_MinChars: function () {
var minchars = this.Input.getAttribute("data-autocomplete-minchars");
if (isNaN(minchars) || minchars === null) {
return this.MinChars;
}
return parseInt(minchars, 10);
},
/**
* Apply transformation on labels response
*/
_Highlight: function (label) {
return label.replace(this.Highlight.getRegex(this._Pre()), this.Highlight.transform);
},
/**
* Returns the HHTP method to use
*/
_HttpMethod: function () {
if (this.Input.hasAttribute("data-autocomplete-method")) {
return this.Input.getAttribute("data-autocomplete-method");
}
return this.HttpMethod;
},
/**
* Returns the query param to use
*/
_QueryArg: function () {
if (this.Input.hasAttribute("data-autocomplete-param-name")) {
return this.Input.getAttribute("data-autocomplete-param-name");
}
return this.QueryArg;
},
/**
* Returns the URL to use for AJAX request
*/
_Url: function () {
if (this.Input.hasAttribute("data-autocomplete")) {
return this.Input.getAttribute("data-autocomplete");
}
return this.Url;
},
/**
* Manage the close
*/
_Blur: function (now) {
if (now === true) {
this.DOMResults.setAttribute("class", "autocomplete");
this.Input.setAttribute("data-autocomplete-old-value", this.Input.value);
}
else {
var params = this;
setTimeout(function () {
params._Blur(true);
}, 150);
}
},
/**
* Manage the cache
*/
_Cache: function (value) {
return this.$Cache[value];
},
/**
* Manage the open
*/
_Focus: function () {
var oldValue = this.Input.getAttribute("data-autocomplete-old-value");
if ((!oldValue || this.Input.value != oldValue) && this._MinChars() <= this.Input.value.length) {
this.DOMResults.setAttribute("class", "autocomplete open");
}
},
/**
* Bind all results item if one result is opened
*/
_Open: function () {
var params = this;
Array.prototype.forEach.call(this.DOMResults.getElementsByTagName("li"), function (li) {
if (li.getAttribute("class") != "locked") {
li.onclick = function (event) {
params._Select(li);
};
li.onmouseenter = function () {
var active = params.DOMResults.querySelector("li.active");
if (active !== li) {
if (active !== null) {
active.classList.remove("active");
}
li.classList.add("active");
}
};
}
});
},
/**
* Position the results HTML element
*/
_Position: function () {
this.DOMResults.setAttribute("class", "autocomplete");
this.DOMResults.setAttribute("style", "top:" + (this.Input.offsetTop + this.Input.offsetHeight) + "px;left:" + this.Input.offsetLeft + "px;width:" + this.Input.clientWidth + "px;");
},
/**
* Execute the render of results DOM element
*/
_Render: function (response) {
var ul;
if (typeof response == "string") {
ul = this._RenderRaw(response);
}
else {
ul = this._RenderResponseItems(response);
}
if (this.DOMResults.hasChildNodes()) {
this.DOMResults.removeChild(this.DOMResults.childNodes[0]);
}
this.DOMResults.appendChild(ul);
},
/**
* ResponseItems[] rendering
*/
_RenderResponseItems: function (response) {
var ul = document.createElement("ul"), li = document.createElement("li"), limit = this._Limit();
// Order
if (limit < 0) {
response = response.reverse();
}
else if (limit === 0) {
limit = response.length;
}
for (var item = 0; item < Math.min(Math.abs(limit), response.length); item++) {
li.innerHTML = response[item].Label;
li.setAttribute("data-autocomplete-value", response[item].Value);
ul.appendChild(li);
li = document.createElement("li");
}
return ul;
},
/**
* string response rendering (RAW HTML)
*/
_RenderRaw: function (response) {
var ul = document.createElement("ul"), li = document.createElement("li");
if (response.length > 0) {
this.DOMResults.innerHTML = response;
}
else {
var emptyMessage = this._EmptyMessage();
if (emptyMessage !== "") {
li.innerHTML = emptyMessage;
li.setAttribute("class", "locked");
ul.appendChild(li);
}
}
return ul;
},
/**
* Deal with request response
*/
_Post: function (response) {
try {
var returnResponse = [];
//JSON return
var json = JSON.parse(response);
if (Object.keys(json).length === 0) {
return "";
}
if (Array.isArray(json)) {
for (var i = 0; i < Object.keys(json).length; i++) {
returnResponse[returnResponse.length] = { "Value": json[i], "Label": this._Highlight(json[i]) };
}
}
else {
for (var value in json) {
returnResponse.push({
"Value": value,
"Label": this._Highlight(json[value])
});
}
}
return returnResponse;
}
catch (event) {
//HTML return
return response;
}
},
/**
* Return the autocomplete value to send (before request)
*/
_Pre: function () {
return this.Input.value;
},
/**
* Choice one result item
*/
_Select: function (item) {
console.log('test test test');
if (item.hasAttribute("data-autocomplete-value")) {
this.Input.value = item.getAttribute("data-autocomplete-value");
}
else {
this.Input.value = item.innerHTML;
}
this.Input.setAttribute("data-autocomplete-old-value", this.Input.value);
},
$AjaxTimer: null,
$Cache: {},
$Listeners: {}
};
module.exports = AutoComplete;
},{}]},{},[1])(1)
});

View file

@ -0,0 +1,151 @@
/**
*
* Google Image Layout v0.0.1
* Description, by Anh Trinh.
* Heavily modified for searx
* http://trinhtrunganh.com
*
* @license Free to use under the MIT License.
*
*/
(function(w, d) {
'use strict';
function ImageLayout(container_selector, results_selector, img_selector, maxHeight) {
this.container_selector = container_selector;
this.results_selector = results_selector;
this.img_selector = img_selector;
this.margin = 10;
this.maxHeight = maxHeight;
this._alignAllDone = true;
}
/**
* Get the height that make all images fit the container
*
* width = w1 + w2 + w3 + ... = r1*h + r2*h + r3*h + ...
*
* @param {[type]} images the images to be calculated
* @param {[type]} width the container witdth
* @param {[type]} margin the margin between each image
*
* @return {[type]} the height
*/
ImageLayout.prototype._getHeigth = function(images, width) {
var r = 0,
img;
width -= images.length * this.margin;
for (var i = 0; i < images.length; i++) {
img = images[i];
if ((img.naturalWidth > 0) && (img.naturalHeight > 0)) {
r += img.naturalWidth / img.naturalHeight;
} else {
// assume that not loaded images are square
r += 1;
}
}
return width / r; //have to round down because Firefox will automatically roundup value with number of decimals > 3
};
ImageLayout.prototype._setSize = function(images, height) {
var img, imgWidth, imagesLength = images.length;
for (var i = 0; i < imagesLength; i++) {
img = images[i];
if ((img.naturalWidth > 0) && (img.naturalHeight > 0)) {
imgWidth = height * img.naturalWidth / img.naturalHeight;
} else {
// not loaded image : make it square as _getHeigth said it
imgWidth = height;
}
img.style.width = imgWidth + 'px';
img.style.height = height + 'px';
img.style.marginLeft = '3px';
img.style.marginTop = '3px';
img.style.marginRight = this.margin - 7 + 'px'; // -4 is the negative margin of the inline element
img.style.marginBottom = this.margin - 7 + 'px';
}
};
ImageLayout.prototype._alignImgs = function(imgGroup) {
var slice, h,
containerWidth = d.querySelector(this.container_selector).clientWidth;
w: while (imgGroup.length > 0) {
for (var i = 1; i <= imgGroup.length; i++) {
slice = imgGroup.slice(0, i);
h = this._getHeigth(slice, containerWidth);
if (h < this.maxHeight) {
this._setSize(slice, h);
imgGroup = imgGroup.slice(i);
continue w;
}
}
this._setSize(slice, Math.min(this.maxHeight, h));
break;
}
};
ImageLayout.prototype.align = function(results_selector) {
var results_selectorNode = d.querySelectorAll(this.results_selector),
results_length = results_selectorNode.length,
previous = null,
current = null,
imgGroup = [];
for (var i = 0; i < results_length; i++) {
current = results_selectorNode[i];
if (current.previousElementSibling !== previous && imgGroup.length > 0) {
// the current image is not conected to previous one
// so the current image is the start of a new group of images.
// so call _alignImgs to align the current group
this._alignImgs(imgGroup);
// and start a new empty group of images
imgGroup = [];
}
// add the current image to the group (only the img tag)
imgGroup.push(current.querySelector(this.img_selector));
// update the previous variable
previous = current;
}
// align the remaining images
if (imgGroup.length > 0) {
this._alignImgs(imgGroup);
}
};
ImageLayout.prototype.watch = function() {
var i, img, imgGroup, imgNodeLength,
obj = this,
results_nodes = d.querySelectorAll(this.results_selector),
results_length = results_nodes.length;
function align(e) {
obj.align();
}
function throttleAlign(e) {
if (obj._alignAllDone) {
obj._alignAllDone = false;
setTimeout(function() {
obj.align();
obj._alignAllDone = true;
}, 100);
}
}
w.addEventListener('resize', throttleAlign);
w.addEventListener('pageshow', align);
for (i = 0; i < results_length; i++) {
img = results_nodes[i].querySelector(this.img_selector);
if (typeof img !== 'undefined') {
img.addEventListener('load', throttleAlign);
img.addEventListener('error', throttleAlign);
}
}
};
w.searx.ImageLayout = ImageLayout;
})(window, document);

View file

@ -0,0 +1,360 @@
searx.ready(function() {
searx.on('.result', 'click', function() {
highlightResult(this)(true);
});
searx.on('.result a', 'focus', function(e) {
var el = e.target;
while (el !== undefined) {
if (el.classList.contains('result')) {
if (el.getAttribute("data-vim-selected") === null) {
highlightResult(el)(true);
}
break;
}
el = el.parentNode;
}
}, true);
var vimKeys = {
27: {
key: 'Escape',
fun: removeFocus,
des: 'remove focus from the focused input',
cat: 'Control'
},
73: {
key: 'i',
fun: searchInputFocus,
des: 'focus on the search input',
cat: 'Control'
},
66: {
key: 'b',
fun: scrollPage(-window.innerHeight),
des: 'scroll one page up',
cat: 'Navigation'
},
70: {
key: 'f',
fun: scrollPage(window.innerHeight),
des: 'scroll one page down',
cat: 'Navigation'
},
85: {
key: 'u',
fun: scrollPage(-window.innerHeight / 2),
des: 'scroll half a page up',
cat: 'Navigation'
},
68: {
key: 'd',
fun: scrollPage(window.innerHeight / 2),
des: 'scroll half a page down',
cat: 'Navigation'
},
71: {
key: 'g',
fun: scrollPageTo(-document.body.scrollHeight, 'top'),
des: 'scroll to the top of the page',
cat: 'Navigation'
},
86: {
key: 'v',
fun: scrollPageTo(document.body.scrollHeight, 'bottom'),
des: 'scroll to the bottom of the page',
cat: 'Navigation'
},
75: {
key: 'k',
fun: highlightResult('up'),
des: 'select previous search result',
cat: 'Results'
},
74: {
key: 'j',
fun: highlightResult('down'),
des: 'select next search result',
cat: 'Results'
},
80: {
key: 'p',
fun: pageButtonClick(0),
des: 'go to previous page',
cat: 'Results'
},
78: {
key: 'n',
fun: pageButtonClick(1),
des: 'go to next page',
cat: 'Results'
},
79: {
key: 'o',
fun: openResult(false),
des: 'open search result',
cat: 'Results'
},
84: {
key: 't',
fun: openResult(true),
des: 'open the result in a new tab',
cat: 'Results'
},
82: {
key: 'r',
fun: reloadPage,
des: 'reload page from the server',
cat: 'Control'
},
72: {
key: 'h',
fun: toggleHelp,
des: 'toggle help window',
cat: 'Other'
}
};
searx.on(document, "keyup", function(e) {
// check for modifiers so we don't break browser's hotkeys
if (vimKeys.hasOwnProperty(e.keyCode) && !e.ctrlKey && !e.altKey && !e.shiftKey && !e.metaKey) {
var tagName = e.target.tagName.toLowerCase();
if (e.keyCode === 27) {
if (tagName === 'input' || tagName === 'select' || tagName === 'textarea') {
vimKeys[e.keyCode].fun();
}
} else {
if (e.target === document.body || tagName === 'a' || tagName === 'button') {
vimKeys[e.keyCode].fun();
}
}
}
});
function highlightResult(which) {
return function(noScroll) {
var current = document.querySelector('.result[data-vim-selected]'),
effectiveWhich = which;
if (current === null) {
// no selection : choose the first one
current = document.querySelector('.result');
if (current === null) {
// no first one : there are no results
return;
}
// replace up/down actions by selecting first one
if (which === "down" || which === "up") {
effectiveWhich = current;
}
}
var next, results = document.querySelectorAll('.result');
if (typeof effectiveWhich !== 'string') {
next = effectiveWhich;
} else {
switch (effectiveWhich) {
case 'visible':
var top = document.documentElement.scrollTop || document.body.scrollTop;
var bot = top + document.documentElement.clientHeight;
for (var i = 0; i < results.length; i++) {
next = results[i];
var etop = next.offsetTop;
var ebot = etop + next.clientHeight;
if ((ebot <= bot) && (etop > top)) {
break;
}
}
break;
case 'down':
next = current.nextElementSibling;
if (next === null) {
next = results[0];
}
break;
case 'up':
next = current.previousElementSibling;
if (next === null) {
next = results[results.length - 1];
}
break;
case 'bottom':
next = results[results.length - 1];
break;
case 'top':
/* falls through */
default:
next = results[0];
}
}
if (next) {
current.removeAttribute('data-vim-selected');
next.setAttribute('data-vim-selected', 'true');
var link = next.querySelector('h3 a') || next.querySelector('a');
if (link !== null) {
link.focus();
}
if (!noScroll) {
scrollPageToSelected();
}
}
};
}
function reloadPage() {
document.location.reload(true);
}
function removeFocus() {
if (document.activeElement) {
document.activeElement.blur();
}
}
function pageButtonClick(num) {
return function() {
var buttons = $('div#pagination button[type="submit"]');
if (buttons.length !== 2) {
console.log('page navigation with this theme is not supported');
return;
}
if (num >= 0 && num < buttons.length) {
buttons[num].click();
} else {
console.log('pageButtonClick(): invalid argument');
}
};
}
function scrollPageToSelected() {
var sel = document.querySelector('.result[data-vim-selected]');
if (sel === null) {
return;
}
var wtop = document.documentElement.scrollTop || document.body.scrollTop,
wheight = document.documentElement.clientHeight,
etop = sel.offsetTop,
ebot = etop + sel.clientHeight,
offset = 120;
// first element ?
if ((sel.previousElementSibling === null) && (ebot < wheight)) {
// set to the top of page if the first element
// is fully included in the viewport
window.scroll(window.scrollX, 0);
return;
}
if (wtop > (etop - offset)) {
window.scroll(window.scrollX, etop - offset);
} else {
var wbot = wtop + wheight;
if (wbot < (ebot + offset)) {
window.scroll(window.scrollX, ebot - wheight + offset);
}
}
}
function scrollPage(amount) {
return function() {
window.scrollBy(0, amount);
highlightResult('visible')();
};
}
function scrollPageTo(position, nav) {
return function() {
window.scrollTo(0, position);
highlightResult(nav)();
};
}
function searchInputFocus() {
window.scrollTo(0, 0);
document.querySelector('#q').focus();
}
function openResult(newTab) {
return function() {
var link = document.querySelector('.result[data-vim-selected] h3 a');
if (link !== null) {
var url = link.getAttribute('href');
if (newTab) {
window.open(url);
} else {
window.location.href = url;
}
}
};
}
function toggleHelp() {
var helpPanel = document.querySelector('#vim-hotkeys-help');
if (helpPanel.length) {
helpPanel.classList.toggle('hidden');
return;
}
var categories = {};
for (var k in vimKeys) {
var key = vimKeys[k];
categories[key.cat] = categories[key.cat] || [];
categories[key.cat].push(key);
}
var sorted = Object.keys(categories).sort(function(a, b) {
return categories[b].length - categories[a].length;
});
if (sorted.length === 0) {
return;
}
var html = '<div id="vim-hotkeys-help" class="well vim-hotkeys-help">';
html += '<div class="container-fluid">';
html += '<div class="row">';
html += '<div class="col-sm-12">';
html += '<h3>How to navigate searx with Vim-like hotkeys</h3>';
html += '</div>'; // col-sm-12
html += '</div>'; // row
for (var i = 0; i < sorted.length; i++) {
var cat = categories[sorted[i]];
var lastCategory = i === (sorted.length - 1);
var first = i % 2 === 0;
if (first) {
html += '<div class="row dflex">';
}
html += '<div class="col-sm-' + (first && lastCategory ? 12 : 6) + ' dflex">';
html += '<div class="panel panel-default iflex">';
html += '<div class="panel-heading">' + cat[0].cat + '</div>';
html += '<div class="panel-body">';
html += '<ul class="list-unstyled">';
for (var cj in cat) {
html += '<li><kbd>' + cat[cj].key + '</kbd> ' + cat[cj].des + '</li>';
}
html += '</ul>';
html += '</div>'; // panel-body
html += '</div>'; // panel
html += '</div>'; // col-sm-*
if (!first || lastCategory) {
html += '</div>'; // row
}
}
html += '</div>'; // container-fluid
html += '</div>'; // vim-hotkeys-help
$('body').append(html);
}
});

View file

@ -0,0 +1,175 @@
/**
* searx is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* searx is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with searx. If not, see < http://www.gnu.org/licenses/ >.
*
* (C) 2014 by Thomas Pointhuber, <thomas.pointhuber@gmx.at>
* (C) 2017 by Alexandre Flament, <alex@al-f.net>
*/
(function (w, d, searx) {
'use strict';
searx.ready(function () {
searx.on('.searx_overpass_request', 'click', function(event) {
// no more request
this.classList.remove("searx_overpass_request");
//
var overpass_url = "https://overpass-api.de/api/interpreter?data=";
var query_start = overpass_url + "[out:json][timeout:25];(";
var query_end = ");out meta;";
var osm_id = this.dataset.osmId;
var osm_type = this.dataset.osmType;
var result_table = d.querySelector("#" + this.dataset.resultTable);
var result_table_loadicon = d.querySelector("#" + this.dataset.resultTableLoadicon);
// tags which can be ignored
var osm_ignore_tags = [ "addr:city", "addr:country", "addr:housenumber", "addr:postcode", "addr:street" ];
if(osm_id && osm_type && result_table) {
var query = null;
switch(osm_type) {
case 'node':
query = query_start + "node(" + osm_id + ");" + query_end;
break;
case 'way':
query = query_start + "way(" + osm_id + ");" + query_end;
break;
case 'relation':
query = query_start + "relation(" + osm_id + ");" + query_end;
break;
default:
break;
}
if(query) {
// console.log(query);
searx.http( 'GET', query ).then(function(html, contentType) {
html = JSON.parse(html);
if(html && html.elements && html.elements[0]) {
var element = html.elements[0];
var newHtml = "";
for (var row in element.tags) {
if(element.tags.name === null || osm_ignore_tags.indexOf(row) == -1) {
newHtml += "<tr><td>" + row + "</td><td>";
switch(row) {
case "phone":
case "fax":
newHtml += "<a href=\"tel:" + element.tags[row].replace(/ /g,'') + "\">" + element.tags[row] + "</a>";
break;
case "email":
newHtml += "<a href=\"mailto:" + element.tags[row] + "\">" + element.tags[row] + "</a>";
break;
case "website":
case "url":
newHtml += "<a href=\"" + element.tags[row] + "\">" + element.tags[row] + "</a>";
break;
case "wikidata":
newHtml += "<a href=\"https://www.wikidata.org/wiki/" + element.tags[row] + "\">" + element.tags[row] + "</a>";
break;
case "wikipedia":
if(element.tags[row].indexOf(":") != -1) {
newHtml += "<a href=\"https://" + element.tags[row].substring(0,element.tags[row].indexOf(":")) + ".wikipedia.org/wiki/" + element.tags[row].substring(element.tags[row].indexOf(":")+1) + "\">" + element.tags[row] + "</a>";
break;
}
/* jshint ignore:start */
default:
/* jshint ignore:end */
newHtml += element.tags[row];
break;
}
newHtml += "</td></tr>";
}
}
result_table_loadicon.classList.add('invisible');
result_table.classList.remove('invisible');
result_table.querySelector("tbody").innerHTML = newHtml;
}
})
.catch(function() {
result_table_loadicon.innerHTML = result_table_loadicon.innerHTML + "<p class=\"text-muted\">could not load data!</p>";
});
}
}
// this event occour only once per element
event.preventDefault();
});
searx.on('.searx_init_map', 'click', function(event) {
// no more request
this.classList.remove("searx_init_map");
//
var leaflet_target = this.dataset.leafletTarget;
var map_lon = parseFloat(this.dataset.mapLon);
var map_lat = parseFloat(this.dataset.mapLat);
var map_zoom = parseFloat(this.dataset.mapZoom);
var map_boundingbox = JSON.parse(this.dataset.mapBoundingbox);
var map_geojson = JSON.parse(this.dataset.mapGeojson);
searx.loadStyle('leaflet/leaflet.css');
searx.loadScript('leaflet/leaflet.js', function() {
var map_bounds = null;
if(map_boundingbox) {
var southWest = L.latLng(map_boundingbox[0], map_boundingbox[2]);
var northEast = L.latLng(map_boundingbox[1], map_boundingbox[3]);
map_bounds = L.latLngBounds(southWest, northEast);
}
// init map
var map = L.map(leaflet_target);
// create the tile layer with correct attribution
var osmMapnikUrl='https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png';
var osmMapnikAttrib='Map data © <a href="https://openstreetmap.org">OpenStreetMap</a> contributors';
var osmMapnik = new L.TileLayer(osmMapnikUrl, {minZoom: 1, maxZoom: 19, attribution: osmMapnikAttrib});
var osmWikimediaUrl='https://maps.wikimedia.org/osm-intl/{z}/{x}/{y}.png';
var osmWikimediaAttrib = 'Wikimedia maps beta | Maps data © <a href="https://openstreetmap.org">OpenStreetMap</a> contributors';
var osmWikimedia = new L.TileLayer(osmWikimediaUrl, {minZoom: 1, maxZoom: 19, attribution: osmWikimediaAttrib});
// init map view
if(map_bounds) {
// TODO hack: https://github.com/Leaflet/Leaflet/issues/2021
// Still useful ?
setTimeout(function () {
map.fitBounds(map_bounds, {
maxZoom:17
});
}, 0);
} else if (map_lon && map_lat) {
if(map_zoom) {
map.setView(new L.latLng(map_lat, map_lon),map_zoom);
} else {
map.setView(new L.latLng(map_lat, map_lon),8);
}
}
map.addLayer(osmMapnik);
var baseLayers = {
"OSM Mapnik": osmMapnik/*,
"OSM Wikimedia": osmWikimedia*/
};
L.control.layers(baseLayers).addTo(map);
if(map_geojson) {
L.geoJson(map_geojson).addTo(map);
} /*else if(map_bounds) {
L.rectangle(map_bounds, {color: "#ff7800", weight: 3, fill:false}).addTo(map);
}*/
});
// this event occour only once per element
event.preventDefault();
});
});
})(window, document, window.searx);

View file

@ -0,0 +1,63 @@
/**
* searx is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* searx is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with searx. If not, see < http://www.gnu.org/licenses/ >.
*
* (C) 2017 by Alexandre Flament, <alex@al-f.net>
*/
(function(w, d, searx) {
'use strict';
searx.ready(function() {
searx.image_thumbnail_layout = new searx.ImageLayout('#urls', '#urls .result-images', 'img.image_thumbnail', 200);
searx.image_thumbnail_layout.watch();
searx.on('.btn-collapse', 'click', function(event) {
var btnLabelCollapsed = this.getAttribute('data-btn-text-collapsed');
var btnLabelNotCollapsed = this.getAttribute('data-btn-text-not-collapsed');
var target = this.getAttribute('data-target');
var targetElement = d.querySelector(target);
var html = this.innerHTML;
if (this.classList.contains('collapsed')) {
html = html.replace(btnLabelCollapsed, btnLabelNotCollapsed);
} else {
html = html.replace(btnLabelNotCollapsed, btnLabelCollapsed);
}
this.innerHTML = html;
this.classList.toggle('collapsed');
targetElement.classList.toggle('invisible');
});
searx.on('.media-loader', 'click', function(event) {
var target = this.getAttribute('data-target');
var iframe_load = d.querySelector(target + ' > iframe');
var srctest = iframe_load.getAttribute('src');
if (srctest === null || srctest === undefined || srctest === false) {
iframe_load.setAttribute('src', iframe_load.getAttribute('data-src'));
}
});
w.addEventListener('scroll', function() {
var e = d.getElementById('backToTop'),
scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
if (e !== null) {
if (scrollTop >= 200) {
e.style.opacity = 1;
} else {
e.style.opacity = 0;
}
}
});
});
})(window, document, window.searx);

View file

@ -0,0 +1,94 @@
/**
* searx is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* searx is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with searx. If not, see < http://www.gnu.org/licenses/ >.
*
* (C) 2017 by Alexandre Flament, <alex@al-f.net>
*/
(function(w, d, searx) {
'use strict';
var firstFocus = true, qinput_id = "q", qinput;
function placeCursorAtEnd(element) {
if (element.setSelectionRange) {
var len = element.value.length;
element.setSelectionRange(len, len);
}
}
function submitIfQuery() {
if (qinput.value.length > 0) {
var search = document.getElementById('search');
setTimeout(search.submit.bind(search), 0);
}
}
searx.ready(function() {
qinput = d.getElementById(qinput_id);
function placeCursorAtEndOnce(e) {
if (firstFocus) {
placeCursorAtEnd(qinput);
firstFocus = false;
} else {
// e.preventDefault();
}
}
if (qinput !== null) {
// autocompleter
if (searx.autocompleter) {
searx.autocomplete = AutoComplete.call(w, {
Url: "./autocompleter",
EmptyMessage: searx.noItemFound,
HttpMethod: searx.method,
MinChars: 4,
Delay: 300,
}, "#" + qinput_id);
// hack, see : https://github.com/autocompletejs/autocomplete.js/issues/37
w.addEventListener('resize', function() {
var event = new CustomEvent("position");
qinput.dispatchEvent(event);
});
}
qinput.addEventListener('focus', placeCursorAtEndOnce, false);
qinput.focus();
}
// vanilla js version of search_on_category_select.js
if (qinput !== null && searx.search_on_category_select) {
d.querySelector('.help').className='invisible';
searx.on('#categories input', 'change', function(e) {
var i, categories = d.querySelectorAll('#categories input[type="checkbox"]');
for(i=0; i<categories.length; i++) {
if (categories[i] !== this && categories[i].checked) {
categories[i].click();
}
}
if (! this.checked) {
this.click();
}
submitIfQuery();
return false;
});
searx.on(d.getElementById('time_range'), 'change', submitIfQuery);
searx.on(d.getElementById('language'), 'change', submitIfQuery);
}
});
})(window, document, window.searx);

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 696 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 618 B

View file

@ -0,0 +1,624 @@
/* required styles */
.leaflet-pane,
.leaflet-tile,
.leaflet-marker-icon,
.leaflet-marker-shadow,
.leaflet-tile-container,
.leaflet-pane > svg,
.leaflet-pane > canvas,
.leaflet-zoom-box,
.leaflet-image-layer,
.leaflet-layer {
position: absolute;
left: 0;
top: 0;
}
.leaflet-container {
overflow: hidden;
}
.leaflet-tile,
.leaflet-marker-icon,
.leaflet-marker-shadow {
-webkit-user-select: none;
-moz-user-select: none;
user-select: none;
-webkit-user-drag: none;
}
/* Safari renders non-retina tile on retina better with this, but Chrome is worse */
.leaflet-safari .leaflet-tile {
image-rendering: -webkit-optimize-contrast;
}
/* hack that prevents hw layers "stretching" when loading new tiles */
.leaflet-safari .leaflet-tile-container {
width: 1600px;
height: 1600px;
-webkit-transform-origin: 0 0;
}
.leaflet-marker-icon,
.leaflet-marker-shadow {
display: block;
}
/* .leaflet-container svg: reset svg max-width decleration shipped in Joomla! (joomla.org) 3.x */
/* .leaflet-container img: map is broken in FF if you have max-width: 100% on tiles */
.leaflet-container .leaflet-overlay-pane svg,
.leaflet-container .leaflet-marker-pane img,
.leaflet-container .leaflet-shadow-pane img,
.leaflet-container .leaflet-tile-pane img,
.leaflet-container img.leaflet-image-layer {
max-width: none !important;
}
.leaflet-container.leaflet-touch-zoom {
-ms-touch-action: pan-x pan-y;
touch-action: pan-x pan-y;
}
.leaflet-container.leaflet-touch-drag {
-ms-touch-action: pinch-zoom;
}
.leaflet-container.leaflet-touch-drag.leaflet-touch-zoom {
-ms-touch-action: none;
touch-action: none;
}
.leaflet-tile {
filter: inherit;
visibility: hidden;
}
.leaflet-tile-loaded {
visibility: inherit;
}
.leaflet-zoom-box {
width: 0;
height: 0;
-moz-box-sizing: border-box;
box-sizing: border-box;
z-index: 800;
}
/* workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=888319 */
.leaflet-overlay-pane svg {
-moz-user-select: none;
}
.leaflet-pane { z-index: 400; }
.leaflet-tile-pane { z-index: 200; }
.leaflet-overlay-pane { z-index: 400; }
.leaflet-shadow-pane { z-index: 500; }
.leaflet-marker-pane { z-index: 600; }
.leaflet-tooltip-pane { z-index: 650; }
.leaflet-popup-pane { z-index: 700; }
.leaflet-map-pane canvas { z-index: 100; }
.leaflet-map-pane svg { z-index: 200; }
.leaflet-vml-shape {
width: 1px;
height: 1px;
}
.lvml {
behavior: url(#default#VML);
display: inline-block;
position: absolute;
}
/* control positioning */
.leaflet-control {
position: relative;
z-index: 800;
pointer-events: visiblePainted; /* IE 9-10 doesn't have auto */
pointer-events: auto;
}
.leaflet-top,
.leaflet-bottom {
position: absolute;
z-index: 1000;
pointer-events: none;
}
.leaflet-top {
top: 0;
}
.leaflet-right {
right: 0;
}
.leaflet-bottom {
bottom: 0;
}
.leaflet-left {
left: 0;
}
.leaflet-control {
float: left;
clear: both;
}
.leaflet-right .leaflet-control {
float: right;
}
.leaflet-top .leaflet-control {
margin-top: 10px;
}
.leaflet-bottom .leaflet-control {
margin-bottom: 10px;
}
.leaflet-left .leaflet-control {
margin-left: 10px;
}
.leaflet-right .leaflet-control {
margin-right: 10px;
}
/* zoom and fade animations */
.leaflet-fade-anim .leaflet-tile {
will-change: opacity;
}
.leaflet-fade-anim .leaflet-popup {
opacity: 0;
-webkit-transition: opacity 0.2s linear;
-moz-transition: opacity 0.2s linear;
-o-transition: opacity 0.2s linear;
transition: opacity 0.2s linear;
}
.leaflet-fade-anim .leaflet-map-pane .leaflet-popup {
opacity: 1;
}
.leaflet-zoom-animated {
-webkit-transform-origin: 0 0;
-ms-transform-origin: 0 0;
transform-origin: 0 0;
}
.leaflet-zoom-anim .leaflet-zoom-animated {
will-change: transform;
}
.leaflet-zoom-anim .leaflet-zoom-animated {
-webkit-transition: -webkit-transform 0.25s cubic-bezier(0,0,0.25,1);
-moz-transition: -moz-transform 0.25s cubic-bezier(0,0,0.25,1);
-o-transition: -o-transform 0.25s cubic-bezier(0,0,0.25,1);
transition: transform 0.25s cubic-bezier(0,0,0.25,1);
}
.leaflet-zoom-anim .leaflet-tile,
.leaflet-pan-anim .leaflet-tile {
-webkit-transition: none;
-moz-transition: none;
-o-transition: none;
transition: none;
}
.leaflet-zoom-anim .leaflet-zoom-hide {
visibility: hidden;
}
/* cursors */
.leaflet-interactive {
cursor: pointer;
}
.leaflet-grab {
cursor: -webkit-grab;
cursor: -moz-grab;
}
.leaflet-crosshair,
.leaflet-crosshair .leaflet-interactive {
cursor: crosshair;
}
.leaflet-popup-pane,
.leaflet-control {
cursor: auto;
}
.leaflet-dragging .leaflet-grab,
.leaflet-dragging .leaflet-grab .leaflet-interactive,
.leaflet-dragging .leaflet-marker-draggable {
cursor: move;
cursor: -webkit-grabbing;
cursor: -moz-grabbing;
}
/* marker & overlays interactivity */
.leaflet-marker-icon,
.leaflet-marker-shadow,
.leaflet-image-layer,
.leaflet-pane > svg path,
.leaflet-tile-container {
pointer-events: none;
}
.leaflet-marker-icon.leaflet-interactive,
.leaflet-image-layer.leaflet-interactive,
.leaflet-pane > svg path.leaflet-interactive {
pointer-events: visiblePainted; /* IE 9-10 doesn't have auto */
pointer-events: auto;
}
/* visual tweaks */
.leaflet-container {
background: #ddd;
outline: 0;
}
.leaflet-container a {
color: #0078A8;
}
.leaflet-container a.leaflet-active {
outline: 2px solid orange;
}
.leaflet-zoom-box {
border: 2px dotted #38f;
background: rgba(255,255,255,0.5);
}
/* general typography */
.leaflet-container {
font: 12px/1.5 "Helvetica Neue", Arial, Helvetica, sans-serif;
}
/* general toolbar styles */
.leaflet-bar {
box-shadow: 0 1px 5px rgba(0,0,0,0.65);
border-radius: 4px;
}
.leaflet-bar a,
.leaflet-bar a:hover {
background-color: #fff;
border-bottom: 1px solid #ccc;
width: 26px;
height: 26px;
line-height: 26px;
display: block;
text-align: center;
text-decoration: none;
color: black;
}
.leaflet-bar a,
.leaflet-control-layers-toggle {
background-position: 50% 50%;
background-repeat: no-repeat;
display: block;
}
.leaflet-bar a:hover {
background-color: #f4f4f4;
}
.leaflet-bar a:first-child {
border-top-left-radius: 4px;
border-top-right-radius: 4px;
}
.leaflet-bar a:last-child {
border-bottom-left-radius: 4px;
border-bottom-right-radius: 4px;
border-bottom: none;
}
.leaflet-bar a.leaflet-disabled {
cursor: default;
background-color: #f4f4f4;
color: #bbb;
}
.leaflet-touch .leaflet-bar a {
width: 30px;
height: 30px;
line-height: 30px;
}
/* zoom control */
.leaflet-control-zoom-in,
.leaflet-control-zoom-out {
font: bold 18px 'Lucida Console', Monaco, monospace;
text-indent: 1px;
}
.leaflet-control-zoom-out {
font-size: 20px;
}
.leaflet-touch .leaflet-control-zoom-in {
font-size: 22px;
}
.leaflet-touch .leaflet-control-zoom-out {
font-size: 24px;
}
/* layers control */
.leaflet-control-layers {
box-shadow: 0 1px 5px rgba(0,0,0,0.4);
background: #fff;
border-radius: 5px;
}
.leaflet-control-layers-toggle {
background-image: url(images/layers.png);
width: 36px;
height: 36px;
}
.leaflet-retina .leaflet-control-layers-toggle {
background-image: url(images/layers-2x.png);
background-size: 26px 26px;
}
.leaflet-touch .leaflet-control-layers-toggle {
width: 44px;
height: 44px;
}
.leaflet-control-layers .leaflet-control-layers-list,
.leaflet-control-layers-expanded .leaflet-control-layers-toggle {
display: none;
}
.leaflet-control-layers-expanded .leaflet-control-layers-list {
display: block;
position: relative;
}
.leaflet-control-layers-expanded {
padding: 6px 10px 6px 6px;
color: #333;
background: #fff;
}
.leaflet-control-layers-scrollbar {
overflow-y: scroll;
padding-right: 5px;
}
.leaflet-control-layers-selector {
margin-top: 2px;
position: relative;
top: 1px;
}
.leaflet-control-layers label {
display: block;
}
.leaflet-control-layers-separator {
height: 0;
border-top: 1px solid #ddd;
margin: 5px -10px 5px -6px;
}
/* Default icon URLs */
.leaflet-default-icon-path {
background-image: url(images/marker-icon.png);
}
/* attribution and scale controls */
.leaflet-container .leaflet-control-attribution {
background: #fff;
background: rgba(255, 255, 255, 0.7);
margin: 0;
}
.leaflet-control-attribution,
.leaflet-control-scale-line {
padding: 0 5px;
color: #333;
}
.leaflet-control-attribution a {
text-decoration: none;
}
.leaflet-control-attribution a:hover {
text-decoration: underline;
}
.leaflet-container .leaflet-control-attribution,
.leaflet-container .leaflet-control-scale {
font-size: 11px;
}
.leaflet-left .leaflet-control-scale {
margin-left: 5px;
}
.leaflet-bottom .leaflet-control-scale {
margin-bottom: 5px;
}
.leaflet-control-scale-line {
border: 2px solid #777;
border-top: none;
line-height: 1.1;
padding: 2px 5px 1px;
font-size: 11px;
white-space: nowrap;
overflow: hidden;
-moz-box-sizing: border-box;
box-sizing: border-box;
background: #fff;
background: rgba(255, 255, 255, 0.5);
}
.leaflet-control-scale-line:not(:first-child) {
border-top: 2px solid #777;
border-bottom: none;
margin-top: -2px;
}
.leaflet-control-scale-line:not(:first-child):not(:last-child) {
border-bottom: 2px solid #777;
}
.leaflet-touch .leaflet-control-attribution,
.leaflet-touch .leaflet-control-layers,
.leaflet-touch .leaflet-bar {
box-shadow: none;
}
.leaflet-touch .leaflet-control-layers,
.leaflet-touch .leaflet-bar {
border: 2px solid rgba(0,0,0,0.2);
background-clip: padding-box;
}
/* popup */
.leaflet-popup {
position: absolute;
text-align: center;
margin-bottom: 20px;
}
.leaflet-popup-content-wrapper {
padding: 1px;
text-align: left;
border-radius: 12px;
}
.leaflet-popup-content {
margin: 13px 19px;
line-height: 1.4;
}
.leaflet-popup-content p {
margin: 18px 0;
}
.leaflet-popup-tip-container {
width: 40px;
height: 20px;
position: absolute;
left: 50%;
margin-left: -20px;
overflow: hidden;
pointer-events: none;
}
.leaflet-popup-tip {
width: 17px;
height: 17px;
padding: 1px;
margin: -10px auto 0;
-webkit-transform: rotate(45deg);
-moz-transform: rotate(45deg);
-ms-transform: rotate(45deg);
-o-transform: rotate(45deg);
transform: rotate(45deg);
}
.leaflet-popup-content-wrapper,
.leaflet-popup-tip {
background: white;
color: #333;
box-shadow: 0 3px 14px rgba(0,0,0,0.4);
}
.leaflet-container a.leaflet-popup-close-button {
position: absolute;
top: 0;
right: 0;
padding: 4px 4px 0 0;
border: none;
text-align: center;
width: 18px;
height: 14px;
font: 16px/14px Tahoma, Verdana, sans-serif;
color: #c3c3c3;
text-decoration: none;
font-weight: bold;
background: transparent;
}
.leaflet-container a.leaflet-popup-close-button:hover {
color: #999;
}
.leaflet-popup-scrolled {
overflow: auto;
border-bottom: 1px solid #ddd;
border-top: 1px solid #ddd;
}
.leaflet-oldie .leaflet-popup-content-wrapper {
zoom: 1;
}
.leaflet-oldie .leaflet-popup-tip {
width: 24px;
margin: 0 auto;
-ms-filter: "progid:DXImageTransform.Microsoft.Matrix(M11=0.70710678, M12=0.70710678, M21=-0.70710678, M22=0.70710678)";
filter: progid:DXImageTransform.Microsoft.Matrix(M11=0.70710678, M12=0.70710678, M21=-0.70710678, M22=0.70710678);
}
.leaflet-oldie .leaflet-popup-tip-container {
margin-top: -1px;
}
.leaflet-oldie .leaflet-control-zoom,
.leaflet-oldie .leaflet-control-layers,
.leaflet-oldie .leaflet-popup-content-wrapper,
.leaflet-oldie .leaflet-popup-tip {
border: 1px solid #999;
}
/* div icon */
.leaflet-div-icon {
background: #fff;
border: 1px solid #666;
}
/* Tooltip */
/* Base styles for the element that has a tooltip */
.leaflet-tooltip {
position: absolute;
padding: 6px;
background-color: #fff;
border: 1px solid #fff;
border-radius: 3px;
color: #222;
white-space: nowrap;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
pointer-events: none;
box-shadow: 0 1px 3px rgba(0,0,0,0.4);
}
.leaflet-tooltip.leaflet-clickable {
cursor: pointer;
pointer-events: auto;
}
.leaflet-tooltip-top:before,
.leaflet-tooltip-bottom:before,
.leaflet-tooltip-left:before,
.leaflet-tooltip-right:before {
position: absolute;
pointer-events: none;
border: 6px solid transparent;
background: transparent;
content: "";
}
/* Directions */
.leaflet-tooltip-bottom {
margin-top: 6px;
}
.leaflet-tooltip-top {
margin-top: -6px;
}
.leaflet-tooltip-bottom:before,
.leaflet-tooltip-top:before {
left: 50%;
margin-left: -6px;
}
.leaflet-tooltip-top:before {
bottom: 0;
margin-bottom: -12px;
border-top-color: #fff;
}
.leaflet-tooltip-bottom:before {
top: 0;
margin-top: -12px;
margin-left: -6px;
border-bottom-color: #fff;
}
.leaflet-tooltip-left {
margin-left: -6px;
}
.leaflet-tooltip-right {
margin-left: 6px;
}
.leaflet-tooltip-left:before,
.leaflet-tooltip-right:before {
top: 50%;
margin-top: -6px;
}
.leaflet-tooltip-left:before {
right: 0;
margin-right: -12px;
border-left-color: #fff;
}
.leaflet-tooltip-right:before {
left: 0;
margin-left: -12px;
border-right-color: #fff;
}

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,67 @@
@background_color: white;
.autocomplete {
position: absolute;
max-height: 0;
overflow-y: hidden;
text-align: left;
&:active, &:focus, &:hover {
background-color: @background_color;
}
&:empty {
display: none;
}
> ul {
list-style-type: none;
margin: 0;
padding: 0;
> li {
cursor: pointer;
padding: 5px 0 5px 10px;
&.active, &:active, &:focus {
background-color: @color-base;
a:active, a:focus, a:hover {
text-decoration: none;
}
}
&.locked {
cursor: inherit;
}
}
}
&.open {
display: block;
background-color: @background_color;
border: 1px solid @color-base;
max-height: 500px;
overflow-y: auto;
z-index:100;
&:empty {
display: none;
}
}
}
@media screen and (max-width: @results-width) {
.autocomplete {
bottom: 0;
}
.autocomplete > ul > li {
padding: 7px 0 7px 10px;
border-bottom: 1px solid @color-result-top-border;
text-align: left;
}
}

View file

@ -0,0 +1,83 @@
.highlight .hll { background-color: #ffffcc }
.highlight { background: #f8f8f8; }
.highlight .c { color: #408080; font-style: italic } /* Comment */
.highlight .err { border: 1px solid #FF0000 } /* Error */
.highlight .k { color: #008000; font-weight: bold } /* Keyword */
.highlight .o { color: #666666 } /* Operator */
.highlight .cm { color: #408080; font-style: italic } /* Comment.Multiline */
.highlight .cp { color: #BC7A00 } /* Comment.Preproc */
.highlight .c1 { color: #408080; font-style: italic } /* Comment.Single */
.highlight .cs { color: #408080; font-style: italic } /* Comment.Special */
.highlight .gd { color: #A00000 } /* Generic.Deleted */
.highlight .ge { font-style: italic } /* Generic.Emph */
.highlight .gr { color: #FF0000 } /* Generic.Error */
.highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */
.highlight .gi { color: #00A000 } /* Generic.Inserted */
.highlight .go { color: #888888 } /* Generic.Output */
.highlight .gp { color: #000080; font-weight: bold } /* Generic.Prompt */
.highlight .gs { font-weight: bold } /* Generic.Strong */
.highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */
.highlight .gt { color: #0044DD } /* Generic.Traceback */
.highlight .kc { color: #008000; font-weight: bold } /* Keyword.Constant */
.highlight .kd { color: #008000; font-weight: bold } /* Keyword.Declaration */
.highlight .kn { color: #008000; font-weight: bold } /* Keyword.Namespace */
.highlight .kp { color: #008000 } /* Keyword.Pseudo */
.highlight .kr { color: #008000; font-weight: bold } /* Keyword.Reserved */
.highlight .kt { color: #B00040 } /* Keyword.Type */
.highlight .m { color: #666666 } /* Literal.Number */
.highlight .s { color: #BA2121 } /* Literal.String */
.highlight .na { color: #7D9029 } /* Name.Attribute */
.highlight .nb { color: #008000 } /* Name.Builtin */
.highlight .nc { color: #0000FF; font-weight: bold } /* Name.Class */
.highlight .no { color: #880000 } /* Name.Constant */
.highlight .nd { color: #AA22FF } /* Name.Decorator */
.highlight .ni { color: #999999; font-weight: bold } /* Name.Entity */
.highlight .ne { color: #D2413A; font-weight: bold } /* Name.Exception */
.highlight .nf { color: #0000FF } /* Name.Function */
.highlight .nl { color: #A0A000 } /* Name.Label */
.highlight .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */
.highlight .nt { color: #008000; font-weight: bold } /* Name.Tag */
.highlight .nv { color: #19177C } /* Name.Variable */
.highlight .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */
.highlight .w { color: #bbbbbb } /* Text.Whitespace */
.highlight .mf { color: #666666 } /* Literal.Number.Float */
.highlight .mh { color: #666666 } /* Literal.Number.Hex */
.highlight .mi { color: #666666 } /* Literal.Number.Integer */
.highlight .mo { color: #666666 } /* Literal.Number.Oct */
.highlight .sb { color: #BA2121 } /* Literal.String.Backtick */
.highlight .sc { color: #BA2121 } /* Literal.String.Char */
.highlight .sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */
.highlight .s2 { color: #BA2121 } /* Literal.String.Double */
.highlight .se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */
.highlight .sh { color: #BA2121 } /* Literal.String.Heredoc */
.highlight .si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */
.highlight .sx { color: #008000 } /* Literal.String.Other */
.highlight .sr { color: #BB6688 } /* Literal.String.Regex */
.highlight .s1 { color: #BA2121 } /* Literal.String.Single */
.highlight .ss { color: #19177C } /* Literal.String.Symbol */
.highlight .bp { color: #008000 } /* Name.Builtin.Pseudo */
.highlight .vc { color: #19177C } /* Name.Variable.Class */
.highlight .vg { color: #19177C } /* Name.Variable.Global */
.highlight .vi { color: #19177C } /* Name.Variable.Instance */
.highlight .il { color: #666666 } /* Literal.Number.Integer.Long */
.highlight pre {
overflow: auto;
}
.highlight .lineno {
-webkit-touch-callout: none;
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
cursor: default;
&::selection {
background: transparent; /* WebKit/Blink Browsers */
}
&::-moz-selection {
background: transparent; /* Gecko Browsers */
}
}

View file

@ -0,0 +1,135 @@
/*
* searx, A privacy-respecting, hackable metasearch engine
*
* To change the colors of the site, simple edit this variables
*/
/// Basic Colors
@color-base: #3498DB;
@color-base-dark: #084999;
@color-base-light: #ECF0F1;
@color-highlight: #094089;
@color-black: #000000;
///
@color-error: #db3434;
@color-error-background: lighten(@color-error, 40%);
@color-warning: #dbba34;
@color-warning-background: lighten(@color-warning, 40%);
/// General
@color-font: #444;
@color-font-light: #888;
@color-red: #25a55b;
@color-url-font: #29314d;
@color-url-visited-font: #684898;
@results-width: 50em;
@search-width: 40em;
//
@color-a-font: @color-base;
@color-a-font-hover: @color-base;
/// Start-Screen
/// Search-Input
@color-search-border: @color-base;
@color-search-background: #FFF;
@color-search-font: #222;
/// Autocompleter
@color-autocompleter-choices-background: #FFF;
@color-autocompleter-choices-border: @color-base;
@color-autocompleter-choices-border-left-right: @color-base;
@color-autocompleter-choices-border-bottom: @color-base;
@color-autocompleter-choices-font: #444;
/// Answers
@color-answers-border: @color-base-dark;
// Selected
@color-autocompleter-selected-background: #444;
@color-autocompleter-selected-font: #FFF;
@color-autocompleter-selected-queried-font: #9FCFFF;
/// Categories
@color-categories-item-selected: @color-base;
@color-categories-item-selected-font: #FFF;
@color-categories-item-border-selected: @color-base-dark;
@color-categories-item-border-unselected: #E8E7E6;
@color-categories-item-border-unselected-hover: @color-base;
/// Results
@color-suggestions-button-background: @color-base;
@color-suggestions-button-font: #FFF;
@color-download-button-background: @color-base;
@color-download-button-font: #FFF;
@color-result-search-background: @color-base-light;
@color-result-definition-border: gray;
@color-result-torrent-border: lightgray;
@color-result-top-border: #E8E7E6;
// Link to result
@color-result-link-font: @color-base-dark;
@color-result-link-visited-font: @color-url-visited-font;
// Url to result
@color-result-url-font: @color-red;
// Publish Date
@color-result-publishdate-font: @color-font-light;
// Images
@color-result-image-span-background-hover: rgba(0, 0, 0, 0.6);
@color-result-image-span-font: #FFF;
// Search-URL
@color-result-search-url-border: #888;
@color-result-search-url-font: #444;
/// Settings
@color-settings-fieldset: @color-base;
@color-settings-table-striped: #dbdbdb;
@color-settings-tr-hover: #ececec;
// Labels
@color-settings-label-allowed-background: #E74C3C;
@color-settings-label-allowed-font: #FFF;
@color-settings-label-deny-background: #2ECC71;
@color-settings-label-deny-font: @color-font;
@color-settings-return-background: @color-base;
@color-settings-return-font: #FFF;
/// Other
@color-engines-font: @color-font-light;
@color-percentage-div-background: #444;
/// Load fonts from this directory.
@icon-font-path: "../../../fonts/";
//** File name for all font files.
@icon-font-name: "glyphicons-halflings-regular";
//** Element ID within SVG icon file.
@icon-font-svg-id: "glyphicons_halflingsregular";

View file

@ -0,0 +1,43 @@
.index {
text-align: center;
.title {
background: url('../img/searx.png') no-repeat;
width: 100%;
min-height: 80px;
background-position: center;
}
h1 {
font-size: 5em;
visibility: hidden;
}
#search {
margin: 0 auto;
background: inherit;
border: inherit;
}
.search_filters {
display: block;
margin: 1em 0;
}
.category label {
padding: 6px 10px;
border-bottom: initial !important;
}
}
@media screen and (max-width: 75em) {
div.title {
h1 {
font-size: 1em;
}
}
}

View file

@ -0,0 +1,174 @@
// Generated by grunt-webfont
@font-face {
font-family:"ion";
src:url("../fonts/ion.eot?94af7082ea096aefe3a7b6642834716e");
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");
font-weight:normal;
font-style:normal;
}
.ion-icon {
&:before {
font-family:"ion";
}
display:inline-block;
vertical-align:middle;
line-height:1;
font-weight:normal;
font-style:normal;
speak:none;
text-decoration:inherit;
text-transform:none;
text-rendering:auto;
-webkit-font-smoothing:antialiased;
-moz-osx-font-smoothing:grayscale;
}
// Icons
.ion-navicon-round {
&:before {
content:"\f101";
}
}
.ion-search {
&:before {
content:"\f102";
}
}
.ion-play {
&:before {
content:"\f103";
}
}
.ion-link {
&:before {
content:"\f104";
}
}
.ion-chevron-up {
&:before {
content:"\f105";
}
}
.ion-chevron-left {
&:before {
content:"\f106";
}
}
.ion-chevron-right {
&:before {
content:"\f107";
}
}
.ion-arrow-down-a {
&:before {
content:"\f108";
}
}
.ion-arrow-up-a {
&:before {
content:"\f109";
}
}
.ion-arrow-swap {
&:before {
content:"\f10a";
}
}
.ion-arrow-dropdown {
&:before {
content:"\f10b";
}
}
.ion-globe {
&:before {
content:"\f10c";
}
}
.ion-time {
&:before {
content:"\f10d";
}
}
.ion-location {
&:before {
content:"\f10e";
}
}
.ion-warning {
&:before {
content:"\f10f";
}
}
.ion-error {
&:before {
content:"\f110";
}
}
.ion-film-outline {
&:before {
content:"\f111";
}
}
.ion-music-note {
&:before {
content:"\f112";
}
}
.ion-more-vertical {
&:before {
content:"\f113";
}
}
.ion-magnet {
&:before {
content:"\f114";
}
}

View file

@ -0,0 +1,62 @@
/*
* searx, A privacy-respecting, hackable metasearch engine
*/
// Mixins
.text-size-adjust (@property: 100%) {
-webkit-text-size-adjust: @property;
-ms-text-size-adjust: @property;
-moz-text-size-adjust: @property;
text-size-adjust: @property;
}
.rounded-corners (@radius: 4px) {
-webkit-border-radius: @radius;
-moz-border-radius: @radius;
border-radius: @radius;
}
// disable user selection
.disable-user-select () {
-webkit-touch-callout: none;
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
// select all on focus
.select-all-on-focus() {
-webkit-user-select: all;
-moz-user-select: all;
-ms-user-select: all;
user-select: all;
}
// see https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Flexible_Box_Layout/Advanced_layouts_with_flexbox
.flexbox() {
display: -webkit-box;
display: -moz-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
}
.inline-flex() {
display: -webkit-inline-box;
display: -moz-inline-box;
display: -webkit-inline-flex;
display: -ms-inline-flexbox;
display: inline-flex;
}
.flex-direction-row() {
-webkit-box-direction: normal;
-webkit-box-orient: horizontal;
-moz-box-direction: normal;
-moz-box-orient: horizontal;
-webkit-flex-direction: row;
-ms-flex-direction: row;
flex-direction: row;
}

View file

@ -0,0 +1,447 @@
/*! normalize.css v7.0.0 | MIT License | github.com/necolas/normalize.css */
/* Document
========================================================================== */
/**
* 1. Correct the line height in all browsers.
* 2. Prevent adjustments of font size after orientation changes in
* IE on Windows Phone and in iOS.
*/
html {
line-height: 1.15; /* 1 */
-ms-text-size-adjust: 100%; /* 2 */
-webkit-text-size-adjust: 100%; /* 2 */
}
/* Sections
========================================================================== */
/**
* Remove the margin in all browsers (opinionated).
*/
body {
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
* `article` contexts in Chrome, Firefox, and Safari.
*/
h1 {
font-size: 2em;
margin: 0.67em 0;
}
/* 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.
* 2. Show the overflow in Edge and IE.
*/
hr {
box-sizing: content-box; /* 1 */
height: 0; /* 1 */
overflow: visible; /* 2 */
}
/**
* 1. Correct the inheritance and scaling of font size in all browsers.
* 2. Correct the odd `em` font sizing in all browsers.
*/
pre {
font-family: monospace, monospace; /* 1 */
font-size: 1em; /* 2 */
}
/* Text-level semantics
========================================================================== */
/**
* 1. Remove the gray background on active links in IE 10.
* 2. Remove gaps in links underline in iOS 8+ and Safari 8+.
*/
a {
background-color: transparent; /* 1 */
-webkit-text-decoration-skip: objects; /* 2 */
}
/**
* 1. Remove the bottom border in Chrome 57- and Firefox 39-.
* 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari.
*/
abbr[title] {
border-bottom: none; /* 1 */
text-decoration: underline; /* 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.
*/
b,
strong {
font-weight: bolder;
}
/**
* 1. Correct the inheritance and scaling of font size in all browsers.
* 2. Correct the odd `em` font sizing in all browsers.
*/
code,
kbd,
samp {
font-family: monospace, monospace; /* 1 */
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.
*/
small {
font-size: 80%;
}
/**
* Prevent `sub` and `sup` elements from affecting the line height in
* all browsers.
*/
sub,
sup {
font-size: 75%;
line-height: 0;
position: relative;
vertical-align: baseline;
}
sub {
bottom: -0.25em;
}
sup {
top: -0.5em;
}
/* Embedded content
========================================================================== */
/**
* Add the correct display in IE 9-.
*/
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 {
border-style: none;
}
/**
* Hide the overflow in IE.
*/
svg:not(:root) {
overflow: hidden;
}
/* Forms
========================================================================== */
/**
* 1. Change the font styles in all browsers (opinionated).
* 2. Remove the margin in Firefox and Safari.
*/
button,
input,
optgroup,
select,
textarea {
font-family: sans-serif; /* 1 */
font-size: 100%; /* 1 */
line-height: 1.15; /* 1 */
margin: 0; /* 2 */
}
/**
* Show the overflow in IE.
* 1. Show the overflow in Edge.
*/
button,
input { /* 1 */
overflow: visible;
}
/**
* Remove the inheritance of text transform in Edge, Firefox, and IE.
* 1. Remove the inheritance of text transform in Firefox.
*/
button,
select { /* 1 */
text-transform: none;
}
/**
* 1. Prevent a WebKit bug where (2) destroys native `audio` and `video`
* controls in Android 4.
* 2. Correct the inability to style clickable types in iOS and Safari.
*/
button,
html [type="button"], /* 1 */
[type="reset"],
[type="submit"] {
-webkit-appearance: button; /* 2 */
}
/**
* Remove the inner border and padding in Firefox.
*/
button::-moz-focus-inner,
[type="button"]::-moz-focus-inner,
[type="reset"]::-moz-focus-inner,
[type="submit"]::-moz-focus-inner {
border-style: none;
padding: 0;
}
/**
* Restore the focus styles unset by the previous rule.
*/
button:-moz-focusring,
[type="button"]:-moz-focusring,
[type="reset"]:-moz-focusring,
[type="submit"]:-moz-focusring {
outline: 1px dotted ButtonText;
}
/**
* Correct the padding in Firefox.
*/
fieldset {
padding: 0.35em 0.75em 0.625em;
}
/**
* 1. Correct the text wrapping in Edge and IE.
* 2. Correct the color inheritance from `fieldset` elements in IE.
* 3. Remove the padding so developers are not caught out when they zero out
* `fieldset` elements in all browsers.
*/
legend {
box-sizing: border-box; /* 1 */
color: inherit; /* 2 */
display: table; /* 1 */
max-width: 100%; /* 1 */
padding: 0; /* 3 */
white-space: normal; /* 1 */
}
/**
* 1. Add the correct display in IE 9-.
* 2. Add the correct vertical alignment in Chrome, Firefox, and Opera.
*/
progress {
display: inline-block; /* 1 */
vertical-align: baseline; /* 2 */
}
/**
* Remove the default vertical scrollbar in IE.
*/
textarea {
overflow: auto;
}
/**
* 1. Add the correct box sizing in IE 10-.
* 2. Remove the padding in IE 10-.
*/
[type="checkbox"],
[type="radio"] {
box-sizing: border-box; /* 1 */
padding: 0; /* 2 */
}
/**
* Correct the cursor style of increment and decrement buttons in Chrome.
*/
[type="number"]::-webkit-inner-spin-button,
[type="number"]::-webkit-outer-spin-button {
height: auto;
}
/**
* 1. Correct the odd appearance in Chrome and Safari.
* 2. Correct the outline style in Safari.
*/
[type="search"] {
-webkit-appearance: textfield; /* 1 */
outline-offset: -2px; /* 2 */
}
/**
* Remove the inner padding and cancel buttons in Chrome and Safari on macOS.
*/
[type="search"]::-webkit-search-cancel-button,
[type="search"]::-webkit-search-decoration {
-webkit-appearance: none;
}
/**
* 1. Correct the inability to style clickable types in iOS and Safari.
* 2. Change font properties to `inherit` in Safari.
*/
::-webkit-file-upload-button {
-webkit-appearance: button; /* 1 */
font: inherit; /* 2 */
}
/* Interactive
========================================================================== */
/*
* Add the correct display in IE 9-.
* 1. Add the correct display in Edge, IE, and Firefox.
*/
details, /* 1 */
menu {
display: block;
}
/*
* Add the correct display in all browsers.
*/
summary {
display: list-item;
}
/* Scripting
========================================================================== */
/**
* Add the correct display in IE 9-.
*/
canvas {
display: inline-block;
}
/**
* Add the correct display in IE.
*/
template {
display: none;
}
/* Hidden
========================================================================== */
/**
* Add the correct display in IE 10-.
*/
[hidden] {
display: none;
}

View file

@ -0,0 +1,78 @@
#main_preferences {
form {
width: 100%;
}
fieldset {
margin: 8px;
border: none;
}
legend {
margin: 0;
padding: 5px 0 0 0;
display: block;
float:left;
width: 300px;
}
.value {
margin: 0;
padding: 0;
float:left;
width: 15em;
}
.description {
margin: 0;
padding: 5px 0 0 0;
float:left;
width: 50%;
color: darken(#dcdcdc, 30%);
font-size: 90%;
}
select {
width: 200px;
font-size: inherit !important;
}
table {
border-collapse: collapse;
}
table td {
text-align: center;
}
.name, .shortcut {
text-align: left;
}
.preferences_back {
background: none repeat scroll 0 0 @color-settings-return-background;
color: white;
border: 0 none;
.rounded-corners;
cursor: pointer;
display: inline-block;
margin: 2px 4px;
padding: 0.5em;
a {
display: block;
color: @color-settings-return-font;
}
a::first-letter {
text-transform: uppercase;
}
}
}
@media screen and (max-width: 75em) {
.preferences_back {
clear: both;
}
}

View file

@ -0,0 +1,232 @@
/*
* searx, A privacy-respecting, hackable metasearch engine
*/
#search {
padding: 0 2em;
margin: 0;
background: #f7f7f7;
border-bottom: 1px solid #d7d7d7;
}
#search_wrapper {
padding: 10px 0;
}
.search_box {
margin: 0 12px 0 0;
display: inline-flex;
flex-direction: row;
white-space: nowrap;
/*
&:has(q:focus) {
box-shadow: 0px 0px 5px #CCC;
}
*/
}
#q, #send_search {
display: block !important;
border-collapse: separate;
box-sizing: border-box;
position: relative;
margin: 0;
padding: 2px;
height: 2.2em;
background: none repeat scroll 0 0 @color-search-background;
border: 1px solid @color-search-border;
border-radius: 0px;
outline: none;
color: @color-search-font;
font-size: 16px;
z-index: 2;
}
#q {
outline: medium none;
padding-left: 8px;
padding-right: 0px !important;
border-right: none;
width: @search-width;
}
#send_search {
border-left: none;
width: 2.2em;
&:hover {
cursor: pointer;
background-color: @color-search-border;
color: @color-base-light;
}
}
.no-js #send_search {
width: auto !important;
}
.search_filters {
display: inline-block;
vertical-align: middle;
}
@media screen and (max-width: 75em) {
#categories {
font-size: 90%;
clear: both;
.checkbox_container {
margin-top: 2px;
margin: auto;
}
}
html.touch {
#main_index, #main_results {
#categories_container {
width: 1000px;
width: -moz-max-content;
width: -webkit-max-content;
width: max-content;
.category {
display: inline-block;
width: auto;
}
}
#categories {
width: 100%;
margin: 0;
text-align: left;
overflow-x: scroll;
overflow-y: hidden;
-webkit-overflow-scrolling: touch;
}
}
}
}
@media screen and (max-width: @results-width) {
#search {
width: 100%;
margin: 0;
padding: 0.1em 0 0 0;
}
#search_wrapper {
width: 100%;
margin: 0 0 0.7em 0;
padding: 0;
}
.search_box {
// hack, should bew 100% ?
width: 99%;
margin: 0.1em;
padding: 0 0.1em 0 0;
display: flex;
flex-direction: row;
}
#q {
width: auto !important;
flex: 1;
}
.search_filters {
display: block;
margin: 0.5em;
}
.language, .time_range {
width: 45%;
}
.category {
display: block;
width: 90%;
label {
border-bottom: 0;
}
}
}
#categories {
margin: 0 10px 0 0;
.disable-user-select;
&::-webkit-scrollbar {
width: 0;
height: 0;
}
}
.category {
display: inline-block;
position: relative;
margin: 0 3px;
padding: 0px;
input {
display: none;
}
label {
cursor: pointer;
padding: 4px 10px;
margin: 0;
display: block;
text-transform: capitalize;
font-size: 0.9em;
border-bottom: 2px solid transparent;
.disable-user-select;
}
input[type="checkbox"]:focus + label {
box-shadow: 0px 0px 8px #3498DB;
}
/*label:hover {
border-bottom: 2px solid @color-categories-item-border-unselected-hover;
}*/
input[type="checkbox"]:checked + label {
background: @color-categories-item-selected;
color: @color-categories-item-selected-font;
border-bottom: 2px solid @color-categories-item-border-selected;
}
}
#categories_container {
position: relative;
.help {
position: absolute;
width: 100%;
bottom: -20px;
overflow: hidden;
opacity: 0;
transition: opacity 1s ease;
font-size: 0.8em;
text-position: center;
background: white;
}
&:hover .help {
opacity: 0.8;
transition: opacity 1s ease;
}
}

View file

@ -0,0 +1,8 @@
.percentage {
position: relative;
width: 300px;
div {
background: @color-percentage-div-background;
}
}

View file

@ -0,0 +1,6 @@
@import "style.less";
#search_submit {
left: 1px;
right:auto;
}

View file

@ -0,0 +1,709 @@
/*
* searx, A privacy-respecting, hackable metasearch engine
*
* To convert "style.less" to "style.css" run: $make styles
*/
@import "normalize.less";
@import "definitions.less";
@import "mixins.less";
@import "code.less";
@import "toolkit.less";
@import "autocomplete.less";
// ion-icon
@import "ion.less";
.ion-icon-big {
.ion-icon;
font-size: 149%;
}
// for index.html template
@import "index.less";
// for preferences.html template
@import "preferences.less";
// Search-Field
@import "search.less";
// Main LESS-Code
html {
font-family: arial, sans-serif;
font-size: 0.9em;
.text-size-adjust;
color: @color-font;
padding: 0;
margin: 0;
}
body, main {
padding: 0;
margin: 0;
}
main {
width: 100%;
// position: absolute;
}
footer {
// position:absolute;
bottom:0;
width:100%;
height:50px;
}
#main_preferences, #main_about, #main_stats {
margin: 3em;
width: auto;
}
footer {
bottom: 0;
height: 3em;
margin: 1em 0;
padding: 1em 0;
clear: both;
width: 100%;
text-align: center;
p {
font-size: 0.9em;
}
}
#main_preferences h1, #main_stats h1 {
background: url('../img/searx.png') no-repeat;
background-size: auto 75%;
min-height: 40px;
margin: 0 auto;
span {
visibility: hidden;
}
}
input[type="submit"], #results button[type="submit"] {
padding: 0.5rem;
margin: 2px 4px;
display: inline-block;
background: @color-download-button-background;
color: @color-download-button-font;
.rounded-corners;
border: 0;
cursor: pointer;
}
a {
text-decoration: none;
color: @color-url-font;
&:visited {
color: @color-url-visited-font;
.highlight {
color: @color-url-visited-font;
}
}
}
article[data-vim-selected] {
background: #f7f7f7;
}
article[data-vim-selected]::before {
position: absolute;
left: 1em;
padding: 2px;
content: ">";
font-weight: bold;
color: @color-base;
}
article.result-images[data-vim-selected] {
background: @color-base;
}
article.result-images[data-vim-selected]::before {
display: none;
content: "";
}
.result {
margin: 19px 0 18px 0;
padding: 0;
h3 {
font-size: 1.1em;
word-wrap:break-word;
margin: 5px 0 1px 0;
padding: 0;
margin-bottom: 0;
a {
color: @color-result-link-font;
font-weight: normal;
font-size: 1.1em;
&:visited {
color: @color-result-link-visited-font;
}
&:focus, &:hover {
text-decoration: underline;
border: none;
-webkit-box-shadow: none;
box-shadow: none;
outline:none;
}
}
}
.cache_link, .proxyfied_link {
font-size: 0.9em !important;
}
.content, .stat, .altlink {
font-size: 0.9em;
margin: 0;
padding: 0;
max-width: 54em;
word-wrap:break-word;
line-height: 1.24;
.highlight {
color: @color-black;
background: inherit;
font-weight: bold;
}
}
.codelines {
.highlight {
color: inherit;
background: inherit;
font-weight: normal;
}
}
.url {
font-size: 0.9em;
margin: 0 0 3px 0;
padding: 0;
max-width: 54em;
word-wrap:break-word;
color: @color-result-url-font;
}
.published_date {
font-size: 0.8em;
color: @color-result-publishdate-font;
}
img {
&.thumbnail {
float: left;
padding: 0 5px 10px 0;
width: 20em;
min-width: 20em;
min-height: 8em;
// background: @color-base-light;
}
&.image {
float: left;
padding: 0 5px 10px 0;
width: 100px;
max-height: 100px;
object-fit: scale-down;
object-position: right top;
}
}
.break {
clear: both;
}
}
.category-social .image {
width: auto !important;
min-width: 48px;
min-height: 48px;
padding: 0 5px 25px 0 !important;
}
.result-videos .content {
overflow: hidden;
}
.engines {
float: right;
color: @color-engines-font;
span {
font-size: smaller;
margin: 0 0.5em 0 0;
}
}
.small_font {
font-size: 0.8em;
}
.highlight {
color: @color-highlight;
background: inherit;
font-weight: bold;
}
.result-images {
display: inline-block;
margin: 0;
padding: 0;
position: relative;
max-height: 200px;
img {
float: inherit;
margin: 0;
padding: 0;
border: none;
max-height: 200px;
background: @color-base-dark;
}
span a {
display: none;
color: @color-result-image-span-font;
}
&:hover span a {
display: block;
position: absolute;
bottom: 0;
right: 0;
padding: 4px;
margin: 0 0 4px 4px;
background-color: @color-result-image-span-background-hover;
font-size: 0.7em;
}
}
.torrent_result {
border-left: 10px solid @color-result-torrent-border;
padding-left: 3px;
p {
margin: 3px;
font-size: 0.8em;
}
a {
color: @color-result-link-font;
&:hover {
text-decoration: underline;
}
&:visited {
color: @color-result-link-visited-font;
}
}
}
#results {
margin: 2em 2em 20px 2em;
padding: 0;
width: @results-width;
}
#suggestions {
.wrapper {
display: flex;
flex-flow: row wrap;
justify-content: flex-end;
form {
display: inline-block;
flex: 1 1 50%;
}
}
}
#suggestions, #answers, #corrections {
max-width: @results-width;
}
#suggestions, #answers, #infoboxes, #corrections {
input {
padding: 0;
margin: 3px;
font-size: 0.9em;
display: inline-block;
background: transparent;
color: @color-result-search-url-font;
cursor: pointer;
}
input[type="submit"], .infobox .url a {
color: @color-result-link-font;
text-decoration: none;
font-size: 0.9rem;
&:hover {
text-decoration: underline;
}
}
}
#corrections {
display: flex;
flex-flow: row wrap;
margin: 1em 0;
h4, input[type="submit"] {
display: inline-block;
margin: 0 0.5em 0 0;
}
input[type="submit"]::after {
content: ", "
}
}
#suggestions .title, #search_url .title, #apis .title {
margin: 2em 0 0.5em 0;
color: @color-font;
}
#answers {
margin: 10px 8px 10px 8px;
border: 1px solid #ddd;
padding: 0.9em;
box-shadow: 0px 0px 5px #CCC;
h4 {
display: none;
}
.answer {
display: block;
font-size: 1.2em;
font-weight: bold;
}
}
#answers, #infoboxes {
form {
min-width: 210px;
}
}
#sidebar {
position: absolute;
top: 100px;
left: 57em;
margin: 0px 2px 5px 5px;
padding: 0px 2px 2px;
max-width: 25em;
word-wrap: break-word;
.infobox {
margin: 10px 0 10px;
border: 1px solid #ddd;
padding: 0.9em;
font-size: 0.9em;
box-shadow: 0px 0px 5px #CCC;
h2 {
margin: 0 0 .5em 0;
}
img {
max-width: 100%;
max-height: 12em;
display: block;
margin: 0;
padding: 0;
}
dl {
margin: 0.5em 0;
}
dt {
display: inline;
margin: 0.5em 0.25em 0.5em 0;
padding: 0;
font-weight: bold;
}
dd {
display: inline;
margin: 0.5em 0;
padding: 0;
}
input {
font-size: 1em;
}
br {
clear: both;
}
.attributes, .urls {
clear: both;
}
}
}
#search_url {
margin-top: 8px;
div {
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 {
display: block;
width: 200em;
font-size: 0.8em;
word-break: break-all;
margin: 0.1em;
.select-all-on-focus();
}
}
}
#linkto_preferences {
position: absolute;
right: 10px;
top: 0.9em;
padding: 0;
border: 0;
display: block;
font-size: 1.2em;
color: @color-search-font;
a:link *, a:hover *, a:visited *, a:active * {
color: @color-search-font;
}
}
#pagination {
clear: both;
br {
clear: both;
}
}
#apis {
margin-top: 8px;
clear: both;
}
#backToTop {
border: 1px solid #ddd;
margin: 0 0 0 2em;
padding: 0;
font-size: 1em;
box-shadow: 0px 0px 5px #CCC;
background: white;
position: fixed;
bottom: 85px;
left: @results-width;
transition: opacity 0.5s;
opacity: 0;
a {
display: block;
margin: 0;
padding: 0.6em;
}
}
@media screen and (max-width: 75em) {
#main_preferences, #main_about, #main_stats {
margin: 0.5em;
width: auto;
}
#suggestions, #answers {
margin-top: 1em;
}
#infoboxes {
position: inherit;
max-width: inherit;
.infobox {
clear:both;
img {
float: left;
max-width: 10em;
margin: 0.5em 0.5em 0.5em 0;
}
}
}
#sidebar {
position: static;
max-width: @results-width;
margin: 0 0 2px 0;
padding: 0;
float: none;
border: none;
width: auto;
input {
border: 0;
}
}
#apis {
display: none;
}
#search_url {
display: none;
}
.result {
border-bottom: 1px solid @color-result-top-border;
margin: 0;
padding-top: 8px;
padding-bottom: 6px;
h3 {
margin: 0 0 1px 0;
}
.thumbnail {
max-width: 98%;
}
.url {
span.url {
display: block;
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
width: 100%;
}
a {
float: right;
padding: 0 0.5em;
}
}
.engines {
float: right;
padding: 0 0 3px 0;
}
}
.result-images {
border-bottom: none !important;
}
.image_result {
max-width: 98%;
img {
max-width: 98%;
}
}
}
@media screen and (max-width: @results-width) {
article[data-vim-selected]::before {
display: none;
content: "";
}
#linkto_preferences {
display: none;
postion: fixed !important;
top: 100px;
right: 0px;
}
#sidebar {
margin: 0 5px 2px 5px;
}
#corrections {
margin: 1em 5px 1em 5px;
}
#results {
margin: 0;
padding: 0;
width: initial;
}
#backToTop {
left: 40em;
bottom: 35px;
}
.result {
padding: 8px 10px 6px 10px;
}
.result-images {
margin: 0;
padding: 0;
border: none;
}
}
@media screen and (max-width: 35em) {
.result-videos {
img.thumbnail {
float: none !important;
}
.content {
overflow: inherit;
}
}
}

View file

@ -0,0 +1,346 @@
// other solution : http://stackoverflow.com/questions/1577598/how-to-hide-parts-of-html-when-javascript-is-disabled/13857783#13857783
html.no-js .hide_if_nojs {
display: none;
}
html.js .show_if_nojs {
display: none;
}
.center {
text-align: center;
}
.right {
float: right ;
}
.left {
float: left;
}
.invisible {
display: none;
}
.danger {
background-color: @color-error-background;
}
.badge {
display: inline-block;
color: #fff;
background-color: #777;
text-align: center;
white-space: nowrap;
vertical-align: baseline;
min-width: 10px;
padding: 1px 5px;
border-radius: 5px;
}
// table
table {
width: 100%;
&.striped {
tr {
border-bottom: 1px solid @color-settings-tr-hover;
}
}
}
th {
padding: 0.4em;
}
td {
padding: 0 4px;
}
tr {
&:hover {
background: @color-settings-tr-hover;
}
}
// dialog
.dialog() {
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;
&:before {
position: absolute;
top: 0.5em;
left: 0.5em;
font-family:"ion";
font-size: 1.5em;
}
.close {
float:right;
position: relative;
top: -3px;
color: inherit;
font-size: 1.5em;
}
ul, ol, p {
margin: 1px 0 0 0;
}
}
.dialog-error {
.dialog();
color: @color-error;
background: @color-error-background;
border-color: @color-error;
.ion-error();
}
.dialog-warning {
.dialog();
color: @color-warning;
background: @color-warning-background;
border-color: @color-warning;
.ion-warning();
}
// btn-collapse
.btn-collapse {
cursor: pointer;
}
//
.scrollx {
overflow-x: auto;
overflow-y: hidden;
display: block;
padding: 0;
margin: 0;
border: none;
}
// tabs
.tabs .tabs > label {
font-size: 90%;
}
.tabs {
.flexbox();
flex-wrap: wrap;
width: 100%;
min-width: 100%;
& > * {
order: 2;
}
& > input[type=radio] {
display: none;
}
& > label {
order: 1;
padding: 0.7em;
margin: 0 0.7em;
letter-spacing:0.5px;
text-transform: uppercase;
border: solid white;
border-width: 0px 0px 2px 0;
.disable-user-select();
cursor: pointer;
}
& > label:hover {
border-bottom: 2px solid @color-categories-item-border-selected;
}
& > section {
min-width: 100%;
padding: 0.7rem 0;
box-sizing: border-box;
border-top: 1px solid black;
display: none;
}
// default selection
& > label:last-of-type {
border-bottom: 2px solid @color-categories-item-border-selected;
background: @color-categories-item-selected;
color: @color-categories-item-selected-font;
font-weight: bold;
letter-spacing:-0.1px;
}
& > section:last-of-type {
display: block;
}
}
html body .tabs > input:checked {
~ section {
display: none;
}
~ label {
position: inherited;
background: inherit;
border-bottom: 2px solid transparent;
font-weight: normal;
color: inherit;
&:hover {
border-bottom: 2px solid @color-categories-item-border-selected;
}
}
+ label {
border-bottom: 2px solid @color-categories-item-border-selected;
background: @color-categories-item-selected;
color: @color-categories-item-selected-font;
font-weight: bold;
letter-spacing:-0.1px;
}
+ label + section {
display: block;
}
}
// select
select {
height: 28px;
margin: 0 1em 0 0;
padding: 2px 8px 2px 0 !important;
color: @color-search-font;
font-size: 12px;
z-index: 2;
&:hover, &:focus {
cursor: pointer;
}
}
@supports ((background-position-x: 100%) and ((appearance: none) or (-webkit-appearance: none) or (-moz-appearance: none))) {
select {
appearance: none;
-webkit-appearance: none;
-moz-appearance: none;
border: none;
border-bottom: 1px solid #d7d7d7;
background: url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4KPCFET0NUWVBFIHN2ZyBQVUJMSUMgIi0vL1czQy8vRFREIFNWRyAxLjEvL0VOIiAiaHR0cDovL3d3dy53My5vcmcvR3JhcGhpY3MvU1ZHLzEuMS9EVEQvc3ZnMTEuZHRkIj4KPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeD0iMHB4IiB5PSIwcHgiIHdpZHRoPSI1MTJweCIgaGVpZ2h0PSI1MTJweCIgdmlld0JveD0iMCAwIDUxMiA1MTIiIGVuYWJsZS1iYWNrZ3JvdW5kPSJuZXcgMCAwIDUxMiA1MTIiIHhtbDpzcGFjZT0icHJlc2VydmUiPjxnPjxwb2x5Z29uIHBvaW50cz0iMTI4LDE5MiAyNTYsMzIwIDM4NCwxOTIiLz48L2c+PC9zdmc+Cg==) no-repeat;
background-position-x: 105%;
background-size: 2em;
background-origin: content-box;
outline: medium none;
&:hover, &:focus {
border-bottom: 1px solid @color-search-border;
}
}
}
// checkbox-onoff
@supports (border-radius: 50px) {
.checkbox-onoff {
display: inline-block;
width: 40px;
height: 10px;
background: #dcdcdc;
margin: 8px auto;
position: relative;
border-radius: 50px;
label {
display: block;
width: 20px;
height: 20px;
position: absolute;
top: -5px;
cursor: pointer;
border-radius: 50px;
box-shadow: 0px 3px 5px 0px rgba(0, 0, 0, 0.3);
transition: all 0.4s ease;
left: 27px;
background-color: #3498DB;
}
input[type=checkbox] {
visibility: hidden;
&:checked + label {
left: -5px;
background: #dcdcdc;
}
}
}
}
// checkbox
@supports (transform: rotate(-45deg)) {
.checkbox {
width: 20px;
position: relative;
margin: 20px auto;
label {
width: 20px;
height: 20px;
cursor: pointer;
position: absolute;
top: 0;
left: 0;
background: white;
border-radius: 4px;
box-shadow: inset 0px 1px 1px white, 0px 1px 4px rgba(0,0,0,0.5);
&:after {
content: '';
width: 9px;
height: 5px;
position: absolute;
top: 4px;
left: 4px;
border: 3px solid #333;
border-top: none;
border-right: none;
background: transparent;
opacity: 0;
transform: rotate(-45deg);
}
}
input[type=checkbox] {
visibility: hidden;
&:checked + label:after {
border-color: #3498DB;
opacity: 1;
}
}
// disabled : can't be focused, show only the check mark
input[disabled] + label {
background-color: transparent !important;
box-shadow: none !important;
cursor: inherit;;
}
// if not checked and possible to checked then display a "light" check mark on hover
input:not(:checked):not([readonly]):not([disabled]) + label:hover::after {
opacity: 0.5;
}
}
}
@media screen and (max-width: 50em) {
.tabs > label {
width: 100%;
}
}

View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" x="0px" y="0px" viewBox="0 0 32 40" enable-background="new 0 0 32 32" xml:space="preserve"><path d="M21.11,21.157h5.002v-6.867c-0.028-1.706-0.61-3.807-2.172-5.841c-1.539-2.014-4.315-3.72-7.939-3.687 C12.374,4.731,9.598,6.437,8.06,8.45c-1.562,2.034-2.145,4.136-2.174,5.842v6.866h5v-6.866c-0.027-0.377,0.303-1.789,1.099-2.748 c0.819-0.979,1.848-1.747,4.014-1.778c2.165,0.032,3.195,0.799,4.013,1.778c0.798,0.959,1.126,2.372,1.099,2.748V21.157 L21.11,21.157z M26.112,27.236c0,0,0-2.354,0-5.079H21.11c0,2.727,0,5.08,0,5.08l5.004-0.001H26.112z M5.886,27.237h5 c0,0,0-2.354,0-5.08h-5C5.886,24.884,5.886,27.237,5.886,27.237z"/><text x="0" y="47" fill="#000000" font-size="5px" font-weight="bold" font-family="'Helvetica Neue', Helvetica, Arial-Unicode, Arial, Sans-serif">Created by Dmitry Baranovskiy</text><text x="0" y="52" fill="#000000" font-size="5px" font-weight="bold" font-family="'Helvetica Neue', Helvetica, Arial-Unicode, Arial, Sans-serif">from the Noun Project</text></svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

View file

@ -0,0 +1,20 @@
{
"devDependencies": {
"grunt": "~1.0.1",
"grunt-contrib-concat": "~1.0.1",
"grunt-contrib-cssmin": "^2.2.1",
"grunt-contrib-jshint": "~1.1.0",
"grunt-contrib-less": "^1.4.1",
"grunt-contrib-uglify": "~3.0.1",
"grunt-contrib-watch": "~1.0.0",
"grunt-webfont": "^1.6.0",
"ionicons-npm": "^2.0.1",
"jslint": "^0.10.3",
"less-plugin-clean-css": "^1.5.1"
},
"scripts": {
"build": "npm install && grunt",
"start": "grunt watch",
"test": "grunt"
}
}

View file

@ -171,7 +171,7 @@
{{ checkbox_toggle('engine_' + search_engine.name|replace(' ', '_') + '__' + categ|replace(' ', '_'), (search_engine.name, categ) in disabled_engines) }}
</td>
<th>{{ search_engine.name }}</th>
<td>{{ shortcuts[search_engine.name] }}</td>
<td class="name">{{ shortcuts[search_engine.name] }}</td>
<td><input type="checkbox" {{ "checked" if current_language == 'all' or current_language in search_engine.supported_languages or current_language.split('-')[0] in search_engine.supported_languages else ""}} readonly="readonly" disabled="disabled"></td>
<td><input type="checkbox" {{ "checked" if search_engine.safesearch==True else ""}} readonly="readonly" disabled="disabled"></td>
<td><input type="checkbox" {{ "checked" if search_engine.time_range_support==True else ""}} readonly="readonly" disabled="disabled"></td>

View file

@ -0,0 +1,9 @@
{% extends "simple/base.html" %}
{% block content %}
<div class="center">
<h1>{{ _('Page not found') }}</h1>
{% autoescape false %}
<p>{{ _('Go to %(search_page)s.', search_page='<a href="{}">{}</a>'.decode('utf-8').format(url_for('index'), _('search page'))) }}</p>
{% endautoescape %}
</div>
{% endblock %}

View file

@ -0,0 +1,4 @@
{% extends 'simple/base.html' %}
{% block content %}
{% include '__common__/about.html' %}
{% endblock %}

View file

@ -0,0 +1,61 @@
<!DOCTYPE html>
<html class="no-js" lang="en" {% if rtl %} dir="rtl"{% endif %}>
<head>
<meta charset="UTF-8" />
<meta name="description" content="searx - a privacy-respecting, hackable metasearch engine">
<meta name="keywords" content="searx, search, search engine, metasearch, meta search">
<meta name="generator" content="searx/{{ searx_version }}">
<meta name="referrer" content="no-referrer">
<meta name="robots" content="noarchive">
<meta name="viewport" content="width=device-width, maximum-scale=1.0, user-scalable=1">
<meta name="HandheldFriendly" content="True">
<meta http-equiv="X-UA-Compatible" content="IE=edge, chrome=1">
<title>{% block title %}{% endblock %}searx</title>
{% if rtl %}
<link rel="stylesheet" href="{{ url_for('static', filename='css/searx-rtl.min.css') }}" type="text/css" media="screen" />
{% else %}
<link rel="stylesheet" href="{{ url_for('static', filename='css/searx.min.css') }}" type="text/css" media="screen" />
{% endif %}
{% block styles %}{% endblock %}
{% block meta %}{% endblock %}
{% block head %}
<link title="{{ instance_name }}" type="application/opensearchdescription+xml" rel="search" href="{{ url_for('opensearch') }}"/>
{% endblock %}
<link rel="shortcut icon" href="{{ url_for('static', filename='img/favicon.png') }}" />
<script type="text/javascript">
var searx = {
autocompleter: {% if autocomplete %}true{% else %}false{% endif %},
method: "{{ method or 'POST' }}",
touch: (("ontouchstart" in window) || window.DocumentTouch && document instanceof DocumentTouch) || false,
staticPath: "{{ url_for('static', filename='themes/simple') }}/",
noItemFound: "{{ _('No item found') }}",
search_on_category_select: {{ 'true' if 'plugins/js/search_on_category_select.js' in scripts else 'false'}},
infinite_scroll: {{ 'true' if 'plugins/js/infinite_scroll.js' in scripts else 'false' }}
};
document.getElementsByTagName("html")[0].className = (searx.touch)?"js touch":"js";
</script>
</head>
<body>
<main id="main_{{ self._TemplateReference__context.name|replace("simple/", "")|replace(".html", "") }}">
{% if errors %}
<div class="dialog-error" role="alert">
<a href="#" class="close" aria-label="close" title="close">×</a>
<ul>
{% for message in errors %}
<li>{{ message }}</li>
{% endfor %}
</ul>
</div>
{% endif %}
{% block content %}
{% endblock %}
</main>
<footer>
<p>{{ _('Powered by') }} <a href="{{ url_for('about') }}">searx</a> - {{ searx_version }} - {{ _('a privacy-respecting, hackable metasearch engine') }}</p>
</footer>
<!--[if gte IE 9]>-->
<script src="{{ url_for('static', filename='js/searx.min.js') }}" ></script>
<!--<![endif]-->
</body>
</html>

View file

@ -0,0 +1,8 @@
<div id="categories">{{- '' -}}
<div id="categories_container">
{%- for category in categories -%}
<div class="category"><input type="checkbox" id="checkbox_{{ category|replace(' ', '_') }}" name="category_{{ category }}"{% if category in selected_categories %} checked="checked"{% endif %}/><label for="checkbox_{{ category|replace(' ', '_') }}" class="tooltips">{{ _(category) }}</label></div>
{%- endfor -%}
{%- if display_tooltip %}<div class="help">{{ _('Click on the magnifier to perform search') }}</div>{% endif -%}
</div>{{- '' -}}
</div>

View file

@ -0,0 +1,12 @@
{% extends "simple/base.html" %}
{% from 'simple/macros.html' import icon %}
{% block meta %}
<link rel="preload" href="{{ url_for('static', filename='img/searx.png') }}" as="image" />
{% endblock %}
{% block content %}
<nav id="linkto_preferences"><a href="{{ url_for('preferences') }}">{{ icon('navicon-round') }}</a></nav>
<div class="index">
<div class="title"><h1>searx</h1></div>
{% include 'simple/search.html' %}
</div>
{% endblock %}

View file

@ -0,0 +1,46 @@
<aside class="infobox">
<h2><bdi>{{ infobox.infobox }}</bdi></h2>
{% if infobox.img_src %}<img src="{{ image_proxify(infobox.img_src) }}" title="{{ infobox.infobox|striptags }}" alt="{{ infobox.infobox|striptags }}" />{% endif %}
<p><bdi>{{ infobox.entity }}</bdi></p>
<p><bdi>{{ infobox.content | safe }}</bdi></p>
{% if infobox.attributes %}
<div class="attributes">
{% for attribute in infobox.attributes %}
<dl>
<dt><bdi>{{ attribute.label }} :</bdi></dt>
{%- if attribute.image -%}
<dd><img src="{{ image_proxify(attribute.image.src) }}" alt="{{ attribute.image.alt }}" /></dd>
{%- else -%}
<dd><bdi>{{ attribute.value }}</bdi></dd>
{%- endif -%}
</dl>
{% endfor %}
</div>
{% endif %}
{% if infobox.urls %}
<div class="urls">
<ul>
{%- for url in infobox.urls -%}
<li class="url"><bdi><a href="{{ url.url }}" {% if results_on_new_tab %}target="_blank" rel="noopener noreferrer"{% else %}rel="noreferrer"{% endif %}>{{ url.title }}</a></bdi></li>
{%- endfor -%}
</ul>
</div>
{% endif %}
{% if infobox.relatedTopics %}
<div class="relatedTopics">
{% for topic in infobox.relatedTopics %}
<div>
<h3><bdi>{{ topic.name }}</bdi></h3>
{% for suggestion in topic.suggestions %}
<form method="{{ method or 'POST' }}" action="{{ url_for('index') }}">
<input type="hidden" name="q" value="{{ suggestion }}">
<input type="submit" value="{{ suggestion }}" />
</form>
{% endfor %}
</div>
{% endfor %}
</div>
{% endif %}
</aside>

View file

@ -0,0 +1,8 @@
<select class="language" id="language" name="language" tabindex="2">{{- '' -}}
<option value="all" {% if current_language == 'all' %}selected="selected"{% endif %}>{{ _('Default language') }}</option>
{%- for lang_id,lang_name,country_name,english_name in language_codes | sort(attribute=1) -%}
<option value="{{ lang_id }}" {% if lang_id == current_language %}selected="selected"{% endif %}>
{{- lang_name }} {% if country_name %}({{ country_name }}) {% endif %}- {{ lang_id -}}
</option>
{%- endfor -%}
</select>

View file

@ -0,0 +1,86 @@
<!-- Draw glyphicon icon from bootstrap-theme -->
{% macro icon(action) -%}
<span class="ion-icon-big ion-{{ action }}"></span>
{%- endmacro %}
{% macro icon_small(action) -%}
<span class="ion-icon ion-{{ action }}"></span>
{%- endmacro %}
<!-- Draw favicon -->
<!-- TODO: using url_for methode -->
{% macro draw_favicon(favicon) -%}
<img width="14" height="14" class="favicon" src="static/themes/simple/img/icons/{{ favicon }}.png" alt="{{ favicon }}" />
{%- endmacro %}
{% macro result_open_link(url, classes='') -%}
<a href="{{ url }}" {% if classes %}class="{{ classes }}" {% endif %}{% if results_on_new_tab %}target="_blank" rel="noopener noreferrer"{% else %}rel="noreferrer"{% endif %}>
{%- endmacro %}
{%- macro result_close_link() -%}
</a>
{%- endmacro %}
{%- macro result_link(url, title, classes='') -%}
{{ result_open_link(url, classes) }}{{ title }}{{ result_close_link() }}
{%- endmacro -%}
<!-- Draw result header -->
{% macro result_header(result, favicons, image_proxify) -%}
<article class="result {% if result['template'] %}result-{{ result.template|replace('.html', '') }}{% else %}result-default{% endif %} {% if result['category'] %}category-{{ result['category'] }}{% endif %}">
{%- if result.img_src %}{{ result_open_link(result.url) }}<img class="image" src="{{ image_proxify(result.img_src) }}" alt="{{ result.title|striptags }}" title="{{ result.title|striptags }}" class="image" />{{ result_close_link() }}{% endif -%}
{%- if result.thumbnail %}{{ result_open_link(result.url) }}<img class="thumbnail" src="{{ image_proxify(result.thumbnail) }}" title="{{ result.title|striptags }}" alt="{{ result.title|striptags }}"/>{{ result_close_link() }}{% endif -%}
<h3>{{ result_link(result.url, result.title|safe) }}</h3>
{%- endmacro -%}
<!-- Draw result sub header -->
{%- macro result_sub_header(result) -%}
{% if result.publishedDate %}<time class="published_date" datetime="{{ result.pubdate }}" >{{ result.publishedDate }}</time>{% endif %}
{%- endmacro -%}
<!-- Draw result sub footer -->
{%- macro result_sub_footer(result, proxify) -%}
<div class="engines">{% for engine in result.engines %}<span>{{ engine }}</span>{% endfor %}</div>{{- '' -}}
<p class="url"><span class="url">{{ result.pretty_url }}</span>{{ result_link("https://web.archive.org/web/" + result.url, icon('link') + _('cached'), "cache_link") }}&lrm; {% if proxify %} {{ result_link(proxify(result.url), icon('link') + _('proxied'), "proxyfied_link") }} {% endif %}</p>{{- '' -}}
<div class="break"></div>{{- '' -}}
{%- endmacro -%}
<!-- Draw result footer -->
{%- macro result_footer(result) -%}
</article>
{%- endmacro -%}
<!-- -->
{%- macro tabs_open() -%}
<div class="tabs" role="tablist">
{%- endmacro -%}
{%- macro tab_header(name, id, label) -%}
<input type="radio" name="{{ name }}" id="tab_{{ id }}"/>
<label for="tab_{{ id }}" role="tab"
aria-controls="panel{{ id }}">{{ label }}</label>
<section id="tab-content{{ id }}" role="tabpanel"
aria-labelledby="{{ label }}" aria-hidden="false">
{%- endmacro -%}
{%- macro tab_footer() -%}
</section>
{%- endmacro -%}
{%- macro tabs_close() -%}
</div>
{%- endmacro -%}
{%- macro checkbox_onoff(name, checked) -%}
<div class="checkbox-onoff">{{- '' -}}
<input type="checkbox" value="None" id="{{ name }}" name="{{ name }}" {% if checked %}checked{% endif %}/>{{- '' -}}
<label for="{{ name }}"></label>{{- '' -}}
</div>
{%- endmacro -%}
{%- macro checkbox(name, checked, readonly, disabled) -%}
<div class="checkbox">{{- '' -}}
<input type="checkbox" value="None" id="{{ name }}" name="{{ name }}" {% if checked %}checked{% endif %}{% if readonly %} readonly="readonly" {% endif %}{% if disabled %} disabled="disabled" {% endif %}/>{{- '' -}}
<label for="{{ name }}"></label>{{- '' -}}
</div>
{%- endmacro -%}

View file

@ -0,0 +1,190 @@
{% from 'simple/macros.html' import tabs_open, tabs_close, tab_header, tab_footer, checkbox_onoff, checkbox %}
{% extends "simple/base.html" %}
{%- macro plugin_preferences(section) -%}
{%- for plugin in plugins -%}
{%- if plugin.preference_section == section -%}
<fieldset>{{- '' -}}
<legend>{{ _(plugin.name) }}</legend>{{- '' -}}
<div class="value">
{{- checkbox_onoff('plugin_' + plugin.id, plugin.id not in allowed_plugins) -}}
</div>{{- '' -}}
<div class="description">
{{- _(plugin.description) -}}
</div>{{- '' -}}
</fieldset>
{%- endif -%}
{%- endfor -%}
{%- endmacro -%}
{% block head %} {% endblock %}
{% block content %}
<a href="{{ url_for('index') }}"><h1><span>searx</span></h1></a>
<h2>{{ _('Preferences') }}</h2>
<form id="search_form" method="post" action="{{ url_for('preferences') }}">
{{ tabs_open() }}
{{ tab_header('maintab', 'general', _('General')) }}
<fieldset>
<legend>{{ _('Default categories') }}</legend>
{% set display_tooltip = false %}
{% include 'simple/categories.html' %}
</fieldset>
<fieldset>
<legend>{{ _('Search language') }}</legend>
<p class="value">{{- '' -}}
<select name='language'>{{- '' -}}
<option value="all" {% if current_language == 'all' %}selected="selected"{% endif %}>{{ _('Default language') }}</option>
{%- for lang_id,lang_name,country_name,english_name in language_codes | sort(attribute=1) -%}
<option value="{{ lang_id }}" {% if lang_id == current_language %}selected="selected"{% endif %}>{{ lang_name }} {% if country_name %}({{ country_name }}) {% endif %}- {{ lang_id }}</option>
{%- endfor -%}
</select>{{- '' -}}
</p>
<div class="description">{{ _('What language do you prefer for search?') }}</div>
</fieldset>
<fieldset>
<legend>{{ _('Autocomplete') }}</legend>
<p class="value">
<select name="autocomplete">
<option value=""> - </option>
{% for backend in autocomplete_backends %}
<option value="{{ backend }}" {% if backend == autocomplete %}selected="selected"{% endif %}>{{ backend }}</option>
{% endfor %}
</select>
</p>
<div class="description">{{ _('Find stuff as you type') }}</div>
</fieldset>
<fieldset>
<legend>{{ _('SafeSearch') }}</legend>
<p class="value">
<select name='safesearch'>
<option value="2" {% if safesearch == '2' %}selected="selected"{% endif %}>{{ _('Strict') }}</option>
<option value="1" {% if safesearch == '1' %}selected="selected"{% endif %}>{{ _('Moderate') }}</option>
<option value="0" {% if safesearch == '0' %}selected="selected"{% endif %}>{{ _('None') }}</option>
</select>
</p>
<div class="description">{{ _('Filter content') }}</p>
</fieldset>
{{ plugin_preferences('general') }}
{{ tab_footer() }}
{{ tab_header('maintab', 'engines', _('Engines')) }}
<p>{{ _('Currently used search engines') }}</p>
{{ tabs_open() }}
{% for categ in all_categories %}
{{ tab_header('enginetab', 'category' + categ, _(categ)) }}
<div class="scrollx">
<table class="striped">
<tr>
<th class="engine_checkbox">{{ _("Allow") }}</th>
<th class="name">{{ _("Engine name") }}</th>
<th class="shortcut">{{ _("Shortcut") }}</th>
<th>{{ _("Supports selected language") }}</th>
<th>{{ _("SafeSearch") }}</th>
<th>{{ _("Time range") }}</th>
<th>{{ _("Avg. time") }}</th>
<th>{{ _("Max time") }}</th>
</tr>
{% for search_engine in engines_by_category[categ] %}
{% if not search_engine.private %}
{% set engine_id = 'engine_' + search_engine.name|replace(' ', '_') + '__' + categ|replace(' ', '_') %}
<tr>
<td class="engine_checkbox">{{ checkbox_onoff(engine_id, (search_engine.name, categ) in disabled_engines) }}</td>
<th class="name">{{ search_engine.name }}</th>
<td class="shortcut">{{ shortcuts[search_engine.name] }}</td>
<td>{{ checkbox(engine_id + '_supported_languages', current_language == 'all' or current_language in search_engine.supported_languages or current_language.split('-')[0] in search_engine.supported_languages, true, true) }}</td>
<td>{{ checkbox(engine_id + '_safesearch', search_engine.safesearch==True, true, true) }}</td>
<td>{{ checkbox(engine_id + '_time_range_support', search_engine.time_range_support==True, true, 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_timeout'] else '' }}">{{ search_engine.timeout }}</td>
</tr>
{% endif %}
{% endfor %}
</table>
<div>
{{ tab_footer() }}
{% endfor %}
{{ tabs_close() }}
{{ tab_footer() }}
{{ tab_header('maintab', 'ui', _('User interface')) }}
<fieldset>
<legend>{{ _('Interface language') }}</legend>
<p class="value">
<select name='locale'>
{% for locale_id,locale_name in locales.items() | sort %}
<option value="{{ locale_id }}" {% if locale_id == current_locale %}selected="selected"{% endif %}>{{ locale_name }}</option>
{% endfor %}
</select>
</p>
<div class="description">{{ _('Change the language of the layout') }}</div>
</fieldset>
<fieldset>
<legend>{{ _('Themes') }}</legend>
<p class="value">
<select name="theme">
{%- for name in themes -%}
<option value="{{ name }}" {% if name == theme %}selected="selected"{% endif %}>{{ name }}</option>
{%- endfor -%}
</select>
</p>
<div class="description">{{ _('Change searx layout') }}</div>
</fieldset>
<fieldset>
<legend>{{ _('Results on new tabs') }}</legend>
<p class="value">
<select name='results_on_new_tab'>
<option value="1" {% if results_on_new_tab %}selected="selected"{% endif %}>{{ _('On') }}</option>
<option value="0" {% if not results_on_new_tab %}selected="selected"{% endif %}>{{ _('Off')}}</option>
</select>
</p>
<div class="description">{{_('Open result links on new browser tabs') }}</div>
</fieldset>
{{ plugin_preferences('ui') }}
{{ tab_footer() }}
{{ tab_header('maintab', 'privacy', _('Privacy')) }}
<fieldset>
<legend>{{ _('Method') }}</legend>
<p class="value">
<select name='method'>
<option value="POST" {% if method == 'POST' %}selected="selected"{% endif %}>POST</option>
<option value="GET" {% if method == 'GET' %}selected="selected"{% endif %}>GET</option>
</select>
</p>
<div class="description">{{ _('Search language') }}</div>
</fieldset>
<fieldset>
<legend>{{ _('Image proxy') }}</legend>
<p class="value">
<select name='image_proxy'>
<option value="1" {% if image_proxy %}selected="selected"{% endif %}>{{ _('Enabled') }}</option>
<option value="" {% if not image_proxy %}selected="selected"{% endif %}>{{ _('Disabled') }}</option>
</select>
</p>
<div class="description">{{ _('Proxying image results through searx') }}</div>
</fieldset>
{{ plugin_preferences('privacy') }}
{{ tab_footer() }}
{{ tabs_close() }}
<p class="small_font">{{ _('These settings are stored in your cookies, this allows us not to store this data about you.') }}
<br />
{{ _("These cookies serve your sole convenience, we don't use these cookies to track you.") }}
</p>
<input type="submit" value="{{ _('save') }}" />
<div class="{% if rtl %}left{% else %}right{% endif %} preferences_back"><a href="{{ url_for('clear_cookies') }}">{{ _('Reset defaults') }}</a></div>
<div class="{% if rtl %}left{% else %}right{% endif %} preferences_back"><a href="{{ url_for('index') }}">{{ _('back') }}</a></div>
</form>
{% endblock %}

View file

@ -0,0 +1,13 @@
{% from 'simple/macros.html' import result_header, result_sub_header, result_sub_footer, result_footer, result_footer_rtl %}
{{ result_header(result, favicons, image_proxify) -}}
{{- result_sub_header(result) -}}
{%- if result.content %}{{ result.content|safe }}{% endif %}</p>
{%- if result.repository -%}
<p class="content"><a href="{{ result.repository|safe }}" {% if results_on_new_tab %}target="_blank" rel="noopener noreferrer"{% else %}rel="noreferrer"{% endif %}>{{ result.repository }}</a></p>
{%- endif -%}
<div dir="ltr" class="codelines">
{{- result.codelines|code_highlighter(result.code_language)|safe -}}
</div>{{- '' -}}
{{- result_sub_footer(result, proxify) -}}
{{ result_footer(result) }}

View file

@ -0,0 +1,17 @@
{% from 'simple/macros.html' import result_header, result_sub_header, result_sub_footer, result_footer, result_footer_rtl %}
{{ result_header(result, favicons, image_proxify) -}}
{{- result_sub_header(result) -}}
{% if result.embedded -%}
<p class="altlink"> &bull; <a class="btn-collapse collapsed media-loader disabled_if_nojs" data-target="#result-media-{{ index }}" data-btn-text-collapsed="{{ _('show media') }}" data-btn-text-not-collapsed="{{ _('hide media') }}">{{ icon('music-note') }} {{ _('show media') }}</a></p>
{%- endif %}
<p class="content">
{%- if result.content %}{{ result.content|safe }}{% endif -%}
</p>
{{- result_sub_footer(result, proxify) -}}
{% if result.embedded -%}
<div id="result-media-{{ index }}" class="invisible">
{{- result.embedded|safe -}}
</div>
{%- endif %}
{{- result_footer(result) }}

View file

@ -0,0 +1,4 @@
<article class="result result-images {% if result['category'] %}category-{{ result['category'] }}{% endif %}">
<a href="{{ result.img_src }}" {% if results_on_new_tab %}target="_blank" rel="noopener noreferrer"{% else %}rel="noreferrer"{% endif %}><img class="image_thumbnail" src="{% if result.thumbnail_src %}{{ image_proxify(result.thumbnail_src) }}{% else %}{{ image_proxify(result.img_src) }}{% endif %}" title="{{ result.title|striptags }}" alt="{{ result.title|striptags }}" /></a>
<span class="url"><a href="{{ result.url }}" {% if results_on_new_tab %}target="_blank" rel="noopener noreferrer"{% else %}rel="noreferrer"{% endif %} class="small_font">{{ result.parsed_url[0] }}://{{ result.parsed_url[1] }}</a></span>
</article>

View file

@ -0,0 +1,71 @@
{% from 'simple/macros.html' import result_header, result_sub_header, result_sub_footer, result_footer, result_footer_rtl, icon %}
{{ result_header(result, favicons, image_proxify) -}}
{{- result_sub_header(result) -}}
{%- if (result.latitude and result.longitude) or result.boundingbox -%}
<small> &bull; <a class="btn-collapse collapsed searx_init_map hide_if_nojs" data-target="#result-map-{{ index }}" data-btn-text-collapsed="{{ _('show map') }}" data-btn-text-not-collapsed="{{ _('hide map') }}" data-leaflet-target="osm-map-{{ index }}" data-map-lon="{{ result.longitude }}" data-map-lat="{{ result.latitude }}" {% if result.boundingbox %}data-map-boundingbox='{{ result.boundingbox|tojson|safe }}'{% endif %} {% if result.geojson %}data-map-geojson='{{ result.geojson|tojson|safe }}'{% endif %}>{{ icon( 'globe') }} {{ _('show map') }}</a></small>
{%- endif -%}
{%- if result.osm and (result.osm.type and result.osm.id) -%}
<small> &bull; <a class="btn-collapse collapsed hide_if_nojs searx_overpass_request" data-target="#result-overpass-{{ index }}" data-btn-text-collapsed="{{ _('show details') }}" data-btn-text-not-collapsed="{{ _('hide details') }}" data-osm-type="{{ result.osm.type }}" data-osm-id="{{ result.osm.id }}" data-result-table="result-overpass-table-{{ index }}" data-result-table-loadicon="result-overpass-table-loading-{{ index }}">{{ icon('location') }} {{ _('show details') }}</a></small>
{%- endif -%}
{#-
{% if (result.latitude and result.longitude) %}
<small> &bull; <a class="btn-collapse disabled_if_nojs" data-target="#result-geodata-{{ index }}" data-btn-text-collapsed="{{ _('show geodata') }}" data-btn-text-not-collapsed="{{ _('hide geodata') }}">{{ icon('location') }} {{ _('show geodata') }}</a></small>
{% endif %}
-#}
{%- if result.address -%}
<p itemscope itemtype="http://schema.org/PostalAddress" class="content">
{%- if result.address.name -%}
<strong itemprop="name">{{ result.address.name }}</strong><br/>
{%- endif -%}
{% if result.address.road -%}
<span itemprop="streetAddress">
{% if result.address.house_number %}{{ result.address.house_number }}, {% endif %}
{{ result.address.road }}
</span><br/>
{%- endif %}
{%- if result.address.locality -%}
<span itemprop="addressLocality">{{ result.address.locality }}</span>
{% if result.address.postcode %}, <span itemprop="postalCode">{{ result.address.postcode }}</span>{% endif %}
<br/>
{%- endif -%}
{%- if result.address.country -%}
<span itemprop="addressCountry">{{ result.address.country }}</span>
{%- endif -%}
</p>
{%- endif -%}
{%- if result.content %}<p class="content">{{ result.content|safe }}</p>{% endif -%}
{{- result_sub_footer(result, proxify) -}}
{% 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 id="result-overpass-table-loading-{{ index }}"><img src="{{ url_for('static', filename='img/loader.gif') }}" alt="Loading ..."/></div>
<table id="result-overpass-table-{{ index }}">
<thead>
<tr><th>key</th><th>value</th></tr>
</thead>
<tbody>
</tbody>
</table>
</div>
{%- endif %}
{#-
{% if (result.latitude and result.longitude) -%}
<div id="result-geodata-{{ index }}" class="invisible">
<strong>Longitude:</strong> {{ result.longitude }} <br/>
<strong>Latitude:</strong> {{ result.latitude }}
</div>
{%- endif %}
-#}
{% if (result.latitude and result.longitude) or result.boundingbox -%}
<div id="result-map-{{ index }}" class="invisible"><div id="osm-map-{{ index }}" style="height:300px; width:100%; margin: 10px 0;" ></div></div>
{%- endif %}
{{- result_footer(result) }}

View file

@ -0,0 +1,24 @@
{% from 'simple/macros.html' import result_header, result_sub_header, result_sub_footer, result_footer, result_footer_rtl, result_link %}
{{ result_header(result, favicons, image_proxify) -}}
{{- result_sub_header(result) -}}
{% if result.magnetlink %}<p class="altlink"> &bull; {{ result_link(result.magnetlink, icon('magnet') + _('magnet link'), "magnetlink") }}</p>{% endif %}
{% if result.torrentfile %}<p class="altlink"> &bull; {{ result_link(result.torrentfile, icon('download-alt') + _('torrent file'), "torrentfile") }}</p>{% endif %}
{% if result.seed %}<p class="stat"> &bull; {{ icon('arrow-swap') }} {{ _('Seeder') }} <span class="badge">{{ result.seed }}</span> &bull; {{ _('Leecher') }} <span class="badge">{{ result.leech }}</span></p>{% endif %}
{%- if result.filesize %}<p class="stat">{{ icon('floppy-disk') }} {{ _('Filesize') }}<span class="badge">
{%- if result.filesize < 1024 %}{{ result.filesize }} {{ _('Bytes') }}
{%- elif result.filesize < 1024*1024 %}{{ '{0:0.2f}'.format(result.filesize/1024) }} {{ _('kiB') }}
{%- elif result.filesize < 1024*1024*1024 %}{{ '{0:0.2f}'.format(result.filesize/1024/1024) }} {{ _('MiB') }}
{%- elif result.filesize < 1024*1024*1024*1024 %}{{ '{0:0.2f}'.format(result.filesize/1024/1024/1024) }} {{ _('GiB') }}
{%- else %}{{ '{0:0.2f}'.format(result.filesize/1024/1024/1024/1024) }} {{ _('TiB') }}{% endif -%}
</span></p>
{%- endif -%}
{%- if result.files %}<p class="stat">{{ icon('file') }} {{ _('Number of Files') }} <span class="badge">{{ result.files }}</span></p>{% endif -%}
{%- if result.content %}<p class="content">{{ result.content|safe }}</p>{% endif -%}
{{- result_sub_footer(result, proxify) -}}
{{- result_footer(result) }}

View file

@ -0,0 +1,15 @@
{% from 'simple/macros.html' import result_header, result_sub_header, result_sub_footer, result_footer, result_footer_rtl %}
{{ result_header(result, favicons, image_proxify) }}
{{ result_sub_header(result) }}
{% if result.embedded -%}
<p class="altlink"> &bull; <a class="btn-collapse collapsed media-loader disabled_if_nojs" data-target="#result-video-{{ index }}" data-btn-text-collapsed="{{ _('show video') }}" data-btn-text-not-collapsed="{{ _('hide video') }}">{{ icon('film-outline') }} {{ _('show video') }}</a></p>
{%- endif %}
{% if result.content %}<p class="content">{{ result.content|safe }}</p>{% endif %}
{{- result_sub_footer(result, proxify) -}}
{% if result.embedded -%}
<div id="result-video-{{ index }}" class="invisible">
{{- result.embedded|safe -}}
</div>
{%- endif %}
{{ result_footer(result) }}

View file

@ -0,0 +1,151 @@
{% extends "simple/base.html" %}
{% from 'simple/macros.html' import icon, icon_small %}
{% block title %}{{ q|e }} - {% 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 %}
<nav id="linkto_preferences"><a href="{{ url_for('preferences') }}">{{ icon('navicon-round') }}</a></nav>
{% include 'simple/search.html' %}
<div id="results">
{% 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">
{% if number_of_results != '0' -%}
<p id="result_count"><small>{{ _('Number of results') }}: {{ number_of_results }}</small></p>
{%- endif %}
{% if unresponsive_engines and results|length >= 1 %}
<div class="dialog-error" role="alert">
<p><strong>{{ _('Error!') }}</strong> {{ _('Engines cannot retrieve results') }}:</p>
<p>{% for engine_name, error_type in unresponsive_engines %}
{{ engine_name }} ({{ error_type }}){% if not loop.last %}, {% endif %}
{% endfor %}</p>
</div>
{% endif %}
{% if infoboxes %}
<div id="infoboxes">
{% for infobox in infoboxes %}
{% include 'simple/infobox.html' %}
{% endfor %}
</div>
{% endif %}
{% if suggestions %}
<div id="suggestions">
<h4 class="title">{{ _('Suggestions') }} : </h4>
<div class="wrapper">
{% for suggestion in suggestions %}
<form method="{{ method or 'POST' }}" action="{{ url_for('index') }}">
<input type="hidden" name="q" value="{{ suggestion }}">
<input type="hidden" name="language" value="{{ current_language }}">
<input type="hidden" name="safesearch" value="{{ safesearch }}">
<input type="hidden" name="theme" value="{{ theme }}">
<input type="submit" class="suggestion" value="&bull; {{ suggestion }}">
</form>
{% endfor %}
</div>
</div>
{% endif %}
<div id="search_url">
<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>
<div id="apis">
<h4 class="title">{{ _('Download results') }}</h4>
{% for output_type in ('csv', 'json', 'rss') %}
<div class="left">
<form method="{{ method or 'POST' }}" action="{{ url_for('index') }}">
<input type="hidden" name="q" value="{{ q|e }}">
{% for category in selected_categories %}
<input type="hidden" name="category_{{ category }}" value="1">
{% endfor %}
<input type="hidden" name="pageno" value="{{ pageno }}">
<input type="hidden" name="time_range" value="{{ time_range }}">
<input type="hidden" name="language" value="{{ current_language }}">
<input type="hidden" name="safesearch" value="{{ safesearch }}">
<input type="hidden" name="format" value="{{ output_type }}">
<input type="submit" value="{{ output_type }}">
</form>
</div>
{% endfor %}
</div>
</div>
{% if corrections %}
<div id="corrections">
<h4>{{ _('Try searching for:') }}</h4>
{% for correction in corrections %}
<div class="left">
<form method="{{ method or 'POST' }}" action="{{ url_for('index') }}" role="navigation">
<input type="hidden" name="q" value="{{ correction }}">
<input type="hidden" name="time_range" value="{{ time_range }}">
<input type="hidden" name="language" value="{{ current_language }}">
<input type="hidden" name="safesearch" value="{{ safesearch }}">
<input type="hidden" name="theme" value="{{ theme }}">
<input type="submit" value="{{ correction }}">
</form>
</div>
{% endfor %}
</div>
{% endif %}
<div id="urls">
{% for result in results %}
{% set index = loop.index %}
{% if result['template'] %}
{% include get_result_template('simple', result['template']) %}
{% else %}
{% include 'simple/result_templates/default.html' %}
{% endif %}
{% endfor %}
{% if not results and not answers %}
{% include 'simple/messages/no_results.html' %}
{% endif %}
</div>
<div id="backToTop">
<a href="#">{{ icon_small('chevron-up') }}</a>
</div>
{% if paging %}
<nav id="pagination">
{% if pageno > 1 %}
<form method="{{ method or 'POST' }}" action="{{ url_for('index') }}">
<div class="{% if rtl %}right{% else %}left{% endif %}">
<input type="hidden" name="q" value="{{ q|e }}" >
{% for category in selected_categories %}
<input type="hidden" name="category_{{ category }}" value="1" >
{% endfor %}
<input type="hidden" name="pageno" value="{{ pageno-1 }}" >
<input type="hidden" name="time_range" value="{{ time_range }}" >
<input type="hidden" name="language" value="{{ current_language }}" >
<input type="hidden" name="safesearch" value="{{ safesearch }}" >
<input type="hidden" name="theme" value="{{ theme }}" >
<button type="submit">{{ icon_small('chevron-left') }} {{ _('previous page') }}</button>
</div>
</form>
{% endif %}
<form method="{{ method or 'POST' }}" action="{{ url_for('index') }}">
<div class="{% if rtl %}left{% else %}right{% endif %}">
<input type="hidden" name="q" value="{{ q|e }}" >
{% for category in selected_categories %}
<input type="hidden" name="category_{{ category }}" value="1" >
{% endfor %}
<input type="hidden" name="pageno" value="{{ pageno+1 }}" >
<input type="hidden" name="time_range" value="{{ time_range }}" >
<input type="hidden" name="language" value="{{ current_language }}" >
<input type="hidden" name="safesearch" value="{{ safesearch }}" >
<input type="hidden" name="theme" value="{{ theme }}" >
<button type="submit">{{ _('next page') }} {{ icon_small('chevron-right') }}</button>
</div>
</form>
</nav>
{% endif %}
</div>
{% endblock %}

View file

@ -0,0 +1,16 @@
<form id="search" method="{{ method or 'POST' }}" action="{{ url_for('index') }}">
<div id="search_wrapper">
<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 %} >
<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 class="search_filters">
{% include 'simple/languages.html' %}
{% include 'simple/time-range.html' %}
</div>
</div>
{% set display_tooltip = true %}
{% include 'simple/categories.html' %}
<input type="hidden" name="safesearch" value="{{ safesearch }}" >
<input type="hidden" name="theme" value="{{ theme }}" >
</form>

View file

@ -0,0 +1,40 @@
#container
.search
#search_form
#results
#sidebar
#result-count
.title
.content
.infobox
h2
img
p
div#attributes
table
tbody
tr
td
td
div#urls
ul
li
#suggestions
.title
.suggestion
#search_url
.title
input
#apis
.title
.api-link
.result

View file

@ -0,0 +1,25 @@
{% extends "simple/base.html" %}
{% block head %} {% endblock %}
{% block content %}
<a href="{{ url_for('index') }}"><h1><span>searx</span></h1></a>
<h2>{{ _('Engine stats') }}</h2>
{% for stat_name,stat_category in stats %}
<div class="left">
<table>
<tr colspan="3">
<th>{{ stat_name }}</th>
</tr>
{% for engine in stat_category %}
<tr>
<td>{{ engine.name }}</td>
<td>{{ '%.02f'|format(engine.avg) }}</td>
<td class="percentage"><div style="width: {{ engine.percentage }}%">&nbsp;</div></td>
</tr>
{% endfor %}
</table>
</div>
{% endfor %}
{% endblock %}

View file

@ -0,0 +1,17 @@
<select name="time_range" id="time_range" class="time_range" tabindex="3">{{- '' -}}
<option id="time-range-anytime" value="" {{ "selected" if time_range=="" or not time_range else ""}}>
{{- _('Anytime') -}}
</option>{{- '' -}}
<option id="time-range-day" value="day" {{ "selected" if time_range=="day" else ""}}>
{{- _('Last day') -}}
</option>{{- '' -}}
<option id="time-range-week" value="week" {{ "selected" if time_range=="week" else ""}}>
{{- _('Last week') -}}
</option>{{- '' -}}
<option id="time-range-month" value="month" {{ "selected" if time_range=="month" else ""}}>
{{- _('Last month') -}}
</option>{{- '' -}}
<option id="time-range-year" value="year" {{ "selected" if time_range=="year" else ""}}>
{{- _('Last year') -}}
</option>{{- '' -}}
</select>