add sources
14
sources/LICENSE
Normal file
|
@ -0,0 +1,14 @@
|
|||
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) 2013- by Adam Tauber, <asciimoo@gmail.com>
|
56
sources/Makefile
Normal file
|
@ -0,0 +1,56 @@
|
|||
# convenience makefile to boostrap & run buildout
|
||||
# use `make options=-v` to run buildout with extra options
|
||||
|
||||
version = 2.7
|
||||
python = bin/python
|
||||
options =
|
||||
|
||||
all: .installed.cfg
|
||||
|
||||
.installed.cfg: bin/buildout buildout.cfg setup.py
|
||||
bin/buildout $(options)
|
||||
|
||||
bin/buildout: $(python) buildout.cfg bootstrap.py
|
||||
$(python) bootstrap.py
|
||||
@touch $@
|
||||
|
||||
$(python):
|
||||
virtualenv -p python$(version) --no-site-packages .
|
||||
@touch $@
|
||||
|
||||
tests: .installed.cfg
|
||||
@bin/test
|
||||
|
||||
robot: .installed.cfg
|
||||
@bin/robot
|
||||
|
||||
flake8: .installed.cfg
|
||||
@bin/flake8 setup.py
|
||||
@bin/flake8 ./searx/
|
||||
|
||||
coverage: .installed.cfg
|
||||
@bin/coverage run --source=./searx/ --branch bin/test
|
||||
@bin/coverage report --show-missing
|
||||
@bin/coverage html --directory ./coverage
|
||||
|
||||
production: bin/buildout production.cfg setup.py
|
||||
bin/buildout -c production.cfg $(options)
|
||||
@echo "* Please modify `readlink --canonicalize-missing ./searx/settings.py`"
|
||||
@echo "* Hint 1: on production, disable debug mode and change secret_key"
|
||||
@echo "* Hint 2: searx will be executed at server startup by crontab"
|
||||
@echo "* Hint 3: to run immediatley, execute 'bin/supervisord'"
|
||||
|
||||
minimal: bin/buildout minimal.cfg setup.py
|
||||
bin/buildout -c minimal.cfg $(options)
|
||||
|
||||
styles:
|
||||
@lessc -x searx/static/less/style.less > searx/static/css/style.css
|
||||
|
||||
locales:
|
||||
@pybabel compile -d searx/translations
|
||||
|
||||
clean:
|
||||
@rm -rf .installed.cfg .mr.developer.cfg bin parts develop-eggs \
|
||||
searx.egg-info lib include .coverage coverage searx/static/css/*.css
|
||||
|
||||
.PHONY: all tests robot flake8 coverage production minimal styles locales clean
|
160
sources/README.rst
Normal file
|
@ -0,0 +1,160 @@
|
|||
searx
|
||||
=====
|
||||
|
||||
A privacy-respecting, hackable `metasearch
|
||||
engine <https://en.wikipedia.org/wiki/Metasearch_engine>`__.
|
||||
|
||||
List of `running
|
||||
instances <https://github.com/asciimoo/searx/wiki/Searx-instances>`__.
|
||||
|
||||
See the `wiki <https://github.com/asciimoo/searx/wiki>`__ for more information.
|
||||
|
||||
|Flattr searx|
|
||||
|
||||
Features
|
||||
~~~~~~~~
|
||||
|
||||
- Tracking free
|
||||
- Supports multiple output formats
|
||||
- json ``curl https://searx.0x2a.tk/?format=json&q=[query]``
|
||||
- csv ``curl https://searx.0x2a.tk/?format=csv&q=[query]``
|
||||
- opensearch/rss ``curl https://searx.0x2a.tk/?format=rss&q=[query]``
|
||||
- Opensearch support (you can set as default search engine)
|
||||
- Configurable search engines/categories
|
||||
- Different search languages
|
||||
- Duckduckgo like !bang functionality with engine shortcuts
|
||||
- Parallel queries - relatively fast
|
||||
|
||||
Installation
|
||||
~~~~~~~~~~~~
|
||||
|
||||
- clone source:
|
||||
``git clone git@github.com:asciimoo/searx.git && cd searx``
|
||||
- install dependencies: ``pip install -r requirements.txt``
|
||||
- edit your
|
||||
`settings.yml <https://github.com/asciimoo/searx/blob/master/settings.yml>`__
|
||||
(set your ``secret_key``!)
|
||||
- run ``python searx/webapp.py`` to start the application
|
||||
|
||||
For all the details, follow this `step by step
|
||||
installation <https://github.com/asciimoo/searx/wiki/Installation>`__
|
||||
|
||||
Alternative (Recommended) Installation
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
- clone source:
|
||||
``git clone git@github.com:asciimoo/searx.git && cd searx``
|
||||
- build in current folder: ``make minimal``
|
||||
- run ``bin/searx-run`` to start the application
|
||||
|
||||
Development
|
||||
~~~~~~~~~~~
|
||||
|
||||
Just run ``make``. Versions of dependencies are pinned down inside
|
||||
``versions.cfg`` to produce most stable build. Also remember, NO make
|
||||
command should be run as root, not even ``make production``
|
||||
|
||||
Deployment
|
||||
~~~~~~~~~~
|
||||
|
||||
- clone source:
|
||||
``git clone git@github.com:asciimoo/searx.git && cd searx``
|
||||
- build in current folder: ``make production``
|
||||
- run ``bin/supervisord`` to start the application
|
||||
|
||||
Upgrading
|
||||
~~~~~~~~~
|
||||
|
||||
- inside previously cloned searx directory run: ``git stash`` to
|
||||
temporarily save any changes you have made
|
||||
- pull source: ``git pull origin master``
|
||||
- re-build in current folder: ``make production``
|
||||
- run ``bin/supervisorctl stop searx`` to stop searx, if it does not,
|
||||
then run ``fuser -k 8888/tcp``
|
||||
- run ``bin/supervisorctl reload`` to re-read supervisor config and
|
||||
start searx
|
||||
|
||||
Command make
|
||||
~~~~~~~~~~~~
|
||||
|
||||
``make``
|
||||
''''''''
|
||||
|
||||
Builds development environment with testing support.
|
||||
|
||||
``make tests``
|
||||
''''''''''''''
|
||||
|
||||
Runs tests. You can write tests
|
||||
`here <https://github.com/asciimoo/searx/tree/master/searx/tests>`__ and
|
||||
remember 'untested code is broken code'.
|
||||
|
||||
``make robot``
|
||||
''''''''''''''
|
||||
|
||||
Runs robot (Selenium) tests, you must have ``firefox`` installed because
|
||||
this functional tests actually run the browser and perform operations on
|
||||
it. Also searx is executed with
|
||||
`settings\_robot <https://github.com/asciimoo/searx/blob/master/searx/settings_robot.py>`__.
|
||||
|
||||
``make flake8``
|
||||
'''''''''''''''
|
||||
|
||||
'pep8 is a tool to check your Python code against some of the style
|
||||
conventions in `PEP 8 <http://www.python.org/dev/peps/pep-0008/>`__.'
|
||||
|
||||
``make coverage``
|
||||
'''''''''''''''''
|
||||
|
||||
Checks coverage of tests, after running this, execute this:
|
||||
``firefox ./coverage/index.html``
|
||||
|
||||
``make production``
|
||||
'''''''''''''''''''
|
||||
|
||||
Used to make co-called production environment - without tests (you
|
||||
should ran tests before deploying searx on the server). This installs
|
||||
supervisord, so if searx crashes, it will try to pick itself up again.
|
||||
And crontab entry is added to start supervisord at server boot.
|
||||
|
||||
``make minimal``
|
||||
''''''''''''''''
|
||||
|
||||
Minimal build - without test frameworks, the quickest build option.
|
||||
|
||||
``make clean``
|
||||
''''''''''''''
|
||||
|
||||
Deletes several folders and files (see ``Makefile`` for more), so that
|
||||
next time you run any other ``make`` command it will rebuild everithing.
|
||||
|
||||
TODO
|
||||
~~~~
|
||||
|
||||
- Moar engines
|
||||
- Better ui
|
||||
- Browser integration
|
||||
- Documentation
|
||||
- Fix ``flake8`` errors, ``make flake8`` will be merged into
|
||||
``make tests`` when it does not fail anymore
|
||||
- Tests
|
||||
- When we have more tests, we can integrate Travis-CI
|
||||
|
||||
Bugs
|
||||
~~~~
|
||||
|
||||
Bugs or suggestions? Visit the `issue
|
||||
tracker <https://github.com/asciimoo/searx/issues>`__.
|
||||
|
||||
`License <https://github.com/asciimoo/searx/blob/master/LICENSE>`__
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
More about searx
|
||||
~~~~~~~~~~~~~~~~
|
||||
|
||||
- `ohloh <https://www.ohloh.net/p/searx/>`__
|
||||
- `twitter <https://twitter.com/Searx_engine>`__
|
||||
- IRC: #searx @ freenode
|
||||
|
||||
.. |Flattr searx| image:: http://api.flattr.com/button/flattr-badge-large.png
|
||||
:target: https://flattr.com/submit/auto?user_id=asciimoo&url=https://github.com/asciimoo/searx&title=searx&language=&tags=github&category=software
|
3
sources/babel.cfg
Normal file
|
@ -0,0 +1,3 @@
|
|||
[python: **.py]
|
||||
[jinja2: **/templates/**.html]
|
||||
extensions=jinja2.ext.autoescape,jinja2.ext.with_
|
23
sources/base.cfg
Normal file
|
@ -0,0 +1,23 @@
|
|||
[buildout]
|
||||
extends = versions.cfg
|
||||
versions = versions
|
||||
unzip = true
|
||||
newest = false
|
||||
extends = versions.cfg
|
||||
versions = versions
|
||||
prefer-final = true
|
||||
develop = .
|
||||
|
||||
extensions =
|
||||
buildout_versions
|
||||
|
||||
eggs =
|
||||
searx
|
||||
|
||||
parts =
|
||||
omelette
|
||||
|
||||
|
||||
[omelette]
|
||||
recipe = collective.recipe.omelette
|
||||
eggs = ${buildout:eggs}
|
277
sources/bootstrap.py
Normal file
|
@ -0,0 +1,277 @@
|
|||
##############################################################################
|
||||
#
|
||||
# Copyright (c) 2006 Zope Foundation and Contributors.
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# This software is subject to the provisions of the Zope Public License,
|
||||
# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
|
||||
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
|
||||
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
|
||||
# FOR A PARTICULAR PURPOSE.
|
||||
#
|
||||
##############################################################################
|
||||
"""Bootstrap a buildout-based project
|
||||
|
||||
Simply run this script in a directory containing a buildout.cfg.
|
||||
The script accepts buildout command-line options, so you can
|
||||
use the -c option to specify an alternate configuration file.
|
||||
"""
|
||||
|
||||
import os, shutil, sys, tempfile, urllib, urllib2, subprocess
|
||||
from optparse import OptionParser
|
||||
|
||||
if sys.platform == 'win32':
|
||||
def quote(c):
|
||||
if ' ' in c:
|
||||
return '"%s"' % c # work around spawn lamosity on windows
|
||||
else:
|
||||
return c
|
||||
else:
|
||||
quote = str
|
||||
|
||||
# See zc.buildout.easy_install._has_broken_dash_S for motivation and comments.
|
||||
stdout, stderr = subprocess.Popen(
|
||||
[sys.executable, '-Sc',
|
||||
'try:\n'
|
||||
' import ConfigParser\n'
|
||||
'except ImportError:\n'
|
||||
' print 1\n'
|
||||
'else:\n'
|
||||
' print 0\n'],
|
||||
stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()
|
||||
has_broken_dash_S = bool(int(stdout.strip()))
|
||||
|
||||
# In order to be more robust in the face of system Pythons, we want to
|
||||
# run without site-packages loaded. This is somewhat tricky, in
|
||||
# particular because Python 2.6's distutils imports site, so starting
|
||||
# with the -S flag is not sufficient. However, we'll start with that:
|
||||
if not has_broken_dash_S and 'site' in sys.modules:
|
||||
# We will restart with python -S.
|
||||
args = sys.argv[:]
|
||||
args[0:0] = [sys.executable, '-S']
|
||||
args = map(quote, args)
|
||||
os.execv(sys.executable, args)
|
||||
# Now we are running with -S. We'll get the clean sys.path, import site
|
||||
# because distutils will do it later, and then reset the path and clean
|
||||
# out any namespace packages from site-packages that might have been
|
||||
# loaded by .pth files.
|
||||
clean_path = sys.path[:]
|
||||
import site # imported because of its side effects
|
||||
sys.path[:] = clean_path
|
||||
for k, v in sys.modules.items():
|
||||
if k in ('setuptools', 'pkg_resources') or (
|
||||
hasattr(v, '__path__') and
|
||||
len(v.__path__) == 1 and
|
||||
not os.path.exists(os.path.join(v.__path__[0], '__init__.py'))):
|
||||
# This is a namespace package. Remove it.
|
||||
sys.modules.pop(k)
|
||||
|
||||
is_jython = sys.platform.startswith('java')
|
||||
|
||||
setuptools_source = 'http://peak.telecommunity.com/dist/ez_setup.py'
|
||||
distribute_source = 'http://python-distribute.org/distribute_setup.py'
|
||||
distribute_source = 'https://bitbucket.org/pypa/setuptools/raw/f657df1f1ed46596d236376649c99a470662b4ba/distribute_setup.py'
|
||||
|
||||
# parsing arguments
|
||||
def normalize_to_url(option, opt_str, value, parser):
|
||||
if value:
|
||||
if '://' not in value: # It doesn't smell like a URL.
|
||||
value = 'file://%s' % (
|
||||
urllib.pathname2url(
|
||||
os.path.abspath(os.path.expanduser(value))),)
|
||||
if opt_str == '--download-base' and not value.endswith('/'):
|
||||
# Download base needs a trailing slash to make the world happy.
|
||||
value += '/'
|
||||
else:
|
||||
value = None
|
||||
name = opt_str[2:].replace('-', '_')
|
||||
setattr(parser.values, name, value)
|
||||
|
||||
usage = '''\
|
||||
[DESIRED PYTHON FOR BUILDOUT] bootstrap.py [options]
|
||||
|
||||
Bootstraps a buildout-based project.
|
||||
|
||||
Simply run this script in a directory containing a buildout.cfg, using the
|
||||
Python that you want bin/buildout to use.
|
||||
|
||||
Note that by using --setup-source and --download-base to point to
|
||||
local resources, you can keep this script from going over the network.
|
||||
'''
|
||||
|
||||
parser = OptionParser(usage=usage)
|
||||
parser.add_option("-v", "--version", dest="version",
|
||||
help="use a specific zc.buildout version")
|
||||
parser.add_option("-d", "--distribute",
|
||||
action="store_true", dest="use_distribute", default=False,
|
||||
help="Use Distribute rather than Setuptools.")
|
||||
parser.add_option("--setup-source", action="callback", dest="setup_source",
|
||||
callback=normalize_to_url, nargs=1, type="string",
|
||||
help=("Specify a URL or file location for the setup file. "
|
||||
"If you use Setuptools, this will default to " +
|
||||
setuptools_source + "; if you use Distribute, this "
|
||||
"will default to " + distribute_source + "."))
|
||||
parser.add_option("--download-base", action="callback", dest="download_base",
|
||||
callback=normalize_to_url, nargs=1, type="string",
|
||||
help=("Specify a URL or directory for downloading "
|
||||
"zc.buildout and either Setuptools or Distribute. "
|
||||
"Defaults to PyPI."))
|
||||
parser.add_option("--eggs",
|
||||
help=("Specify a directory for storing eggs. Defaults to "
|
||||
"a temporary directory that is deleted when the "
|
||||
"bootstrap script completes."))
|
||||
parser.add_option("-t", "--accept-buildout-test-releases",
|
||||
dest='accept_buildout_test_releases',
|
||||
action="store_true", default=False,
|
||||
help=("Normally, if you do not specify a --version, the "
|
||||
"bootstrap script and buildout gets the newest "
|
||||
"*final* versions of zc.buildout and its recipes and "
|
||||
"extensions for you. If you use this flag, "
|
||||
"bootstrap and buildout will get the newest releases "
|
||||
"even if they are alphas or betas."))
|
||||
parser.add_option("-c", None, action="store", dest="config_file",
|
||||
help=("Specify the path to the buildout configuration "
|
||||
"file to be used."))
|
||||
|
||||
options, args = parser.parse_args()
|
||||
|
||||
if options.eggs:
|
||||
eggs_dir = os.path.abspath(os.path.expanduser(options.eggs))
|
||||
else:
|
||||
eggs_dir = tempfile.mkdtemp()
|
||||
|
||||
if options.setup_source is None:
|
||||
if options.use_distribute:
|
||||
options.setup_source = distribute_source
|
||||
else:
|
||||
options.setup_source = setuptools_source
|
||||
|
||||
if options.accept_buildout_test_releases:
|
||||
args.insert(0, 'buildout:accept-buildout-test-releases=true')
|
||||
|
||||
try:
|
||||
import pkg_resources
|
||||
import setuptools # A flag. Sometimes pkg_resources is installed alone.
|
||||
if not hasattr(pkg_resources, '_distribute'):
|
||||
raise ImportError
|
||||
except ImportError:
|
||||
ez_code = urllib2.urlopen(
|
||||
options.setup_source).read().replace('\r\n', '\n')
|
||||
ez = {}
|
||||
exec ez_code in ez
|
||||
setup_args = dict(to_dir=eggs_dir, download_delay=0)
|
||||
if options.download_base:
|
||||
setup_args['download_base'] = options.download_base
|
||||
if options.use_distribute:
|
||||
setup_args['no_fake'] = True
|
||||
if sys.version_info[:2] == (2, 4):
|
||||
setup_args['version'] = '0.6.32'
|
||||
ez['use_setuptools'](**setup_args)
|
||||
if 'pkg_resources' in sys.modules:
|
||||
reload(sys.modules['pkg_resources'])
|
||||
import pkg_resources
|
||||
# This does not (always?) update the default working set. We will
|
||||
# do it.
|
||||
for path in sys.path:
|
||||
if path not in pkg_resources.working_set.entries:
|
||||
pkg_resources.working_set.add_entry(path)
|
||||
|
||||
cmd = [quote(sys.executable),
|
||||
'-c',
|
||||
quote('from setuptools.command.easy_install import main; main()'),
|
||||
'-mqNxd',
|
||||
quote(eggs_dir)]
|
||||
|
||||
if not has_broken_dash_S:
|
||||
cmd.insert(1, '-S')
|
||||
|
||||
find_links = options.download_base
|
||||
if not find_links:
|
||||
find_links = os.environ.get('bootstrap-testing-find-links')
|
||||
if not find_links and options.accept_buildout_test_releases:
|
||||
find_links = 'http://downloads.buildout.org/'
|
||||
if find_links:
|
||||
cmd.extend(['-f', quote(find_links)])
|
||||
|
||||
if options.use_distribute:
|
||||
setup_requirement = 'distribute'
|
||||
else:
|
||||
setup_requirement = 'setuptools'
|
||||
ws = pkg_resources.working_set
|
||||
setup_requirement_path = ws.find(
|
||||
pkg_resources.Requirement.parse(setup_requirement)).location
|
||||
env = dict(
|
||||
os.environ,
|
||||
PYTHONPATH=setup_requirement_path)
|
||||
|
||||
requirement = 'zc.buildout'
|
||||
version = options.version
|
||||
if version is None and not options.accept_buildout_test_releases:
|
||||
# Figure out the most recent final version of zc.buildout.
|
||||
import setuptools.package_index
|
||||
_final_parts = '*final-', '*final'
|
||||
|
||||
def _final_version(parsed_version):
|
||||
for part in parsed_version:
|
||||
if (part[:1] == '*') and (part not in _final_parts):
|
||||
return False
|
||||
return True
|
||||
index = setuptools.package_index.PackageIndex(
|
||||
search_path=[setup_requirement_path])
|
||||
if find_links:
|
||||
index.add_find_links((find_links,))
|
||||
req = pkg_resources.Requirement.parse(requirement)
|
||||
if index.obtain(req) is not None:
|
||||
best = []
|
||||
bestv = None
|
||||
for dist in index[req.project_name]:
|
||||
distv = dist.parsed_version
|
||||
if distv >= pkg_resources.parse_version('2dev'):
|
||||
continue
|
||||
if _final_version(distv):
|
||||
if bestv is None or distv > bestv:
|
||||
best = [dist]
|
||||
bestv = distv
|
||||
elif distv == bestv:
|
||||
best.append(dist)
|
||||
if best:
|
||||
best.sort()
|
||||
version = best[-1].version
|
||||
|
||||
if version:
|
||||
requirement += '=='+version
|
||||
else:
|
||||
requirement += '<2dev'
|
||||
|
||||
cmd.append(requirement)
|
||||
|
||||
if is_jython:
|
||||
import subprocess
|
||||
exitcode = subprocess.Popen(cmd, env=env).wait()
|
||||
else: # Windows prefers this, apparently; otherwise we would prefer subprocess
|
||||
exitcode = os.spawnle(*([os.P_WAIT, sys.executable] + cmd + [env]))
|
||||
if exitcode != 0:
|
||||
sys.stdout.flush()
|
||||
sys.stderr.flush()
|
||||
print ("An error occurred when trying to install zc.buildout. "
|
||||
"Look above this message for any errors that "
|
||||
"were output by easy_install.")
|
||||
sys.exit(exitcode)
|
||||
|
||||
ws.add_entry(eggs_dir)
|
||||
ws.require(requirement)
|
||||
import zc.buildout.buildout
|
||||
|
||||
# If there isn't already a command in the args, add bootstrap
|
||||
if not [a for a in args if '=' not in a]:
|
||||
args.append('bootstrap')
|
||||
|
||||
|
||||
# if -c was provided, we push it back into args for buildout's main function
|
||||
if options.config_file is not None:
|
||||
args[0:0] = ['-c', options.config_file]
|
||||
|
||||
zc.buildout.buildout.main(args)
|
||||
if not options.eggs: # clean up temporary egg directory
|
||||
shutil.rmtree(eggs_dir)
|
30
sources/buildout.cfg
Normal file
|
@ -0,0 +1,30 @@
|
|||
[buildout]
|
||||
extends = base.cfg
|
||||
develop = .
|
||||
|
||||
eggs =
|
||||
searx [test]
|
||||
|
||||
parts +=
|
||||
pyscripts
|
||||
robot
|
||||
test
|
||||
|
||||
|
||||
[pyscripts]
|
||||
recipe = zc.recipe.egg:script
|
||||
eggs = ${buildout:eggs}
|
||||
interpreter = py
|
||||
dependent-scripts = true
|
||||
|
||||
|
||||
[robot]
|
||||
recipe = zc.recipe.testrunner
|
||||
eggs = ${buildout:eggs}
|
||||
defaults = ['--color', '--auto-progress', '--layer', 'SearxRobotLayer']
|
||||
|
||||
|
||||
[test]
|
||||
recipe = zc.recipe.testrunner
|
||||
eggs = ${buildout:eggs}
|
||||
defaults = ['--color', '--auto-progress', '--layer', 'SearxTestLayer', '--layer', '!SearxRobotLayer']
|
25
sources/examples/basic_engine.py
Normal file
|
@ -0,0 +1,25 @@
|
|||
|
||||
categories = ['general'] # optional
|
||||
|
||||
def request(query, params):
|
||||
'''pre-request callback
|
||||
params<dict>:
|
||||
method : POST/GET
|
||||
headers : {}
|
||||
data : {} # if method == POST
|
||||
url : ''
|
||||
category: 'search category'
|
||||
pageno : 1 # number of the requested page
|
||||
'''
|
||||
|
||||
params['url'] = 'https://host/%s' % query
|
||||
|
||||
return params
|
||||
|
||||
|
||||
def response(resp):
|
||||
'''post-response callback
|
||||
resp: requests response object
|
||||
'''
|
||||
return [{'url': '', 'title': '', 'content': ''}]
|
||||
|
15
sources/minimal.cfg
Normal file
|
@ -0,0 +1,15 @@
|
|||
[buildout]
|
||||
extends = base.cfg
|
||||
develop = .
|
||||
|
||||
eggs =
|
||||
searx
|
||||
|
||||
parts +=
|
||||
pyscripts
|
||||
|
||||
|
||||
[pyscripts]
|
||||
recipe = zc.recipe.egg:script
|
||||
eggs = ${buildout:eggs}
|
||||
interpreter = py
|
34
sources/production.cfg
Normal file
|
@ -0,0 +1,34 @@
|
|||
[buildout]
|
||||
extends = base.cfg
|
||||
develop = .
|
||||
|
||||
eggs =
|
||||
searx
|
||||
|
||||
parts +=
|
||||
pyscripts
|
||||
supervisor
|
||||
crontab_reboot
|
||||
|
||||
|
||||
[pyscripts]
|
||||
recipe = zc.recipe.egg:script
|
||||
eggs = ${buildout:eggs}
|
||||
interpreter = py
|
||||
|
||||
|
||||
[supervisor]
|
||||
recipe = collective.recipe.supervisor
|
||||
http-socket = unix
|
||||
user = searxer
|
||||
password = ohpleasedochangeme
|
||||
file = /tmp/supervisor.sock
|
||||
chmod = 0700
|
||||
programs =
|
||||
50 searx ${buildout:bin-directory}/searx-run
|
||||
|
||||
|
||||
[crontab_reboot]
|
||||
recipe = z3c.recipe.usercrontab
|
||||
times = @reboot
|
||||
command = ${buildout:bin-directory}/supervisord
|
6
sources/requirements.txt
Normal file
|
@ -0,0 +1,6 @@
|
|||
flask
|
||||
flask-babel
|
||||
grequests
|
||||
lxml
|
||||
pyyaml
|
||||
python-dateutil
|
20
sources/searx/__init__.py
Normal file
|
@ -0,0 +1,20 @@
|
|||
from os import environ
|
||||
from os.path import realpath, dirname, join, abspath
|
||||
try:
|
||||
from yaml import load
|
||||
except:
|
||||
from sys import exit, stderr
|
||||
stderr.write('[E] install pyyaml\n')
|
||||
exit(2)
|
||||
|
||||
searx_dir = abspath(dirname(__file__))
|
||||
engine_dir = dirname(realpath(__file__))
|
||||
|
||||
if 'SEARX_SETTINGS_PATH' in environ:
|
||||
settings_path = environ['SEARX_SETTINGS_PATH']
|
||||
else:
|
||||
settings_path = join(searx_dir, 'settings.yml')
|
||||
|
||||
|
||||
with open(settings_path) as settings_yaml:
|
||||
settings = load(settings_yaml)
|
53
sources/searx/autocomplete.py
Normal file
|
@ -0,0 +1,53 @@
|
|||
from lxml import etree
|
||||
from requests import get
|
||||
from json import loads
|
||||
from urllib import urlencode
|
||||
|
||||
|
||||
def dbpedia(query):
|
||||
# dbpedia autocompleter
|
||||
autocomplete_url = 'http://lookup.dbpedia.org/api/search.asmx/KeywordSearch?' # noqa
|
||||
|
||||
response = get(autocomplete_url
|
||||
+ urlencode(dict(QueryString=query)))
|
||||
|
||||
results = []
|
||||
|
||||
if response.ok:
|
||||
dom = etree.fromstring(response.content)
|
||||
results = dom.xpath('//a:Result/a:Label//text()',
|
||||
namespaces={'a': 'http://lookup.dbpedia.org/'})
|
||||
|
||||
return results
|
||||
|
||||
|
||||
def google(query):
|
||||
# google autocompleter
|
||||
autocomplete_url = 'http://suggestqueries.google.com/complete/search?client=toolbar&' # noqa
|
||||
|
||||
response = get(autocomplete_url
|
||||
+ urlencode(dict(q=query)))
|
||||
|
||||
results = []
|
||||
|
||||
if response.ok:
|
||||
dom = etree.fromstring(response.text)
|
||||
results = dom.xpath('//suggestion/@data')
|
||||
|
||||
return results
|
||||
|
||||
|
||||
def wikipedia(query):
|
||||
# wikipedia autocompleter
|
||||
url = 'https://en.wikipedia.org/w/api.php?action=opensearch&{0}&limit=10&namespace=0&format=json' # noqa
|
||||
|
||||
resp = loads(get(url.format(urlencode(dict(q=query)))).text)
|
||||
if len(resp) > 1:
|
||||
return resp[1]
|
||||
return []
|
||||
|
||||
|
||||
backends = {'dbpedia': dbpedia,
|
||||
'google': google,
|
||||
'wikipedia': wikipedia
|
||||
}
|
330
sources/searx/engines/__init__.py
Normal file
|
@ -0,0 +1,330 @@
|
|||
|
||||
'''
|
||||
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) 2013- by Adam Tauber, <asciimoo@gmail.com>
|
||||
'''
|
||||
|
||||
from os.path import realpath, dirname, splitext, join
|
||||
import sys
|
||||
from imp import load_source
|
||||
from itertools import izip_longest, chain
|
||||
from operator import itemgetter
|
||||
from urlparse import urlparse
|
||||
from datetime import datetime
|
||||
import grequests
|
||||
from flask.ext.babel import gettext
|
||||
from searx import settings
|
||||
from searx.utils import gen_useragent
|
||||
|
||||
engine_dir = dirname(realpath(__file__))
|
||||
|
||||
number_of_searches = 0
|
||||
|
||||
engines = {}
|
||||
|
||||
categories = {'general': []}
|
||||
|
||||
engine_shortcuts = {}
|
||||
|
||||
|
||||
def load_module(filename):
|
||||
modname = splitext(filename)[0]
|
||||
if modname in sys.modules:
|
||||
del sys.modules[modname]
|
||||
filepath = join(engine_dir, filename)
|
||||
module = load_source(modname, filepath)
|
||||
module.name = modname
|
||||
return module
|
||||
|
||||
if not 'engines' in settings or not settings['engines']:
|
||||
print '[E] Error no engines found. Edit your settings.yml'
|
||||
exit(2)
|
||||
|
||||
for engine_data in settings['engines']:
|
||||
engine_name = engine_data['engine']
|
||||
engine = load_module(engine_name + '.py')
|
||||
|
||||
for param_name in engine_data:
|
||||
if param_name == 'engine':
|
||||
continue
|
||||
if param_name == 'categories':
|
||||
if engine_data['categories'] == 'none':
|
||||
engine.categories = []
|
||||
else:
|
||||
engine.categories = map(
|
||||
str.strip, engine_data['categories'].split(','))
|
||||
continue
|
||||
setattr(engine, param_name, engine_data[param_name])
|
||||
|
||||
if not hasattr(engine, 'paging'):
|
||||
engine.paging = False
|
||||
|
||||
if not hasattr(engine, 'categories'):
|
||||
engine.categories = ['general']
|
||||
|
||||
if not hasattr(engine, 'language_support'):
|
||||
#engine.language_support = False
|
||||
engine.language_support = True
|
||||
|
||||
if not hasattr(engine, 'timeout'):
|
||||
#engine.language_support = False
|
||||
engine.timeout = settings['server']['request_timeout']
|
||||
|
||||
if not hasattr(engine, 'shortcut'):
|
||||
#engine.shortcut = '''
|
||||
engine.shortcut = ''
|
||||
|
||||
# checking required variables
|
||||
for engine_attr in dir(engine):
|
||||
if engine_attr.startswith('_'):
|
||||
continue
|
||||
if getattr(engine, engine_attr) is None:
|
||||
print '[E] Engine config error: Missing attribute "{0}.{1}"'.format(engine.name, engine_attr) # noqa
|
||||
sys.exit(1)
|
||||
|
||||
engines[engine.name] = engine
|
||||
engine.stats = {
|
||||
'result_count': 0,
|
||||
'search_count': 0,
|
||||
'page_load_time': 0,
|
||||
'score_count': 0,
|
||||
'errors': 0
|
||||
}
|
||||
|
||||
if hasattr(engine, 'categories'):
|
||||
for category_name in engine.categories:
|
||||
categories.setdefault(category_name, []).append(engine)
|
||||
else:
|
||||
categories['general'].append(engine)
|
||||
|
||||
if engine.shortcut:
|
||||
# TODO check duplications
|
||||
engine_shortcuts[engine.shortcut] = engine.name
|
||||
|
||||
|
||||
def default_request_params():
|
||||
return {
|
||||
'method': 'GET', 'headers': {}, 'data': {}, 'url': '', 'cookies': {}}
|
||||
|
||||
|
||||
def make_callback(engine_name, results, suggestions, callback, params):
|
||||
# creating a callback wrapper for the search engine results
|
||||
def process_callback(response, **kwargs):
|
||||
cb_res = []
|
||||
response.search_params = params
|
||||
engines[engine_name].stats['page_load_time'] += \
|
||||
(datetime.now() - params['started']).total_seconds()
|
||||
try:
|
||||
search_results = callback(response)
|
||||
except Exception, e:
|
||||
engines[engine_name].stats['errors'] += 1
|
||||
results[engine_name] = cb_res
|
||||
print '[E] Error with engine "{0}":\n\t{1}'.format(
|
||||
engine_name, str(e))
|
||||
return
|
||||
for result in search_results:
|
||||
result['engine'] = engine_name
|
||||
if 'suggestion' in result:
|
||||
# TODO type checks
|
||||
suggestions.add(result['suggestion'])
|
||||
continue
|
||||
cb_res.append(result)
|
||||
results[engine_name] = cb_res
|
||||
return process_callback
|
||||
|
||||
|
||||
def score_results(results):
|
||||
flat_res = filter(
|
||||
None, chain.from_iterable(izip_longest(*results.values())))
|
||||
flat_len = len(flat_res)
|
||||
engines_len = len(results)
|
||||
results = []
|
||||
# deduplication + scoring
|
||||
for i, res in enumerate(flat_res):
|
||||
res['parsed_url'] = urlparse(res['url'])
|
||||
res['engines'] = [res['engine']]
|
||||
weight = 1.0
|
||||
if hasattr(engines[res['engine']], 'weight'):
|
||||
weight = float(engines[res['engine']].weight)
|
||||
score = int((flat_len - i) / engines_len) * weight + 1
|
||||
duplicated = False
|
||||
for new_res in results:
|
||||
p1 = res['parsed_url'].path[:-1] if res['parsed_url'].path.endswith('/') else res['parsed_url'].path # noqa
|
||||
p2 = new_res['parsed_url'].path[:-1] if new_res['parsed_url'].path.endswith('/') else new_res['parsed_url'].path # noqa
|
||||
if res['parsed_url'].netloc == new_res['parsed_url'].netloc and\
|
||||
p1 == p2 and\
|
||||
res['parsed_url'].query == new_res['parsed_url'].query and\
|
||||
res.get('template') == new_res.get('template'):
|
||||
duplicated = new_res
|
||||
break
|
||||
if duplicated:
|
||||
if res.get('content') > duplicated.get('content'):
|
||||
duplicated['content'] = res['content']
|
||||
duplicated['score'] += score
|
||||
duplicated['engines'].append(res['engine'])
|
||||
if duplicated['parsed_url'].scheme == 'https':
|
||||
continue
|
||||
elif res['parsed_url'].scheme == 'https':
|
||||
duplicated['url'] = res['parsed_url'].geturl()
|
||||
duplicated['parsed_url'] = res['parsed_url']
|
||||
else:
|
||||
res['score'] = score
|
||||
results.append(res)
|
||||
return sorted(results, key=itemgetter('score'), reverse=True)
|
||||
|
||||
|
||||
def search(query, request, selected_engines, pageno=1, lang='all'):
|
||||
global engines, categories, number_of_searches
|
||||
requests = []
|
||||
results = {}
|
||||
suggestions = set()
|
||||
number_of_searches += 1
|
||||
#user_agent = request.headers.get('User-Agent', '')
|
||||
user_agent = gen_useragent()
|
||||
|
||||
for selected_engine in selected_engines:
|
||||
if selected_engine['name'] not in engines:
|
||||
continue
|
||||
|
||||
engine = engines[selected_engine['name']]
|
||||
|
||||
if pageno > 1 and not engine.paging:
|
||||
continue
|
||||
|
||||
if lang != 'all' and not engine.language_support:
|
||||
continue
|
||||
|
||||
request_params = default_request_params()
|
||||
request_params['headers']['User-Agent'] = user_agent
|
||||
request_params['category'] = selected_engine['category']
|
||||
request_params['started'] = datetime.now()
|
||||
request_params['pageno'] = pageno
|
||||
request_params['language'] = lang
|
||||
request_params = engine.request(query.encode('utf-8'), request_params)
|
||||
|
||||
callback = make_callback(
|
||||
selected_engine['name'],
|
||||
results,
|
||||
suggestions,
|
||||
engine.response,
|
||||
request_params
|
||||
)
|
||||
|
||||
request_args = dict(
|
||||
headers=request_params['headers'],
|
||||
hooks=dict(response=callback),
|
||||
cookies=request_params['cookies'],
|
||||
timeout=engine.timeout
|
||||
)
|
||||
|
||||
if request_params['method'] == 'GET':
|
||||
req = grequests.get
|
||||
else:
|
||||
req = grequests.post
|
||||
request_args['data'] = request_params['data']
|
||||
|
||||
# ignoring empty urls
|
||||
if not request_params['url']:
|
||||
continue
|
||||
|
||||
requests.append(req(request_params['url'], **request_args))
|
||||
grequests.map(requests)
|
||||
for engine_name, engine_results in results.items():
|
||||
engines[engine_name].stats['search_count'] += 1
|
||||
engines[engine_name].stats['result_count'] += len(engine_results)
|
||||
|
||||
results = score_results(results)
|
||||
|
||||
for result in results:
|
||||
for res_engine in result['engines']:
|
||||
engines[result['engine']].stats['score_count'] += result['score']
|
||||
|
||||
return results, suggestions
|
||||
|
||||
|
||||
def get_engines_stats():
|
||||
# TODO refactor
|
||||
pageloads = []
|
||||
results = []
|
||||
scores = []
|
||||
errors = []
|
||||
scores_per_result = []
|
||||
|
||||
max_pageload = max_results = max_score = max_errors = max_score_per_result = 0 # noqa
|
||||
for engine in engines.values():
|
||||
if engine.stats['search_count'] == 0:
|
||||
continue
|
||||
results_num = \
|
||||
engine.stats['result_count'] / float(engine.stats['search_count'])
|
||||
load_times = engine.stats['page_load_time'] / float(engine.stats['search_count']) # noqa
|
||||
if results_num:
|
||||
score = engine.stats['score_count'] / float(engine.stats['search_count']) # noqa
|
||||
score_per_result = score / results_num
|
||||
else:
|
||||
score = score_per_result = 0.0
|
||||
max_results = max(results_num, max_results)
|
||||
max_pageload = max(load_times, max_pageload)
|
||||
max_score = max(score, max_score)
|
||||
max_score_per_result = max(score_per_result, max_score_per_result)
|
||||
max_errors = max(max_errors, engine.stats['errors'])
|
||||
pageloads.append({'avg': load_times, 'name': engine.name})
|
||||
results.append({'avg': results_num, 'name': engine.name})
|
||||
scores.append({'avg': score, 'name': engine.name})
|
||||
errors.append({'avg': engine.stats['errors'], 'name': engine.name})
|
||||
scores_per_result.append({
|
||||
'avg': score_per_result,
|
||||
'name': engine.name
|
||||
})
|
||||
|
||||
for engine in pageloads:
|
||||
engine['percentage'] = int(engine['avg'] / max_pageload * 100)
|
||||
|
||||
for engine in results:
|
||||
engine['percentage'] = int(engine['avg'] / max_results * 100)
|
||||
|
||||
for engine in scores:
|
||||
engine['percentage'] = int(engine['avg'] / max_score * 100)
|
||||
|
||||
for engine in scores_per_result:
|
||||
engine['percentage'] = int(engine['avg'] / max_score_per_result * 100)
|
||||
|
||||
for engine in errors:
|
||||
if max_errors:
|
||||
engine['percentage'] = int(float(engine['avg']) / max_errors * 100)
|
||||
else:
|
||||
engine['percentage'] = 0
|
||||
|
||||
return [
|
||||
(
|
||||
gettext('Page loads (sec)'),
|
||||
sorted(pageloads, key=itemgetter('avg'))
|
||||
),
|
||||
(
|
||||
gettext('Number of results'),
|
||||
sorted(results, key=itemgetter('avg'), reverse=True)
|
||||
),
|
||||
(
|
||||
gettext('Scores'),
|
||||
sorted(scores, key=itemgetter('avg'), reverse=True)
|
||||
),
|
||||
(
|
||||
gettext('Scores per result'),
|
||||
sorted(scores_per_result, key=itemgetter('avg'), reverse=True)
|
||||
),
|
||||
(
|
||||
gettext('Errors'),
|
||||
sorted(errors, key=itemgetter('avg'), reverse=True)
|
||||
),
|
||||
]
|
49
sources/searx/engines/bing.py
Normal file
|
@ -0,0 +1,49 @@
|
|||
from urllib import urlencode
|
||||
from cgi import escape
|
||||
from lxml import html
|
||||
|
||||
base_url = 'http://www.bing.com/'
|
||||
search_string = 'search?{query}&first={offset}'
|
||||
paging = True
|
||||
language_support = True
|
||||
|
||||
|
||||
def request(query, params):
|
||||
offset = (params['pageno'] - 1) * 10 + 1
|
||||
if params['language'] == 'all':
|
||||
language = 'en-US'
|
||||
else:
|
||||
language = params['language'].replace('_', '-')
|
||||
search_path = search_string.format(
|
||||
query=urlencode({'q': query, 'setmkt': language}),
|
||||
offset=offset)
|
||||
|
||||
params['cookies']['SRCHHPGUSR'] = \
|
||||
'NEWWND=0&NRSLT=-1&SRCHLANG=' + language.split('-')[0]
|
||||
#if params['category'] == 'images':
|
||||
# params['url'] = base_url + 'images/' + search_path
|
||||
params['url'] = base_url + search_path
|
||||
return params
|
||||
|
||||
|
||||
def response(resp):
|
||||
global base_url
|
||||
results = []
|
||||
dom = html.fromstring(resp.content)
|
||||
for result in dom.xpath('//div[@class="sa_cc"]'):
|
||||
link = result.xpath('.//h3/a')[0]
|
||||
url = link.attrib.get('href')
|
||||
title = ' '.join(link.xpath('.//text()'))
|
||||
content = escape(' '.join(result.xpath('.//p//text()')))
|
||||
results.append({'url': url, 'title': title, 'content': content})
|
||||
|
||||
if results:
|
||||
return results
|
||||
|
||||
for result in dom.xpath('//li[@class="b_algo"]'):
|
||||
link = result.xpath('.//h2/a')[0]
|
||||
url = link.attrib.get('href')
|
||||
title = ' '.join(link.xpath('.//text()'))
|
||||
content = escape(' '.join(result.xpath('.//p//text()')))
|
||||
results.append({'url': url, 'title': title, 'content': content})
|
||||
return results
|
51
sources/searx/engines/bing_news.py
Normal file
|
@ -0,0 +1,51 @@
|
|||
from urllib import urlencode
|
||||
from cgi import escape
|
||||
from lxml import html
|
||||
|
||||
categories = ['news']
|
||||
|
||||
base_url = 'http://www.bing.com/'
|
||||
search_string = 'news/search?{query}&first={offset}'
|
||||
paging = True
|
||||
language_support = True
|
||||
|
||||
|
||||
def request(query, params):
|
||||
offset = (params['pageno'] - 1) * 10 + 1
|
||||
if params['language'] == 'all':
|
||||
language = 'en-US'
|
||||
else:
|
||||
language = params['language'].replace('_', '-')
|
||||
search_path = search_string.format(
|
||||
query=urlencode({'q': query, 'setmkt': language}),
|
||||
offset=offset)
|
||||
|
||||
params['cookies']['SRCHHPGUSR'] = \
|
||||
'NEWWND=0&NRSLT=-1&SRCHLANG=' + language.split('-')[0]
|
||||
#if params['category'] == 'images':
|
||||
# params['url'] = base_url + 'images/' + search_path
|
||||
params['url'] = base_url + search_path
|
||||
return params
|
||||
|
||||
|
||||
def response(resp):
|
||||
global base_url
|
||||
results = []
|
||||
dom = html.fromstring(resp.content)
|
||||
for result in dom.xpath('//div[@class="sa_cc"]'):
|
||||
link = result.xpath('.//h3/a')[0]
|
||||
url = link.attrib.get('href')
|
||||
title = ' '.join(link.xpath('.//text()'))
|
||||
content = escape(' '.join(result.xpath('.//p//text()')))
|
||||
results.append({'url': url, 'title': title, 'content': content})
|
||||
|
||||
if results:
|
||||
return results
|
||||
|
||||
for result in dom.xpath('//li[@class="b_algo"]'):
|
||||
link = result.xpath('.//h2/a')[0]
|
||||
url = link.attrib.get('href')
|
||||
title = ' '.join(link.xpath('.//text()'))
|
||||
content = escape(' '.join(result.xpath('.//p//text()')))
|
||||
results.append({'url': url, 'title': title, 'content': content})
|
||||
return results
|
62
sources/searx/engines/currency_convert.py
Normal file
|
@ -0,0 +1,62 @@
|
|||
from datetime import datetime
|
||||
import re
|
||||
|
||||
categories = []
|
||||
url = 'http://finance.yahoo.com/d/quotes.csv?e=.csv&f=sl1d1t1&s={query}=X'
|
||||
weight = 100
|
||||
|
||||
parser_re = re.compile(r'^\W*(\d+(?:\.\d+)?)\W*([a-z]{3})\W*(?:in)?\W*([a-z]{3})\W*$', re.I) # noqa
|
||||
|
||||
|
||||
def request(query, params):
|
||||
m = parser_re.match(query)
|
||||
if not m:
|
||||
# wrong query
|
||||
return params
|
||||
try:
|
||||
ammount, from_currency, to_currency = m.groups()
|
||||
ammount = float(ammount)
|
||||
except:
|
||||
# wrong params
|
||||
return params
|
||||
|
||||
q = (from_currency + to_currency).upper()
|
||||
|
||||
params['url'] = url.format(query=q)
|
||||
params['ammount'] = ammount
|
||||
params['from'] = from_currency
|
||||
params['to'] = to_currency
|
||||
|
||||
return params
|
||||
|
||||
|
||||
def response(resp):
|
||||
global base_url
|
||||
results = []
|
||||
try:
|
||||
_, conversion_rate, _ = resp.text.split(',', 2)
|
||||
conversion_rate = float(conversion_rate)
|
||||
except:
|
||||
return results
|
||||
|
||||
title = '{0} {1} in {2} is {3}'.format(
|
||||
resp.search_params['ammount'],
|
||||
resp.search_params['from'],
|
||||
resp.search_params['to'],
|
||||
resp.search_params['ammount'] * conversion_rate
|
||||
)
|
||||
|
||||
content = '1 {0} is {1} {2}'.format(resp.search_params['from'],
|
||||
conversion_rate,
|
||||
resp.search_params['to'])
|
||||
now_date = datetime.now().strftime('%Y%m%d')
|
||||
url = 'http://finance.yahoo.com/currency/converter-results/{0}/{1}-{2}-to-{3}.html' # noqa
|
||||
url = url.format(
|
||||
now_date,
|
||||
resp.search_params['ammount'],
|
||||
resp.search_params['from'].lower(),
|
||||
resp.search_params['to'].lower()
|
||||
)
|
||||
results.append({'title': title, 'content': content, 'url': url})
|
||||
|
||||
return results
|
45
sources/searx/engines/dailymotion.py
Normal file
|
@ -0,0 +1,45 @@
|
|||
from urllib import urlencode
|
||||
from json import loads
|
||||
from lxml import html
|
||||
|
||||
categories = ['videos']
|
||||
locale = 'en_US'
|
||||
|
||||
# see http://www.dailymotion.com/doc/api/obj-video.html
|
||||
search_url = 'https://api.dailymotion.com/videos?fields=title,description,duration,url,thumbnail_360_url&sort=relevance&limit=25&page={pageno}&{query}' # noqa
|
||||
|
||||
# TODO use video result template
|
||||
content_tpl = '<a href="{0}" title="{0}" ><img src="{1}" /></a><br />'
|
||||
|
||||
paging = True
|
||||
|
||||
|
||||
def request(query, params):
|
||||
params['url'] = search_url.format(
|
||||
query=urlencode({'search': query, 'localization': locale}),
|
||||
pageno=params['pageno'])
|
||||
return params
|
||||
|
||||
|
||||
def response(resp):
|
||||
results = []
|
||||
search_res = loads(resp.text)
|
||||
if not 'list' in search_res:
|
||||
return results
|
||||
for res in search_res['list']:
|
||||
title = res['title']
|
||||
url = res['url']
|
||||
if res['thumbnail_360_url']:
|
||||
content = content_tpl.format(url, res['thumbnail_360_url'])
|
||||
else:
|
||||
content = ''
|
||||
if res['description']:
|
||||
description = text_content_from_html(res['description'])
|
||||
content += description[:500]
|
||||
results.append({'url': url, 'title': title, 'content': content})
|
||||
return results
|
||||
|
||||
|
||||
def text_content_from_html(html_string):
|
||||
desc_html = html.fragment_fromstring(html_string, create_parent=True)
|
||||
return desc_html.text_content()
|
36
sources/searx/engines/deviantart.py
Normal file
|
@ -0,0 +1,36 @@
|
|||
from urllib import urlencode
|
||||
from urlparse import urljoin
|
||||
from lxml import html
|
||||
|
||||
categories = ['images']
|
||||
|
||||
base_url = 'https://www.deviantart.com/'
|
||||
search_url = base_url+'search?offset={offset}&{query}'
|
||||
|
||||
paging = True
|
||||
|
||||
|
||||
def request(query, params):
|
||||
offset = (params['pageno'] - 1) * 24
|
||||
params['url'] = search_url.format(offset=offset,
|
||||
query=urlencode({'q': query}))
|
||||
return params
|
||||
|
||||
|
||||
def response(resp):
|
||||
global base_url
|
||||
results = []
|
||||
if resp.status_code == 302:
|
||||
return results
|
||||
dom = html.fromstring(resp.text)
|
||||
for result in dom.xpath('//div[contains(@class, "tt-a tt-fh")]'):
|
||||
link = result.xpath('.//a[contains(@class, "thumb")]')[0]
|
||||
url = urljoin(base_url, link.attrib.get('href'))
|
||||
title_links = result.xpath('.//span[@class="details"]//a[contains(@class, "t")]') # noqa
|
||||
title = ''.join(title_links[0].xpath('.//text()'))
|
||||
img_src = link.xpath('.//img')[0].attrib['src']
|
||||
results.append({'url': url,
|
||||
'title': title,
|
||||
'img_src': img_src,
|
||||
'template': 'images.html'})
|
||||
return results
|
65
sources/searx/engines/duckduckgo.py
Normal file
|
@ -0,0 +1,65 @@
|
|||
from urllib import urlencode
|
||||
from lxml.html import fromstring
|
||||
from searx.utils import html_to_text
|
||||
|
||||
url = 'https://duckduckgo.com/html?{query}&s={offset}'
|
||||
locale = 'us-en'
|
||||
|
||||
|
||||
def request(query, params):
|
||||
offset = (params['pageno'] - 1) * 30
|
||||
q = urlencode({'q': query,
|
||||
'l': locale})
|
||||
params['url'] = url.format(query=q, offset=offset)
|
||||
return params
|
||||
|
||||
|
||||
def response(resp):
|
||||
result_xpath = '//div[@class="results_links results_links_deep web-result"]' # noqa
|
||||
url_xpath = './/a[@class="large"]/@href'
|
||||
title_xpath = './/a[@class="large"]//text()'
|
||||
content_xpath = './/div[@class="snippet"]//text()'
|
||||
results = []
|
||||
|
||||
doc = fromstring(resp.text)
|
||||
|
||||
for r in doc.xpath(result_xpath):
|
||||
try:
|
||||
res_url = r.xpath(url_xpath)[-1]
|
||||
except:
|
||||
continue
|
||||
if not res_url:
|
||||
continue
|
||||
title = html_to_text(''.join(r.xpath(title_xpath)))
|
||||
content = html_to_text(''.join(r.xpath(content_xpath)))
|
||||
results.append({'title': title,
|
||||
'content': content,
|
||||
'url': res_url})
|
||||
|
||||
return results
|
||||
|
||||
|
||||
#from json import loads
|
||||
#search_url = url + 'd.js?{query}&p=1&s={offset}'
|
||||
#
|
||||
#paging = True
|
||||
#
|
||||
#
|
||||
#def request(query, params):
|
||||
# offset = (params['pageno'] - 1) * 30
|
||||
# q = urlencode({'q': query,
|
||||
# 'l': locale})
|
||||
# params['url'] = search_url.format(query=q, offset=offset)
|
||||
# return params
|
||||
#
|
||||
#
|
||||
#def response(resp):
|
||||
# results = []
|
||||
# search_res = loads(resp.text[resp.text.find('[{'):-2])[:-1]
|
||||
# for r in search_res:
|
||||
# if not r.get('t'):
|
||||
# continue
|
||||
# results.append({'title': r['t'],
|
||||
# 'content': html_to_text(r['a']),
|
||||
# 'url': r['u']})
|
||||
# return results
|
23
sources/searx/engines/duckduckgo_definitions.py
Normal file
|
@ -0,0 +1,23 @@
|
|||
import json
|
||||
from urllib import urlencode
|
||||
|
||||
url = 'http://api.duckduckgo.com/?{query}&format=json&pretty=0&no_redirect=1'
|
||||
|
||||
|
||||
def request(query, params):
|
||||
params['url'] = url.format(query=urlencode({'q': query}))
|
||||
return params
|
||||
|
||||
|
||||
def response(resp):
|
||||
search_res = json.loads(resp.text)
|
||||
results = []
|
||||
if 'Definition' in search_res:
|
||||
if search_res.get('AbstractURL'):
|
||||
res = {'title': search_res.get('Heading', ''),
|
||||
'content': search_res.get('Definition', ''),
|
||||
'url': search_res.get('AbstractURL', ''),
|
||||
'class': 'definition_result'}
|
||||
results.append(res)
|
||||
|
||||
return results
|
6
sources/searx/engines/dummy.py
Normal file
|
@ -0,0 +1,6 @@
|
|||
def request(query, params):
|
||||
return params
|
||||
|
||||
|
||||
def response(resp):
|
||||
return []
|
84
sources/searx/engines/filecrop.py
Normal file
|
@ -0,0 +1,84 @@
|
|||
from urllib import urlencode
|
||||
from HTMLParser import HTMLParser
|
||||
|
||||
url = 'http://www.filecrop.com/'
|
||||
search_url = url + '/search.php?{query}&size_i=0&size_f=100000000&engine_r=1&engine_d=1&engine_e=1&engine_4=1&engine_m=1&pos={index}' # noqa
|
||||
|
||||
paging = True
|
||||
|
||||
|
||||
class FilecropResultParser(HTMLParser):
|
||||
def __init__(self):
|
||||
HTMLParser.__init__(self)
|
||||
self.__start_processing = False
|
||||
|
||||
self.results = []
|
||||
self.result = {}
|
||||
|
||||
self.tr_counter = 0
|
||||
self.data_counter = 0
|
||||
|
||||
def handle_starttag(self, tag, attrs):
|
||||
|
||||
if tag == 'tr':
|
||||
if ('bgcolor', '#edeff5') in attrs or\
|
||||
('bgcolor', '#ffffff') in attrs:
|
||||
self.__start_processing = True
|
||||
|
||||
if not self.__start_processing:
|
||||
return
|
||||
|
||||
if tag == 'label':
|
||||
self.result['title'] = [attr[1] for attr in attrs
|
||||
if attr[0] == 'title'][0]
|
||||
elif tag == 'a' and ('rel', 'nofollow') in attrs\
|
||||
and ('class', 'sourcelink') in attrs:
|
||||
if 'content' in self.result:
|
||||
self.result['content'] += [attr[1] for attr in attrs
|
||||
if attr[0] == 'title'][0]
|
||||
else:
|
||||
self.result['content'] = [attr[1] for attr in attrs
|
||||
if attr[0] == 'title'][0]
|
||||
self.result['content'] += ' '
|
||||
elif tag == 'a':
|
||||
self.result['url'] = url + [attr[1] for attr in attrs
|
||||
if attr[0] == 'href'][0]
|
||||
|
||||
def handle_endtag(self, tag):
|
||||
if self.__start_processing is False:
|
||||
return
|
||||
|
||||
if tag == 'tr':
|
||||
self.tr_counter += 1
|
||||
|
||||
if self.tr_counter == 2:
|
||||
self.__start_processing = False
|
||||
self.tr_counter = 0
|
||||
self.data_counter = 0
|
||||
self.results.append(self.result)
|
||||
self.result = {}
|
||||
|
||||
def handle_data(self, data):
|
||||
if not self.__start_processing:
|
||||
return
|
||||
|
||||
if 'content' in self.result:
|
||||
self.result['content'] += data + ' '
|
||||
else:
|
||||
self.result['content'] = data + ' '
|
||||
|
||||
self.data_counter += 1
|
||||
|
||||
|
||||
def request(query, params):
|
||||
index = 1 + (params['pageno'] - 1) * 30
|
||||
params['url'] = search_url.format(query=urlencode({'w': query}),
|
||||
index=index)
|
||||
return params
|
||||
|
||||
|
||||
def response(resp):
|
||||
parser = FilecropResultParser()
|
||||
parser.feed(resp.text)
|
||||
|
||||
return parser.results
|
37
sources/searx/engines/flickr.py
Normal file
|
@ -0,0 +1,37 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
from urllib import urlencode
|
||||
from lxml import html
|
||||
from urlparse import urljoin
|
||||
|
||||
categories = ['images']
|
||||
|
||||
url = 'https://secure.flickr.com/'
|
||||
search_url = url+'search/?{query}&page={page}'
|
||||
results_xpath = '//div[@id="thumbnails"]//a[@class="rapidnofollow photo-click" and @data-track="photo-click"]' # noqa
|
||||
|
||||
paging = True
|
||||
|
||||
|
||||
def request(query, params):
|
||||
params['url'] = search_url.format(query=urlencode({'q': query}),
|
||||
page=params['pageno'])
|
||||
return params
|
||||
|
||||
|
||||
def response(resp):
|
||||
global base_url
|
||||
results = []
|
||||
dom = html.fromstring(resp.text)
|
||||
for result in dom.xpath(results_xpath):
|
||||
href = urljoin(url, result.attrib.get('href'))
|
||||
img = result.xpath('.//img')[0]
|
||||
title = img.attrib.get('alt', '')
|
||||
img_src = img.attrib.get('data-defer-src')
|
||||
if not img_src:
|
||||
continue
|
||||
results.append({'url': href,
|
||||
'title': title,
|
||||
'img_src': img_src,
|
||||
'template': 'images.html'})
|
||||
return results
|
32
sources/searx/engines/github.py
Normal file
|
@ -0,0 +1,32 @@
|
|||
from urllib import urlencode
|
||||
from json import loads
|
||||
from cgi import escape
|
||||
|
||||
categories = ['it']
|
||||
|
||||
search_url = 'https://api.github.com/search/repositories?sort=stars&order=desc&{query}' # noqa
|
||||
|
||||
accept_header = 'application/vnd.github.preview.text-match+json'
|
||||
|
||||
|
||||
def request(query, params):
|
||||
global search_url
|
||||
params['url'] = search_url.format(query=urlencode({'q': query}))
|
||||
params['headers']['Accept'] = accept_header
|
||||
return params
|
||||
|
||||
|
||||
def response(resp):
|
||||
results = []
|
||||
search_res = loads(resp.text)
|
||||
if not 'items' in search_res:
|
||||
return results
|
||||
for res in search_res['items']:
|
||||
title = res['name']
|
||||
url = res['html_url']
|
||||
if res['description']:
|
||||
content = escape(res['description'][:500])
|
||||
else:
|
||||
content = ''
|
||||
results.append({'url': url, 'title': title, 'content': content})
|
||||
return results
|
37
sources/searx/engines/google.py
Normal file
|
@ -0,0 +1,37 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
from urllib import urlencode
|
||||
from json import loads
|
||||
|
||||
categories = ['general']
|
||||
|
||||
url = 'https://ajax.googleapis.com/'
|
||||
search_url = url + 'ajax/services/search/web?v=2.0&start={offset}&rsz=large&safe=off&filter=off&{query}&hl={language}' # noqa
|
||||
|
||||
paging = True
|
||||
language_support = True
|
||||
|
||||
|
||||
def request(query, params):
|
||||
offset = (params['pageno'] - 1) * 8
|
||||
language = 'en-US'
|
||||
if params['language'] != 'all':
|
||||
language = params['language'].replace('_', '-')
|
||||
params['url'] = search_url.format(offset=offset,
|
||||
query=urlencode({'q': query}),
|
||||
language=language)
|
||||
return params
|
||||
|
||||
|
||||
def response(resp):
|
||||
results = []
|
||||
search_res = loads(resp.text)
|
||||
|
||||
if not search_res.get('responseData', {}).get('results'):
|
||||
return []
|
||||
|
||||
for result in search_res['responseData']['results']:
|
||||
results.append({'url': result['unescapedUrl'],
|
||||
'title': result['titleNoFormatting'],
|
||||
'content': result['content']})
|
||||
return results
|
36
sources/searx/engines/google_images.py
Normal file
|
@ -0,0 +1,36 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
from urllib import urlencode
|
||||
from json import loads
|
||||
|
||||
categories = ['images']
|
||||
|
||||
url = 'https://ajax.googleapis.com/'
|
||||
search_url = url + 'ajax/services/search/images?v=1.0&start={offset}&rsz=large&safe=off&filter=off&{query}' # noqa
|
||||
|
||||
|
||||
def request(query, params):
|
||||
offset = (params['pageno'] - 1) * 8
|
||||
params['url'] = search_url.format(query=urlencode({'q': query}),
|
||||
offset=offset)
|
||||
return params
|
||||
|
||||
|
||||
def response(resp):
|
||||
results = []
|
||||
search_res = loads(resp.text)
|
||||
if not search_res.get('responseData'):
|
||||
return []
|
||||
if not search_res['responseData'].get('results'):
|
||||
return []
|
||||
for result in search_res['responseData']['results']:
|
||||
href = result['originalContextUrl']
|
||||
title = result['title']
|
||||
if not result['url']:
|
||||
continue
|
||||
results.append({'url': href,
|
||||
'title': title,
|
||||
'content': '',
|
||||
'img_src': result['url'],
|
||||
'template': 'images.html'})
|
||||
return results
|
43
sources/searx/engines/google_news.py
Normal file
|
@ -0,0 +1,43 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
from urllib import urlencode
|
||||
from json import loads
|
||||
from dateutil import parser
|
||||
|
||||
categories = ['news']
|
||||
|
||||
url = 'https://ajax.googleapis.com/'
|
||||
search_url = url + 'ajax/services/search/news?v=2.0&start={offset}&rsz=large&safe=off&filter=off&{query}&hl={language}' # noqa
|
||||
|
||||
paging = True
|
||||
language_support = True
|
||||
|
||||
|
||||
def request(query, params):
|
||||
offset = (params['pageno'] - 1) * 8
|
||||
language = 'en-US'
|
||||
if params['language'] != 'all':
|
||||
language = params['language'].replace('_', '-')
|
||||
params['url'] = search_url.format(offset=offset,
|
||||
query=urlencode({'q': query}),
|
||||
language=language)
|
||||
return params
|
||||
|
||||
|
||||
def response(resp):
|
||||
results = []
|
||||
search_res = loads(resp.text)
|
||||
|
||||
if not search_res.get('responseData', {}).get('results'):
|
||||
return []
|
||||
|
||||
for result in search_res['responseData']['results']:
|
||||
|
||||
# Mon, 10 Mar 2014 16:26:15 -0700
|
||||
publishedDate = parser.parse(result['publishedDate'])
|
||||
|
||||
results.append({'url': result['unescapedUrl'],
|
||||
'title': result['titleNoFormatting'],
|
||||
'publishedDate': publishedDate,
|
||||
'content': result['content']})
|
||||
return results
|
87
sources/searx/engines/json_engine.py
Normal file
|
@ -0,0 +1,87 @@
|
|||
from urllib import urlencode
|
||||
from json import loads
|
||||
from collections import Iterable
|
||||
|
||||
search_url = None
|
||||
url_query = None
|
||||
content_query = None
|
||||
title_query = None
|
||||
#suggestion_xpath = ''
|
||||
|
||||
|
||||
def iterate(iterable):
|
||||
if type(iterable) == dict:
|
||||
it = iterable.iteritems()
|
||||
|
||||
else:
|
||||
it = enumerate(iterable)
|
||||
for index, value in it:
|
||||
yield str(index), value
|
||||
|
||||
|
||||
def is_iterable(obj):
|
||||
if type(obj) == str:
|
||||
return False
|
||||
if type(obj) == unicode:
|
||||
return False
|
||||
return isinstance(obj, Iterable)
|
||||
|
||||
|
||||
def parse(query):
|
||||
q = []
|
||||
for part in query.split('/'):
|
||||
if part == '':
|
||||
continue
|
||||
else:
|
||||
q.append(part)
|
||||
return q
|
||||
|
||||
|
||||
def do_query(data, q):
|
||||
ret = []
|
||||
if not q:
|
||||
return ret
|
||||
|
||||
qkey = q[0]
|
||||
|
||||
for key, value in iterate(data):
|
||||
|
||||
if len(q) == 1:
|
||||
if key == qkey:
|
||||
ret.append(value)
|
||||
elif is_iterable(value):
|
||||
ret.extend(do_query(value, q))
|
||||
else:
|
||||
if not is_iterable(value):
|
||||
continue
|
||||
if key == qkey:
|
||||
ret.extend(do_query(value, q[1:]))
|
||||
else:
|
||||
ret.extend(do_query(value, q))
|
||||
return ret
|
||||
|
||||
|
||||
def query(data, query_string):
|
||||
q = parse(query_string)
|
||||
|
||||
return do_query(data, q)
|
||||
|
||||
|
||||
def request(query, params):
|
||||
query = urlencode({'q': query})[2:]
|
||||
params['url'] = search_url.format(query=query)
|
||||
params['query'] = query
|
||||
return params
|
||||
|
||||
|
||||
def response(resp):
|
||||
results = []
|
||||
|
||||
json = loads(resp.text)
|
||||
|
||||
urls = query(json, url_query)
|
||||
contents = query(json, content_query)
|
||||
titles = query(json, title_query)
|
||||
for url, title, content in zip(urls, titles, contents):
|
||||
results.append({'url': url, 'title': title, 'content': content})
|
||||
return results
|
22
sources/searx/engines/mediawiki.py
Normal file
|
@ -0,0 +1,22 @@
|
|||
from json import loads
|
||||
from urllib import urlencode, quote
|
||||
|
||||
url = 'https://en.wikipedia.org/'
|
||||
|
||||
search_url = url + 'w/api.php?action=query&list=search&{query}&srprop=timestamp&format=json&sroffset={offset}' # noqa
|
||||
|
||||
number_of_results = 10
|
||||
|
||||
|
||||
def request(query, params):
|
||||
offset = (params['pageno'] - 1) * 10
|
||||
params['url'] = search_url.format(query=urlencode({'srsearch': query}),
|
||||
offset=offset)
|
||||
return params
|
||||
|
||||
|
||||
def response(resp):
|
||||
search_results = loads(resp.text)
|
||||
res = search_results.get('query', {}).get('search', [])
|
||||
return [{'url': url + 'wiki/' + quote(result['title'].replace(' ', '_').encode('utf-8')), # noqa
|
||||
'title': result['title']} for result in res[:int(number_of_results)]]
|
48
sources/searx/engines/piratebay.py
Normal file
|
@ -0,0 +1,48 @@
|
|||
from urlparse import urljoin
|
||||
from cgi import escape
|
||||
from urllib import quote
|
||||
from lxml import html
|
||||
|
||||
categories = ['videos', 'music']
|
||||
|
||||
url = 'https://thepiratebay.se/'
|
||||
search_url = url + 'search/{search_term}/{pageno}/99/{search_type}'
|
||||
search_types = {'videos': '200',
|
||||
'music': '100',
|
||||
'files': '0'}
|
||||
|
||||
magnet_xpath = './/a[@title="Download this torrent using magnet"]'
|
||||
content_xpath = './/font[@class="detDesc"]//text()'
|
||||
|
||||
paging = True
|
||||
|
||||
|
||||
def request(query, params):
|
||||
search_type = search_types.get(params['category'], '200')
|
||||
params['url'] = search_url.format(search_term=quote(query),
|
||||
search_type=search_type,
|
||||
pageno=params['pageno'] - 1)
|
||||
return params
|
||||
|
||||
|
||||
def response(resp):
|
||||
results = []
|
||||
dom = html.fromstring(resp.text)
|
||||
search_res = dom.xpath('//table[@id="searchResult"]//tr')
|
||||
if not search_res:
|
||||
return results
|
||||
for result in search_res[1:]:
|
||||
link = result.xpath('.//div[@class="detName"]//a')[0]
|
||||
href = urljoin(url, link.attrib.get('href'))
|
||||
title = ' '.join(link.xpath('.//text()'))
|
||||
content = escape(' '.join(result.xpath(content_xpath)))
|
||||
seed, leech = result.xpath('.//td[@align="right"]/text()')[:2]
|
||||
magnetlink = result.xpath(magnet_xpath)[0]
|
||||
results.append({'url': href,
|
||||
'title': title,
|
||||
'content': content,
|
||||
'seed': seed,
|
||||
'leech': leech,
|
||||
'magnetlink': magnetlink.attrib['href'],
|
||||
'template': 'torrent.html'})
|
||||
return results
|
31
sources/searx/engines/soundcloud.py
Normal file
|
@ -0,0 +1,31 @@
|
|||
from json import loads
|
||||
from urllib import urlencode
|
||||
|
||||
categories = ['music']
|
||||
|
||||
guest_client_id = 'b45b1aa10f1ac2941910a7f0d10f8e28'
|
||||
url = 'https://api.soundcloud.com/'
|
||||
search_url = url + 'search?{query}&facet=model&limit=20&offset={offset}&linked_partitioning=1&client_id='+guest_client_id # noqa
|
||||
|
||||
paging = True
|
||||
|
||||
|
||||
def request(query, params):
|
||||
offset = (params['pageno'] - 1) * 20
|
||||
params['url'] = search_url.format(query=urlencode({'q': query}),
|
||||
offset=offset)
|
||||
return params
|
||||
|
||||
|
||||
def response(resp):
|
||||
global base_url
|
||||
results = []
|
||||
search_res = loads(resp.text)
|
||||
for result in search_res.get('collection', []):
|
||||
if result['kind'] in ('track', 'playlist'):
|
||||
title = result['title']
|
||||
content = result['description']
|
||||
results.append({'url': result['permalink_url'],
|
||||
'title': title,
|
||||
'content': content})
|
||||
return results
|
30
sources/searx/engines/stackoverflow.py
Normal file
|
@ -0,0 +1,30 @@
|
|||
from urlparse import urljoin
|
||||
from cgi import escape
|
||||
from urllib import urlencode
|
||||
from lxml import html
|
||||
|
||||
categories = ['it']
|
||||
|
||||
url = 'http://stackoverflow.com/'
|
||||
search_url = url+'search?{query}&page={pageno}'
|
||||
result_xpath = './/div[@class="excerpt"]//text()'
|
||||
|
||||
paging = True
|
||||
|
||||
|
||||
def request(query, params):
|
||||
params['url'] = search_url.format(query=urlencode({'q': query}),
|
||||
pageno=params['pageno'])
|
||||
return params
|
||||
|
||||
|
||||
def response(resp):
|
||||
results = []
|
||||
dom = html.fromstring(resp.text)
|
||||
for result in dom.xpath('//div[@class="question-summary search-result"]'):
|
||||
link = result.xpath('.//div[@class="result-link"]//a')[0]
|
||||
href = urljoin(url, link.attrib.get('href'))
|
||||
title = escape(' '.join(link.xpath('.//text()')))
|
||||
content = escape(' '.join(result.xpath(result_xpath)))
|
||||
results.append({'url': href, 'title': title, 'content': content})
|
||||
return results
|
46
sources/searx/engines/startpage.py
Normal file
|
@ -0,0 +1,46 @@
|
|||
from urllib import urlencode
|
||||
from lxml import html
|
||||
|
||||
base_url = None
|
||||
search_url = None
|
||||
|
||||
# TODO paging
|
||||
paging = False
|
||||
# TODO complete list of country mapping
|
||||
country_map = {'en_US': 'eng',
|
||||
'en_UK': 'uk',
|
||||
'nl_NL': 'ned'}
|
||||
|
||||
|
||||
def request(query, params):
|
||||
query = urlencode({'q': query})[2:]
|
||||
params['url'] = search_url
|
||||
params['method'] = 'POST'
|
||||
params['data'] = {'query': query,
|
||||
'startat': (params['pageno'] - 1) * 10} # offset
|
||||
country = country_map.get(params['language'], 'eng')
|
||||
params['cookies']['preferences'] = \
|
||||
'lang_homepageEEEs/air/{country}/N1NsslEEE1N1Nfont_sizeEEEmediumN1Nrecent_results_filterEEE1N1Nlanguage_uiEEEenglishN1Ndisable_open_in_new_windowEEE0N1Ncolor_schemeEEEnewN1Nnum_of_resultsEEE10N1N'.format(country=country) # noqa
|
||||
return params
|
||||
|
||||
|
||||
def response(resp):
|
||||
results = []
|
||||
dom = html.fromstring(resp.content)
|
||||
# ads xpath //div[@id="results"]/div[@id="sponsored"]//div[@class="result"]
|
||||
# not ads: div[@class="result"] are the direct childs of div[@id="results"]
|
||||
for result in dom.xpath('//div[@class="result"]'):
|
||||
link = result.xpath('.//h3/a')[0]
|
||||
url = link.attrib.get('href')
|
||||
if url.startswith('http://www.google.')\
|
||||
or url.startswith('https://www.google.'):
|
||||
continue
|
||||
title = link.text_content()
|
||||
|
||||
content = ''
|
||||
if result.xpath('./p[@class="desc"]'):
|
||||
content = result.xpath('./p[@class="desc"]')[0].text_content()
|
||||
|
||||
results.append({'url': url, 'title': title, 'content': content})
|
||||
|
||||
return results
|
32
sources/searx/engines/twitter.py
Normal file
|
@ -0,0 +1,32 @@
|
|||
from urlparse import urljoin
|
||||
from urllib import urlencode
|
||||
from lxml import html
|
||||
from cgi import escape
|
||||
|
||||
categories = ['social media']
|
||||
|
||||
base_url = 'https://twitter.com/'
|
||||
search_url = base_url+'search?'
|
||||
title_xpath = './/span[@class="username js-action-profile-name"]//text()'
|
||||
content_xpath = './/p[@class="js-tweet-text tweet-text"]//text()'
|
||||
|
||||
|
||||
def request(query, params):
|
||||
global search_url
|
||||
params['url'] = search_url + urlencode({'q': query})
|
||||
return params
|
||||
|
||||
|
||||
def response(resp):
|
||||
global base_url
|
||||
results = []
|
||||
dom = html.fromstring(resp.text)
|
||||
for tweet in dom.xpath('//li[@data-item-type="tweet"]'):
|
||||
link = tweet.xpath('.//small[@class="time"]//a')[0]
|
||||
url = urljoin(base_url, link.attrib.get('href'))
|
||||
title = ''.join(tweet.xpath(title_xpath))
|
||||
content = escape(''.join(tweet.xpath(content_xpath)))
|
||||
results.append({'url': url,
|
||||
'title': title,
|
||||
'content': content})
|
||||
return results
|
54
sources/searx/engines/vimeo.py
Normal file
|
@ -0,0 +1,54 @@
|
|||
from urllib import urlencode
|
||||
from HTMLParser import HTMLParser
|
||||
from lxml import html
|
||||
from searx.engines.xpath import extract_text
|
||||
from dateutil import parser
|
||||
|
||||
base_url = 'http://vimeo.com'
|
||||
search_url = base_url + '/search?{query}'
|
||||
url_xpath = None
|
||||
content_xpath = None
|
||||
title_xpath = None
|
||||
results_xpath = ''
|
||||
content_tpl = '<a href="{0}"> <img src="{2}"/> </a>'
|
||||
publishedDate_xpath = './/p[@class="meta"]//attribute::datetime'
|
||||
|
||||
# the cookie set by vimeo contains all the following values,
|
||||
# but only __utma seems to be requiered
|
||||
cookie = {
|
||||
#'vuid':'918282893.1027205400'
|
||||
# 'ab_bs':'%7B%223%22%3A279%7D'
|
||||
'__utma': '00000000.000#0000000.0000000000.0000000000.0000000000.0'
|
||||
# '__utmb':'18302654.1.10.1388942090'
|
||||
#, '__utmc':'18302654'
|
||||
#, '__utmz':'18#302654.1388942090.1.1.utmcsr=(direct)|utmccn=(direct)|utmcmd=(none)' # noqa
|
||||
#, '__utml':'search'
|
||||
}
|
||||
|
||||
|
||||
def request(query, params):
|
||||
params['url'] = search_url.format(query=urlencode({'q': query}))
|
||||
params['cookies'] = cookie
|
||||
return params
|
||||
|
||||
|
||||
def response(resp):
|
||||
results = []
|
||||
dom = html.fromstring(resp.text)
|
||||
|
||||
p = HTMLParser()
|
||||
|
||||
for result in dom.xpath(results_xpath):
|
||||
url = base_url + result.xpath(url_xpath)[0]
|
||||
title = p.unescape(extract_text(result.xpath(title_xpath)))
|
||||
thumbnail = extract_text(result.xpath(content_xpath)[0])
|
||||
publishedDate = parser.parse(extract_text(
|
||||
result.xpath(publishedDate_xpath)[0]))
|
||||
|
||||
results.append({'url': url,
|
||||
'title': title,
|
||||
'content': content_tpl.format(url, title, thumbnail),
|
||||
'template': 'videos.html',
|
||||
'publishedDate': publishedDate,
|
||||
'thumbnail': thumbnail})
|
||||
return results
|
30
sources/searx/engines/wikipedia.py
Normal file
|
@ -0,0 +1,30 @@
|
|||
from json import loads
|
||||
from urllib import urlencode, quote
|
||||
|
||||
url = 'https://{language}.wikipedia.org/'
|
||||
|
||||
search_url = url + 'w/api.php?action=query&list=search&{query}&srprop=timestamp&format=json&sroffset={offset}' # noqa
|
||||
|
||||
number_of_results = 10
|
||||
|
||||
language_support = True
|
||||
|
||||
|
||||
def request(query, params):
|
||||
offset = (params['pageno'] - 1) * 10
|
||||
if params['language'] == 'all':
|
||||
language = 'en'
|
||||
else:
|
||||
language = params['language'].split('_')[0]
|
||||
params['language'] = language
|
||||
params['url'] = search_url.format(query=urlencode({'srsearch': query}),
|
||||
offset=offset,
|
||||
language=language)
|
||||
return params
|
||||
|
||||
|
||||
def response(resp):
|
||||
search_results = loads(resp.text)
|
||||
res = search_results.get('query', {}).get('search', [])
|
||||
return [{'url': url.format(language=resp.search_params['language']) + 'wiki/' + quote(result['title'].replace(' ', '_').encode('utf-8')), # noqa
|
||||
'title': result['title']} for result in res[:int(number_of_results)]]
|
106
sources/searx/engines/xpath.py
Normal file
|
@ -0,0 +1,106 @@
|
|||
from lxml import html
|
||||
from urllib import urlencode, unquote
|
||||
from urlparse import urlparse, urljoin
|
||||
from lxml.etree import _ElementStringResult, _ElementUnicodeResult
|
||||
from searx.utils import html_to_text
|
||||
|
||||
search_url = None
|
||||
url_xpath = None
|
||||
content_xpath = None
|
||||
title_xpath = None
|
||||
suggestion_xpath = ''
|
||||
results_xpath = ''
|
||||
|
||||
|
||||
'''
|
||||
if xpath_results is list, extract the text from each result and concat the list
|
||||
if xpath_results is a xml element, extract all the text node from it
|
||||
( text_content() method from lxml )
|
||||
if xpath_results is a string element, then it's already done
|
||||
'''
|
||||
|
||||
|
||||
def extract_text(xpath_results):
|
||||
if type(xpath_results) == list:
|
||||
# it's list of result : concat everything using recursive call
|
||||
if not xpath_results:
|
||||
raise Exception('Empty url resultset')
|
||||
result = ''
|
||||
for e in xpath_results:
|
||||
result = result + extract_text(e)
|
||||
return result
|
||||
elif type(xpath_results) in [_ElementStringResult, _ElementUnicodeResult]:
|
||||
# it's a string
|
||||
return ''.join(xpath_results)
|
||||
else:
|
||||
# it's a element
|
||||
return html_to_text(xpath_results.text_content())
|
||||
|
||||
|
||||
def extract_url(xpath_results, search_url):
|
||||
url = extract_text(xpath_results)
|
||||
|
||||
if url.startswith('//'):
|
||||
# add http or https to this kind of url //example.com/
|
||||
parsed_search_url = urlparse(search_url)
|
||||
url = parsed_search_url.scheme+url
|
||||
elif url.startswith('/'):
|
||||
# fix relative url to the search engine
|
||||
url = urljoin(search_url, url)
|
||||
|
||||
# normalize url
|
||||
url = normalize_url(url)
|
||||
|
||||
return url
|
||||
|
||||
|
||||
def normalize_url(url):
|
||||
parsed_url = urlparse(url)
|
||||
|
||||
# add a / at this end of the url if there is no path
|
||||
if not parsed_url.netloc:
|
||||
raise Exception('Cannot parse url')
|
||||
if not parsed_url.path:
|
||||
url += '/'
|
||||
|
||||
# FIXME : hack for yahoo
|
||||
if parsed_url.hostname == 'search.yahoo.com'\
|
||||
and parsed_url.path.startswith('/r'):
|
||||
p = parsed_url.path
|
||||
mark = p.find('/**')
|
||||
if mark != -1:
|
||||
return unquote(p[mark+3:]).decode('utf-8')
|
||||
|
||||
return url
|
||||
|
||||
|
||||
def request(query, params):
|
||||
query = urlencode({'q': query})[2:]
|
||||
params['url'] = search_url.format(query=query)
|
||||
params['query'] = query
|
||||
return params
|
||||
|
||||
|
||||
def response(resp):
|
||||
results = []
|
||||
dom = html.fromstring(resp.text)
|
||||
if results_xpath:
|
||||
for result in dom.xpath(results_xpath):
|
||||
url = extract_url(result.xpath(url_xpath), search_url)
|
||||
title = extract_text(result.xpath(title_xpath)[0])
|
||||
content = extract_text(result.xpath(content_xpath)[0])
|
||||
results.append({'url': url, 'title': title, 'content': content})
|
||||
else:
|
||||
for url, title, content in zip(
|
||||
(extract_url(x, search_url) for
|
||||
x in dom.xpath(url_xpath)),
|
||||
map(extract_text, dom.xpath(title_xpath)),
|
||||
map(extract_text, dom.xpath(content_xpath))
|
||||
):
|
||||
results.append({'url': url, 'title': title, 'content': content})
|
||||
|
||||
if not suggestion_xpath:
|
||||
return results
|
||||
for suggestion in dom.xpath(suggestion_xpath):
|
||||
results.append({'suggestion': extract_text(suggestion)})
|
||||
return results
|
40
sources/searx/engines/yacy.py
Normal file
|
@ -0,0 +1,40 @@
|
|||
from json import loads
|
||||
from urllib import urlencode
|
||||
|
||||
url = 'http://localhost:8090'
|
||||
search_url = '/yacysearch.json?{query}&maximumRecords=10'
|
||||
|
||||
|
||||
def request(query, params):
|
||||
params['url'] = url + search_url.format(query=urlencode({'query': query}))
|
||||
return params
|
||||
|
||||
|
||||
def response(resp):
|
||||
raw_search_results = loads(resp.text)
|
||||
|
||||
if not raw_search_results:
|
||||
return []
|
||||
|
||||
search_results = raw_search_results.get('channels', {})[0].get('items', [])
|
||||
|
||||
results = []
|
||||
|
||||
for result in search_results:
|
||||
tmp_result = {}
|
||||
tmp_result['title'] = result['title']
|
||||
tmp_result['url'] = result['link']
|
||||
tmp_result['content'] = ''
|
||||
|
||||
if result['description']:
|
||||
tmp_result['content'] += result['description'] + "<br/>"
|
||||
|
||||
if result['pubDate']:
|
||||
tmp_result['content'] += result['pubDate'] + "<br/>"
|
||||
|
||||
if result['size'] != '-1':
|
||||
tmp_result['content'] += result['sizename']
|
||||
|
||||
results.append(tmp_result)
|
||||
|
||||
return results
|
64
sources/searx/engines/yahoo.py
Normal file
|
@ -0,0 +1,64 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
from urllib import urlencode
|
||||
from urlparse import unquote
|
||||
from lxml import html
|
||||
from searx.engines.xpath import extract_text, extract_url
|
||||
|
||||
categories = ['general']
|
||||
search_url = 'http://search.yahoo.com/search?{query}&b={offset}'
|
||||
results_xpath = '//div[@class="res"]'
|
||||
url_xpath = './/h3/a/@href'
|
||||
title_xpath = './/h3/a'
|
||||
content_xpath = './/div[@class="abstr"]'
|
||||
suggestion_xpath = '//div[@id="satat"]//a'
|
||||
|
||||
paging = True
|
||||
|
||||
|
||||
def parse_url(url_string):
|
||||
endings = ['/RS', '/RK']
|
||||
endpositions = []
|
||||
start = url_string.find('http', url_string.find('/RU=')+1)
|
||||
for ending in endings:
|
||||
endpos = url_string.rfind(ending)
|
||||
if endpos > -1:
|
||||
endpositions.append(endpos)
|
||||
|
||||
end = min(endpositions)
|
||||
return unquote(url_string[start:end])
|
||||
|
||||
|
||||
def request(query, params):
|
||||
offset = (params['pageno'] - 1) * 10 + 1
|
||||
if params['language'] == 'all':
|
||||
language = 'en'
|
||||
else:
|
||||
language = params['language'].split('_')[0]
|
||||
params['url'] = search_url.format(offset=offset,
|
||||
query=urlencode({'p': query}))
|
||||
params['cookies']['sB'] = 'fl=1&vl=lang_{lang}&sh=1&rw=new&v=1'\
|
||||
.format(lang=language)
|
||||
return params
|
||||
|
||||
|
||||
def response(resp):
|
||||
results = []
|
||||
dom = html.fromstring(resp.text)
|
||||
|
||||
for result in dom.xpath(results_xpath):
|
||||
try:
|
||||
url = parse_url(extract_url(result.xpath(url_xpath), search_url))
|
||||
title = extract_text(result.xpath(title_xpath)[0])
|
||||
except:
|
||||
continue
|
||||
content = extract_text(result.xpath(content_xpath)[0])
|
||||
results.append({'url': url, 'title': title, 'content': content})
|
||||
|
||||
if not suggestion_xpath:
|
||||
return results
|
||||
|
||||
for suggestion in dom.xpath(suggestion_xpath):
|
||||
results.append({'suggestion': extract_text(suggestion)})
|
||||
|
||||
return results
|
72
sources/searx/engines/yahoo_news.py
Normal file
|
@ -0,0 +1,72 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
from urllib import urlencode
|
||||
from lxml import html
|
||||
from searx.engines.xpath import extract_text, extract_url
|
||||
from searx.engines.yahoo import parse_url
|
||||
from datetime import datetime, timedelta
|
||||
import re
|
||||
from dateutil import parser
|
||||
|
||||
categories = ['news']
|
||||
search_url = 'http://news.search.yahoo.com/search?{query}&b={offset}'
|
||||
results_xpath = '//div[@class="res"]'
|
||||
url_xpath = './/h3/a/@href'
|
||||
title_xpath = './/h3/a'
|
||||
content_xpath = './/div[@class="abstr"]'
|
||||
publishedDate_xpath = './/span[@class="timestamp"]'
|
||||
suggestion_xpath = '//div[@id="satat"]//a'
|
||||
|
||||
paging = True
|
||||
|
||||
|
||||
def request(query, params):
|
||||
offset = (params['pageno'] - 1) * 10 + 1
|
||||
if params['language'] == 'all':
|
||||
language = 'en'
|
||||
else:
|
||||
language = params['language'].split('_')[0]
|
||||
params['url'] = search_url.format(offset=offset,
|
||||
query=urlencode({'p': query}))
|
||||
params['cookies']['sB'] = 'fl=1&vl=lang_{lang}&sh=1&rw=new&v=1'\
|
||||
.format(lang=language)
|
||||
return params
|
||||
|
||||
|
||||
def response(resp):
|
||||
results = []
|
||||
dom = html.fromstring(resp.text)
|
||||
|
||||
for result in dom.xpath(results_xpath):
|
||||
url = parse_url(extract_url(result.xpath(url_xpath), search_url))
|
||||
title = extract_text(result.xpath(title_xpath)[0])
|
||||
content = extract_text(result.xpath(content_xpath)[0])
|
||||
publishedDate = extract_text(result.xpath(publishedDate_xpath)[0])
|
||||
|
||||
if re.match("^[0-9]+ minute(s|) ago$", publishedDate):
|
||||
publishedDate = datetime.now() - timedelta(minutes=int(re.match(r'\d+', publishedDate).group())) # noqa
|
||||
else:
|
||||
if re.match("^[0-9]+ hour(s|), [0-9]+ minute(s|) ago$",
|
||||
publishedDate):
|
||||
timeNumbers = re.findall(r'\d+', publishedDate)
|
||||
publishedDate = datetime.now()\
|
||||
- timedelta(hours=int(timeNumbers[0]))\
|
||||
- timedelta(minutes=int(timeNumbers[1]))
|
||||
else:
|
||||
publishedDate = parser.parse(publishedDate)
|
||||
|
||||
if publishedDate.year == 1900:
|
||||
publishedDate = publishedDate.replace(year=datetime.now().year)
|
||||
|
||||
results.append({'url': url,
|
||||
'title': title,
|
||||
'content': content,
|
||||
'publishedDate': publishedDate})
|
||||
|
||||
if not suggestion_xpath:
|
||||
return results
|
||||
|
||||
for suggestion in dom.xpath(suggestion_xpath):
|
||||
results.append({'suggestion': extract_text(suggestion)})
|
||||
|
||||
return results
|
59
sources/searx/engines/youtube.py
Normal file
|
@ -0,0 +1,59 @@
|
|||
from json import loads
|
||||
from urllib import urlencode
|
||||
from dateutil import parser
|
||||
|
||||
categories = ['videos']
|
||||
|
||||
search_url = ('https://gdata.youtube.com/feeds/api/videos'
|
||||
'?alt=json&{query}&start-index={index}&max-results=25') # noqa
|
||||
|
||||
paging = True
|
||||
|
||||
|
||||
def request(query, params):
|
||||
index = (params['pageno'] - 1) * 25 + 1
|
||||
params['url'] = search_url.format(query=urlencode({'q': query}),
|
||||
index=index)
|
||||
return params
|
||||
|
||||
|
||||
def response(resp):
|
||||
results = []
|
||||
search_results = loads(resp.text)
|
||||
if not 'feed' in search_results:
|
||||
return results
|
||||
feed = search_results['feed']
|
||||
|
||||
for result in feed['entry']:
|
||||
url = [x['href'] for x in result['link'] if x['type'] == 'text/html']
|
||||
if not url:
|
||||
return
|
||||
# remove tracking
|
||||
url = url[0].replace('feature=youtube_gdata', '')
|
||||
if url.endswith('&'):
|
||||
url = url[:-1]
|
||||
title = result['title']['$t']
|
||||
content = ''
|
||||
thumbnail = ''
|
||||
|
||||
#"2013-12-31T15:22:51.000Z"
|
||||
pubdate = result['published']['$t']
|
||||
publishedDate = parser.parse(pubdate)
|
||||
|
||||
if result['media$group']['media$thumbnail']:
|
||||
thumbnail = result['media$group']['media$thumbnail'][0]['url']
|
||||
content += '<a href="{0}" title="{0}" ><img src="{1}" /></a>'.format(url, thumbnail) # noqa
|
||||
|
||||
if content:
|
||||
content += '<br />' + result['content']['$t']
|
||||
else:
|
||||
content = result['content']['$t']
|
||||
|
||||
results.append({'url': url,
|
||||
'title': title,
|
||||
'content': content,
|
||||
'template': 'videos.html',
|
||||
'publishedDate': publishedDate,
|
||||
'thumbnail': thumbnail})
|
||||
|
||||
return results
|
59
sources/searx/languages.py
Normal file
|
@ -0,0 +1,59 @@
|
|||
language_codes = (
|
||||
("ar_XA", "Arabic", "Arabia"),
|
||||
("bg_BG", "Bulgarian", "Bulgaria"),
|
||||
("cs_CZ", "Czech", "Czech Republic"),
|
||||
("de_DE", "German", "Germany"),
|
||||
("da_DK", "Danish", "Denmark"),
|
||||
("de_AT", "German", "Austria"),
|
||||
("de_CH", "German", "Switzerland"),
|
||||
("el_GR", "Greek", "Greece"),
|
||||
("en_AU", "English", "Australia"),
|
||||
("en_CA", "English", "Canada"),
|
||||
("en_GB", "English", "United Kingdom"),
|
||||
("en_ID", "English", "Indonesia"),
|
||||
("en_IE", "English", "Ireland"),
|
||||
("en_IN", "English", "India"),
|
||||
("en_MY", "English", "Malaysia"),
|
||||
("en_NZ", "English", "New Zealand"),
|
||||
("en_PH", "English", "Philippines"),
|
||||
("en_SG", "English", "Singapore"),
|
||||
("en_US", "English", "United States"),
|
||||
("en_XA", "English", "Arabia"),
|
||||
("en_ZA", "English", "South Africa"),
|
||||
("es_AR", "Spanish", "Argentina"),
|
||||
("es_CL", "Spanish", "Chile"),
|
||||
("es_ES", "Spanish", "Spain"),
|
||||
("es_MX", "Spanish", "Mexico"),
|
||||
("es_US", "Spanish", "United States"),
|
||||
("es_XL", "Spanish", "Latin America"),
|
||||
("et_EE", "Estonian", "Estonia"),
|
||||
("fi_FI", "Finnish", "Finland"),
|
||||
("fr_BE", "French", "Belgium"),
|
||||
("fr_CA", "French", "Canada"),
|
||||
("fr_CH", "French", "Switzerland"),
|
||||
("fr_FR", "French", "France"),
|
||||
("he_IL", "Hebrew", "Israel"),
|
||||
("hr_HR", "Croatian", "Croatia"),
|
||||
("hu_HU", "Hungarian", "Hungary"),
|
||||
("it_IT", "Italian", "Italy"),
|
||||
("ja_JP", "Japanese", "Japan"),
|
||||
("ko_KR", "Korean", "Korea"),
|
||||
("lt_LT", "Lithuanian", "Lithuania"),
|
||||
("lv_LV", "Latvian", "Latvia"),
|
||||
("nb_NO", "Norwegian", "Norway"),
|
||||
("nl_BE", "Dutch", "Belgium"),
|
||||
("nl_NL", "Dutch", "Netherlands"),
|
||||
("pl_PL", "Polish", "Poland"),
|
||||
("pt_BR", "Portuguese", "Brazil"),
|
||||
("pt_PT", "Portuguese", "Portugal"),
|
||||
("ro_RO", "Romanian", "Romania"),
|
||||
("ru_RU", "Russian", "Russia"),
|
||||
("sk_SK", "Slovak", "Slovak Republic"),
|
||||
("sl_SL", "Slovenian", "Slovenia"),
|
||||
("sv_SE", "Swedish", "Sweden"),
|
||||
("th_TH", "Thai", "Thailand"),
|
||||
("tr_TR", "Turkish", "Turkey"),
|
||||
("uk_UA", "Ukrainian", "Ukraine"),
|
||||
("zh_CN", "Chinese", "China"),
|
||||
("zh_HK", "Chinese", "Hong Kong SAR"),
|
||||
("zh_TW", "Chinese", "Taiwan"))
|
114
sources/searx/search.py
Normal file
|
@ -0,0 +1,114 @@
|
|||
from searx.engines import (
|
||||
categories, engines, engine_shortcuts
|
||||
)
|
||||
from searx.languages import language_codes
|
||||
|
||||
|
||||
class Search(object):
|
||||
|
||||
"""Search information container"""
|
||||
|
||||
def __init__(self, request):
|
||||
super(Search, self).__init__()
|
||||
self.query = None
|
||||
self.engines = []
|
||||
self.categories = []
|
||||
self.paging = False
|
||||
self.pageno = 1
|
||||
self.lang = 'all'
|
||||
if request.cookies.get('blocked_engines'):
|
||||
self.blocked_engines = request.cookies['blocked_engines'].split(',') # noqa
|
||||
else:
|
||||
self.blocked_engines = []
|
||||
self.results = []
|
||||
self.suggestions = []
|
||||
self.request_data = {}
|
||||
|
||||
if request.cookies.get('language')\
|
||||
and request.cookies['language'] in (x[0] for x in language_codes):
|
||||
self.lang = request.cookies['language']
|
||||
|
||||
if request.method == 'POST':
|
||||
self.request_data = request.form
|
||||
else:
|
||||
self.request_data = request.args
|
||||
|
||||
# TODO better exceptions
|
||||
if not self.request_data.get('q'):
|
||||
raise Exception('noquery')
|
||||
|
||||
self.query = self.request_data['q']
|
||||
|
||||
pageno_param = self.request_data.get('pageno', '1')
|
||||
if not pageno_param.isdigit() or int(pageno_param) < 1:
|
||||
raise Exception('wrong pagenumber')
|
||||
|
||||
self.pageno = int(pageno_param)
|
||||
|
||||
self.parse_query()
|
||||
|
||||
self.categories = []
|
||||
|
||||
if self.engines:
|
||||
self.categories = list(set(engine['category']
|
||||
for engine in self.engines))
|
||||
else:
|
||||
for pd_name, pd in self.request_data.items():
|
||||
if pd_name.startswith('category_'):
|
||||
category = pd_name[9:]
|
||||
if not category in categories:
|
||||
continue
|
||||
self.categories.append(category)
|
||||
if not self.categories:
|
||||
cookie_categories = request.cookies.get('categories', '')
|
||||
cookie_categories = cookie_categories.split(',')
|
||||
for ccateg in cookie_categories:
|
||||
if ccateg in categories:
|
||||
self.categories.append(ccateg)
|
||||
if not self.categories:
|
||||
self.categories = ['general']
|
||||
|
||||
for categ in self.categories:
|
||||
self.engines.extend({'category': categ,
|
||||
'name': x.name}
|
||||
for x in categories[categ]
|
||||
if not x.name in self.blocked_engines)
|
||||
|
||||
def parse_query(self):
|
||||
query_parts = self.query.split()
|
||||
modified = False
|
||||
if query_parts[0].startswith(':'):
|
||||
lang = query_parts[0][1:].lower()
|
||||
|
||||
for lc in language_codes:
|
||||
lang_id, lang_name, country = map(str.lower, lc)
|
||||
if lang == lang_id\
|
||||
or lang_id.startswith(lang)\
|
||||
or lang == lang_name\
|
||||
or lang == country:
|
||||
self.lang = lang
|
||||
modified = True
|
||||
break
|
||||
|
||||
elif query_parts[0].startswith('!'):
|
||||
prefix = query_parts[0][1:].replace('_', ' ')
|
||||
|
||||
if prefix in engine_shortcuts\
|
||||
and not engine_shortcuts[prefix] in self.blocked_engines:
|
||||
modified = True
|
||||
self.engines.append({'category': 'none',
|
||||
'name': engine_shortcuts[prefix]})
|
||||
elif prefix in engines\
|
||||
and not prefix in self.blocked_engines:
|
||||
modified = True
|
||||
self.engines.append({'category': 'none',
|
||||
'name': prefix})
|
||||
elif prefix in categories:
|
||||
modified = True
|
||||
self.engines.extend({'category': prefix,
|
||||
'name': engine.name}
|
||||
for engine in categories[prefix]
|
||||
if not engine in self.blocked_engines)
|
||||
if modified:
|
||||
self.query = self.query.replace(query_parts[0], '', 1).strip()
|
||||
self.parse_query()
|
156
sources/searx/settings.yml
Normal file
|
@ -0,0 +1,156 @@
|
|||
server:
|
||||
port : 8888
|
||||
secret_key : "ultrasecretkey" # change this!
|
||||
debug : True
|
||||
request_timeout : 2.0 # seconds
|
||||
base_url : False
|
||||
|
||||
engines:
|
||||
- name : wikipedia
|
||||
engine : wikipedia
|
||||
number_of_results : 1
|
||||
paging : False
|
||||
shortcut : wp
|
||||
|
||||
- name : bing
|
||||
engine : bing
|
||||
locale : en-US
|
||||
shortcut : bi
|
||||
|
||||
- name : bing news
|
||||
engine : bing_news
|
||||
locale : en-US
|
||||
shortcut : bin
|
||||
|
||||
- name : currency
|
||||
engine : currency_convert
|
||||
categories : general
|
||||
shortcut : cc
|
||||
|
||||
- name : deviantart
|
||||
engine : deviantart
|
||||
categories : images
|
||||
shortcut : da
|
||||
timeout: 3.0
|
||||
|
||||
- name : ddg definitions
|
||||
engine : duckduckgo_definitions
|
||||
shortcut : ddd
|
||||
|
||||
- name : duckduckgo
|
||||
engine : duckduckgo
|
||||
locale : en-us
|
||||
shortcut : ddg
|
||||
|
||||
- name : filecrop
|
||||
engine : filecrop
|
||||
categories : files
|
||||
shortcut : fc
|
||||
|
||||
- name : flickr
|
||||
engine : flickr
|
||||
categories : images
|
||||
shortcut : fl
|
||||
timeout: 3.0
|
||||
|
||||
- name : github
|
||||
engine : github
|
||||
categories : it
|
||||
shortcut : gh
|
||||
|
||||
- name : google
|
||||
engine : google
|
||||
shortcut : go
|
||||
|
||||
- name : google images
|
||||
engine : google_images
|
||||
shortcut : goi
|
||||
|
||||
- name : google news
|
||||
engine : google_news
|
||||
shortcut : gon
|
||||
|
||||
- name : piratebay
|
||||
engine : piratebay
|
||||
categories : videos, music, files
|
||||
shortcut : tpb
|
||||
|
||||
- name : soundcloud
|
||||
engine : soundcloud
|
||||
categories : music
|
||||
shortcut : sc
|
||||
|
||||
- name : stackoverflow
|
||||
engine : stackoverflow
|
||||
categories : it
|
||||
shortcut : st
|
||||
|
||||
- name : startpage
|
||||
engine : startpage
|
||||
base_url : 'https://startpage.com/'
|
||||
search_url : 'https://startpage.com/do/search'
|
||||
shortcut : sp
|
||||
|
||||
# +30% page load time
|
||||
# - name : ixquick
|
||||
# engine : startpage
|
||||
# base_url : 'https://www.ixquick.com/'
|
||||
# search_url : 'https://www.ixquick.com/do/search'
|
||||
|
||||
- name : twitter
|
||||
engine : twitter
|
||||
categories : social media
|
||||
shortcut : tw
|
||||
|
||||
# maybe in a fun category
|
||||
# - name : uncyclopedia
|
||||
# engine : mediawiki
|
||||
# categories : general
|
||||
# shortcut : unc
|
||||
# url : https://uncyclopedia.wikia.com/
|
||||
|
||||
# tmp suspended - too slow, too many errors
|
||||
# - name : urbandictionary
|
||||
# engine : xpath
|
||||
# search_url : http://www.urbandictionary.com/define.php?term={query}
|
||||
# url_xpath : //div[@class="word"]//a/@href
|
||||
# title_xpath : //div[@class="word"]//a
|
||||
# content_xpath : //div[@class="definition"]
|
||||
# shortcut : ud
|
||||
|
||||
- name : yahoo
|
||||
engine : yahoo
|
||||
shortcut : yh
|
||||
|
||||
- name : yahoo news
|
||||
engine : yahoo_news
|
||||
shortcut : yhn
|
||||
|
||||
- name : youtube
|
||||
engine : youtube
|
||||
categories : videos
|
||||
shortcut : yt
|
||||
|
||||
- name : dailymotion
|
||||
engine : dailymotion
|
||||
locale : en_US
|
||||
categories : videos
|
||||
shortcut : dm
|
||||
|
||||
- name : vimeo
|
||||
engine : vimeo
|
||||
categories : videos
|
||||
results_xpath : //div[@id="browse_content"]/ol/li
|
||||
url_xpath : ./a/@href
|
||||
title_xpath : ./a/div[@class="data"]/p[@class="title"]/text()
|
||||
content_xpath : ./a/img/@src
|
||||
shortcut : vm
|
||||
|
||||
locales:
|
||||
en : English
|
||||
de : Deutsch
|
||||
hu : Magyar
|
||||
fr : Français
|
||||
es : Español
|
||||
it : Italiano
|
||||
nl : Nederlands
|
19
sources/searx/settings_robot.yml
Normal file
|
@ -0,0 +1,19 @@
|
|||
server:
|
||||
port : 11111
|
||||
secret_key : "ultrasecretkey" # change this!
|
||||
debug : False
|
||||
request_timeout : 3.0 # seconds
|
||||
base_url: False
|
||||
|
||||
engines:
|
||||
- name : general_dummy
|
||||
engine : dummy
|
||||
categories : general
|
||||
|
||||
- name : dummy_dummy
|
||||
engine : dummy
|
||||
categories : dummy
|
||||
|
||||
locales:
|
||||
en : English
|
||||
hu : Magyar
|
74
sources/searx/static/css/style.css
Normal file
|
@ -0,0 +1,74 @@
|
|||
html{font-family:sans-serif;font-size:.9em;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%;-moz-text-size-adjust:100%;text-size-adjust:100%;color:#444;padding:0;margin:0}
|
||||
body,#container{padding:0;margin:0}
|
||||
#container{width:100%;position:absolute;top:0}
|
||||
.search{padding:0;margin:0}.search .checkbox_container label{font-size:.9em;border-bottom:2px solid #e8e7e6}
|
||||
.search .checkbox_container label:hover{border-bottom:2px solid #3498db}
|
||||
.search .checkbox_container input[type="checkbox"]:checked+label{border-bottom:2px solid #2980b9}
|
||||
#search_wrapper{position:relative;width:50em;padding:10px}
|
||||
.center #search_wrapper{margin-left:auto;margin-right:auto}
|
||||
.q{background:none repeat scroll 0 0 #fff;border:1px solid #3498db;color:#222;font-size:16px;height:28px;margin:0;outline:medium none;padding:2px;padding-left:8px;padding-right:0 !important;width:100%;z-index:2}
|
||||
#search_submit{position:absolute;top:13px;right:1px;padding:0;border:0;background:url('../img/search-icon.png') no-repeat;background-size:24px 24px;opacity:.8;width:24px;height:30px;font-size:0}
|
||||
@media screen and (max-width:50em){#search_wrapper{width:90%;clear:both;overflow:hidden}}ul.autocompleter-choices{position:absolute;margin:0;padding:0;list-style:none;border:1px solid #3498db;border-left-color:#3498db;border-right-color:#3498db;border-bottom-color:#3498db;text-align:left;font-family:Verdana,Geneva,Arial,Helvetica,sans-serif;z-index:50;background-color:#fff;color:#444}ul.autocompleter-choices li{position:relative;margin:-2px 0 0 0;padding:.2em 1.5em .2em 1em;display:block;float:none !important;cursor:pointer;font-weight:normal;white-space:nowrap;font-size:1em;line-height:1.5em}ul.autocompleter-choices li.autocompleter-selected{background-color:#444;color:#fff}ul.autocompleter-choices li.autocompleter-selected span.autocompleter-queried{color:#9fcfff}
|
||||
ul.autocompleter-choices span.autocompleter-queried{display:inline;float:none;font-weight:bold;margin:0;padding:0}
|
||||
.row{max-width:800px;margin:20px auto;text-align:justify}.row h1{font-size:3em;margin-top:50px}
|
||||
.row p{padding:0 10px;max-width:700px}
|
||||
.row h3,.row ul{margin:4px 8px}
|
||||
.hmarg{margin:0 20px;border:1px solid #3498db;padding:4px 10px}
|
||||
a:link.hmarg{color:#3498db}
|
||||
a:visited.hmarg{color:#3498db}
|
||||
a:active.hmarg{color:#3498db}
|
||||
a:hover.hmarg{color:#3498db}
|
||||
.top_margin{margin-top:60px}
|
||||
.center{text-align:center}
|
||||
h1{font-size:5em}
|
||||
div.title{background:url('../img/searx.png') no-repeat;width:100%;background-position:center}div.title h1{visibility:hidden}
|
||||
input[type="submit"]{padding:2px 6px;margin:2px 4px;display:inline-block;background:#3498db;color:#fff;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;border:0;cursor:pointer}
|
||||
input[type="checkbox"]{visibility:hidden}
|
||||
fieldset{margin:8px;border:1px solid #3498db}
|
||||
#categories{margin:0 10px}
|
||||
.checkbox_container{display:inline-block;position:relative;margin:0 3px;padding:0}.checkbox_container input{display:none}
|
||||
.checkbox_container label,.engine_checkbox label{cursor:pointer;padding:4px 10px;margin:0;display:block;text-transform:capitalize;-webkit-touch-callout:none;-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}
|
||||
.checkbox_container input[type="checkbox"]:checked+label{background:#3498db;color:#fff}
|
||||
.engine_checkbox{padding:4px}
|
||||
label.allow{background:#e74c3c;padding:4px 8px;color:#fff;display:none}
|
||||
label.deny{background:#2ecc71;padding:4px 8px;color:#444;display:inline}
|
||||
.engine_checkbox input[type="checkbox"]:checked+label:nth-child(2)+label{display:none}
|
||||
.engine_checkbox input[type="checkbox"]:checked+label.allow{display:inline}
|
||||
a{text-decoration:none;color:#1a11be}a:visited{color:#8e44ad}
|
||||
.result{margin:19px 0 18px 0;padding:0;clear:both}
|
||||
.result_title{margin-bottom:0}.result_title a{color:#2980b9;font-weight:normal;font-size:1.1em}.result_title a:hover{text-decoration:underline}
|
||||
.result_title a:visited{color:#8e44ad}
|
||||
.result h3{font-size:1em;word-wrap:break-word;margin:5px 0 1px 0;padding:0}
|
||||
.result .content{font-size:.8em;margin:0;padding:0;max-width:54em;word-wrap:break-word;line-height:1.24}
|
||||
.result .url{font-size:.8em;margin:3px 0 0 0;padding:0;max-width:54em;word-wrap:break-word;color:#c0392b}
|
||||
.result .published_date{font-size:.8em;color:#888;margin:5px 20px}
|
||||
.engines{color:#888}
|
||||
.small_font{font-size:.8em}
|
||||
.small p{margin:2px 0}
|
||||
.right{float:right}
|
||||
.invisible{display:none}
|
||||
.left{float:left}
|
||||
.highlight{color:#094089}
|
||||
.content .highlight{color:#000}
|
||||
.image_result{float:left;margin:10px 10px;position:relative;height:160px}.image_result img{border:0;height:160px}
|
||||
.image_result p{margin:0;padding:0}.image_result p span a{display:none;color:#fff}
|
||||
.image_result p:hover span a{display:block;position:absolute;bottom:0;right:0;padding:4px;background-color:rgba(0,0,0,0.6);font-size:.7em}
|
||||
.torrent_result{border-left:10px solid #d3d3d3;padding-left:3px}.torrent_result p{margin:3px;font-size:.8em}
|
||||
.definition_result{border-left:10px solid #808080;padding-left:3px}
|
||||
.percentage{position:relative;width:300px}.percentage div{background:#444}
|
||||
table{width:100%}
|
||||
td{padding:0 4px}
|
||||
tr:hover{background:#ddd}
|
||||
#results{margin:auto;padding:0;width:50em;margin-bottom:20px}
|
||||
#sidebar{position:absolute;top:100px;right:10px;margin:0 2px 5px 5px;padding:0 2px 2px 2px;width:14em}#sidebar input{padding:0;margin:3px;font-size:.8em;display:inline-block;background:transparent;color:#444;cursor:pointer}
|
||||
#sidebar input[type="submit"]{text-decoration:underline}
|
||||
#suggestions{margin-top:20px}#suggestions span{display:inline;margin:0 2px 2px 2px;padding:0}
|
||||
#suggestions input{padding:0;margin:3px;font-size:.8em;display:inline-block;background:transparent;color:#444;cursor:pointer}
|
||||
#suggestions input[type="submit"]{text-decoration:underline}
|
||||
#suggestions form{display:inline}
|
||||
#search_url{margin-top:8px}#search_url input{border:1px solid #888;padding:4px;color:#444;width:14em;display:block;margin:4px;font-size:.8em}
|
||||
#preferences{top:10px;padding:0;border:0;background:url('../img/preference-icon.png') no-repeat;background-size:28px 28px;opacity:.8;width:28px;height:30px;display:block}#preferences *{display:none}
|
||||
#pagination{clear:both;width:40em}
|
||||
#apis{margin-top:8px;clear:both}
|
||||
@media screen and (max-width:50em){#categories{font-size:90%;clear:both}#categories .checkbox_container{margin-top:2px;margin:auto} #results{margin:auto;padding:0;width:90%} .checkbox_container{display:block;width:90%}.checkbox_container label{border-bottom:0}}@media screen and (max-width:70em){.right{display:none;postion:fixed !important;top:100px;right:0} #sidebar{position:static;max-width:50em;margin:0 0 2px 0;padding:0;float:none;border:none;width:auto}#sidebar input{border:0} #apis{display:none} #search_url{display:none} .result{border-top:1px solid #e8e7e6;margin:7px 0 6px 0}.result img{max-width:90%;width:auto;height:auto}}.favicon{float:left;margin-right:4px;margin-top:2px}
|
||||
.preferences_back{background:none repeat scroll 0 0 #3498db;border:0 none;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;cursor:pointer;display:inline-block;margin:2px 4px;padding:4px 6px}.preferences_back a{color:#fff}
|
BIN
sources/searx/static/img/favicon.png
Normal file
After Width: | Height: | Size: 3.1 KiB |
BIN
sources/searx/static/img/github_ribbon.png
Normal file
After Width: | Height: | Size: 7.6 KiB |
BIN
sources/searx/static/img/icon_github.ico
Normal file
After Width: | Height: | Size: 6.4 KiB |
BIN
sources/searx/static/img/icon_soundcloud.ico
Normal file
After Width: | Height: | Size: 1.1 KiB |
BIN
sources/searx/static/img/icon_stackoverflow.ico
Normal file
After Width: | Height: | Size: 1.1 KiB |
BIN
sources/searx/static/img/icon_twitter.ico
Normal file
After Width: | Height: | Size: 1.1 KiB |
BIN
sources/searx/static/img/icon_vimeo.ico
Normal file
After Width: | Height: | Size: 6.4 KiB |
BIN
sources/searx/static/img/icon_wikipedia.ico
Normal file
After Width: | Height: | Size: 14 KiB |
BIN
sources/searx/static/img/icon_youtube.ico
Normal file
After Width: | Height: | Size: 1.1 KiB |
BIN
sources/searx/static/img/preference-icon.png
Normal file
After Width: | Height: | Size: 837 B |
BIN
sources/searx/static/img/search-icon.png
Normal file
After Width: | Height: | Size: 3.2 KiB |
BIN
sources/searx/static/img/searx.png
Normal file
After Width: | Height: | Size: 7.5 KiB |
203
sources/searx/static/img/searx_logo.svg
Normal 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 |
2
sources/searx/static/js/mootools-autocompleter-1.1.2-min.js
vendored
Normal file
491
sources/searx/static/js/mootools-core-1.4.5-min.js
vendored
Normal file
|
@ -0,0 +1,491 @@
|
|||
/*
|
||||
---
|
||||
MooTools: the javascript framework
|
||||
|
||||
web build:
|
||||
- http://mootools.net/core/76bf47062d6c1983d66ce47ad66aa0e0
|
||||
|
||||
packager build:
|
||||
- packager build Core/Core Core/Array Core/String Core/Number Core/Function Core/Object Core/Event Core/Browser Core/Class Core/Class.Extras Core/Slick.Parser Core/Slick.Finder Core/Element Core/Element.Style Core/Element.Event Core/Element.Delegation Core/Element.Dimensions Core/Fx Core/Fx.CSS Core/Fx.Tween Core/Fx.Morph Core/Fx.Transitions Core/Request Core/Request.HTML Core/Request.JSON Core/Cookie Core/JSON Core/DOMReady Core/Swiff
|
||||
|
||||
copyrights:
|
||||
- [MooTools](http://mootools.net)
|
||||
|
||||
licenses:
|
||||
- [MIT License](http://mootools.net/license.txt)
|
||||
...
|
||||
*/
|
||||
|
||||
(function(){this.MooTools={version:"1.4.5",build:"ab8ea8824dc3b24b6666867a2c4ed58ebb762cf0"};var o=this.typeOf=function(i){if(i==null){return"null";}if(i.$family!=null){return i.$family();
|
||||
}if(i.nodeName){if(i.nodeType==1){return"element";}if(i.nodeType==3){return(/\S/).test(i.nodeValue)?"textnode":"whitespace";}}else{if(typeof i.length=="number"){if(i.callee){return"arguments";
|
||||
}if("item" in i){return"collection";}}}return typeof i;};var j=this.instanceOf=function(t,i){if(t==null){return false;}var s=t.$constructor||t.constructor;
|
||||
while(s){if(s===i){return true;}s=s.parent;}if(!t.hasOwnProperty){return false;}return t instanceof i;};var f=this.Function;var p=true;for(var k in {toString:1}){p=null;
|
||||
}if(p){p=["hasOwnProperty","valueOf","isPrototypeOf","propertyIsEnumerable","toLocaleString","toString","constructor"];}f.prototype.overloadSetter=function(s){var i=this;
|
||||
return function(u,t){if(u==null){return this;}if(s||typeof u!="string"){for(var v in u){i.call(this,v,u[v]);}if(p){for(var w=p.length;w--;){v=p[w];if(u.hasOwnProperty(v)){i.call(this,v,u[v]);
|
||||
}}}}else{i.call(this,u,t);}return this;};};f.prototype.overloadGetter=function(s){var i=this;return function(u){var v,t;if(typeof u!="string"){v=u;}else{if(arguments.length>1){v=arguments;
|
||||
}else{if(s){v=[u];}}}if(v){t={};for(var w=0;w<v.length;w++){t[v[w]]=i.call(this,v[w]);}}else{t=i.call(this,u);}return t;};};f.prototype.extend=function(i,s){this[i]=s;
|
||||
}.overloadSetter();f.prototype.implement=function(i,s){this.prototype[i]=s;}.overloadSetter();var n=Array.prototype.slice;f.from=function(i){return(o(i)=="function")?i:function(){return i;
|
||||
};};Array.from=function(i){if(i==null){return[];}return(a.isEnumerable(i)&&typeof i!="string")?(o(i)=="array")?i:n.call(i):[i];};Number.from=function(s){var i=parseFloat(s);
|
||||
return isFinite(i)?i:null;};String.from=function(i){return i+"";};f.implement({hide:function(){this.$hidden=true;return this;},protect:function(){this.$protected=true;
|
||||
return this;}});var a=this.Type=function(u,t){if(u){var s=u.toLowerCase();var i=function(v){return(o(v)==s);};a["is"+u]=i;if(t!=null){t.prototype.$family=(function(){return s;
|
||||
}).hide();}}if(t==null){return null;}t.extend(this);t.$constructor=a;t.prototype.$constructor=t;return t;};var e=Object.prototype.toString;a.isEnumerable=function(i){return(i!=null&&typeof i.length=="number"&&e.call(i)!="[object Function]");
|
||||
};var q={};var r=function(i){var s=o(i.prototype);return q[s]||(q[s]=[]);};var b=function(t,x){if(x&&x.$hidden){return;}var s=r(this);for(var u=0;u<s.length;
|
||||
u++){var w=s[u];if(o(w)=="type"){b.call(w,t,x);}else{w.call(this,t,x);}}var v=this.prototype[t];if(v==null||!v.$protected){this.prototype[t]=x;}if(this[t]==null&&o(x)=="function"){m.call(this,t,function(i){return x.apply(i,n.call(arguments,1));
|
||||
});}};var m=function(i,t){if(t&&t.$hidden){return;}var s=this[i];if(s==null||!s.$protected){this[i]=t;}};a.implement({implement:b.overloadSetter(),extend:m.overloadSetter(),alias:function(i,s){b.call(this,i,this.prototype[s]);
|
||||
}.overloadSetter(),mirror:function(i){r(this).push(i);return this;}});new a("Type",a);var d=function(s,x,v){var u=(x!=Object),B=x.prototype;if(u){x=new a(s,x);
|
||||
}for(var y=0,w=v.length;y<w;y++){var C=v[y],A=x[C],z=B[C];if(A){A.protect();}if(u&&z){x.implement(C,z.protect());}}if(u){var t=B.propertyIsEnumerable(v[0]);
|
||||
x.forEachMethod=function(G){if(!t){for(var F=0,D=v.length;F<D;F++){G.call(B,B[v[F]],v[F]);}}for(var E in B){G.call(B,B[E],E);}};}return d;};d("String",String,["charAt","charCodeAt","concat","indexOf","lastIndexOf","match","quote","replace","search","slice","split","substr","substring","trim","toLowerCase","toUpperCase"])("Array",Array,["pop","push","reverse","shift","sort","splice","unshift","concat","join","slice","indexOf","lastIndexOf","filter","forEach","every","map","some","reduce","reduceRight"])("Number",Number,["toExponential","toFixed","toLocaleString","toPrecision"])("Function",f,["apply","call","bind"])("RegExp",RegExp,["exec","test"])("Object",Object,["create","defineProperty","defineProperties","keys","getPrototypeOf","getOwnPropertyDescriptor","getOwnPropertyNames","preventExtensions","isExtensible","seal","isSealed","freeze","isFrozen"])("Date",Date,["now"]);
|
||||
Object.extend=m.overloadSetter();Date.extend("now",function(){return +(new Date);});new a("Boolean",Boolean);Number.prototype.$family=function(){return isFinite(this)?"number":"null";
|
||||
}.hide();Number.extend("random",function(s,i){return Math.floor(Math.random()*(i-s+1)+s);});var g=Object.prototype.hasOwnProperty;Object.extend("forEach",function(i,t,u){for(var s in i){if(g.call(i,s)){t.call(u,i[s],s,i);
|
||||
}}});Object.each=Object.forEach;Array.implement({forEach:function(u,v){for(var t=0,s=this.length;t<s;t++){if(t in this){u.call(v,this[t],t,this);}}},each:function(i,s){Array.forEach(this,i,s);
|
||||
return this;}});var l=function(i){switch(o(i)){case"array":return i.clone();case"object":return Object.clone(i);default:return i;}};Array.implement("clone",function(){var s=this.length,t=new Array(s);
|
||||
while(s--){t[s]=l(this[s]);}return t;});var h=function(s,i,t){switch(o(t)){case"object":if(o(s[i])=="object"){Object.merge(s[i],t);}else{s[i]=Object.clone(t);
|
||||
}break;case"array":s[i]=t.clone();break;default:s[i]=t;}return s;};Object.extend({merge:function(z,u,t){if(o(u)=="string"){return h(z,u,t);}for(var y=1,s=arguments.length;
|
||||
y<s;y++){var w=arguments[y];for(var x in w){h(z,x,w[x]);}}return z;},clone:function(i){var t={};for(var s in i){t[s]=l(i[s]);}return t;},append:function(w){for(var v=1,t=arguments.length;
|
||||
v<t;v++){var s=arguments[v]||{};for(var u in s){w[u]=s[u];}}return w;}});["Object","WhiteSpace","TextNode","Collection","Arguments"].each(function(i){new a(i);
|
||||
});var c=Date.now();String.extend("uniqueID",function(){return(c++).toString(36);});})();Array.implement({every:function(c,d){for(var b=0,a=this.length>>>0;
|
||||
b<a;b++){if((b in this)&&!c.call(d,this[b],b,this)){return false;}}return true;},filter:function(d,f){var c=[];for(var e,b=0,a=this.length>>>0;b<a;b++){if(b in this){e=this[b];
|
||||
if(d.call(f,e,b,this)){c.push(e);}}}return c;},indexOf:function(c,d){var b=this.length>>>0;for(var a=(d<0)?Math.max(0,b+d):d||0;a<b;a++){if(this[a]===c){return a;
|
||||
}}return -1;},map:function(c,e){var d=this.length>>>0,b=Array(d);for(var a=0;a<d;a++){if(a in this){b[a]=c.call(e,this[a],a,this);}}return b;},some:function(c,d){for(var b=0,a=this.length>>>0;
|
||||
b<a;b++){if((b in this)&&c.call(d,this[b],b,this)){return true;}}return false;},clean:function(){return this.filter(function(a){return a!=null;});},invoke:function(a){var b=Array.slice(arguments,1);
|
||||
return this.map(function(c){return c[a].apply(c,b);});},associate:function(c){var d={},b=Math.min(this.length,c.length);for(var a=0;a<b;a++){d[c[a]]=this[a];
|
||||
}return d;},link:function(c){var a={};for(var e=0,b=this.length;e<b;e++){for(var d in c){if(c[d](this[e])){a[d]=this[e];delete c[d];break;}}}return a;},contains:function(a,b){return this.indexOf(a,b)!=-1;
|
||||
},append:function(a){this.push.apply(this,a);return this;},getLast:function(){return(this.length)?this[this.length-1]:null;},getRandom:function(){return(this.length)?this[Number.random(0,this.length-1)]:null;
|
||||
},include:function(a){if(!this.contains(a)){this.push(a);}return this;},combine:function(c){for(var b=0,a=c.length;b<a;b++){this.include(c[b]);}return this;
|
||||
},erase:function(b){for(var a=this.length;a--;){if(this[a]===b){this.splice(a,1);}}return this;},empty:function(){this.length=0;return this;},flatten:function(){var d=[];
|
||||
for(var b=0,a=this.length;b<a;b++){var c=typeOf(this[b]);if(c=="null"){continue;}d=d.concat((c=="array"||c=="collection"||c=="arguments"||instanceOf(this[b],Array))?Array.flatten(this[b]):this[b]);
|
||||
}return d;},pick:function(){for(var b=0,a=this.length;b<a;b++){if(this[b]!=null){return this[b];}}return null;},hexToRgb:function(b){if(this.length!=3){return null;
|
||||
}var a=this.map(function(c){if(c.length==1){c+=c;}return c.toInt(16);});return(b)?a:"rgb("+a+")";},rgbToHex:function(d){if(this.length<3){return null;}if(this.length==4&&this[3]==0&&!d){return"transparent";
|
||||
}var b=[];for(var a=0;a<3;a++){var c=(this[a]-0).toString(16);b.push((c.length==1)?"0"+c:c);}return(d)?b:"#"+b.join("");}});String.implement({test:function(a,b){return((typeOf(a)=="regexp")?a:new RegExp(""+a,b)).test(this);
|
||||
},contains:function(a,b){return(b)?(b+this+b).indexOf(b+a+b)>-1:String(this).indexOf(a)>-1;},trim:function(){return String(this).replace(/^\s+|\s+$/g,"");
|
||||
},clean:function(){return String(this).replace(/\s+/g," ").trim();},camelCase:function(){return String(this).replace(/-\D/g,function(a){return a.charAt(1).toUpperCase();
|
||||
});},hyphenate:function(){return String(this).replace(/[A-Z]/g,function(a){return("-"+a.charAt(0).toLowerCase());});},capitalize:function(){return String(this).replace(/\b[a-z]/g,function(a){return a.toUpperCase();
|
||||
});},escapeRegExp:function(){return String(this).replace(/([-.*+?^${}()|[\]\/\\])/g,"\\$1");},toInt:function(a){return parseInt(this,a||10);},toFloat:function(){return parseFloat(this);
|
||||
},hexToRgb:function(b){var a=String(this).match(/^#?(\w{1,2})(\w{1,2})(\w{1,2})$/);return(a)?a.slice(1).hexToRgb(b):null;},rgbToHex:function(b){var a=String(this).match(/\d{1,3}/g);
|
||||
return(a)?a.rgbToHex(b):null;},substitute:function(a,b){return String(this).replace(b||(/\\?\{([^{}]+)\}/g),function(d,c){if(d.charAt(0)=="\\"){return d.slice(1);
|
||||
}return(a[c]!=null)?a[c]:"";});}});Number.implement({limit:function(b,a){return Math.min(a,Math.max(b,this));},round:function(a){a=Math.pow(10,a||0).toFixed(a<0?-a:0);
|
||||
return Math.round(this*a)/a;},times:function(b,c){for(var a=0;a<this;a++){b.call(c,a,this);}},toFloat:function(){return parseFloat(this);},toInt:function(a){return parseInt(this,a||10);
|
||||
}});Number.alias("each","times");(function(b){var a={};b.each(function(c){if(!Number[c]){a[c]=function(){return Math[c].apply(null,[this].concat(Array.from(arguments)));
|
||||
};}});Number.implement(a);})(["abs","acos","asin","atan","atan2","ceil","cos","exp","floor","log","max","min","pow","sin","sqrt","tan"]);Function.extend({attempt:function(){for(var b=0,a=arguments.length;
|
||||
b<a;b++){try{return arguments[b]();}catch(c){}}return null;}});Function.implement({attempt:function(a,c){try{return this.apply(c,Array.from(a));}catch(b){}return null;
|
||||
},bind:function(e){var a=this,b=arguments.length>1?Array.slice(arguments,1):null,d=function(){};var c=function(){var g=e,h=arguments.length;if(this instanceof c){d.prototype=a.prototype;
|
||||
g=new d;}var f=(!b&&!h)?a.call(g):a.apply(g,b&&h?b.concat(Array.slice(arguments)):b||arguments);return g==e?f:g;};return c;},pass:function(b,c){var a=this;
|
||||
if(b!=null){b=Array.from(b);}return function(){return a.apply(c,b||arguments);};},delay:function(b,c,a){return setTimeout(this.pass((a==null?[]:a),c),b);
|
||||
},periodical:function(c,b,a){return setInterval(this.pass((a==null?[]:a),b),c);}});(function(){var a=Object.prototype.hasOwnProperty;Object.extend({subset:function(d,g){var f={};
|
||||
for(var e=0,b=g.length;e<b;e++){var c=g[e];if(c in d){f[c]=d[c];}}return f;},map:function(b,e,f){var d={};for(var c in b){if(a.call(b,c)){d[c]=e.call(f,b[c],c,b);
|
||||
}}return d;},filter:function(b,e,g){var d={};for(var c in b){var f=b[c];if(a.call(b,c)&&e.call(g,f,c,b)){d[c]=f;}}return d;},every:function(b,d,e){for(var c in b){if(a.call(b,c)&&!d.call(e,b[c],c)){return false;
|
||||
}}return true;},some:function(b,d,e){for(var c in b){if(a.call(b,c)&&d.call(e,b[c],c)){return true;}}return false;},keys:function(b){var d=[];for(var c in b){if(a.call(b,c)){d.push(c);
|
||||
}}return d;},values:function(c){var b=[];for(var d in c){if(a.call(c,d)){b.push(c[d]);}}return b;},getLength:function(b){return Object.keys(b).length;},keyOf:function(b,d){for(var c in b){if(a.call(b,c)&&b[c]===d){return c;
|
||||
}}return null;},contains:function(b,c){return Object.keyOf(b,c)!=null;},toQueryString:function(b,c){var d=[];Object.each(b,function(h,g){if(c){g=c+"["+g+"]";
|
||||
}var f;switch(typeOf(h)){case"object":f=Object.toQueryString(h,g);break;case"array":var e={};h.each(function(k,j){e[j]=k;});f=Object.toQueryString(e,g);
|
||||
break;default:f=g+"="+encodeURIComponent(h);}if(h!=null){d.push(f);}});return d.join("&");}});})();(function(){var j=this.document;var g=j.window=this;
|
||||
var a=navigator.userAgent.toLowerCase(),b=navigator.platform.toLowerCase(),h=a.match(/(opera|ie|firefox|chrome|version)[\s\/:]([\w\d\.]+)?.*?(safari|version[\s\/:]([\w\d\.]+)|$)/)||[null,"unknown",0],d=h[1]=="ie"&&j.documentMode;
|
||||
var n=this.Browser={extend:Function.prototype.extend,name:(h[1]=="version")?h[3]:h[1],version:d||parseFloat((h[1]=="opera"&&h[4])?h[4]:h[2]),Platform:{name:a.match(/ip(?:ad|od|hone)/)?"ios":(a.match(/(?:webos|android)/)||b.match(/mac|win|linux/)||["other"])[0]},Features:{xpath:!!(j.evaluate),air:!!(g.runtime),query:!!(j.querySelector),json:!!(g.JSON)},Plugins:{}};
|
||||
n[n.name]=true;n[n.name+parseInt(n.version,10)]=true;n.Platform[n.Platform.name]=true;n.Request=(function(){var p=function(){return new XMLHttpRequest();
|
||||
};var o=function(){return new ActiveXObject("MSXML2.XMLHTTP");};var e=function(){return new ActiveXObject("Microsoft.XMLHTTP");};return Function.attempt(function(){p();
|
||||
return p;},function(){o();return o;},function(){e();return e;});})();n.Features.xhr=!!(n.Request);var i=(Function.attempt(function(){return navigator.plugins["Shockwave Flash"].description;
|
||||
},function(){return new ActiveXObject("ShockwaveFlash.ShockwaveFlash").GetVariable("$version");})||"0 r0").match(/\d+/g);n.Plugins.Flash={version:Number(i[0]||"0."+i[1])||0,build:Number(i[2])||0};
|
||||
n.exec=function(o){if(!o){return o;}if(g.execScript){g.execScript(o);}else{var e=j.createElement("script");e.setAttribute("type","text/javascript");e.text=o;
|
||||
j.head.appendChild(e);j.head.removeChild(e);}return o;};String.implement("stripScripts",function(o){var e="";var p=this.replace(/<script[^>]*>([\s\S]*?)<\/script>/gi,function(q,r){e+=r+"\n";
|
||||
return"";});if(o===true){n.exec(e);}else{if(typeOf(o)=="function"){o(e,p);}}return p;});n.extend({Document:this.Document,Window:this.Window,Element:this.Element,Event:this.Event});
|
||||
this.Window=this.$constructor=new Type("Window",function(){});this.$family=Function.from("window").hide();Window.mirror(function(e,o){g[e]=o;});this.Document=j.$constructor=new Type("Document",function(){});
|
||||
j.$family=Function.from("document").hide();Document.mirror(function(e,o){j[e]=o;});j.html=j.documentElement;if(!j.head){j.head=j.getElementsByTagName("head")[0];
|
||||
}if(j.execCommand){try{j.execCommand("BackgroundImageCache",false,true);}catch(f){}}if(this.attachEvent&&!this.addEventListener){var c=function(){this.detachEvent("onunload",c);
|
||||
j.head=j.html=j.window=null;};this.attachEvent("onunload",c);}var l=Array.from;try{l(j.html.childNodes);}catch(f){Array.from=function(o){if(typeof o!="string"&&Type.isEnumerable(o)&&typeOf(o)!="array"){var e=o.length,p=new Array(e);
|
||||
while(e--){p[e]=o[e];}return p;}return l(o);};var k=Array.prototype,m=k.slice;["pop","push","reverse","shift","sort","splice","unshift","concat","join","slice"].each(function(e){var o=k[e];
|
||||
Array[e]=function(p){return o.apply(Array.from(p),m.call(arguments,1));};});}})();(function(){var b={};var a=this.DOMEvent=new Type("DOMEvent",function(c,g){if(!g){g=window;
|
||||
}c=c||g.event;if(c.$extended){return c;}this.event=c;this.$extended=true;this.shift=c.shiftKey;this.control=c.ctrlKey;this.alt=c.altKey;this.meta=c.metaKey;
|
||||
var i=this.type=c.type;var h=c.target||c.srcElement;while(h&&h.nodeType==3){h=h.parentNode;}this.target=document.id(h);if(i.indexOf("key")==0){var d=this.code=(c.which||c.keyCode);
|
||||
this.key=b[d];if(i=="keydown"){if(d>111&&d<124){this.key="f"+(d-111);}else{if(d>95&&d<106){this.key=d-96;}}}if(this.key==null){this.key=String.fromCharCode(d).toLowerCase();
|
||||
}}else{if(i=="click"||i=="dblclick"||i=="contextmenu"||i=="DOMMouseScroll"||i.indexOf("mouse")==0){var j=g.document;j=(!j.compatMode||j.compatMode=="CSS1Compat")?j.html:j.body;
|
||||
this.page={x:(c.pageX!=null)?c.pageX:c.clientX+j.scrollLeft,y:(c.pageY!=null)?c.pageY:c.clientY+j.scrollTop};this.client={x:(c.pageX!=null)?c.pageX-g.pageXOffset:c.clientX,y:(c.pageY!=null)?c.pageY-g.pageYOffset:c.clientY};
|
||||
if(i=="DOMMouseScroll"||i=="mousewheel"){this.wheel=(c.wheelDelta)?c.wheelDelta/120:-(c.detail||0)/3;}this.rightClick=(c.which==3||c.button==2);if(i=="mouseover"||i=="mouseout"){var k=c.relatedTarget||c[(i=="mouseover"?"from":"to")+"Element"];
|
||||
while(k&&k.nodeType==3){k=k.parentNode;}this.relatedTarget=document.id(k);}}else{if(i.indexOf("touch")==0||i.indexOf("gesture")==0){this.rotation=c.rotation;
|
||||
this.scale=c.scale;this.targetTouches=c.targetTouches;this.changedTouches=c.changedTouches;var f=this.touches=c.touches;if(f&&f[0]){var e=f[0];this.page={x:e.pageX,y:e.pageY};
|
||||
this.client={x:e.clientX,y:e.clientY};}}}}if(!this.client){this.client={};}if(!this.page){this.page={};}});a.implement({stop:function(){return this.preventDefault().stopPropagation();
|
||||
},stopPropagation:function(){if(this.event.stopPropagation){this.event.stopPropagation();}else{this.event.cancelBubble=true;}return this;},preventDefault:function(){if(this.event.preventDefault){this.event.preventDefault();
|
||||
}else{this.event.returnValue=false;}return this;}});a.defineKey=function(d,c){b[d]=c;return this;};a.defineKeys=a.defineKey.overloadSetter(true);a.defineKeys({"38":"up","40":"down","37":"left","39":"right","27":"esc","32":"space","8":"backspace","9":"tab","46":"delete","13":"enter"});
|
||||
})();(function(){var a=this.Class=new Type("Class",function(h){if(instanceOf(h,Function)){h={initialize:h};}var g=function(){e(this);if(g.$prototyping){return this;
|
||||
}this.$caller=null;var i=(this.initialize)?this.initialize.apply(this,arguments):this;this.$caller=this.caller=null;return i;}.extend(this).implement(h);
|
||||
g.$constructor=a;g.prototype.$constructor=g;g.prototype.parent=c;return g;});var c=function(){if(!this.$caller){throw new Error('The method "parent" cannot be called.');
|
||||
}var g=this.$caller.$name,h=this.$caller.$owner.parent,i=(h)?h.prototype[g]:null;if(!i){throw new Error('The method "'+g+'" has no parent.');}return i.apply(this,arguments);
|
||||
};var e=function(g){for(var h in g){var j=g[h];switch(typeOf(j)){case"object":var i=function(){};i.prototype=j;g[h]=e(new i);break;case"array":g[h]=j.clone();
|
||||
break;}}return g;};var b=function(g,h,j){if(j.$origin){j=j.$origin;}var i=function(){if(j.$protected&&this.$caller==null){throw new Error('The method "'+h+'" cannot be called.');
|
||||
}var l=this.caller,m=this.$caller;this.caller=m;this.$caller=i;var k=j.apply(this,arguments);this.$caller=m;this.caller=l;return k;}.extend({$owner:g,$origin:j,$name:h});
|
||||
return i;};var f=function(h,i,g){if(a.Mutators.hasOwnProperty(h)){i=a.Mutators[h].call(this,i);if(i==null){return this;}}if(typeOf(i)=="function"){if(i.$hidden){return this;
|
||||
}this.prototype[h]=(g)?i:b(this,h,i);}else{Object.merge(this.prototype,h,i);}return this;};var d=function(g){g.$prototyping=true;var h=new g;delete g.$prototyping;
|
||||
return h;};a.implement("implement",f.overloadSetter());a.Mutators={Extends:function(g){this.parent=g;this.prototype=d(g);},Implements:function(g){Array.from(g).each(function(j){var h=new j;
|
||||
for(var i in h){f.call(this,i,h[i],true);}},this);}};})();(function(){this.Chain=new Class({$chain:[],chain:function(){this.$chain.append(Array.flatten(arguments));
|
||||
return this;},callChain:function(){return(this.$chain.length)?this.$chain.shift().apply(this,arguments):false;},clearChain:function(){this.$chain.empty();
|
||||
return this;}});var a=function(b){return b.replace(/^on([A-Z])/,function(c,d){return d.toLowerCase();});};this.Events=new Class({$events:{},addEvent:function(d,c,b){d=a(d);
|
||||
this.$events[d]=(this.$events[d]||[]).include(c);if(b){c.internal=true;}return this;},addEvents:function(b){for(var c in b){this.addEvent(c,b[c]);}return this;
|
||||
},fireEvent:function(e,c,b){e=a(e);var d=this.$events[e];if(!d){return this;}c=Array.from(c);d.each(function(f){if(b){f.delay(b,this,c);}else{f.apply(this,c);
|
||||
}},this);return this;},removeEvent:function(e,d){e=a(e);var c=this.$events[e];if(c&&!d.internal){var b=c.indexOf(d);if(b!=-1){delete c[b];}}return this;
|
||||
},removeEvents:function(d){var e;if(typeOf(d)=="object"){for(e in d){this.removeEvent(e,d[e]);}return this;}if(d){d=a(d);}for(e in this.$events){if(d&&d!=e){continue;
|
||||
}var c=this.$events[e];for(var b=c.length;b--;){if(b in c){this.removeEvent(e,c[b]);}}}return this;}});this.Options=new Class({setOptions:function(){var b=this.options=Object.merge.apply(null,[{},this.options].append(arguments));
|
||||
if(this.addEvent){for(var c in b){if(typeOf(b[c])!="function"||!(/^on[A-Z]/).test(c)){continue;}this.addEvent(c,b[c]);delete b[c];}}return this;}});})();
|
||||
(function(){var k,n,l,g,a={},c={},m=/\\/g;var e=function(q,p){if(q==null){return null;}if(q.Slick===true){return q;}q=(""+q).replace(/^\s+|\s+$/g,"");g=!!p;
|
||||
var o=(g)?c:a;if(o[q]){return o[q];}k={Slick:true,expressions:[],raw:q,reverse:function(){return e(this.raw,true);}};n=-1;while(q!=(q=q.replace(j,b))){}k.length=k.expressions.length;
|
||||
return o[k.raw]=(g)?h(k):k;};var i=function(o){if(o==="!"){return" ";}else{if(o===" "){return"!";}else{if((/^!/).test(o)){return o.replace(/^!/,"");}else{return"!"+o;
|
||||
}}}};var h=function(u){var r=u.expressions;for(var p=0;p<r.length;p++){var t=r[p];var q={parts:[],tag:"*",combinator:i(t[0].combinator)};for(var o=0;o<t.length;
|
||||
o++){var s=t[o];if(!s.reverseCombinator){s.reverseCombinator=" ";}s.combinator=s.reverseCombinator;delete s.reverseCombinator;}t.reverse().push(q);}return u;
|
||||
};var f=function(o){return o.replace(/[-[\]{}()*+?.\\^$|,#\s]/g,function(p){return"\\"+p;});};var j=new RegExp("^(?:\\s*(,)\\s*|\\s*(<combinator>+)\\s*|(\\s+)|(<unicode>+|\\*)|\\#(<unicode>+)|\\.(<unicode>+)|\\[\\s*(<unicode1>+)(?:\\s*([*^$!~|]?=)(?:\\s*(?:([\"']?)(.*?)\\9)))?\\s*\\](?!\\])|(:+)(<unicode>+)(?:\\((?:(?:([\"'])([^\\13]*)\\13)|((?:\\([^)]+\\)|[^()]*)+))\\))?)".replace(/<combinator>/,"["+f(">+~`!@$%^&={}\\;</")+"]").replace(/<unicode>/g,"(?:[\\w\\u00a1-\\uFFFF-]|\\\\[^\\s0-9a-f])").replace(/<unicode1>/g,"(?:[:\\w\\u00a1-\\uFFFF-]|\\\\[^\\s0-9a-f])"));
|
||||
function b(x,s,D,z,r,C,q,B,A,y,u,F,G,v,p,w){if(s||n===-1){k.expressions[++n]=[];l=-1;if(s){return"";}}if(D||z||l===-1){D=D||" ";var t=k.expressions[n];
|
||||
if(g&&t[l]){t[l].reverseCombinator=i(D);}t[++l]={combinator:D,tag:"*"};}var o=k.expressions[n][l];if(r){o.tag=r.replace(m,"");}else{if(C){o.id=C.replace(m,"");
|
||||
}else{if(q){q=q.replace(m,"");if(!o.classList){o.classList=[];}if(!o.classes){o.classes=[];}o.classList.push(q);o.classes.push({value:q,regexp:new RegExp("(^|\\s)"+f(q)+"(\\s|$)")});
|
||||
}else{if(G){w=w||p;w=w?w.replace(m,""):null;if(!o.pseudos){o.pseudos=[];}o.pseudos.push({key:G.replace(m,""),value:w,type:F.length==1?"class":"element"});
|
||||
}else{if(B){B=B.replace(m,"");u=(u||"").replace(m,"");var E,H;switch(A){case"^=":H=new RegExp("^"+f(u));break;case"$=":H=new RegExp(f(u)+"$");break;case"~=":H=new RegExp("(^|\\s)"+f(u)+"(\\s|$)");
|
||||
break;case"|=":H=new RegExp("^"+f(u)+"(-|$)");break;case"=":E=function(I){return u==I;};break;case"*=":E=function(I){return I&&I.indexOf(u)>-1;};break;
|
||||
case"!=":E=function(I){return u!=I;};break;default:E=function(I){return !!I;};}if(u==""&&(/^[*$^]=$/).test(A)){E=function(){return false;};}if(!E){E=function(I){return I&&H.test(I);
|
||||
};}if(!o.attributes){o.attributes=[];}o.attributes.push({key:B,operator:A,value:u,test:E});}}}}}return"";}var d=(this.Slick||{});d.parse=function(o){return e(o);
|
||||
};d.escapeRegExp=f;if(!this.Slick){this.Slick=d;}}).apply((typeof exports!="undefined")?exports:this);(function(){var k={},m={},d=Object.prototype.toString;
|
||||
k.isNativeCode=function(c){return(/\{\s*\[native code\]\s*\}/).test(""+c);};k.isXML=function(c){return(!!c.xmlVersion)||(!!c.xml)||(d.call(c)=="[object XMLDocument]")||(c.nodeType==9&&c.documentElement.nodeName!="HTML");
|
||||
};k.setDocument=function(w){var p=w.nodeType;if(p==9){}else{if(p){w=w.ownerDocument;}else{if(w.navigator){w=w.document;}else{return;}}}if(this.document===w){return;
|
||||
}this.document=w;var A=w.documentElement,o=this.getUIDXML(A),s=m[o],r;if(s){for(r in s){this[r]=s[r];}return;}s=m[o]={};s.root=A;s.isXMLDocument=this.isXML(w);
|
||||
s.brokenStarGEBTN=s.starSelectsClosedQSA=s.idGetsName=s.brokenMixedCaseQSA=s.brokenGEBCN=s.brokenCheckedQSA=s.brokenEmptyAttributeQSA=s.isHTMLDocument=s.nativeMatchesSelector=false;
|
||||
var q,u,y,z,t;var x,v="slick_uniqueid";var c=w.createElement("div");var n=w.body||w.getElementsByTagName("body")[0]||A;n.appendChild(c);try{c.innerHTML='<a id="'+v+'"></a>';
|
||||
s.isHTMLDocument=!!w.getElementById(v);}catch(C){}if(s.isHTMLDocument){c.style.display="none";c.appendChild(w.createComment(""));u=(c.getElementsByTagName("*").length>1);
|
||||
try{c.innerHTML="foo</foo>";x=c.getElementsByTagName("*");q=(x&&!!x.length&&x[0].nodeName.charAt(0)=="/");}catch(C){}s.brokenStarGEBTN=u||q;try{c.innerHTML='<a name="'+v+'"></a><b id="'+v+'"></b>';
|
||||
s.idGetsName=w.getElementById(v)===c.firstChild;}catch(C){}if(c.getElementsByClassName){try{c.innerHTML='<a class="f"></a><a class="b"></a>';c.getElementsByClassName("b").length;
|
||||
c.firstChild.className="b";z=(c.getElementsByClassName("b").length!=2);}catch(C){}try{c.innerHTML='<a class="a"></a><a class="f b a"></a>';y=(c.getElementsByClassName("a").length!=2);
|
||||
}catch(C){}s.brokenGEBCN=z||y;}if(c.querySelectorAll){try{c.innerHTML="foo</foo>";x=c.querySelectorAll("*");s.starSelectsClosedQSA=(x&&!!x.length&&x[0].nodeName.charAt(0)=="/");
|
||||
}catch(C){}try{c.innerHTML='<a class="MiX"></a>';s.brokenMixedCaseQSA=!c.querySelectorAll(".MiX").length;}catch(C){}try{c.innerHTML='<select><option selected="selected">a</option></select>';
|
||||
s.brokenCheckedQSA=(c.querySelectorAll(":checked").length==0);}catch(C){}try{c.innerHTML='<a class=""></a>';s.brokenEmptyAttributeQSA=(c.querySelectorAll('[class*=""]').length!=0);
|
||||
}catch(C){}}try{c.innerHTML='<form action="s"><input id="action"/></form>';t=(c.firstChild.getAttribute("action")!="s");}catch(C){}s.nativeMatchesSelector=A.matchesSelector||A.mozMatchesSelector||A.webkitMatchesSelector;
|
||||
if(s.nativeMatchesSelector){try{s.nativeMatchesSelector.call(A,":slick");s.nativeMatchesSelector=null;}catch(C){}}}try{A.slick_expando=1;delete A.slick_expando;
|
||||
s.getUID=this.getUIDHTML;}catch(C){s.getUID=this.getUIDXML;}n.removeChild(c);c=x=n=null;s.getAttribute=(s.isHTMLDocument&&t)?function(G,E){var H=this.attributeGetters[E];
|
||||
if(H){return H.call(G);}var F=G.getAttributeNode(E);return(F)?F.nodeValue:null;}:function(F,E){var G=this.attributeGetters[E];return(G)?G.call(F):F.getAttribute(E);
|
||||
};s.hasAttribute=(A&&this.isNativeCode(A.hasAttribute))?function(F,E){return F.hasAttribute(E);}:function(F,E){F=F.getAttributeNode(E);return !!(F&&(F.specified||F.nodeValue));
|
||||
};var D=A&&this.isNativeCode(A.contains),B=w&&this.isNativeCode(w.contains);s.contains=(D&&B)?function(E,F){return E.contains(F);}:(D&&!B)?function(E,F){return E===F||((E===w)?w.documentElement:E).contains(F);
|
||||
}:(A&&A.compareDocumentPosition)?function(E,F){return E===F||!!(E.compareDocumentPosition(F)&16);}:function(E,F){if(F){do{if(F===E){return true;}}while((F=F.parentNode));
|
||||
}return false;};s.documentSorter=(A.compareDocumentPosition)?function(F,E){if(!F.compareDocumentPosition||!E.compareDocumentPosition){return 0;}return F.compareDocumentPosition(E)&4?-1:F===E?0:1;
|
||||
}:("sourceIndex" in A)?function(F,E){if(!F.sourceIndex||!E.sourceIndex){return 0;}return F.sourceIndex-E.sourceIndex;}:(w.createRange)?function(H,F){if(!H.ownerDocument||!F.ownerDocument){return 0;
|
||||
}var G=H.ownerDocument.createRange(),E=F.ownerDocument.createRange();G.setStart(H,0);G.setEnd(H,0);E.setStart(F,0);E.setEnd(F,0);return G.compareBoundaryPoints(Range.START_TO_END,E);
|
||||
}:null;A=null;for(r in s){this[r]=s[r];}};var f=/^([#.]?)((?:[\w-]+|\*))$/,h=/\[.+[*$^]=(?:""|'')?\]/,g={};k.search=function(U,z,H,s){var p=this.found=(s)?null:(H||[]);
|
||||
if(!U){return p;}else{if(U.navigator){U=U.document;}else{if(!U.nodeType){return p;}}}var F,O,V=this.uniques={},I=!!(H&&H.length),y=(U.nodeType==9);if(this.document!==(y?U:U.ownerDocument)){this.setDocument(U);
|
||||
}if(I){for(O=p.length;O--;){V[this.getUID(p[O])]=true;}}if(typeof z=="string"){var r=z.match(f);simpleSelectors:if(r){var u=r[1],v=r[2],A,E;if(!u){if(v=="*"&&this.brokenStarGEBTN){break simpleSelectors;
|
||||
}E=U.getElementsByTagName(v);if(s){return E[0]||null;}for(O=0;A=E[O++];){if(!(I&&V[this.getUID(A)])){p.push(A);}}}else{if(u=="#"){if(!this.isHTMLDocument||!y){break simpleSelectors;
|
||||
}A=U.getElementById(v);if(!A){return p;}if(this.idGetsName&&A.getAttributeNode("id").nodeValue!=v){break simpleSelectors;}if(s){return A||null;}if(!(I&&V[this.getUID(A)])){p.push(A);
|
||||
}}else{if(u=="."){if(!this.isHTMLDocument||((!U.getElementsByClassName||this.brokenGEBCN)&&U.querySelectorAll)){break simpleSelectors;}if(U.getElementsByClassName&&!this.brokenGEBCN){E=U.getElementsByClassName(v);
|
||||
if(s){return E[0]||null;}for(O=0;A=E[O++];){if(!(I&&V[this.getUID(A)])){p.push(A);}}}else{var T=new RegExp("(^|\\s)"+e.escapeRegExp(v)+"(\\s|$)");E=U.getElementsByTagName("*");
|
||||
for(O=0;A=E[O++];){className=A.className;if(!(className&&T.test(className))){continue;}if(s){return A;}if(!(I&&V[this.getUID(A)])){p.push(A);}}}}}}if(I){this.sort(p);
|
||||
}return(s)?null:p;}querySelector:if(U.querySelectorAll){if(!this.isHTMLDocument||g[z]||this.brokenMixedCaseQSA||(this.brokenCheckedQSA&&z.indexOf(":checked")>-1)||(this.brokenEmptyAttributeQSA&&h.test(z))||(!y&&z.indexOf(",")>-1)||e.disableQSA){break querySelector;
|
||||
}var S=z,x=U;if(!y){var C=x.getAttribute("id"),t="slickid__";x.setAttribute("id",t);S="#"+t+" "+S;U=x.parentNode;}try{if(s){return U.querySelector(S)||null;
|
||||
}else{E=U.querySelectorAll(S);}}catch(Q){g[z]=1;break querySelector;}finally{if(!y){if(C){x.setAttribute("id",C);}else{x.removeAttribute("id");}U=x;}}if(this.starSelectsClosedQSA){for(O=0;
|
||||
A=E[O++];){if(A.nodeName>"@"&&!(I&&V[this.getUID(A)])){p.push(A);}}}else{for(O=0;A=E[O++];){if(!(I&&V[this.getUID(A)])){p.push(A);}}}if(I){this.sort(p);
|
||||
}return p;}F=this.Slick.parse(z);if(!F.length){return p;}}else{if(z==null){return p;}else{if(z.Slick){F=z;}else{if(this.contains(U.documentElement||U,z)){(p)?p.push(z):p=z;
|
||||
return p;}else{return p;}}}}this.posNTH={};this.posNTHLast={};this.posNTHType={};this.posNTHTypeLast={};this.push=(!I&&(s||(F.length==1&&F.expressions[0].length==1)))?this.pushArray:this.pushUID;
|
||||
if(p==null){p=[];}var M,L,K;var B,J,D,c,q,G,W;var N,P,o,w,R=F.expressions;search:for(O=0;(P=R[O]);O++){for(M=0;(o=P[M]);M++){B="combinator:"+o.combinator;
|
||||
if(!this[B]){continue search;}J=(this.isXMLDocument)?o.tag:o.tag.toUpperCase();D=o.id;c=o.classList;q=o.classes;G=o.attributes;W=o.pseudos;w=(M===(P.length-1));
|
||||
this.bitUniques={};if(w){this.uniques=V;this.found=p;}else{this.uniques={};this.found=[];}if(M===0){this[B](U,J,D,q,G,W,c);if(s&&w&&p.length){break search;
|
||||
}}else{if(s&&w){for(L=0,K=N.length;L<K;L++){this[B](N[L],J,D,q,G,W,c);if(p.length){break search;}}}else{for(L=0,K=N.length;L<K;L++){this[B](N[L],J,D,q,G,W,c);
|
||||
}}}N=this.found;}}if(I||(F.expressions.length>1)){this.sort(p);}return(s)?(p[0]||null):p;};k.uidx=1;k.uidk="slick-uniqueid";k.getUIDXML=function(n){var c=n.getAttribute(this.uidk);
|
||||
if(!c){c=this.uidx++;n.setAttribute(this.uidk,c);}return c;};k.getUIDHTML=function(c){return c.uniqueNumber||(c.uniqueNumber=this.uidx++);};k.sort=function(c){if(!this.documentSorter){return c;
|
||||
}c.sort(this.documentSorter);return c;};k.cacheNTH={};k.matchNTH=/^([+-]?\d*)?([a-z]+)?([+-]\d+)?$/;k.parseNTHArgument=function(q){var o=q.match(this.matchNTH);
|
||||
if(!o){return false;}var p=o[2]||false;var n=o[1]||1;if(n=="-"){n=-1;}var c=+o[3]||0;o=(p=="n")?{a:n,b:c}:(p=="odd")?{a:2,b:1}:(p=="even")?{a:2,b:0}:{a:0,b:n};
|
||||
return(this.cacheNTH[q]=o);};k.createNTHPseudo=function(p,n,c,o){return function(s,q){var u=this.getUID(s);if(!this[c][u]){var A=s.parentNode;if(!A){return false;
|
||||
}var r=A[p],t=1;if(o){var z=s.nodeName;do{if(r.nodeName!=z){continue;}this[c][this.getUID(r)]=t++;}while((r=r[n]));}else{do{if(r.nodeType!=1){continue;
|
||||
}this[c][this.getUID(r)]=t++;}while((r=r[n]));}}q=q||"n";var v=this.cacheNTH[q]||this.parseNTHArgument(q);if(!v){return false;}var y=v.a,x=v.b,w=this[c][u];
|
||||
if(y==0){return x==w;}if(y>0){if(w<x){return false;}}else{if(x<w){return false;}}return((w-x)%y)==0;};};k.pushArray=function(p,c,r,o,n,q){if(this.matchSelector(p,c,r,o,n,q)){this.found.push(p);
|
||||
}};k.pushUID=function(q,c,s,p,n,r){var o=this.getUID(q);if(!this.uniques[o]&&this.matchSelector(q,c,s,p,n,r)){this.uniques[o]=true;this.found.push(q);}};
|
||||
k.matchNode=function(n,o){if(this.isHTMLDocument&&this.nativeMatchesSelector){try{return this.nativeMatchesSelector.call(n,o.replace(/\[([^=]+)=\s*([^'"\]]+?)\s*\]/g,'[$1="$2"]'));
|
||||
}catch(u){}}var t=this.Slick.parse(o);if(!t){return true;}var r=t.expressions,s=0,q;for(q=0;(currentExpression=r[q]);q++){if(currentExpression.length==1){var p=currentExpression[0];
|
||||
if(this.matchSelector(n,(this.isXMLDocument)?p.tag:p.tag.toUpperCase(),p.id,p.classes,p.attributes,p.pseudos)){return true;}s++;}}if(s==t.length){return false;
|
||||
}var c=this.search(this.document,t),v;for(q=0;v=c[q++];){if(v===n){return true;}}return false;};k.matchPseudo=function(q,c,p){var n="pseudo:"+c;if(this[n]){return this[n](q,p);
|
||||
}var o=this.getAttribute(q,c);return(p)?p==o:!!o;};k.matchSelector=function(o,v,c,p,q,s){if(v){var t=(this.isXMLDocument)?o.nodeName:o.nodeName.toUpperCase();
|
||||
if(v=="*"){if(t<"@"){return false;}}else{if(t!=v){return false;}}}if(c&&o.getAttribute("id")!=c){return false;}var r,n,u;if(p){for(r=p.length;r--;){u=this.getAttribute(o,"class");
|
||||
if(!(u&&p[r].regexp.test(u))){return false;}}}if(q){for(r=q.length;r--;){n=q[r];if(n.operator?!n.test(this.getAttribute(o,n.key)):!this.hasAttribute(o,n.key)){return false;
|
||||
}}}if(s){for(r=s.length;r--;){n=s[r];if(!this.matchPseudo(o,n.key,n.value)){return false;}}}return true;};var j={" ":function(q,w,n,r,s,u,p){var t,v,o;
|
||||
if(this.isHTMLDocument){getById:if(n){v=this.document.getElementById(n);if((!v&&q.all)||(this.idGetsName&&v&&v.getAttributeNode("id").nodeValue!=n)){o=q.all[n];
|
||||
if(!o){return;}if(!o[0]){o=[o];}for(t=0;v=o[t++];){var c=v.getAttributeNode("id");if(c&&c.nodeValue==n){this.push(v,w,null,r,s,u);break;}}return;}if(!v){if(this.contains(this.root,q)){return;
|
||||
}else{break getById;}}else{if(this.document!==q&&!this.contains(q,v)){return;}}this.push(v,w,null,r,s,u);return;}getByClass:if(r&&q.getElementsByClassName&&!this.brokenGEBCN){o=q.getElementsByClassName(p.join(" "));
|
||||
if(!(o&&o.length)){break getByClass;}for(t=0;v=o[t++];){this.push(v,w,n,null,s,u);}return;}}getByTag:{o=q.getElementsByTagName(w);if(!(o&&o.length)){break getByTag;
|
||||
}if(!this.brokenStarGEBTN){w=null;}for(t=0;v=o[t++];){this.push(v,w,n,r,s,u);}}},">":function(p,c,r,o,n,q){if((p=p.firstChild)){do{if(p.nodeType==1){this.push(p,c,r,o,n,q);
|
||||
}}while((p=p.nextSibling));}},"+":function(p,c,r,o,n,q){while((p=p.nextSibling)){if(p.nodeType==1){this.push(p,c,r,o,n,q);break;}}},"^":function(p,c,r,o,n,q){p=p.firstChild;
|
||||
if(p){if(p.nodeType==1){this.push(p,c,r,o,n,q);}else{this["combinator:+"](p,c,r,o,n,q);}}},"~":function(q,c,s,p,n,r){while((q=q.nextSibling)){if(q.nodeType!=1){continue;
|
||||
}var o=this.getUID(q);if(this.bitUniques[o]){break;}this.bitUniques[o]=true;this.push(q,c,s,p,n,r);}},"++":function(p,c,r,o,n,q){this["combinator:+"](p,c,r,o,n,q);
|
||||
this["combinator:!+"](p,c,r,o,n,q);},"~~":function(p,c,r,o,n,q){this["combinator:~"](p,c,r,o,n,q);this["combinator:!~"](p,c,r,o,n,q);},"!":function(p,c,r,o,n,q){while((p=p.parentNode)){if(p!==this.document){this.push(p,c,r,o,n,q);
|
||||
}}},"!>":function(p,c,r,o,n,q){p=p.parentNode;if(p!==this.document){this.push(p,c,r,o,n,q);}},"!+":function(p,c,r,o,n,q){while((p=p.previousSibling)){if(p.nodeType==1){this.push(p,c,r,o,n,q);
|
||||
break;}}},"!^":function(p,c,r,o,n,q){p=p.lastChild;if(p){if(p.nodeType==1){this.push(p,c,r,o,n,q);}else{this["combinator:!+"](p,c,r,o,n,q);}}},"!~":function(q,c,s,p,n,r){while((q=q.previousSibling)){if(q.nodeType!=1){continue;
|
||||
}var o=this.getUID(q);if(this.bitUniques[o]){break;}this.bitUniques[o]=true;this.push(q,c,s,p,n,r);}}};for(var i in j){k["combinator:"+i]=j[i];}var l={empty:function(c){var n=c.firstChild;
|
||||
return !(n&&n.nodeType==1)&&!(c.innerText||c.textContent||"").length;},not:function(c,n){return !this.matchNode(c,n);},contains:function(c,n){return(c.innerText||c.textContent||"").indexOf(n)>-1;
|
||||
},"first-child":function(c){while((c=c.previousSibling)){if(c.nodeType==1){return false;}}return true;},"last-child":function(c){while((c=c.nextSibling)){if(c.nodeType==1){return false;
|
||||
}}return true;},"only-child":function(o){var n=o;while((n=n.previousSibling)){if(n.nodeType==1){return false;}}var c=o;while((c=c.nextSibling)){if(c.nodeType==1){return false;
|
||||
}}return true;},"nth-child":k.createNTHPseudo("firstChild","nextSibling","posNTH"),"nth-last-child":k.createNTHPseudo("lastChild","previousSibling","posNTHLast"),"nth-of-type":k.createNTHPseudo("firstChild","nextSibling","posNTHType",true),"nth-last-of-type":k.createNTHPseudo("lastChild","previousSibling","posNTHTypeLast",true),index:function(n,c){return this["pseudo:nth-child"](n,""+(c+1));
|
||||
},even:function(c){return this["pseudo:nth-child"](c,"2n");},odd:function(c){return this["pseudo:nth-child"](c,"2n+1");},"first-of-type":function(c){var n=c.nodeName;
|
||||
while((c=c.previousSibling)){if(c.nodeName==n){return false;}}return true;},"last-of-type":function(c){var n=c.nodeName;while((c=c.nextSibling)){if(c.nodeName==n){return false;
|
||||
}}return true;},"only-of-type":function(o){var n=o,p=o.nodeName;while((n=n.previousSibling)){if(n.nodeName==p){return false;}}var c=o;while((c=c.nextSibling)){if(c.nodeName==p){return false;
|
||||
}}return true;},enabled:function(c){return !c.disabled;},disabled:function(c){return c.disabled;},checked:function(c){return c.checked||c.selected;},focus:function(c){return this.isHTMLDocument&&this.document.activeElement===c&&(c.href||c.type||this.hasAttribute(c,"tabindex"));
|
||||
},root:function(c){return(c===this.root);},selected:function(c){return c.selected;}};for(var b in l){k["pseudo:"+b]=l[b];}var a=k.attributeGetters={"for":function(){return("htmlFor" in this)?this.htmlFor:this.getAttribute("for");
|
||||
},href:function(){return("href" in this)?this.getAttribute("href",2):this.getAttribute("href");},style:function(){return(this.style)?this.style.cssText:this.getAttribute("style");
|
||||
},tabindex:function(){var c=this.getAttributeNode("tabindex");return(c&&c.specified)?c.nodeValue:null;},type:function(){return this.getAttribute("type");
|
||||
},maxlength:function(){var c=this.getAttributeNode("maxLength");return(c&&c.specified)?c.nodeValue:null;}};a.MAXLENGTH=a.maxLength=a.maxlength;var e=k.Slick=(this.Slick||{});
|
||||
e.version="1.1.7";e.search=function(n,o,c){return k.search(n,o,c);};e.find=function(c,n){return k.search(c,n,null,true);};e.contains=function(c,n){k.setDocument(c);
|
||||
return k.contains(c,n);};e.getAttribute=function(n,c){k.setDocument(n);return k.getAttribute(n,c);};e.hasAttribute=function(n,c){k.setDocument(n);return k.hasAttribute(n,c);
|
||||
};e.match=function(n,c){if(!(n&&c)){return false;}if(!c||c===n){return true;}k.setDocument(n);return k.matchNode(n,c);};e.defineAttributeGetter=function(c,n){k.attributeGetters[c]=n;
|
||||
return this;};e.lookupAttributeGetter=function(c){return k.attributeGetters[c];};e.definePseudo=function(c,n){k["pseudo:"+c]=function(p,o){return n.call(p,o);
|
||||
};return this;};e.lookupPseudo=function(c){var n=k["pseudo:"+c];if(n){return function(o){return n.call(this,o);};}return null;};e.override=function(n,c){k.override(n,c);
|
||||
return this;};e.isXML=k.isXML;e.uidOf=function(c){return k.getUIDHTML(c);};if(!this.Slick){this.Slick=e;}}).apply((typeof exports!="undefined")?exports:this);
|
||||
var Element=function(b,g){var h=Element.Constructors[b];if(h){return h(g);}if(typeof b!="string"){return document.id(b).set(g);}if(!g){g={};}if(!(/^[\w-]+$/).test(b)){var e=Slick.parse(b).expressions[0][0];
|
||||
b=(e.tag=="*")?"div":e.tag;if(e.id&&g.id==null){g.id=e.id;}var d=e.attributes;if(d){for(var a,f=0,c=d.length;f<c;f++){a=d[f];if(g[a.key]!=null){continue;
|
||||
}if(a.value!=null&&a.operator=="="){g[a.key]=a.value;}else{if(!a.value&&!a.operator){g[a.key]=true;}}}}if(e.classList&&g["class"]==null){g["class"]=e.classList.join(" ");
|
||||
}}return document.newElement(b,g);};if(Browser.Element){Element.prototype=Browser.Element.prototype;Element.prototype._fireEvent=(function(a){return function(b,c){return a.call(this,b,c);
|
||||
};})(Element.prototype.fireEvent);}new Type("Element",Element).mirror(function(a){if(Array.prototype[a]){return;}var b={};b[a]=function(){var h=[],e=arguments,j=true;
|
||||
for(var g=0,d=this.length;g<d;g++){var f=this[g],c=h[g]=f[a].apply(f,e);j=(j&&typeOf(c)=="element");}return(j)?new Elements(h):h;};Elements.implement(b);
|
||||
});if(!Browser.Element){Element.parent=Object;Element.Prototype={"$constructor":Element,"$family":Function.from("element").hide()};Element.mirror(function(a,b){Element.Prototype[a]=b;
|
||||
});}Element.Constructors={};var IFrame=new Type("IFrame",function(){var e=Array.link(arguments,{properties:Type.isObject,iframe:function(f){return(f!=null);
|
||||
}});var c=e.properties||{},b;if(e.iframe){b=document.id(e.iframe);}var d=c.onload||function(){};delete c.onload;c.id=c.name=[c.id,c.name,b?(b.id||b.name):"IFrame_"+String.uniqueID()].pick();
|
||||
b=new Element(b||"iframe",c);var a=function(){d.call(b.contentWindow);};if(window.frames[c.id]){a();}else{b.addListener("load",a);}return b;});var Elements=this.Elements=function(a){if(a&&a.length){var e={},d;
|
||||
for(var c=0;d=a[c++];){var b=Slick.uidOf(d);if(!e[b]){e[b]=true;this.push(d);}}}};Elements.prototype={length:0};Elements.parent=Array;new Type("Elements",Elements).implement({filter:function(a,b){if(!a){return this;
|
||||
}return new Elements(Array.filter(this,(typeOf(a)=="string")?function(c){return c.match(a);}:a,b));}.protect(),push:function(){var d=this.length;for(var b=0,a=arguments.length;
|
||||
b<a;b++){var c=document.id(arguments[b]);if(c){this[d++]=c;}}return(this.length=d);}.protect(),unshift:function(){var b=[];for(var c=0,a=arguments.length;
|
||||
c<a;c++){var d=document.id(arguments[c]);if(d){b.push(d);}}return Array.prototype.unshift.apply(this,b);}.protect(),concat:function(){var b=new Elements(this);
|
||||
for(var c=0,a=arguments.length;c<a;c++){var d=arguments[c];if(Type.isEnumerable(d)){b.append(d);}else{b.push(d);}}return b;}.protect(),append:function(c){for(var b=0,a=c.length;
|
||||
b<a;b++){this.push(c[b]);}return this;}.protect(),empty:function(){while(this.length){delete this[--this.length];}return this;}.protect()});(function(){var f=Array.prototype.splice,a={"0":0,"1":1,length:2};
|
||||
f.call(a,1,1);if(a[1]==1){Elements.implement("splice",function(){var g=this.length;var e=f.apply(this,arguments);while(g>=this.length){delete this[g--];
|
||||
}return e;}.protect());}Array.forEachMethod(function(g,e){Elements.implement(e,g);});Array.mirror(Elements);var d;try{d=(document.createElement("<input name=x>").name=="x");
|
||||
}catch(b){}var c=function(e){return(""+e).replace(/&/g,"&").replace(/"/g,""");};Document.implement({newElement:function(e,g){if(g&&g.checked!=null){g.defaultChecked=g.checked;
|
||||
}if(d&&g){e="<"+e;if(g.name){e+=' name="'+c(g.name)+'"';}if(g.type){e+=' type="'+c(g.type)+'"';}e+=">";delete g.name;delete g.type;}return this.id(this.createElement(e)).set(g);
|
||||
}});})();(function(){Slick.uidOf(window);Slick.uidOf(document);Document.implement({newTextNode:function(e){return this.createTextNode(e);},getDocument:function(){return this;
|
||||
},getWindow:function(){return this.window;},id:(function(){var e={string:function(E,D,l){E=Slick.find(l,"#"+E.replace(/(\W)/g,"\\$1"));return(E)?e.element(E,D):null;
|
||||
},element:function(D,E){Slick.uidOf(D);if(!E&&!D.$family&&!(/^(?:object|embed)$/i).test(D.tagName)){var l=D.fireEvent;D._fireEvent=function(F,G){return l(F,G);
|
||||
};Object.append(D,Element.Prototype);}return D;},object:function(D,E,l){if(D.toElement){return e.element(D.toElement(l),E);}return null;}};e.textnode=e.whitespace=e.window=e.document=function(l){return l;
|
||||
};return function(D,F,E){if(D&&D.$family&&D.uniqueNumber){return D;}var l=typeOf(D);return(e[l])?e[l](D,F,E||document):null;};})()});if(window.$==null){Window.implement("$",function(e,l){return document.id(e,l,this.document);
|
||||
});}Window.implement({getDocument:function(){return this.document;},getWindow:function(){return this;}});[Document,Element].invoke("implement",{getElements:function(e){return Slick.search(this,e,new Elements);
|
||||
},getElement:function(e){return document.id(Slick.find(this,e));}});var m={contains:function(e){return Slick.contains(this,e);}};if(!document.contains){Document.implement(m);
|
||||
}if(!document.createElement("div").contains){Element.implement(m);}var r=function(E,D){if(!E){return D;}E=Object.clone(Slick.parse(E));var l=E.expressions;
|
||||
for(var e=l.length;e--;){l[e][0].combinator=D;}return E;};Object.forEach({getNext:"~",getPrevious:"!~",getParent:"!"},function(e,l){Element.implement(l,function(D){return this.getElement(r(D,e));
|
||||
});});Object.forEach({getAllNext:"~",getAllPrevious:"!~",getSiblings:"~~",getChildren:">",getParents:"!"},function(e,l){Element.implement(l,function(D){return this.getElements(r(D,e));
|
||||
});});Element.implement({getFirst:function(e){return document.id(Slick.search(this,r(e,">"))[0]);},getLast:function(e){return document.id(Slick.search(this,r(e,">")).getLast());
|
||||
},getWindow:function(){return this.ownerDocument.window;},getDocument:function(){return this.ownerDocument;},getElementById:function(e){return document.id(Slick.find(this,"#"+(""+e).replace(/(\W)/g,"\\$1")));
|
||||
},match:function(e){return !e||Slick.match(this,e);}});if(window.$$==null){Window.implement("$$",function(e){if(arguments.length==1){if(typeof e=="string"){return Slick.search(this.document,e,new Elements);
|
||||
}else{if(Type.isEnumerable(e)){return new Elements(e);}}}return new Elements(arguments);});}var w={before:function(l,e){var D=e.parentNode;if(D){D.insertBefore(l,e);
|
||||
}},after:function(l,e){var D=e.parentNode;if(D){D.insertBefore(l,e.nextSibling);}},bottom:function(l,e){e.appendChild(l);},top:function(l,e){e.insertBefore(l,e.firstChild);
|
||||
}};w.inside=w.bottom;var j={},d={};var k={};Array.forEach(["type","value","defaultValue","accessKey","cellPadding","cellSpacing","colSpan","frameBorder","rowSpan","tabIndex","useMap"],function(e){k[e.toLowerCase()]=e;
|
||||
});k.html="innerHTML";k.text=(document.createElement("div").textContent==null)?"innerText":"textContent";Object.forEach(k,function(l,e){d[e]=function(D,E){D[l]=E;
|
||||
};j[e]=function(D){return D[l];};});var x=["compact","nowrap","ismap","declare","noshade","checked","disabled","readOnly","multiple","selected","noresize","defer","defaultChecked","autofocus","controls","autoplay","loop"];
|
||||
var h={};Array.forEach(x,function(e){var l=e.toLowerCase();h[l]=e;d[l]=function(D,E){D[e]=!!E;};j[l]=function(D){return !!D[e];};});Object.append(d,{"class":function(e,l){("className" in e)?e.className=(l||""):e.setAttribute("class",l);
|
||||
},"for":function(e,l){("htmlFor" in e)?e.htmlFor=l:e.setAttribute("for",l);},style:function(e,l){(e.style)?e.style.cssText=l:e.setAttribute("style",l);
|
||||
},value:function(e,l){e.value=(l!=null)?l:"";}});j["class"]=function(e){return("className" in e)?e.className||null:e.getAttribute("class");};var f=document.createElement("button");
|
||||
try{f.type="button";}catch(z){}if(f.type!="button"){d.type=function(e,l){e.setAttribute("type",l);};}f=null;var p=document.createElement("input");p.value="t";
|
||||
p.type="submit";if(p.value!="t"){d.type=function(l,e){var D=l.value;l.type=e;l.value=D;};}p=null;var q=(function(e){e.random="attribute";return(e.getAttribute("random")=="attribute");
|
||||
})(document.createElement("div"));Element.implement({setProperty:function(l,D){var E=d[l.toLowerCase()];if(E){E(this,D);}else{if(q){var e=this.retrieve("$attributeWhiteList",{});
|
||||
}if(D==null){this.removeAttribute(l);if(q){delete e[l];}}else{this.setAttribute(l,""+D);if(q){e[l]=true;}}}return this;},setProperties:function(e){for(var l in e){this.setProperty(l,e[l]);
|
||||
}return this;},getProperty:function(F){var D=j[F.toLowerCase()];if(D){return D(this);}if(q){var l=this.getAttributeNode(F),E=this.retrieve("$attributeWhiteList",{});
|
||||
if(!l){return null;}if(l.expando&&!E[F]){var G=this.outerHTML;if(G.substr(0,G.search(/\/?['"]?>(?![^<]*<['"])/)).indexOf(F)<0){return null;}E[F]=true;}}var e=Slick.getAttribute(this,F);
|
||||
return(!e&&!Slick.hasAttribute(this,F))?null:e;},getProperties:function(){var e=Array.from(arguments);return e.map(this.getProperty,this).associate(e);
|
||||
},removeProperty:function(e){return this.setProperty(e,null);},removeProperties:function(){Array.each(arguments,this.removeProperty,this);return this;},set:function(D,l){var e=Element.Properties[D];
|
||||
(e&&e.set)?e.set.call(this,l):this.setProperty(D,l);}.overloadSetter(),get:function(l){var e=Element.Properties[l];return(e&&e.get)?e.get.apply(this):this.getProperty(l);
|
||||
}.overloadGetter(),erase:function(l){var e=Element.Properties[l];(e&&e.erase)?e.erase.apply(this):this.removeProperty(l);return this;},hasClass:function(e){return this.className.clean().contains(e," ");
|
||||
},addClass:function(e){if(!this.hasClass(e)){this.className=(this.className+" "+e).clean();}return this;},removeClass:function(e){this.className=this.className.replace(new RegExp("(^|\\s)"+e+"(?:\\s|$)"),"$1");
|
||||
return this;},toggleClass:function(e,l){if(l==null){l=!this.hasClass(e);}return(l)?this.addClass(e):this.removeClass(e);},adopt:function(){var E=this,e,G=Array.flatten(arguments),F=G.length;
|
||||
if(F>1){E=e=document.createDocumentFragment();}for(var D=0;D<F;D++){var l=document.id(G[D],true);if(l){E.appendChild(l);}}if(e){this.appendChild(e);}return this;
|
||||
},appendText:function(l,e){return this.grab(this.getDocument().newTextNode(l),e);},grab:function(l,e){w[e||"bottom"](document.id(l,true),this);return this;
|
||||
},inject:function(l,e){w[e||"bottom"](this,document.id(l,true));return this;},replaces:function(e){e=document.id(e,true);e.parentNode.replaceChild(this,e);
|
||||
return this;},wraps:function(l,e){l=document.id(l,true);return this.replaces(l).grab(l,e);},getSelected:function(){this.selectedIndex;return new Elements(Array.from(this.options).filter(function(e){return e.selected;
|
||||
}));},toQueryString:function(){var e=[];this.getElements("input, select, textarea").each(function(D){var l=D.type;if(!D.name||D.disabled||l=="submit"||l=="reset"||l=="file"||l=="image"){return;
|
||||
}var E=(D.get("tag")=="select")?D.getSelected().map(function(F){return document.id(F).get("value");}):((l=="radio"||l=="checkbox")&&!D.checked)?null:D.get("value");
|
||||
Array.from(E).each(function(F){if(typeof F!="undefined"){e.push(encodeURIComponent(D.name)+"="+encodeURIComponent(F));}});});return e.join("&");}});var i={},A={};
|
||||
var B=function(e){return(A[e]||(A[e]={}));};var v=function(l){var e=l.uniqueNumber;if(l.removeEvents){l.removeEvents();}if(l.clearAttributes){l.clearAttributes();
|
||||
}if(e!=null){delete i[e];delete A[e];}return l;};var C={input:"checked",option:"selected",textarea:"value"};Element.implement({destroy:function(){var e=v(this).getElementsByTagName("*");
|
||||
Array.each(e,v);Element.dispose(this);return null;},empty:function(){Array.from(this.childNodes).each(Element.dispose);return this;},dispose:function(){return(this.parentNode)?this.parentNode.removeChild(this):this;
|
||||
},clone:function(G,E){G=G!==false;var L=this.cloneNode(G),D=[L],F=[this],J;if(G){D.append(Array.from(L.getElementsByTagName("*")));F.append(Array.from(this.getElementsByTagName("*")));
|
||||
}for(J=D.length;J--;){var H=D[J],K=F[J];if(!E){H.removeAttribute("id");}if(H.clearAttributes){H.clearAttributes();H.mergeAttributes(K);H.removeAttribute("uniqueNumber");
|
||||
if(H.options){var O=H.options,e=K.options;for(var I=O.length;I--;){O[I].selected=e[I].selected;}}}var l=C[K.tagName.toLowerCase()];if(l&&K[l]){H[l]=K[l];
|
||||
}}if(Browser.ie){var M=L.getElementsByTagName("object"),N=this.getElementsByTagName("object");for(J=M.length;J--;){M[J].outerHTML=N[J].outerHTML;}}return document.id(L);
|
||||
}});[Element,Window,Document].invoke("implement",{addListener:function(E,D){if(E=="unload"){var e=D,l=this;D=function(){l.removeListener("unload",D);e();
|
||||
};}else{i[Slick.uidOf(this)]=this;}if(this.addEventListener){this.addEventListener(E,D,!!arguments[2]);}else{this.attachEvent("on"+E,D);}return this;},removeListener:function(l,e){if(this.removeEventListener){this.removeEventListener(l,e,!!arguments[2]);
|
||||
}else{this.detachEvent("on"+l,e);}return this;},retrieve:function(l,e){var E=B(Slick.uidOf(this)),D=E[l];if(e!=null&&D==null){D=E[l]=e;}return D!=null?D:null;
|
||||
},store:function(l,e){var D=B(Slick.uidOf(this));D[l]=e;return this;},eliminate:function(e){var l=B(Slick.uidOf(this));delete l[e];return this;}});if(window.attachEvent&&!window.addEventListener){window.addListener("unload",function(){Object.each(i,v);
|
||||
if(window.CollectGarbage){CollectGarbage();}});}Element.Properties={};Element.Properties.style={set:function(e){this.style.cssText=e;},get:function(){return this.style.cssText;
|
||||
},erase:function(){this.style.cssText="";}};Element.Properties.tag={get:function(){return this.tagName.toLowerCase();}};Element.Properties.html={set:function(e){if(e==null){e="";
|
||||
}else{if(typeOf(e)=="array"){e=e.join("");}}this.innerHTML=e;},erase:function(){this.innerHTML="";}};var t=document.createElement("div");t.innerHTML="<nav></nav>";
|
||||
var a=(t.childNodes.length==1);if(!a){var s="abbr article aside audio canvas datalist details figcaption figure footer header hgroup mark meter nav output progress section summary time video".split(" "),b=document.createDocumentFragment(),u=s.length;
|
||||
while(u--){b.createElement(s[u]);}}t=null;var g=Function.attempt(function(){var e=document.createElement("table");e.innerHTML="<tr><td></td></tr>";return true;
|
||||
});var c=document.createElement("tr"),o="<td></td>";c.innerHTML=o;var y=(c.innerHTML==o);c=null;if(!g||!y||!a){Element.Properties.html.set=(function(l){var e={table:[1,"<table>","</table>"],select:[1,"<select>","</select>"],tbody:[2,"<table><tbody>","</tbody></table>"],tr:[3,"<table><tbody><tr>","</tr></tbody></table>"]};
|
||||
e.thead=e.tfoot=e.tbody;return function(D){var E=e[this.get("tag")];if(!E&&!a){E=[0,"",""];}if(!E){return l.call(this,D);}var H=E[0],G=document.createElement("div"),F=G;
|
||||
if(!a){b.appendChild(G);}G.innerHTML=[E[1],D,E[2]].flatten().join("");while(H--){F=F.firstChild;}this.empty().adopt(F.childNodes);if(!a){b.removeChild(G);
|
||||
}G=null;};})(Element.Properties.html.set);}var n=document.createElement("form");n.innerHTML="<select><option>s</option></select>";if(n.firstChild.value!="s"){Element.Properties.value={set:function(G){var l=this.get("tag");
|
||||
if(l!="select"){return this.setProperty("value",G);}var D=this.getElements("option");for(var E=0;E<D.length;E++){var F=D[E],e=F.getAttributeNode("value"),H=(e&&e.specified)?F.value:F.get("text");
|
||||
if(H==G){return F.selected=true;}}},get:function(){var D=this,l=D.get("tag");if(l!="select"&&l!="option"){return this.getProperty("value");}if(l=="select"&&!(D=D.getSelected()[0])){return"";
|
||||
}var e=D.getAttributeNode("value");return(e&&e.specified)?D.value:D.get("text");}};}n=null;if(document.createElement("div").getAttributeNode("id")){Element.Properties.id={set:function(e){this.id=this.getAttributeNode("id").value=e;
|
||||
},get:function(){return this.id||null;},erase:function(){this.id=this.getAttributeNode("id").value="";}};}})();(function(){var i=document.html;var d=document.createElement("div");
|
||||
d.style.color="red";d.style.color=null;var c=d.style.color=="red";d=null;Element.Properties.styles={set:function(k){this.setStyles(k);}};var h=(i.style.opacity!=null),e=(i.style.filter!=null),j=/alpha\(opacity=([\d.]+)\)/i;
|
||||
var a=function(l,k){l.store("$opacity",k);l.style.visibility=k>0||k==null?"visible":"hidden";};var f=(h?function(l,k){l.style.opacity=k;}:(e?function(l,k){var n=l.style;
|
||||
if(!l.currentStyle||!l.currentStyle.hasLayout){n.zoom=1;}if(k==null||k==1){k="";}else{k="alpha(opacity="+(k*100).limit(0,100).round()+")";}var m=n.filter||l.getComputedStyle("filter")||"";
|
||||
n.filter=j.test(m)?m.replace(j,k):m+k;if(!n.filter){n.removeAttribute("filter");}}:a));var g=(h?function(l){var k=l.style.opacity||l.getComputedStyle("opacity");
|
||||
return(k=="")?1:k.toFloat();}:(e?function(l){var m=(l.style.filter||l.getComputedStyle("filter")),k;if(m){k=m.match(j);}return(k==null||m==null)?1:(k[1]/100);
|
||||
}:function(l){var k=l.retrieve("$opacity");if(k==null){k=(l.style.visibility=="hidden"?0:1);}return k;}));var b=(i.style.cssFloat==null)?"styleFloat":"cssFloat";
|
||||
Element.implement({getComputedStyle:function(m){if(this.currentStyle){return this.currentStyle[m.camelCase()];}var l=Element.getDocument(this).defaultView,k=l?l.getComputedStyle(this,null):null;
|
||||
return(k)?k.getPropertyValue((m==b)?"float":m.hyphenate()):null;},setStyle:function(l,k){if(l=="opacity"){if(k!=null){k=parseFloat(k);}f(this,k);return this;
|
||||
}l=(l=="float"?b:l).camelCase();if(typeOf(k)!="string"){var m=(Element.Styles[l]||"@").split(" ");k=Array.from(k).map(function(o,n){if(!m[n]){return"";
|
||||
}return(typeOf(o)=="number")?m[n].replace("@",Math.round(o)):o;}).join(" ");}else{if(k==String(Number(k))){k=Math.round(k);}}this.style[l]=k;if((k==""||k==null)&&c&&this.style.removeAttribute){this.style.removeAttribute(l);
|
||||
}return this;},getStyle:function(q){if(q=="opacity"){return g(this);}q=(q=="float"?b:q).camelCase();var k=this.style[q];if(!k||q=="zIndex"){k=[];for(var p in Element.ShortStyles){if(q!=p){continue;
|
||||
}for(var o in Element.ShortStyles[p]){k.push(this.getStyle(o));}return k.join(" ");}k=this.getComputedStyle(q);}if(k){k=String(k);var m=k.match(/rgba?\([\d\s,]+\)/);
|
||||
if(m){k=k.replace(m[0],m[0].rgbToHex());}}if(Browser.opera||Browser.ie){if((/^(height|width)$/).test(q)&&!(/px$/.test(k))){var l=(q=="width")?["left","right"]:["top","bottom"],n=0;
|
||||
l.each(function(r){n+=this.getStyle("border-"+r+"-width").toInt()+this.getStyle("padding-"+r).toInt();},this);return this["offset"+q.capitalize()]-n+"px";
|
||||
}if(Browser.ie&&(/^border(.+)Width|margin|padding/).test(q)&&isNaN(parseFloat(k))){return"0px";}}return k;},setStyles:function(l){for(var k in l){this.setStyle(k,l[k]);
|
||||
}return this;},getStyles:function(){var k={};Array.flatten(arguments).each(function(l){k[l]=this.getStyle(l);},this);return k;}});Element.Styles={left:"@px",top:"@px",bottom:"@px",right:"@px",width:"@px",height:"@px",maxWidth:"@px",maxHeight:"@px",minWidth:"@px",minHeight:"@px",backgroundColor:"rgb(@, @, @)",backgroundPosition:"@px @px",color:"rgb(@, @, @)",fontSize:"@px",letterSpacing:"@px",lineHeight:"@px",clip:"rect(@px @px @px @px)",margin:"@px @px @px @px",padding:"@px @px @px @px",border:"@px @ rgb(@, @, @) @px @ rgb(@, @, @) @px @ rgb(@, @, @)",borderWidth:"@px @px @px @px",borderStyle:"@ @ @ @",borderColor:"rgb(@, @, @) rgb(@, @, @) rgb(@, @, @) rgb(@, @, @)",zIndex:"@",zoom:"@",fontWeight:"@",textIndent:"@px",opacity:"@"};
|
||||
Element.ShortStyles={margin:{},padding:{},border:{},borderWidth:{},borderStyle:{},borderColor:{}};["Top","Right","Bottom","Left"].each(function(q){var p=Element.ShortStyles;
|
||||
var l=Element.Styles;["margin","padding"].each(function(r){var s=r+q;p[r][s]=l[s]="@px";});var o="border"+q;p.border[o]=l[o]="@px @ rgb(@, @, @)";var n=o+"Width",k=o+"Style",m=o+"Color";
|
||||
p[o]={};p.borderWidth[n]=p[o][n]=l[n]="@px";p.borderStyle[k]=p[o][k]=l[k]="@";p.borderColor[m]=p[o][m]=l[m]="rgb(@, @, @)";});})();(function(){Element.Properties.events={set:function(b){this.addEvents(b);
|
||||
}};[Element,Window,Document].invoke("implement",{addEvent:function(f,h){var i=this.retrieve("events",{});if(!i[f]){i[f]={keys:[],values:[]};}if(i[f].keys.contains(h)){return this;
|
||||
}i[f].keys.push(h);var g=f,b=Element.Events[f],d=h,j=this;if(b){if(b.onAdd){b.onAdd.call(this,h,f);}if(b.condition){d=function(k){if(b.condition.call(this,k,f)){return h.call(this,k);
|
||||
}return true;};}if(b.base){g=Function.from(b.base).call(this,f);}}var e=function(){return h.call(j);};var c=Element.NativeEvents[g];if(c){if(c==2){e=function(k){k=new DOMEvent(k,j.getWindow());
|
||||
if(d.call(j,k)===false){k.stop();}};}this.addListener(g,e,arguments[2]);}i[f].values.push(e);return this;},removeEvent:function(e,d){var c=this.retrieve("events");
|
||||
if(!c||!c[e]){return this;}var h=c[e];var b=h.keys.indexOf(d);if(b==-1){return this;}var g=h.values[b];delete h.keys[b];delete h.values[b];var f=Element.Events[e];
|
||||
if(f){if(f.onRemove){f.onRemove.call(this,d,e);}if(f.base){e=Function.from(f.base).call(this,e);}}return(Element.NativeEvents[e])?this.removeListener(e,g,arguments[2]):this;
|
||||
},addEvents:function(b){for(var c in b){this.addEvent(c,b[c]);}return this;},removeEvents:function(b){var d;if(typeOf(b)=="object"){for(d in b){this.removeEvent(d,b[d]);
|
||||
}return this;}var c=this.retrieve("events");if(!c){return this;}if(!b){for(d in c){this.removeEvents(d);}this.eliminate("events");}else{if(c[b]){c[b].keys.each(function(e){this.removeEvent(b,e);
|
||||
},this);delete c[b];}}return this;},fireEvent:function(e,c,b){var d=this.retrieve("events");if(!d||!d[e]){return this;}c=Array.from(c);d[e].keys.each(function(f){if(b){f.delay(b,this,c);
|
||||
}else{f.apply(this,c);}},this);return this;},cloneEvents:function(e,d){e=document.id(e);var c=e.retrieve("events");if(!c){return this;}if(!d){for(var b in c){this.cloneEvents(e,b);
|
||||
}}else{if(c[d]){c[d].keys.each(function(f){this.addEvent(d,f);},this);}}return this;}});Element.NativeEvents={click:2,dblclick:2,mouseup:2,mousedown:2,contextmenu:2,mousewheel:2,DOMMouseScroll:2,mouseover:2,mouseout:2,mousemove:2,selectstart:2,selectend:2,keydown:2,keypress:2,keyup:2,orientationchange:2,touchstart:2,touchmove:2,touchend:2,touchcancel:2,gesturestart:2,gesturechange:2,gestureend:2,focus:2,blur:2,change:2,reset:2,select:2,submit:2,paste:2,input:2,load:2,unload:1,beforeunload:2,resize:1,move:1,DOMContentLoaded:1,readystatechange:1,error:1,abort:1,scroll:1};
|
||||
Element.Events={mousewheel:{base:(Browser.firefox)?"DOMMouseScroll":"mousewheel"}};if("onmouseenter" in document.documentElement){Element.NativeEvents.mouseenter=Element.NativeEvents.mouseleave=2;
|
||||
}else{var a=function(b){var c=b.relatedTarget;if(c==null){return true;}if(!c){return false;}return(c!=this&&c.prefix!="xul"&&typeOf(this)!="document"&&!this.contains(c));
|
||||
};Element.Events.mouseenter={base:"mouseover",condition:a};Element.Events.mouseleave={base:"mouseout",condition:a};}if(!window.addEventListener){Element.NativeEvents.propertychange=2;
|
||||
Element.Events.change={base:function(){var b=this.type;return(this.get("tag")=="input"&&(b=="radio"||b=="checkbox"))?"propertychange":"change";},condition:function(b){return this.type!="radio"||(b.event.propertyName=="checked"&&this.checked);
|
||||
}};}})();(function(){var c=!!window.addEventListener;Element.NativeEvents.focusin=Element.NativeEvents.focusout=2;var k=function(l,m,n,o,p){while(p&&p!=l){if(m(p,o)){return n.call(p,o,p);
|
||||
}p=document.id(p.parentNode);}};var a={mouseenter:{base:"mouseover"},mouseleave:{base:"mouseout"},focus:{base:"focus"+(c?"":"in"),capture:true},blur:{base:c?"blur":"focusout",capture:true}};
|
||||
var b="$delegation:";var i=function(l){return{base:"focusin",remove:function(m,o){var p=m.retrieve(b+l+"listeners",{})[o];if(p&&p.forms){for(var n=p.forms.length;
|
||||
n--;){p.forms[n].removeEvent(l,p.fns[n]);}}},listen:function(x,r,v,n,t,s){var o=(t.get("tag")=="form")?t:n.target.getParent("form");if(!o){return;}var u=x.retrieve(b+l+"listeners",{}),p=u[s]||{forms:[],fns:[]},m=p.forms,w=p.fns;
|
||||
if(m.indexOf(o)!=-1){return;}m.push(o);var q=function(y){k(x,r,v,y,t);};o.addEvent(l,q);w.push(q);u[s]=p;x.store(b+l+"listeners",u);}};};var d=function(l){return{base:"focusin",listen:function(m,n,p,q,r){var o={blur:function(){this.removeEvents(o);
|
||||
}};o[l]=function(s){k(m,n,p,s,r);};q.target.addEvents(o);}};};if(!c){Object.append(a,{submit:i("submit"),reset:i("reset"),change:d("change"),select:d("select")});
|
||||
}var h=Element.prototype,f=h.addEvent,j=h.removeEvent;var e=function(l,m){return function(r,q,n){if(r.indexOf(":relay")==-1){return l.call(this,r,q,n);
|
||||
}var o=Slick.parse(r).expressions[0][0];if(o.pseudos[0].key!="relay"){return l.call(this,r,q,n);}var p=o.tag;o.pseudos.slice(1).each(function(s){p+=":"+s.key+(s.value?"("+s.value+")":"");
|
||||
});l.call(this,r,q);return m.call(this,p,o.pseudos[0].value,q);};};var g={addEvent:function(v,q,x){var t=this.retrieve("$delegates",{}),r=t[v];if(r){for(var y in r){if(r[y].fn==x&&r[y].match==q){return this;
|
||||
}}}var p=v,u=q,o=x,n=a[v]||{};v=n.base||p;q=function(B){return Slick.match(B,u);};var w=Element.Events[p];if(w&&w.condition){var l=q,m=w.condition;q=function(C,B){return l(C,B)&&m.call(C,B,v);
|
||||
};}var z=this,s=String.uniqueID();var A=n.listen?function(B,C){if(!C&&B&&B.target){C=B.target;}if(C){n.listen(z,q,x,B,C,s);}}:function(B,C){if(!C&&B&&B.target){C=B.target;
|
||||
}if(C){k(z,q,x,B,C);}};if(!r){r={};}r[s]={match:u,fn:o,delegator:A};t[p]=r;return f.call(this,v,A,n.capture);},removeEvent:function(r,n,t,u){var q=this.retrieve("$delegates",{}),p=q[r];
|
||||
if(!p){return this;}if(u){var m=r,w=p[u].delegator,l=a[r]||{};r=l.base||m;if(l.remove){l.remove(this,u);}delete p[u];q[m]=p;return j.call(this,r,w);}var o,v;
|
||||
if(t){for(o in p){v=p[o];if(v.match==n&&v.fn==t){return g.removeEvent.call(this,r,n,t,o);}}}else{for(o in p){v=p[o];if(v.match==n){g.removeEvent.call(this,r,n,v.fn,o);
|
||||
}}}return this;}};[Element,Window,Document].invoke("implement",{addEvent:e(f,g.addEvent),removeEvent:e(j,g.removeEvent)});})();(function(){var h=document.createElement("div"),e=document.createElement("div");
|
||||
h.style.height="0";h.appendChild(e);var d=(e.offsetParent===h);h=e=null;var l=function(m){return k(m,"position")!="static"||a(m);};var i=function(m){return l(m)||(/^(?:table|td|th)$/i).test(m.tagName);
|
||||
};Element.implement({scrollTo:function(m,n){if(a(this)){this.getWindow().scrollTo(m,n);}else{this.scrollLeft=m;this.scrollTop=n;}return this;},getSize:function(){if(a(this)){return this.getWindow().getSize();
|
||||
}return{x:this.offsetWidth,y:this.offsetHeight};},getScrollSize:function(){if(a(this)){return this.getWindow().getScrollSize();}return{x:this.scrollWidth,y:this.scrollHeight};
|
||||
},getScroll:function(){if(a(this)){return this.getWindow().getScroll();}return{x:this.scrollLeft,y:this.scrollTop};},getScrolls:function(){var n=this.parentNode,m={x:0,y:0};
|
||||
while(n&&!a(n)){m.x+=n.scrollLeft;m.y+=n.scrollTop;n=n.parentNode;}return m;},getOffsetParent:d?function(){var m=this;if(a(m)||k(m,"position")=="fixed"){return null;
|
||||
}var n=(k(m,"position")=="static")?i:l;while((m=m.parentNode)){if(n(m)){return m;}}return null;}:function(){var m=this;if(a(m)||k(m,"position")=="fixed"){return null;
|
||||
}try{return m.offsetParent;}catch(n){}return null;},getOffsets:function(){if(this.getBoundingClientRect&&!Browser.Platform.ios){var r=this.getBoundingClientRect(),o=document.id(this.getDocument().documentElement),q=o.getScroll(),t=this.getScrolls(),s=(k(this,"position")=="fixed");
|
||||
return{x:r.left.toInt()+t.x+((s)?0:q.x)-o.clientLeft,y:r.top.toInt()+t.y+((s)?0:q.y)-o.clientTop};}var n=this,m={x:0,y:0};if(a(this)){return m;}while(n&&!a(n)){m.x+=n.offsetLeft;
|
||||
m.y+=n.offsetTop;if(Browser.firefox){if(!c(n)){m.x+=b(n);m.y+=g(n);}var p=n.parentNode;if(p&&k(p,"overflow")!="visible"){m.x+=b(p);m.y+=g(p);}}else{if(n!=this&&Browser.safari){m.x+=b(n);
|
||||
m.y+=g(n);}}n=n.offsetParent;}if(Browser.firefox&&!c(this)){m.x-=b(this);m.y-=g(this);}return m;},getPosition:function(p){var q=this.getOffsets(),n=this.getScrolls();
|
||||
var m={x:q.x-n.x,y:q.y-n.y};if(p&&(p=document.id(p))){var o=p.getPosition();return{x:m.x-o.x-b(p),y:m.y-o.y-g(p)};}return m;},getCoordinates:function(o){if(a(this)){return this.getWindow().getCoordinates();
|
||||
}var m=this.getPosition(o),n=this.getSize();var p={left:m.x,top:m.y,width:n.x,height:n.y};p.right=p.left+p.width;p.bottom=p.top+p.height;return p;},computePosition:function(m){return{left:m.x-j(this,"margin-left"),top:m.y-j(this,"margin-top")};
|
||||
},setPosition:function(m){return this.setStyles(this.computePosition(m));}});[Document,Window].invoke("implement",{getSize:function(){var m=f(this);return{x:m.clientWidth,y:m.clientHeight};
|
||||
},getScroll:function(){var n=this.getWindow(),m=f(this);return{x:n.pageXOffset||m.scrollLeft,y:n.pageYOffset||m.scrollTop};},getScrollSize:function(){var o=f(this),n=this.getSize(),m=this.getDocument().body;
|
||||
return{x:Math.max(o.scrollWidth,m.scrollWidth,n.x),y:Math.max(o.scrollHeight,m.scrollHeight,n.y)};},getPosition:function(){return{x:0,y:0};},getCoordinates:function(){var m=this.getSize();
|
||||
return{top:0,left:0,bottom:m.y,right:m.x,height:m.y,width:m.x};}});var k=Element.getComputedStyle;function j(m,n){return k(m,n).toInt()||0;}function c(m){return k(m,"-moz-box-sizing")=="border-box";
|
||||
}function g(m){return j(m,"border-top-width");}function b(m){return j(m,"border-left-width");}function a(m){return(/^(?:body|html)$/i).test(m.tagName);
|
||||
}function f(m){var n=m.getDocument();return(!n.compatMode||n.compatMode=="CSS1Compat")?n.html:n.body;}})();Element.alias({position:"setPosition"});[Window,Document,Element].invoke("implement",{getHeight:function(){return this.getSize().y;
|
||||
},getWidth:function(){return this.getSize().x;},getScrollTop:function(){return this.getScroll().y;},getScrollLeft:function(){return this.getScroll().x;
|
||||
},getScrollHeight:function(){return this.getScrollSize().y;},getScrollWidth:function(){return this.getScrollSize().x;},getTop:function(){return this.getPosition().y;
|
||||
},getLeft:function(){return this.getPosition().x;}});(function(){var f=this.Fx=new Class({Implements:[Chain,Events,Options],options:{fps:60,unit:false,duration:500,frames:null,frameSkip:true,link:"ignore"},initialize:function(g){this.subject=this.subject||this;
|
||||
this.setOptions(g);},getTransition:function(){return function(g){return -(Math.cos(Math.PI*g)-1)/2;};},step:function(g){if(this.options.frameSkip){var h=(this.time!=null)?(g-this.time):0,i=h/this.frameInterval;
|
||||
this.time=g;this.frame+=i;}else{this.frame++;}if(this.frame<this.frames){var j=this.transition(this.frame/this.frames);this.set(this.compute(this.from,this.to,j));
|
||||
}else{this.frame=this.frames;this.set(this.compute(this.from,this.to,1));this.stop();}},set:function(g){return g;},compute:function(i,h,g){return f.compute(i,h,g);
|
||||
},check:function(){if(!this.isRunning()){return true;}switch(this.options.link){case"cancel":this.cancel();return true;case"chain":this.chain(this.caller.pass(arguments,this));
|
||||
return false;}return false;},start:function(k,j){if(!this.check(k,j)){return this;}this.from=k;this.to=j;this.frame=(this.options.frameSkip)?0:-1;this.time=null;
|
||||
this.transition=this.getTransition();var i=this.options.frames,h=this.options.fps,g=this.options.duration;this.duration=f.Durations[g]||g.toInt();this.frameInterval=1000/h;
|
||||
this.frames=i||Math.round(this.duration/this.frameInterval);this.fireEvent("start",this.subject);b.call(this,h);return this;},stop:function(){if(this.isRunning()){this.time=null;
|
||||
d.call(this,this.options.fps);if(this.frames==this.frame){this.fireEvent("complete",this.subject);if(!this.callChain()){this.fireEvent("chainComplete",this.subject);
|
||||
}}else{this.fireEvent("stop",this.subject);}}return this;},cancel:function(){if(this.isRunning()){this.time=null;d.call(this,this.options.fps);this.frame=this.frames;
|
||||
this.fireEvent("cancel",this.subject).clearChain();}return this;},pause:function(){if(this.isRunning()){this.time=null;d.call(this,this.options.fps);}return this;
|
||||
},resume:function(){if((this.frame<this.frames)&&!this.isRunning()){b.call(this,this.options.fps);}return this;},isRunning:function(){var g=e[this.options.fps];
|
||||
return g&&g.contains(this);}});f.compute=function(i,h,g){return(h-i)*g+i;};f.Durations={"short":250,normal:500,"long":1000};var e={},c={};var a=function(){var h=Date.now();
|
||||
for(var j=this.length;j--;){var g=this[j];if(g){g.step(h);}}};var b=function(h){var g=e[h]||(e[h]=[]);g.push(this);if(!c[h]){c[h]=a.periodical(Math.round(1000/h),g);
|
||||
}};var d=function(h){var g=e[h];if(g){g.erase(this);if(!g.length&&c[h]){delete e[h];c[h]=clearInterval(c[h]);}}};})();Fx.CSS=new Class({Extends:Fx,prepare:function(b,e,a){a=Array.from(a);
|
||||
var h=a[0],g=a[1];if(g==null){g=h;h=b.getStyle(e);var c=this.options.unit;if(c&&h.slice(-c.length)!=c&&parseFloat(h)!=0){b.setStyle(e,g+c);var d=b.getComputedStyle(e);
|
||||
if(!(/px$/.test(d))){d=b.style[("pixel-"+e).camelCase()];if(d==null){var f=b.style.left;b.style.left=g+c;d=b.style.pixelLeft;b.style.left=f;}}h=(g||1)/(parseFloat(d)||1)*(parseFloat(h)||0);
|
||||
b.setStyle(e,h+c);}}return{from:this.parse(h),to:this.parse(g)};},parse:function(a){a=Function.from(a)();a=(typeof a=="string")?a.split(" "):Array.from(a);
|
||||
return a.map(function(c){c=String(c);var b=false;Object.each(Fx.CSS.Parsers,function(f,e){if(b){return;}var d=f.parse(c);if(d||d===0){b={value:d,parser:f};
|
||||
}});b=b||{value:c,parser:Fx.CSS.Parsers.String};return b;});},compute:function(d,c,b){var a=[];(Math.min(d.length,c.length)).times(function(e){a.push({value:d[e].parser.compute(d[e].value,c[e].value,b),parser:d[e].parser});
|
||||
});a.$family=Function.from("fx:css:value");return a;},serve:function(c,b){if(typeOf(c)!="fx:css:value"){c=this.parse(c);}var a=[];c.each(function(d){a=a.concat(d.parser.serve(d.value,b));
|
||||
});return a;},render:function(a,d,c,b){a.setStyle(d,this.serve(c,b));},search:function(a){if(Fx.CSS.Cache[a]){return Fx.CSS.Cache[a];}var c={},b=new RegExp("^"+a.escapeRegExp()+"$");
|
||||
Array.each(document.styleSheets,function(f,e){var d=f.href;if(d&&d.contains("://")&&!d.contains(document.domain)){return;}var g=f.rules||f.cssRules;Array.each(g,function(k,h){if(!k.style){return;
|
||||
}var j=(k.selectorText)?k.selectorText.replace(/^\w+/,function(i){return i.toLowerCase();}):null;if(!j||!b.test(j)){return;}Object.each(Element.Styles,function(l,i){if(!k.style[i]||Element.ShortStyles[i]){return;
|
||||
}l=String(k.style[i]);c[i]=((/^rgb/).test(l))?l.rgbToHex():l;});});});return Fx.CSS.Cache[a]=c;}});Fx.CSS.Cache={};Fx.CSS.Parsers={Color:{parse:function(a){if(a.match(/^#[0-9a-f]{3,6}$/i)){return a.hexToRgb(true);
|
||||
}return((a=a.match(/(\d+),\s*(\d+),\s*(\d+)/)))?[a[1],a[2],a[3]]:false;},compute:function(c,b,a){return c.map(function(e,d){return Math.round(Fx.compute(c[d],b[d],a));
|
||||
});},serve:function(a){return a.map(Number);}},Number:{parse:parseFloat,compute:Fx.compute,serve:function(b,a){return(a)?b+a:b;}},String:{parse:Function.from(false),compute:function(b,a){return a;
|
||||
},serve:function(a){return a;}}};Fx.Tween=new Class({Extends:Fx.CSS,initialize:function(b,a){this.element=this.subject=document.id(b);this.parent(a);},set:function(b,a){if(arguments.length==1){a=b;
|
||||
b=this.property||this.options.property;}this.render(this.element,b,a,this.options.unit);return this;},start:function(c,e,d){if(!this.check(c,e,d)){return this;
|
||||
}var b=Array.flatten(arguments);this.property=this.options.property||b.shift();var a=this.prepare(this.element,this.property,b);return this.parent(a.from,a.to);
|
||||
}});Element.Properties.tween={set:function(a){this.get("tween").cancel().setOptions(a);return this;},get:function(){var a=this.retrieve("tween");if(!a){a=new Fx.Tween(this,{link:"cancel"});
|
||||
this.store("tween",a);}return a;}};Element.implement({tween:function(a,c,b){this.get("tween").start(a,c,b);return this;},fade:function(d){var e=this.get("tween"),g,c=["opacity"].append(arguments),a;
|
||||
if(c[1]==null){c[1]="toggle";}switch(c[1]){case"in":g="start";c[1]=1;break;case"out":g="start";c[1]=0;break;case"show":g="set";c[1]=1;break;case"hide":g="set";
|
||||
c[1]=0;break;case"toggle":var b=this.retrieve("fade:flag",this.getStyle("opacity")==1);g="start";c[1]=b?0:1;this.store("fade:flag",!b);a=true;break;default:g="start";
|
||||
}if(!a){this.eliminate("fade:flag");}e[g].apply(e,c);var f=c[c.length-1];if(g=="set"||f!=0){this.setStyle("visibility",f==0?"hidden":"visible");}else{e.chain(function(){this.element.setStyle("visibility","hidden");
|
||||
this.callChain();});}return this;},highlight:function(c,a){if(!a){a=this.retrieve("highlight:original",this.getStyle("background-color"));a=(a=="transparent")?"#fff":a;
|
||||
}var b=this.get("tween");b.start("background-color",c||"#ffff88",a).chain(function(){this.setStyle("background-color",this.retrieve("highlight:original"));
|
||||
b.callChain();}.bind(this));return this;}});Fx.Morph=new Class({Extends:Fx.CSS,initialize:function(b,a){this.element=this.subject=document.id(b);this.parent(a);
|
||||
},set:function(a){if(typeof a=="string"){a=this.search(a);}for(var b in a){this.render(this.element,b,a[b],this.options.unit);}return this;},compute:function(e,d,c){var a={};
|
||||
for(var b in e){a[b]=this.parent(e[b],d[b],c);}return a;},start:function(b){if(!this.check(b)){return this;}if(typeof b=="string"){b=this.search(b);}var e={},d={};
|
||||
for(var c in b){var a=this.prepare(this.element,c,b[c]);e[c]=a.from;d[c]=a.to;}return this.parent(e,d);}});Element.Properties.morph={set:function(a){this.get("morph").cancel().setOptions(a);
|
||||
return this;},get:function(){var a=this.retrieve("morph");if(!a){a=new Fx.Morph(this,{link:"cancel"});this.store("morph",a);}return a;}};Element.implement({morph:function(a){this.get("morph").start(a);
|
||||
return this;}});Fx.implement({getTransition:function(){var a=this.options.transition||Fx.Transitions.Sine.easeInOut;if(typeof a=="string"){var b=a.split(":");
|
||||
a=Fx.Transitions;a=a[b[0]]||a[b[0].capitalize()];if(b[1]){a=a["ease"+b[1].capitalize()+(b[2]?b[2].capitalize():"")];}}return a;}});Fx.Transition=function(c,b){b=Array.from(b);
|
||||
var a=function(d){return c(d,b);};return Object.append(a,{easeIn:a,easeOut:function(d){return 1-c(1-d,b);},easeInOut:function(d){return(d<=0.5?c(2*d,b):(2-c(2*(1-d),b)))/2;
|
||||
}});};Fx.Transitions={linear:function(a){return a;}};Fx.Transitions.extend=function(a){for(var b in a){Fx.Transitions[b]=new Fx.Transition(a[b]);}};Fx.Transitions.extend({Pow:function(b,a){return Math.pow(b,a&&a[0]||6);
|
||||
},Expo:function(a){return Math.pow(2,8*(a-1));},Circ:function(a){return 1-Math.sin(Math.acos(a));},Sine:function(a){return 1-Math.cos(a*Math.PI/2);},Back:function(b,a){a=a&&a[0]||1.618;
|
||||
return Math.pow(b,2)*((a+1)*b-a);},Bounce:function(f){var e;for(var d=0,c=1;1;d+=c,c/=2){if(f>=(7-4*d)/11){e=c*c-Math.pow((11-6*d-11*f)/4,2);break;}}return e;
|
||||
},Elastic:function(b,a){return Math.pow(2,10*--b)*Math.cos(20*b*Math.PI*(a&&a[0]||1)/3);}});["Quad","Cubic","Quart","Quint"].each(function(b,a){Fx.Transitions[b]=new Fx.Transition(function(c){return Math.pow(c,a+2);
|
||||
});});(function(){var d=function(){},a=("onprogress" in new Browser.Request);var c=this.Request=new Class({Implements:[Chain,Events,Options],options:{url:"",data:"",headers:{"X-Requested-With":"XMLHttpRequest",Accept:"text/javascript, text/html, application/xml, text/xml, */*"},async:true,format:false,method:"post",link:"ignore",isSuccess:null,emulation:true,urlEncoded:true,encoding:"utf-8",evalScripts:false,evalResponse:false,timeout:0,noCache:false},initialize:function(e){this.xhr=new Browser.Request();
|
||||
this.setOptions(e);this.headers=this.options.headers;},onStateChange:function(){var e=this.xhr;if(e.readyState!=4||!this.running){return;}this.running=false;
|
||||
this.status=0;Function.attempt(function(){var f=e.status;this.status=(f==1223)?204:f;}.bind(this));e.onreadystatechange=d;if(a){e.onprogress=e.onloadstart=d;
|
||||
}clearTimeout(this.timer);this.response={text:this.xhr.responseText||"",xml:this.xhr.responseXML};if(this.options.isSuccess.call(this,this.status)){this.success(this.response.text,this.response.xml);
|
||||
}else{this.failure();}},isSuccess:function(){var e=this.status;return(e>=200&&e<300);},isRunning:function(){return !!this.running;},processScripts:function(e){if(this.options.evalResponse||(/(ecma|java)script/).test(this.getHeader("Content-type"))){return Browser.exec(e);
|
||||
}return e.stripScripts(this.options.evalScripts);},success:function(f,e){this.onSuccess(this.processScripts(f),e);},onSuccess:function(){this.fireEvent("complete",arguments).fireEvent("success",arguments).callChain();
|
||||
},failure:function(){this.onFailure();},onFailure:function(){this.fireEvent("complete").fireEvent("failure",this.xhr);},loadstart:function(e){this.fireEvent("loadstart",[e,this.xhr]);
|
||||
},progress:function(e){this.fireEvent("progress",[e,this.xhr]);},timeout:function(){this.fireEvent("timeout",this.xhr);},setHeader:function(e,f){this.headers[e]=f;
|
||||
return this;},getHeader:function(e){return Function.attempt(function(){return this.xhr.getResponseHeader(e);}.bind(this));},check:function(){if(!this.running){return true;
|
||||
}switch(this.options.link){case"cancel":this.cancel();return true;case"chain":this.chain(this.caller.pass(arguments,this));return false;}return false;},send:function(o){if(!this.check(o)){return this;
|
||||
}this.options.isSuccess=this.options.isSuccess||this.isSuccess;this.running=true;var l=typeOf(o);if(l=="string"||l=="element"){o={data:o};}var h=this.options;
|
||||
o=Object.append({data:h.data,url:h.url,method:h.method},o);var j=o.data,f=String(o.url),e=o.method.toLowerCase();switch(typeOf(j)){case"element":j=document.id(j).toQueryString();
|
||||
break;case"object":case"hash":j=Object.toQueryString(j);}if(this.options.format){var m="format="+this.options.format;j=(j)?m+"&"+j:m;}if(this.options.emulation&&!["get","post"].contains(e)){var k="_method="+e;
|
||||
j=(j)?k+"&"+j:k;e="post";}if(this.options.urlEncoded&&["post","put"].contains(e)){var g=(this.options.encoding)?"; charset="+this.options.encoding:"";this.headers["Content-type"]="application/x-www-form-urlencoded"+g;
|
||||
}if(!f){f=document.location.pathname;}var i=f.lastIndexOf("/");if(i>-1&&(i=f.indexOf("#"))>-1){f=f.substr(0,i);}if(this.options.noCache){f+=(f.contains("?")?"&":"?")+String.uniqueID();
|
||||
}if(j&&e=="get"){f+=(f.contains("?")?"&":"?")+j;j=null;}var n=this.xhr;if(a){n.onloadstart=this.loadstart.bind(this);n.onprogress=this.progress.bind(this);
|
||||
}n.open(e.toUpperCase(),f,this.options.async,this.options.user,this.options.password);if(this.options.user&&"withCredentials" in n){n.withCredentials=true;
|
||||
}n.onreadystatechange=this.onStateChange.bind(this);Object.each(this.headers,function(q,p){try{n.setRequestHeader(p,q);}catch(r){this.fireEvent("exception",[p,q]);
|
||||
}},this);this.fireEvent("request");n.send(j);if(!this.options.async){this.onStateChange();}else{if(this.options.timeout){this.timer=this.timeout.delay(this.options.timeout,this);
|
||||
}}return this;},cancel:function(){if(!this.running){return this;}this.running=false;var e=this.xhr;e.abort();clearTimeout(this.timer);e.onreadystatechange=d;
|
||||
if(a){e.onprogress=e.onloadstart=d;}this.xhr=new Browser.Request();this.fireEvent("cancel");return this;}});var b={};["get","post","put","delete","GET","POST","PUT","DELETE"].each(function(e){b[e]=function(g){var f={method:e};
|
||||
if(g!=null){f.data=g;}return this.send(f);};});c.implement(b);Element.Properties.send={set:function(e){var f=this.get("send").cancel();f.setOptions(e);
|
||||
return this;},get:function(){var e=this.retrieve("send");if(!e){e=new c({data:this,link:"cancel",method:this.get("method")||"post",url:this.get("action")});
|
||||
this.store("send",e);}return e;}};Element.implement({send:function(e){var f=this.get("send");f.send({data:this,url:e||f.options.url});return this;}});})();
|
||||
Request.HTML=new Class({Extends:Request,options:{update:false,append:false,evalScripts:true,filter:false,headers:{Accept:"text/html, application/xml, text/xml, */*"}},success:function(f){var e=this.options,c=this.response;
|
||||
c.html=f.stripScripts(function(h){c.javascript=h;});var d=c.html.match(/<body[^>]*>([\s\S]*?)<\/body>/i);if(d){c.html=d[1];}var b=new Element("div").set("html",c.html);
|
||||
c.tree=b.childNodes;c.elements=b.getElements(e.filter||"*");if(e.filter){c.tree=c.elements;}if(e.update){var g=document.id(e.update).empty();if(e.filter){g.adopt(c.elements);
|
||||
}else{g.set("html",c.html);}}else{if(e.append){var a=document.id(e.append);if(e.filter){c.elements.reverse().inject(a);}else{a.adopt(b.getChildren());}}}if(e.evalScripts){Browser.exec(c.javascript);
|
||||
}this.onSuccess(c.tree,c.elements,c.html,c.javascript);}});Element.Properties.load={set:function(a){var b=this.get("load").cancel();b.setOptions(a);return this;
|
||||
},get:function(){var a=this.retrieve("load");if(!a){a=new Request.HTML({data:this,link:"cancel",update:this,method:"get"});this.store("load",a);}return a;
|
||||
}};Element.implement({load:function(){this.get("load").send(Array.link(arguments,{data:Type.isObject,url:Type.isString}));return this;}});if(typeof JSON=="undefined"){this.JSON={};
|
||||
}(function(){var special={"\b":"\\b","\t":"\\t","\n":"\\n","\f":"\\f","\r":"\\r",'"':'\\"',"\\":"\\\\"};var escape=function(chr){return special[chr]||"\\u"+("0000"+chr.charCodeAt(0).toString(16)).slice(-4);
|
||||
};JSON.validate=function(string){string=string.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,"@").replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,"]").replace(/(?:^|:|,)(?:\s*\[)+/g,"");
|
||||
return(/^[\],:{}\s]*$/).test(string);};JSON.encode=JSON.stringify?function(obj){return JSON.stringify(obj);}:function(obj){if(obj&&obj.toJSON){obj=obj.toJSON();
|
||||
}switch(typeOf(obj)){case"string":return'"'+obj.replace(/[\x00-\x1f\\"]/g,escape)+'"';case"array":return"["+obj.map(JSON.encode).clean()+"]";case"object":case"hash":var string=[];
|
||||
Object.each(obj,function(value,key){var json=JSON.encode(value);if(json){string.push(JSON.encode(key)+":"+json);}});return"{"+string+"}";case"number":case"boolean":return""+obj;
|
||||
case"null":return"null";}return null;};JSON.decode=function(string,secure){if(!string||typeOf(string)!="string"){return null;}if(secure||JSON.secure){if(JSON.parse){return JSON.parse(string);
|
||||
}if(!JSON.validate(string)){throw new Error("JSON could not decode the input; security is enabled and the value is not secure.");}}return eval("("+string+")");
|
||||
};})();Request.JSON=new Class({Extends:Request,options:{secure:true},initialize:function(a){this.parent(a);Object.append(this.headers,{Accept:"application/json","X-Request":"JSON"});
|
||||
},success:function(c){var b;try{b=this.response.json=JSON.decode(c,this.options.secure);}catch(a){this.fireEvent("error",[c,a]);return;}if(b==null){this.onFailure();
|
||||
}else{this.onSuccess(b,c);}}});var Cookie=new Class({Implements:Options,options:{path:"/",domain:false,duration:false,secure:false,document:document,encode:true},initialize:function(b,a){this.key=b;
|
||||
this.setOptions(a);},write:function(b){if(this.options.encode){b=encodeURIComponent(b);}if(this.options.domain){b+="; domain="+this.options.domain;}if(this.options.path){b+="; path="+this.options.path;
|
||||
}if(this.options.duration){var a=new Date();a.setTime(a.getTime()+this.options.duration*24*60*60*1000);b+="; expires="+a.toGMTString();}if(this.options.secure){b+="; secure";
|
||||
}this.options.document.cookie=this.key+"="+b;return this;},read:function(){var a=this.options.document.cookie.match("(?:^|;)\\s*"+this.key.escapeRegExp()+"=([^;]*)");
|
||||
return(a)?decodeURIComponent(a[1]):null;},dispose:function(){new Cookie(this.key,Object.merge({},this.options,{duration:-1})).write("");return this;}});
|
||||
Cookie.write=function(b,c,a){return new Cookie(b,a).write(c);};Cookie.read=function(a){return new Cookie(a).read();};Cookie.dispose=function(b,a){return new Cookie(b,a).dispose();
|
||||
};(function(i,k){var l,f,e=[],c,b,d=k.createElement("div");var g=function(){clearTimeout(b);if(l){return;}Browser.loaded=l=true;k.removeListener("DOMContentLoaded",g).removeListener("readystatechange",a);
|
||||
k.fireEvent("domready");i.fireEvent("domready");};var a=function(){for(var m=e.length;m--;){if(e[m]()){g();return true;}}return false;};var j=function(){clearTimeout(b);
|
||||
if(!a()){b=setTimeout(j,10);}};k.addListener("DOMContentLoaded",g);var h=function(){try{d.doScroll();return true;}catch(m){}return false;};if(d.doScroll&&!h()){e.push(h);
|
||||
c=true;}if(k.readyState){e.push(function(){var m=k.readyState;return(m=="loaded"||m=="complete");});}if("onreadystatechange" in k){k.addListener("readystatechange",a);
|
||||
}else{c=true;}if(c){j();}Element.Events.domready={onAdd:function(m){if(l){m.call(this);}}};Element.Events.load={base:"load",onAdd:function(m){if(f&&this==i){m.call(this);
|
||||
}},condition:function(){if(this==i){g();delete Element.Events.load;}return true;}};i.addEvent("load",function(){f=true;});})(window,document);(function(){var Swiff=this.Swiff=new Class({Implements:Options,options:{id:null,height:1,width:1,container:null,properties:{},params:{quality:"high",allowScriptAccess:"always",wMode:"window",swLiveConnect:true},callBacks:{},vars:{}},toElement:function(){return this.object;
|
||||
},initialize:function(path,options){this.instance="Swiff_"+String.uniqueID();this.setOptions(options);options=this.options;var id=this.id=options.id||this.instance;
|
||||
var container=document.id(options.container);Swiff.CallBacks[this.instance]={};var params=options.params,vars=options.vars,callBacks=options.callBacks;
|
||||
var properties=Object.append({height:options.height,width:options.width},options.properties);var self=this;for(var callBack in callBacks){Swiff.CallBacks[this.instance][callBack]=(function(option){return function(){return option.apply(self.object,arguments);
|
||||
};})(callBacks[callBack]);vars[callBack]="Swiff.CallBacks."+this.instance+"."+callBack;}params.flashVars=Object.toQueryString(vars);if(Browser.ie){properties.classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000";
|
||||
params.movie=path;}else{properties.type="application/x-shockwave-flash";}properties.data=path;var build='<object id="'+id+'"';for(var property in properties){build+=" "+property+'="'+properties[property]+'"';
|
||||
}build+=">";for(var param in params){if(params[param]){build+='<param name="'+param+'" value="'+params[param]+'" />';}}build+="</object>";this.object=((container)?container.empty():new Element("div")).set("html",build).firstChild;
|
||||
},replaces:function(element){element=document.id(element,true);element.parentNode.replaceChild(this.toElement(),element);return this;},inject:function(element){document.id(element,true).appendChild(this.toElement());
|
||||
return this;},remote:function(){return Swiff.remote.apply(Swiff,[this.toElement()].append(arguments));}});Swiff.CallBacks={};Swiff.remote=function(obj,fn){var rs=obj.CallFunction('<invoke name="'+fn+'" returntype="javascript">'+__flash__argumentsToXML(arguments,2)+"</invoke>");
|
||||
return eval(rs);};})();
|
45
sources/searx/static/js/searx.js
Normal file
|
@ -0,0 +1,45 @@
|
|||
if(searx.autocompleter) {
|
||||
window.addEvent('domready', function() {
|
||||
new Autocompleter.Request.JSON('q', '/autocompleter', {
|
||||
postVar:'q',
|
||||
postData:{
|
||||
'format': 'json'
|
||||
},
|
||||
ajaxOptions:{
|
||||
timeout: 5 // Correct option?
|
||||
},
|
||||
'minLength': 4,
|
||||
// 'selectMode': 'type-ahead',
|
||||
cache: true,
|
||||
delay: 300
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
(function (w, d) {
|
||||
'use strict';
|
||||
function addListener(el, type, fn) {
|
||||
if (el.addEventListener) {
|
||||
el.addEventListener(type, fn, false);
|
||||
} else {
|
||||
el.attachEvent('on' + type, fn);
|
||||
}
|
||||
}
|
||||
|
||||
function placeCursorAtEnd() {
|
||||
if (this.setSelectionRange) {
|
||||
var len = this.value.length * 2;
|
||||
this.setSelectionRange(len, len);
|
||||
}
|
||||
}
|
||||
|
||||
addListener(w, 'load', function () {
|
||||
var qinput = d.getElementById('q');
|
||||
if (qinput !== null && qinput.value === "") {
|
||||
addListener(qinput, 'focus', placeCursorAtEnd);
|
||||
qinput.focus();
|
||||
}
|
||||
});
|
||||
|
||||
})(window, document);
|
||||
|
61
sources/searx/static/less/autocompleter.less
Normal file
|
@ -0,0 +1,61 @@
|
|||
/*
|
||||
* searx, A privacy-respecting, hackable metasearch engine
|
||||
*/
|
||||
|
||||
ul {
|
||||
&.autocompleter-choices {
|
||||
position: absolute;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
list-style: none;
|
||||
border: 1px solid @color-autocompleter-choices-border;
|
||||
border-left-color: @color-autocompleter-choices-border-left-right;
|
||||
border-right-color: @color-autocompleter-choices-border-left-right;
|
||||
border-bottom-color: @color-autocompleter-choices-border-bottom;
|
||||
text-align: left;
|
||||
font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;
|
||||
z-index: 50;
|
||||
background-color: @color-autocompleter-choices-background;
|
||||
color: @color-autocompleter-choices-font;
|
||||
|
||||
li {
|
||||
position: relative;
|
||||
margin: -2px 0 0 0;
|
||||
padding: 0.2em 1.5em 0.2em 1em;
|
||||
display: block;
|
||||
float: none !important;
|
||||
cursor: pointer;
|
||||
font-weight: normal;
|
||||
white-space: nowrap;
|
||||
font-size: 1em;
|
||||
line-height: 1.5em;
|
||||
|
||||
&.autocompleter-selected {
|
||||
background-color: @color-autocompleter-selected-background;
|
||||
color: @color-autocompleter-selected-font;
|
||||
|
||||
span.autocompleter-queried {
|
||||
color: @color-autocompleter-selected-queried-font;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
span.autocompleter-queried {
|
||||
display: inline;
|
||||
float: none;
|
||||
font-weight: bold;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*.autocompleter-loading {
|
||||
//background-image: url(images/spinner.gif);
|
||||
background-repeat: no-repeat;
|
||||
background-position: right 50%;
|
||||
}*/
|
||||
|
||||
/*textarea.autocompleter-loading {
|
||||
background-position: right bottom;
|
||||
}*/
|
113
sources/searx/static/less/definitions.less
Normal file
|
@ -0,0 +1,113 @@
|
|||
/*
|
||||
* 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: #2980B9;
|
||||
@color-base-light: #ECF0F1;
|
||||
@color-highlight: #094089;
|
||||
@color-black: #000000;
|
||||
|
||||
/// General
|
||||
|
||||
@color-font: #444;
|
||||
|
||||
@color-url-font: #1a11be;
|
||||
@color-url-visited-font: #8E44AD;
|
||||
@results-width: 50em;
|
||||
|
||||
|
||||
/// Start-Screen
|
||||
|
||||
// hmarg
|
||||
@color-hmarg-border: @color-base;
|
||||
@color-hmarg-font: @color-base;
|
||||
@color-hmarg-font-hover: @color-base;
|
||||
|
||||
|
||||
/// 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;
|
||||
|
||||
// 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: #C0392B;
|
||||
|
||||
// Publish Date
|
||||
@color-result-publishdate-font: #888;
|
||||
|
||||
// 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-tr-hover: #DDD;
|
||||
|
||||
// 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: #888;
|
||||
@color-percentage-div-background: #444;
|
27
sources/searx/static/less/mixins.less
Normal file
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
* 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;
|
||||
}
|
||||
|
||||
.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;
|
||||
}
|
68
sources/searx/static/less/search.less
Normal file
|
@ -0,0 +1,68 @@
|
|||
/*
|
||||
* searx, A privacy-respecting, hackable metasearch engine
|
||||
*/
|
||||
|
||||
.search {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
.checkbox_container label {
|
||||
font-size: 0.9em;
|
||||
border-bottom: 2px solid @color-categories-item-border-unselected;
|
||||
}
|
||||
|
||||
.checkbox_container label:hover {
|
||||
border-bottom: 2px solid @color-categories-item-border-unselected-hover;
|
||||
}
|
||||
|
||||
.checkbox_container input[type="checkbox"]:checked + label {
|
||||
border-bottom: 2px solid @color-categories-item-border-selected;
|
||||
}
|
||||
}
|
||||
|
||||
#search_wrapper {
|
||||
position: relative;
|
||||
width: @results-width;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.center #search_wrapper {
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
.q {
|
||||
background: none repeat scroll 0 0 @color-search-background;
|
||||
border: 1px solid @color-search-border;
|
||||
color: @color-search-font;
|
||||
font-size: 16px;
|
||||
height: 28px;
|
||||
margin: 0;
|
||||
outline: medium none;
|
||||
padding: 2px;
|
||||
padding-left: 8px;
|
||||
padding-right: 0px !important;
|
||||
width: 100%;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
#search_submit {
|
||||
position: absolute;
|
||||
top: 13px;
|
||||
right: 1px;
|
||||
padding: 0;
|
||||
border: 0;
|
||||
background: url('../img/search-icon.png') no-repeat;
|
||||
background-size: 24px 24px;
|
||||
opacity: 0.8;
|
||||
width: 24px;
|
||||
height: 30px;
|
||||
font-size: 0;
|
||||
}
|
||||
|
||||
@media screen and (max-width: @results-width) {
|
||||
#search_wrapper {
|
||||
width: 90%;
|
||||
clear:both;
|
||||
overflow: hidden
|
||||
}
|
||||
}
|
538
sources/searx/static/less/style.less
Normal file
|
@ -0,0 +1,538 @@
|
|||
/*
|
||||
* searx, A privacy-respecting, hackable metasearch engine
|
||||
*
|
||||
* To convert "style.less" to "style.css" run: $make styles
|
||||
*/
|
||||
|
||||
@import "definitions.less";
|
||||
|
||||
@import "mixins.less";
|
||||
|
||||
// Main LESS-Code
|
||||
|
||||
html {
|
||||
font-family: sans-serif;
|
||||
font-size: 0.9em;
|
||||
.text-size-adjust;
|
||||
color: @color-font;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
body, #container {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
#container {
|
||||
width: 100%;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
}
|
||||
|
||||
// Search-Field
|
||||
|
||||
@import "search.less";
|
||||
|
||||
// Autocompleter
|
||||
|
||||
@import "autocompleter.less";
|
||||
|
||||
.row {
|
||||
max-width: 800px;
|
||||
margin: 20px auto;
|
||||
text-align: justify;
|
||||
|
||||
h1 {
|
||||
font-size: 3em;
|
||||
margin-top: 50px;
|
||||
}
|
||||
|
||||
p {
|
||||
padding: 0 10px;
|
||||
max-width: 700px;
|
||||
}
|
||||
|
||||
h3,ul {
|
||||
margin: 4px 8px;
|
||||
}
|
||||
}
|
||||
|
||||
.hmarg {
|
||||
margin: 0 20px;
|
||||
border: 1px solid @color-hmarg-border;
|
||||
padding: 4px 10px;
|
||||
}
|
||||
|
||||
a {
|
||||
&:link.hmarg {
|
||||
color: @color-hmarg-font;
|
||||
}
|
||||
|
||||
&:visited.hmarg {
|
||||
color: @color-hmarg-font;
|
||||
}
|
||||
|
||||
&:active.hmarg {
|
||||
color: @color-hmarg-font-hover;
|
||||
}
|
||||
|
||||
&:hover.hmarg {
|
||||
color: @color-hmarg-font-hover;
|
||||
}
|
||||
}
|
||||
|
||||
.top_margin {
|
||||
margin-top: 60px;
|
||||
}
|
||||
|
||||
.center {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 5em;
|
||||
}
|
||||
|
||||
div.title {
|
||||
background: url('../img/searx.png') no-repeat;
|
||||
width: 100%;
|
||||
background-position: center;
|
||||
|
||||
h1 {
|
||||
visibility: hidden;
|
||||
}
|
||||
}
|
||||
|
||||
input[type="submit"] {
|
||||
padding: 2px 6px;
|
||||
margin: 2px 4px;
|
||||
display: inline-block;
|
||||
background: @color-download-button-background;
|
||||
color: @color-download-button-font;
|
||||
.rounded-corners;
|
||||
border: 0;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
input[type="checkbox"] {
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
fieldset {
|
||||
margin: 8px;
|
||||
border: 1px solid @color-settings-fieldset;
|
||||
}
|
||||
|
||||
#categories {
|
||||
margin: 0 10px;
|
||||
}
|
||||
|
||||
.checkbox_container {
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
margin: 0 3px;
|
||||
padding: 0px;
|
||||
|
||||
input {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.checkbox_container label, .engine_checkbox label {
|
||||
cursor: pointer;
|
||||
padding: 4px 10px;
|
||||
margin: 0;
|
||||
display: block;
|
||||
text-transform: capitalize;
|
||||
.user-select;
|
||||
}
|
||||
|
||||
.checkbox_container input[type="checkbox"]:checked + label {
|
||||
background: @color-categories-item-selected;
|
||||
color: @color-categories-item-selected-font;
|
||||
}
|
||||
|
||||
.engine_checkbox {
|
||||
padding: 4px;
|
||||
}
|
||||
|
||||
label {
|
||||
&.allow {
|
||||
background: @color-settings-label-allowed-background;
|
||||
padding: 4px 8px;
|
||||
color: @color-settings-label-allowed-font;
|
||||
display: none;
|
||||
}
|
||||
|
||||
&.deny {
|
||||
background: @color-settings-label-deny-background;
|
||||
padding: 4px 8px;
|
||||
color: @color-settings-label-deny-font;
|
||||
display: inline;
|
||||
}
|
||||
}
|
||||
|
||||
.engine_checkbox input[type="checkbox"]:checked + label {
|
||||
&:nth-child(2) + label {
|
||||
display: none;
|
||||
}
|
||||
|
||||
&.allow {
|
||||
display: inline;
|
||||
}
|
||||
}
|
||||
|
||||
a {
|
||||
text-decoration: none;
|
||||
color: @color-url-font;
|
||||
|
||||
&:visited {
|
||||
color: @color-url-visited-font;
|
||||
}
|
||||
}
|
||||
|
||||
.result {
|
||||
margin: 19px 0 18px 0;
|
||||
padding: 0;
|
||||
clear: both;
|
||||
}
|
||||
|
||||
.result_title {
|
||||
margin-bottom: 0;
|
||||
|
||||
a {
|
||||
color: @color-result-link-font;
|
||||
font-weight: normal;
|
||||
font-size: 1.1em;
|
||||
|
||||
&:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
&:visited {
|
||||
color: @color-result-link-visited-font;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.result {
|
||||
h3 {
|
||||
font-size: 1em;
|
||||
word-wrap:break-word;
|
||||
margin: 5px 0 1px 0;
|
||||
padding: 0
|
||||
}
|
||||
|
||||
.content {
|
||||
font-size: 0.8em;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
max-width: 54em;
|
||||
word-wrap:break-word;
|
||||
line-height: 1.24;
|
||||
}
|
||||
|
||||
.url {
|
||||
font-size: 0.8em;
|
||||
margin: 3px 0 0 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;
|
||||
margin: 5px 20px;
|
||||
}
|
||||
}
|
||||
|
||||
.engines {
|
||||
color: @color-engines-font;
|
||||
}
|
||||
|
||||
.small_font {
|
||||
font-size: 0.8em;
|
||||
}
|
||||
|
||||
.small p {
|
||||
margin: 2px 0;
|
||||
}
|
||||
|
||||
.right {
|
||||
float: right;
|
||||
}
|
||||
|
||||
.invisible {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.left {
|
||||
float: left;
|
||||
}
|
||||
|
||||
.highlight {
|
||||
color: @color-highlight;
|
||||
}
|
||||
|
||||
.content .highlight {
|
||||
color: @color-black;
|
||||
}
|
||||
|
||||
.image_result {
|
||||
float: left;
|
||||
margin: 10px 10px;
|
||||
position: relative;
|
||||
height: 160px;
|
||||
|
||||
img {
|
||||
border: 0;
|
||||
height: 160px;
|
||||
}
|
||||
|
||||
p {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
|
||||
span a {
|
||||
display: none;
|
||||
color: @color-result-image-span-font;
|
||||
}
|
||||
|
||||
&:hover span a {
|
||||
display: block;
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
padding: 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;
|
||||
}
|
||||
}
|
||||
|
||||
.definition_result {
|
||||
border-left: 10px solid @color-result-definition-border;
|
||||
padding-left: 3px;
|
||||
}
|
||||
|
||||
.percentage {
|
||||
position: relative;
|
||||
width: 300px;
|
||||
|
||||
div {
|
||||
background: @color-percentage-div-background;
|
||||
}
|
||||
}
|
||||
|
||||
table {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
td {
|
||||
padding: 0 4px;
|
||||
}
|
||||
|
||||
tr {
|
||||
&:hover {
|
||||
background: @color-settings-tr-hover;
|
||||
}
|
||||
}
|
||||
|
||||
#results {
|
||||
margin: auto;
|
||||
padding: 0;
|
||||
width: @results-width;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
#sidebar {
|
||||
position: absolute;
|
||||
top: 100px;
|
||||
right: 10px;
|
||||
margin: 0 2px 5px 5px;
|
||||
padding: 0 2px 2px 2px;
|
||||
width: 14em;
|
||||
|
||||
input {
|
||||
padding: 0;
|
||||
margin: 3px;
|
||||
font-size: 0.8em;
|
||||
display: inline-block;
|
||||
background: transparent;
|
||||
color: @color-result-search-url-font;
|
||||
cursor: pointer;
|
||||
}
|
||||
input[type="submit"] {
|
||||
text-decoration: underline;
|
||||
}
|
||||
}
|
||||
|
||||
#suggestions {
|
||||
|
||||
margin-top: 20px;
|
||||
|
||||
span {
|
||||
display: inline;
|
||||
margin: 0 2px 2px 2px;
|
||||
padding: 0;
|
||||
}
|
||||
input {
|
||||
padding: 0;
|
||||
margin: 3px;
|
||||
font-size: 0.8em;
|
||||
display: inline-block;
|
||||
background: transparent;
|
||||
color: @color-result-search-url-font;
|
||||
cursor: pointer;
|
||||
}
|
||||
input[type="submit"] {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
form {
|
||||
display: inline;
|
||||
}
|
||||
}
|
||||
|
||||
#search_url {
|
||||
margin-top: 8px;
|
||||
|
||||
input {
|
||||
border: 1px solid @color-result-search-url-border;
|
||||
padding: 4px;
|
||||
color: @color-result-search-url-font;
|
||||
width: 14em;
|
||||
display: block;
|
||||
margin: 4px;
|
||||
font-size: 0.8em;
|
||||
}
|
||||
}
|
||||
|
||||
#preferences {
|
||||
top: 10px;
|
||||
padding: 0;
|
||||
border: 0;
|
||||
background: url('../img/preference-icon.png') no-repeat;
|
||||
background-size: 28px 28px;
|
||||
opacity: 0.8;
|
||||
width: 28px;
|
||||
height: 30px;
|
||||
display: block;
|
||||
|
||||
* {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
#pagination {
|
||||
clear: both;
|
||||
width: 40em;
|
||||
}
|
||||
|
||||
#apis {
|
||||
margin-top: 8px;
|
||||
clear: both;
|
||||
}
|
||||
|
||||
@media screen and (max-width: @results-width) {
|
||||
|
||||
#categories {
|
||||
font-size: 90%;
|
||||
clear: both;
|
||||
|
||||
.checkbox_container {
|
||||
margin-top: 2px;
|
||||
margin: auto;
|
||||
}
|
||||
}
|
||||
|
||||
#results {
|
||||
margin: auto;
|
||||
padding: 0;
|
||||
width: 90%;
|
||||
}
|
||||
|
||||
.checkbox_container {
|
||||
display: block;
|
||||
width: 90%;
|
||||
//float: left;
|
||||
|
||||
label {
|
||||
border-bottom: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: 70em) {
|
||||
.right {
|
||||
display: none;
|
||||
postion: fixed !important;
|
||||
top: 100px;
|
||||
right: 0px;
|
||||
}
|
||||
|
||||
#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-top: 1px solid @color-result-top-border;
|
||||
margin: 7px 0 6px 0;
|
||||
|
||||
img {
|
||||
max-width: 90%;
|
||||
width: auto;
|
||||
height: auto
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.favicon {
|
||||
float: left;
|
||||
margin-right: 4px;
|
||||
margin-top: 2px;
|
||||
}
|
||||
|
||||
.preferences_back {
|
||||
background: none repeat scroll 0 0 @color-settings-return-background;
|
||||
border: 0 none;
|
||||
.rounded-corners;
|
||||
cursor: pointer;
|
||||
display: inline-block;
|
||||
margin: 2px 4px;
|
||||
padding: 4px 6px;
|
||||
|
||||
a {
|
||||
color: @color-settings-return-font;
|
||||
}
|
||||
}
|
66
sources/searx/templates/about.html
Normal file
|
@ -0,0 +1,66 @@
|
|||
{% extends 'base.html' %}
|
||||
{% block content %}
|
||||
{% include 'github_ribbon.html' %}
|
||||
<div class="row">
|
||||
<h1>About <a href="{{ url_for('index') }}">searx</a></h1>
|
||||
|
||||
<p>Searx is a <a href="https://en.wikipedia.org/wiki/Metasearch_engine">metasearch engine</a>, aggregating the results of other <a href="{{ url_for('preferences') }}">search engines</a> while not storing information about its users.
|
||||
</p>
|
||||
<h2>Why use Searx?</h2>
|
||||
<ul>
|
||||
<li>Searx may not offer you as personalised results as Google, but it doesn't generate a profile about you</li>
|
||||
<li>Searx doesn't care about what you search for, never shares anything with a third party, and it can't be used to compromise you</li>
|
||||
<li>Searx is free software, the code is 100% open and you can help to make it better. See more on <a href="https://github.com/asciimoo/searx">github</a></li>
|
||||
</ul>
|
||||
<p>If you do care about privacy, want to be a conscious user, or otherwise believe
|
||||
in digital freedom, make Searx your default search engine or run it on your own server</p>
|
||||
|
||||
<h2>Technical details - How does it work?</h2>
|
||||
|
||||
<p>Searx is a <a href="https://en.wikipedia.org/wiki/Metasearch_engine">metasearch engine</a>,
|
||||
inspired by the <a href="http://seeks-project.info/">seeks project</a>.<br />
|
||||
It provides basic privacy by mixing your queries with searches on other platforms without storing search data. Queries are made using a POST request on every browser (except chrome*). Therefore they show up in neither our logs, nor your url history. In case of Chrome* users there is an exception, Searx uses the search bar to perform GET requests.<br />
|
||||
Searx can be added to your browser's search bar; moreover, it can be set as the default search engine.
|
||||
</p>
|
||||
|
||||
<h2>How can I make it my own?</h2>
|
||||
|
||||
<p>Searx appreciates your concern regarding logs, so take the <a href="https://github.com/asciimoo/searx">code</a> and run it yourself! <br />Add your Searx to this <a href="https://github.com/asciimoo/searx/wiki/Searx-instances">list</a> to help other people reclaim their privacy and make the Internet freer!
|
||||
<br />The more decentralized the Internet, is the more freedom we have!</p>
|
||||
|
||||
|
||||
<h2>More about searx</h2>
|
||||
|
||||
<ul>
|
||||
<li><a href="https://github.com/asciimoo/searx">github</a></li>
|
||||
<li><a href="https://www.ohloh.net/p/searx/">ohloh</a></li>
|
||||
<li><a href="https://twitter.com/Searx_engine">twitter</a></li>
|
||||
<li>IRC: #searx @ freenode (<a href="https://kiwiirc.com/client/irc.freenode.com/searx">webclient</a>)</li>
|
||||
<li><a href="https://www.transifex.com/projects/p/searx/">transifex</a></li>
|
||||
</ul>
|
||||
|
||||
|
||||
<hr />
|
||||
|
||||
<h2 id="faq">FAQ</h2>
|
||||
|
||||
<h3>How to add to firefox?</h3>
|
||||
<p><a href="#" onclick="window.external.AddSearchProvider(window.location.protocol + '//' + window.location.host + '{{ url_for('opensearch') }}');">Install</a> searx as a search engine on any version of Firefox! (javascript required)</p>
|
||||
|
||||
<h2 id="dev_faq">Developer FAQ</h2>
|
||||
|
||||
<h3>New engines?</h3>
|
||||
<ul>
|
||||
<li>Edit your <a href="https://raw.github.com/asciimoo/searx/master/searx/settings.yml">settings.yml</a></li>
|
||||
<li>Create your custom engine module, check the <a href="https://github.com/asciimoo/searx/blob/master/examples/basic_engine.py">example engine</a></li>
|
||||
</ul>
|
||||
<p>Don't forget to restart searx after config edit!</p>
|
||||
|
||||
<h3>Installation/WSGI support?</h3>
|
||||
<p>See the <a href="https://github.com/asciimoo/searx/wiki/Installation">installation and setup</a> wiki page</p>
|
||||
|
||||
<h3>How to debug engines?</h3>
|
||||
<p><a href="{{ url_for('stats') }}">Stats page</a> contains some useful data about the engines used.</p>
|
||||
|
||||
</div>
|
||||
{% endblock %}
|
32
sources/searx/templates/base.html
Normal file
|
@ -0,0 +1,32 @@
|
|||
<!DOCTYPE html>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
|
||||
<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="viewport" content="width=device-width, maximum-scale=1.0, user-scalable=1" />
|
||||
<title>{% block title %}{% endblock %}searx</title>
|
||||
<link rel="stylesheet" href="{{ url_for('static', filename='css/style.css') }}" type="text/css" media="screen" />
|
||||
<link rel="shortcut icon" href="{{ url_for('static', filename='img/favicon.png') }}?v=2" />
|
||||
{% block styles %}
|
||||
{% endblock %}
|
||||
{% block head %}
|
||||
<link title="searx" type="application/opensearchdescription+xml" rel="search" href="{{ url_for('opensearch') }}"/>
|
||||
{% endblock %}
|
||||
<script type="text/javascript">
|
||||
searx = {};
|
||||
searx.autocompleter = {% if autocomplete %}true{% else %}false{% endif %};
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="container">
|
||||
{% block content %}
|
||||
{% endblock %}
|
||||
{% if autocomplete %}
|
||||
<script src="{{ url_for('static', filename='js/mootools-core-1.4.5-min.js') }}" ></script>
|
||||
<script src="{{ url_for('static', filename='js/mootools-autocompleter-1.1.2-min.js') }}" ></script>
|
||||
{% endif %}
|
||||
<script src="{{ url_for('static', filename='js/searx.js') }}" ></script>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
7
sources/searx/templates/categories.html
Normal file
|
@ -0,0 +1,7 @@
|
|||
<div id="categories">
|
||||
{% for category in categories %}
|
||||
<div class="checkbox_container">
|
||||
<input type="checkbox" id="checkbox_{{ category|replace(' ', '_') }}" name="category_{{ category }}" {% if category in selected_categories %}checked="checked"{% endif %} /><label for="checkbox_{{ category|replace(' ', '_') }}">{{ _(category) }}</label>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
3
sources/searx/templates/github_ribbon.html
Normal file
|
@ -0,0 +1,3 @@
|
|||
<a href="https://github.com/asciimoo/searx" class="github">
|
||||
<img style="position: absolute; top: 0; right: 0; border: 0;" src="{{ url_for('static', filename='img/github_ribbon.png') }}" alt="Fork me on GitHub" class="github"/>
|
||||
</a>
|
11
sources/searx/templates/index.html
Normal file
|
@ -0,0 +1,11 @@
|
|||
{% extends "base.html" %}
|
||||
{% block content %}
|
||||
<div class="center">
|
||||
<div class="title"><h1>searx</h1></div>
|
||||
{% include 'search.html' %}
|
||||
<p class="top_margin">
|
||||
<a href="{{ url_for('about') }}" class="hmarg">{{ _('about') }}</a>
|
||||
<a href="{{ url_for('preferences') }}" class="hmarg">{{ _('preferences') }}</a>
|
||||
</p>
|
||||
</div>
|
||||
{% endblock %}
|
27
sources/searx/templates/opensearch.xml
Normal file
|
@ -0,0 +1,27 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/">
|
||||
<ShortName>searx</ShortName>
|
||||
<Description>Search searx</Description>
|
||||
<InputEncoding>UTF-8</InputEncoding>
|
||||
<LongName>searx metasearch</LongName>
|
||||
{% if opensearch_method == 'get' %}
|
||||
<Url type="text/html" method="get" template="{{ host }}search?q={searchTerms}"/>
|
||||
{% if autocomplete %}
|
||||
<Url type="application/x-suggestions+json" method="get" template="{{ host }}autocompleter">
|
||||
<Param name="format" value="x-suggestions" />
|
||||
<Param name="q" value="{searchTerms}" />
|
||||
</Url>
|
||||
{% endif %}
|
||||
{% else %}
|
||||
<Url type="text/html" method="post" template="{{ host }}">
|
||||
<Param name="q" value="{searchTerms}" />
|
||||
</Url>
|
||||
{% if autocomplete %}
|
||||
<!-- TODO, POST REQUEST doesn't work -->
|
||||
<Url type="application/x-suggestions+json" method="get" template="{{ host }}autocompleter">
|
||||
<Param name="format" value="x-suggestions" />
|
||||
<Param name="q" value="{searchTerms}" />
|
||||
</Url>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
</OpenSearchDescription>
|
23
sources/searx/templates/opensearch_response_rss.xml
Normal file
|
@ -0,0 +1,23 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<rss version="2.0"
|
||||
xmlns:opensearch="http://a9.com/-/spec/opensearch/1.1/"
|
||||
xmlns:atom="http://www.w3.org/2005/Atom">
|
||||
<channel>
|
||||
<title>Searx search: {{ q }}</title>
|
||||
<link>{{ base_url }}?q={{ q }}</link>
|
||||
<description>Search results for "{{ q }}" - searx</description>
|
||||
<opensearch:totalResults>{{ number_of_results }}</opensearch:totalResults>
|
||||
<opensearch:startIndex>1</opensearch:startIndex>
|
||||
<opensearch:itemsPerPage>{{ number_of_results }}</opensearch:itemsPerPage>
|
||||
<atom:link rel="search" type="application/opensearchdescription+xml" href="{{ base_url }}opensearch.xml"/>
|
||||
<opensearch:Query role="request" searchTerms="{{ q }}" startPage="1" />
|
||||
{% for r in results %}
|
||||
<item>
|
||||
<title>{{ r.title }}</title>
|
||||
<link>{{ r.url }}</link>
|
||||
<description>{{ r.content }}</description>
|
||||
{% if r.pubdate %}<pubDate>{{ r.pubdate }}</pubDate>{% endif %}
|
||||
</item>
|
||||
{% endfor %}
|
||||
</channel>
|
||||
</rss>
|
91
sources/searx/templates/preferences.html
Normal file
|
@ -0,0 +1,91 @@
|
|||
{% extends "base.html" %}
|
||||
{% block head %} {% endblock %}
|
||||
{% block content %}
|
||||
<div class="row">
|
||||
<h2>{{ _('Preferences') }}</h2>
|
||||
|
||||
<form method="post" action="{{ url_for('preferences') }}" id="search_form">
|
||||
<fieldset>
|
||||
<legend>{{ _('Default categories') }}</legend>
|
||||
<p>
|
||||
{% include 'categories.html' %}
|
||||
</p>
|
||||
</fieldset>
|
||||
<fieldset>
|
||||
<legend>{{ _('Search language') }}</legend>
|
||||
<p>
|
||||
<select name='language'>
|
||||
<option value="all" {% if current_language == 'all' %}selected="selected"{% endif %}>{{ _('Automatic') }}</option>
|
||||
{% for lang_id,lang_name,country_name in language_codes %}
|
||||
<option value="{{ lang_id }}" {% if lang_id == current_language %}selected="selected"{% endif %}>{{ lang_name }} ({{ country_name }}) - {{ lang_id }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</p>
|
||||
</fieldset>
|
||||
<fieldset>
|
||||
<legend>{{ _('Interface language') }}</legend>
|
||||
<p>
|
||||
<select name='locale'>
|
||||
{% for locale_id,locale_name in locales.items() %}
|
||||
<option value="{{ locale_id }}" {% if locale_id == current_locale %}selected="selected"{% endif %}>{{ locale_name }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</p>
|
||||
</fieldset>
|
||||
<fieldset>
|
||||
<legend>{{ _('Autocomplete') }}</legend>
|
||||
<p>
|
||||
<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>
|
||||
</fieldset>
|
||||
<fieldset>
|
||||
<legend>{{ _('Method') }}</legend>
|
||||
<p>
|
||||
<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>
|
||||
</fieldset>
|
||||
<fieldset>
|
||||
<legend>{{ _('Currently used search engines') }}</legend>
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<th>{{ _('Engine name') }}</th>
|
||||
<th>{{ _('Category') }}</th>
|
||||
<th>{{ _('Allow') }} / {{ _('Block') }}</th>
|
||||
</tr>
|
||||
{% for (categ,search_engines) in categs %}
|
||||
{% for search_engine in search_engines %}
|
||||
|
||||
{% if not search_engine.private %}
|
||||
<tr>
|
||||
<td>{{ search_engine.name }} ({{ shortcuts[search_engine.name] }})</td>
|
||||
<td>{{ _(categ) }}</td>
|
||||
<td class="engine_checkbox">
|
||||
<input type="checkbox" id="engine_{{ categ }}_{{ search_engine.name|replace(' ', '_') }}" name="engine_{{ search_engine.name }}"{% if search_engine.name in blocked_engines %} checked="checked"{% endif %} />
|
||||
<label class="allow" for="engine_{{ categ }}_{{ search_engine.name|replace(' ', '_') }}">{{ _('Allow') }}</label>
|
||||
<label class="deny" for="engine_{{ categ }}_{{ search_engine.name|replace(' ', '_') }}">{{ _('Block') }}</label>
|
||||
</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% endfor %}
|
||||
</table>
|
||||
</fieldset>
|
||||
<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="right preferences_back"><a href="{{ url_for('index') }}">{{ _('back') }}</a></div>
|
||||
</form>
|
||||
</div>
|
||||
{% endblock %}
|
13
sources/searx/templates/result_templates/default.html
Normal file
|
@ -0,0 +1,13 @@
|
|||
<div class="result {{ result.class }}">
|
||||
|
||||
{% if result['favicon'] %}
|
||||
<img width="14" height="14" class="favicon" src="static/img/icon_{{result['favicon']}}.ico" />
|
||||
{% endif %}
|
||||
|
||||
<div>
|
||||
<h3 class="result_title"><a href="{{ result.url }}">{{ result.title|safe }}</a></h3>
|
||||
{% if result.publishedDate %}<p class="published_date">{{ result.publishedDate }}</p>{% endif %}
|
||||
<p class="content">{% if result.content %}{{ result.content|safe }}<br />{% endif %}</p>
|
||||
<p class="url">{{ result.pretty_url }}</p>
|
||||
</div>
|
||||
</div>
|
6
sources/searx/templates/result_templates/images.html
Normal file
|
@ -0,0 +1,6 @@
|
|||
<div class="image_result">
|
||||
<p>
|
||||
<a href="{{ result.img_src }}"><img src="{{ result.img_src }}" title={{ result.title }}/></a>
|
||||
<span class="url"><a href="{{ result.url }}" class="small_font">original context</a></span>
|
||||
</p>
|
||||
</div>
|
7
sources/searx/templates/result_templates/torrent.html
Normal file
|
@ -0,0 +1,7 @@
|
|||
<div class="result torrent_result">
|
||||
<h3 class="result_title"><a href="{{ result.url }}">{{ result.title|safe }}</a></h3>
|
||||
{% if result.content %}<p class="content">{{ result.content|safe }}</p>{% endif %}
|
||||
<p class="stats">Seed: {{ result.seed }}, Leech: {{ result.leech }}</p>
|
||||
<p><a href="{{ result.magnetlink }}" class="magnetlink">magnet link</a></p>
|
||||
<p class="url">{{ result.pretty_url }}</p>
|
||||
</div>
|
12
sources/searx/templates/result_templates/videos.html
Normal file
|
@ -0,0 +1,12 @@
|
|||
<div class="result">
|
||||
{% if result['favicon'] %}
|
||||
<img width="14" height="14" class="favicon" src="static/img/icon_{{result['favicon']}}.ico" />
|
||||
{% endif %}
|
||||
|
||||
<p>
|
||||
<h3 class="result_title"><a href="{{ result.url }}">{{ result.title|safe }}</a></h3>
|
||||
{% if result.publishedDate %}<p class="published_date">{{ result.publishedDate }}</p>{% endif %}
|
||||
<a href="{{ result.url }}"><img width="400px" src="{{ result.thumbnail }}" title={{ result.title }} alt=" {{ result.title }}"/></a>
|
||||
<p class="url">{{ result.url }}</p>
|
||||
</p>
|
||||
</div>
|
79
sources/searx/templates/results.html
Normal file
|
@ -0,0 +1,79 @@
|
|||
{% extends "base.html" %}
|
||||
{% block title %}{{ q }} - {% endblock %}
|
||||
{% block content %}
|
||||
<div class="right"><a href="{{ url_for('preferences') }}" id="preferences"><span>preferences</span></a></div>
|
||||
<div class="small search center">
|
||||
{% include 'search.html' %}
|
||||
</div>
|
||||
<div id="results">
|
||||
<div id="sidebar">
|
||||
|
||||
<div id="search_url">
|
||||
{{ _('Search URL') }}:
|
||||
<input type="text" value="{{ base_url }}?q={{ q|urlencode }}&pageno={{ pageno }}{% if selected_categories %}&category_{{ selected_categories|join("&category_") }}{% endif %}" readonly="" />
|
||||
</div>
|
||||
<div id="apis">
|
||||
{{ _('Download results') }}
|
||||
{% for output_type in ('csv', 'json', 'rss') %}
|
||||
<form method="{{ method or 'POST' }}" action="{{ url_for('index') }}">
|
||||
<div class="left">
|
||||
<input type="hidden" name="q" value="{{ q }}" />
|
||||
<input type="hidden" name="format" value="{{ output_type }}" />
|
||||
{% for category in selected_categories %}
|
||||
<input type="hidden" name="category_{{ category }}" value="1"/>
|
||||
{% endfor %}
|
||||
<input type="hidden" name="pageno" value="{{ pageno }}" />
|
||||
<input type="submit" value="{{ output_type }}" />
|
||||
</div>
|
||||
</form>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% if suggestions %}
|
||||
<div id="suggestions"><span>{{ _('Suggestions') }}</span>
|
||||
{% for suggestion in 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>
|
||||
{% endif %}
|
||||
|
||||
{% for result in results %}
|
||||
{% if result['template'] %}
|
||||
{% include 'result_templates/'+result['template'] %}
|
||||
{% else %}
|
||||
{% include 'result_templates/default.html' %}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
|
||||
{% if paging %}
|
||||
<div id="pagination">
|
||||
{% if pageno > 1 %}
|
||||
<form method="{{ method or 'POST' }}" action="{{ url_for('index') }}">
|
||||
<div class="left">
|
||||
<input type="hidden" name="q" value="{{ q }}" />
|
||||
{% for category in selected_categories %}
|
||||
<input type="hidden" name="category_{{ category }}" value="1"/>
|
||||
{% endfor %}
|
||||
<input type="hidden" name="pageno" value="{{ pageno-1 }}" />
|
||||
<input type="submit" value="<< {{ _('previous page') }}" />
|
||||
</div>
|
||||
</form>
|
||||
{% endif %}
|
||||
<form method="{{ method or 'POST' }}" action="{{ url_for('index') }}">
|
||||
<div class="left">
|
||||
{% for category in selected_categories %}
|
||||
<input type="hidden" name="category_{{ category }}" value="1"/>
|
||||
{% endfor %}
|
||||
<input type="hidden" name="q" value="{{ q }}" />
|
||||
<input type="hidden" name="pageno" value="{{ pageno+1 }}" />
|
||||
<input type="submit" value="{{ _('next page') }} >>" />
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endblock %}
|
7
sources/searx/templates/search.html
Normal file
|
@ -0,0 +1,7 @@
|
|||
<form method="{{ method or 'POST' }}" action="{{ url_for('index') }}" id="search_form">
|
||||
<div id="search_wrapper">
|
||||
<input type="text" placeholder="{{ _('Search for...') }}" id="q" class="q" name="q" tabindex="1" autocomplete="off" {% if q %}value="{{ q }}"{% endif %}/>
|
||||
<input type="submit" value="search" id="search_submit" />
|
||||
</div>
|
||||
{% include 'categories.html' %}
|
||||
</form>
|
22
sources/searx/templates/stats.html
Normal file
|
@ -0,0 +1,22 @@
|
|||
{% extends "base.html" %}
|
||||
{% block head %} {% endblock %}
|
||||
{% block content %}
|
||||
<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 }}%"> </div></td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
</div>
|
||||
{% endfor %}
|
||||
{% endblock %}
|
72
sources/searx/testing.py
Normal file
|
@ -0,0 +1,72 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
"""Shared testing code."""
|
||||
|
||||
from plone.testing import Layer
|
||||
from unittest2 import TestCase
|
||||
|
||||
|
||||
import os
|
||||
import subprocess
|
||||
|
||||
|
||||
class SearxTestLayer:
|
||||
"""Base layer for non-robot tests."""
|
||||
|
||||
__name__ = u'SearxTestLayer'
|
||||
|
||||
def setUp(cls):
|
||||
pass
|
||||
setUp = classmethod(setUp)
|
||||
|
||||
def tearDown(cls):
|
||||
pass
|
||||
tearDown = classmethod(tearDown)
|
||||
|
||||
def testSetUp(cls):
|
||||
pass
|
||||
testSetUp = classmethod(testSetUp)
|
||||
|
||||
def testTearDown(cls):
|
||||
pass
|
||||
testTearDown = classmethod(testTearDown)
|
||||
|
||||
|
||||
class SearxRobotLayer(Layer):
|
||||
"""Searx Robot Test Layer"""
|
||||
|
||||
def setUp(self):
|
||||
os.setpgrp() # create new process group, become its leader
|
||||
|
||||
# get program paths
|
||||
webapp = os.path.join(
|
||||
os.path.abspath(os.path.dirname(os.path.realpath(__file__))),
|
||||
'webapp.py'
|
||||
)
|
||||
exe = os.path.abspath(os.path.dirname(__file__) + '/../bin/py')
|
||||
|
||||
# set robot settings path
|
||||
os.environ['SEARX_SETTINGS_PATH'] = os.path.abspath(
|
||||
os.path.dirname(__file__) + '/settings_robot.yml')
|
||||
|
||||
# run the server
|
||||
self.server = subprocess.Popen(
|
||||
[exe, webapp],
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.STDOUT
|
||||
)
|
||||
|
||||
def tearDown(self):
|
||||
# send TERM signal to all processes in my group, to stop subprocesses
|
||||
os.killpg(os.getpgid(self.server.pid), 15)
|
||||
|
||||
# remove previously set environment variable
|
||||
del os.environ['SEARX_SETTINGS_PATH']
|
||||
|
||||
|
||||
SEARXROBOTLAYER = SearxRobotLayer()
|
||||
|
||||
|
||||
class SearxTestCase(TestCase):
|
||||
"""Base test case for non-robot tests."""
|
||||
|
||||
layer = SearxTestLayer
|
0
sources/searx/tests/__init__.py
Normal file
0
sources/searx/tests/robot/__init__.py
Normal file
44
sources/searx/tests/robot/test_basic.robot
Normal file
|
@ -0,0 +1,44 @@
|
|||
*** Settings ***
|
||||
Library Selenium2Library timeout=10 implicit_wait=0.5
|
||||
Test Setup Open Browser http://localhost:11111/
|
||||
Test Teardown Close All Browsers
|
||||
|
||||
|
||||
*** Test Cases ***
|
||||
Front page
|
||||
Page Should Contain about
|
||||
Page Should Contain preferences
|
||||
|
||||
About page
|
||||
Click Element link=about
|
||||
Page Should Contain Why use Searx?
|
||||
Page Should Contain Element link=search engines
|
||||
|
||||
Preferences page
|
||||
Click Element link=preferences
|
||||
Page Should Contain Preferences
|
||||
Page Should Contain Default categories
|
||||
Page Should Contain Currently used search engines
|
||||
Page Should Contain dummy_dummy
|
||||
Page Should Contain general_dummy
|
||||
|
||||
Switch category
|
||||
Go To http://localhost:11111/preferences
|
||||
Page Should Contain Checkbox category_general
|
||||
Page Should Contain Checkbox category_dummy
|
||||
Click Element xpath=//*[.="general"]
|
||||
Click Element xpath=//*[.="dummy"]
|
||||
Submit Form id=search_form
|
||||
Location Should Be http://localhost:11111/
|
||||
Checkbox Should Not Be Selected category_general
|
||||
Checkbox Should Be Selected category_dummy
|
||||
|
||||
Change language
|
||||
Page Should Contain about
|
||||
Page Should Contain preferences
|
||||
Go To http://localhost:11111/preferences
|
||||
Select From List locale hu
|
||||
Submit Form id=search_form
|
||||
Location Should Be http://localhost:11111/
|
||||
Page Should Contain rólunk
|
||||
Page Should Contain beállítások
|
23
sources/searx/tests/test_robot.py
Normal file
|
@ -0,0 +1,23 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
import os
|
||||
import unittest2 as unittest
|
||||
from plone.testing import layered
|
||||
from robotsuite import RobotTestSuite
|
||||
from searx.testing import SEARXROBOTLAYER
|
||||
|
||||
|
||||
def test_suite():
|
||||
suite = unittest.TestSuite()
|
||||
current_dir = os.path.abspath(os.path.dirname(__file__))
|
||||
robot_dir = os.path.join(current_dir, 'robot')
|
||||
tests = [
|
||||
os.path.join('robot', f) for f in
|
||||
os.listdir(robot_dir) if f.endswith('.robot') and
|
||||
f.startswith('test_')
|
||||
]
|
||||
for test in tests:
|
||||
suite.addTests([
|
||||
layered(RobotTestSuite(test), layer=SEARXROBOTLAYER),
|
||||
])
|
||||
return suite
|
160
sources/searx/tests/test_webapp.py
Normal file
|
@ -0,0 +1,160 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
import json
|
||||
from urlparse import ParseResult
|
||||
from mock import patch
|
||||
from searx import webapp
|
||||
from searx.testing import SearxTestCase
|
||||
|
||||
|
||||
class ViewsTestCase(SearxTestCase):
|
||||
|
||||
def setUp(self):
|
||||
webapp.app.config['TESTING'] = True # to get better error messages
|
||||
self.app = webapp.app.test_client()
|
||||
|
||||
# set some defaults
|
||||
self.test_results = [
|
||||
{
|
||||
'content': 'first test content',
|
||||
'title': 'First Test',
|
||||
'url': 'http://first.test.xyz',
|
||||
'engines': ['youtube', 'startpage'],
|
||||
'engine': 'startpage',
|
||||
'parsed_url': ParseResult(scheme='http', netloc='first.test.xyz', path='/', params='', query='', fragment=''), # noqa
|
||||
}, {
|
||||
'content': 'second test content',
|
||||
'title': 'Second Test',
|
||||
'url': 'http://second.test.xyz',
|
||||
'engines': ['youtube', 'startpage'],
|
||||
'engine': 'youtube',
|
||||
'parsed_url': ParseResult(scheme='http', netloc='second.test.xyz', path='/', params='', query='', fragment=''), # noqa
|
||||
},
|
||||
]
|
||||
|
||||
self.maxDiff = None # to see full diffs
|
||||
|
||||
def test_index_empty(self):
|
||||
result = self.app.post('/')
|
||||
self.assertEqual(result.status_code, 200)
|
||||
self.assertIn('<div class="title"><h1>searx</h1></div>', result.data)
|
||||
|
||||
@patch('searx.webapp.do_search')
|
||||
def test_index_html(self, search):
|
||||
search.return_value = (
|
||||
self.test_results,
|
||||
set()
|
||||
)
|
||||
result = self.app.post('/', data={'q': 'test'})
|
||||
self.assertIn(
|
||||
'<h3 class="result_title"><a href="http://first.test.xyz">First <span class="highlight">Test</span></a></h3>', # noqa
|
||||
result.data
|
||||
)
|
||||
self.assertIn(
|
||||
'<p class="content">first <span class="highlight">test</span> content<br /></p>',
|
||||
result.data
|
||||
)
|
||||
|
||||
@patch('searx.webapp.do_search')
|
||||
def test_index_json(self, search):
|
||||
search.return_value = (
|
||||
self.test_results,
|
||||
set()
|
||||
)
|
||||
result = self.app.post('/', data={'q': 'test', 'format': 'json'})
|
||||
|
||||
result_dict = json.loads(result.data)
|
||||
|
||||
self.assertEqual('test', result_dict['query'])
|
||||
self.assertEqual(
|
||||
result_dict['results'][0]['content'], 'first test content')
|
||||
self.assertEqual(
|
||||
result_dict['results'][0]['url'], 'http://first.test.xyz')
|
||||
|
||||
@patch('searx.webapp.do_search')
|
||||
def test_index_csv(self, search):
|
||||
search.return_value = (
|
||||
self.test_results,
|
||||
set()
|
||||
)
|
||||
result = self.app.post('/', data={'q': 'test', 'format': 'csv'})
|
||||
|
||||
self.assertEqual(
|
||||
'title,url,content,host,engine,score\r\n'
|
||||
'First Test,http://first.test.xyz,first test content,first.test.xyz,startpage,\r\n' # noqa
|
||||
'Second Test,http://second.test.xyz,second test content,second.test.xyz,youtube,\r\n', # noqa
|
||||
result.data
|
||||
)
|
||||
|
||||
@patch('searx.webapp.do_search')
|
||||
def test_index_rss(self, search):
|
||||
search.return_value = (
|
||||
self.test_results,
|
||||
set()
|
||||
)
|
||||
result = self.app.post('/', data={'q': 'test', 'format': 'rss'})
|
||||
|
||||
self.assertIn(
|
||||
'<description>Search results for "test" - searx</description>',
|
||||
result.data
|
||||
)
|
||||
|
||||
self.assertIn(
|
||||
'<opensearch:totalResults>2</opensearch:totalResults>',
|
||||
result.data
|
||||
)
|
||||
|
||||
self.assertIn(
|
||||
'<title>First Test</title>',
|
||||
result.data
|
||||
)
|
||||
|
||||
self.assertIn(
|
||||
'<link>http://first.test.xyz</link>',
|
||||
result.data
|
||||
)
|
||||
|
||||
self.assertIn(
|
||||
'<description>first test content</description>',
|
||||
result.data
|
||||
)
|
||||
|
||||
def test_about(self):
|
||||
result = self.app.get('/about')
|
||||
self.assertEqual(result.status_code, 200)
|
||||
self.assertIn('<h1>About <a href="/">searx</a></h1>', result.data)
|
||||
|
||||
def test_preferences(self):
|
||||
result = self.app.get('/preferences')
|
||||
self.assertEqual(result.status_code, 200)
|
||||
self.assertIn(
|
||||
'<form method="post" action="/preferences" id="search_form">',
|
||||
result.data
|
||||
)
|
||||
self.assertIn(
|
||||
'<legend>Default categories</legend>',
|
||||
result.data
|
||||
)
|
||||
self.assertIn(
|
||||
'<legend>Interface language</legend>',
|
||||
result.data
|
||||
)
|
||||
|
||||
def test_stats(self):
|
||||
result = self.app.get('/stats')
|
||||
self.assertEqual(result.status_code, 200)
|
||||
self.assertIn('<h2>Engine stats</h2>', result.data)
|
||||
|
||||
def test_robots_txt(self):
|
||||
result = self.app.get('/robots.txt')
|
||||
self.assertEqual(result.status_code, 200)
|
||||
self.assertIn('Allow: /', result.data)
|
||||
|
||||
def test_opensearch_xml(self):
|
||||
result = self.app.get('/opensearch.xml')
|
||||
self.assertEqual(result.status_code, 200)
|
||||
self.assertIn('<Description>Search searx</Description>', result.data)
|
||||
|
||||
def test_favicon(self):
|
||||
result = self.app.get('/favicon.ico')
|
||||
self.assertEqual(result.status_code, 200)
|
BIN
sources/searx/translations/de/LC_MESSAGES/messages.mo
Normal file
176
sources/searx/translations/de/LC_MESSAGES/messages.po
Normal file
|
@ -0,0 +1,176 @@
|
|||
# English translations for .
|
||||
# Copyright (C) 2014 ORGANIZATION
|
||||
# This file is distributed under the same license as the project.
|
||||
#
|
||||
# Translators:
|
||||
# pointhi, 2014
|
||||
# stf <stefan.marsiske@gmail.com>, 2014
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: searx\n"
|
||||
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
|
||||
"POT-Creation-Date: 2014-03-18 17:10+0100\n"
|
||||
"PO-Revision-Date: 2014-03-15 18:40+0000\n"
|
||||
"Last-Translator: pointhi\n"
|
||||
"Language-Team: German "
|
||||
"(http://www.transifex.com/projects/p/searx/language/de/)\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=utf-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Generated-By: Babel 1.3\n"
|
||||
|
||||
#: searx/webapp.py:167
|
||||
msgid "{minutes} minute(s) ago"
|
||||
msgstr ""
|
||||
|
||||
#: searx/webapp.py:169
|
||||
msgid "{hours} hour(s), {minutes} minute(s) ago"
|
||||
msgstr ""
|
||||
|
||||
#: searx/engines/__init__.py:311
|
||||
msgid "Page loads (sec)"
|
||||
msgstr "Ladezeit (sek)"
|
||||
|
||||
#: searx/engines/__init__.py:315
|
||||
msgid "Number of results"
|
||||
msgstr "Trefferanzahl"
|
||||
|
||||
#: searx/engines/__init__.py:319
|
||||
msgid "Scores"
|
||||
msgstr "Punkte"
|
||||
|
||||
#: searx/engines/__init__.py:323
|
||||
msgid "Scores per result"
|
||||
msgstr "Punkte pro Treffer"
|
||||
|
||||
#: searx/engines/__init__.py:327
|
||||
msgid "Errors"
|
||||
msgstr "Fehler"
|
||||
|
||||
#: searx/templates/index.html:7
|
||||
msgid "about"
|
||||
msgstr "Über uns"
|
||||
|
||||
#: searx/templates/index.html:8
|
||||
msgid "preferences"
|
||||
msgstr "Einstellungen"
|
||||
|
||||
#: searx/templates/preferences.html:5
|
||||
msgid "Preferences"
|
||||
msgstr "Einstellungen"
|
||||
|
||||
#: searx/templates/preferences.html:9
|
||||
msgid "Default categories"
|
||||
msgstr "Standard Kategorien"
|
||||
|
||||
#: searx/templates/preferences.html:15
|
||||
msgid "Search language"
|
||||
msgstr "Suchsprache"
|
||||
|
||||
#: searx/templates/preferences.html:18
|
||||
msgid "Automatic"
|
||||
msgstr "Automatisch"
|
||||
|
||||
#: searx/templates/preferences.html:26
|
||||
msgid "Interface language"
|
||||
msgstr "Oberflächensprache"
|
||||
|
||||
#: searx/templates/preferences.html:36
|
||||
msgid "Currently used search engines"
|
||||
msgstr "Aktuell benutzte Suchmaschinen"
|
||||
|
||||
#: searx/templates/preferences.html:40
|
||||
msgid "Engine name"
|
||||
msgstr "Suchmaschinenname"
|
||||
|
||||
#: searx/templates/preferences.html:41
|
||||
msgid "Category"
|
||||
msgstr "Kategorie"
|
||||
|
||||
#: searx/templates/preferences.html:42 searx/templates/preferences.html:53
|
||||
msgid "Allow"
|
||||
msgstr "Erlauben"
|
||||
|
||||
#: searx/templates/preferences.html:42 searx/templates/preferences.html:54
|
||||
msgid "Block"
|
||||
msgstr "Blockieren"
|
||||
|
||||
#: searx/templates/preferences.html:62
|
||||
msgid ""
|
||||
"These settings are stored in your cookies, this allows us not to store "
|
||||
"this data about you."
|
||||
msgstr ""
|
||||
"Diese Informationen werden in Cookies gespeichert, damit wir keine ihrer "
|
||||
"persönlichen Daten speichern müssen."
|
||||
|
||||
#: searx/templates/preferences.html:64
|
||||
msgid ""
|
||||
"These cookies serve your sole convenience, we don't use these cookies to "
|
||||
"track you."
|
||||
msgstr ""
|
||||
"Diese Cookies dienen ihrer Gemütlichkeit, wir verwenden sie nicht zum "
|
||||
"überwachen."
|
||||
|
||||
#: searx/templates/preferences.html:67
|
||||
msgid "save"
|
||||
msgstr "Speichern"
|
||||
|
||||
#: searx/templates/preferences.html:68
|
||||
msgid "back"
|
||||
msgstr "Zurück"
|
||||
|
||||
#: searx/templates/results.html:11
|
||||
msgid "Suggestions"
|
||||
msgstr "Vorschläge"
|
||||
|
||||
#: searx/templates/results.html:22
|
||||
msgid "Search URL"
|
||||
msgstr "Such-URL"
|
||||
|
||||
#: searx/templates/results.html:26
|
||||
msgid "Download results"
|
||||
msgstr "Ergebnisse herunterladen"
|
||||
|
||||
#: searx/templates/results.html:62
|
||||
msgid "previous page"
|
||||
msgstr "vorherige Seite"
|
||||
|
||||
#: searx/templates/results.html:73
|
||||
msgid "next page"
|
||||
msgstr "nächste Seite"
|
||||
|
||||
#: searx/templates/search.html:3
|
||||
msgid "Search for..."
|
||||
msgstr "Suche nach..."
|
||||
|
||||
#: searx/templates/stats.html:4
|
||||
msgid "Engine stats"
|
||||
msgstr "Suchmaschienen Statistiken"
|
||||
|
||||
# categories - manually added
|
||||
# TODO - automatically add
|
||||
msgid "files"
|
||||
msgstr "Dateien"
|
||||
|
||||
msgid "general"
|
||||
msgstr "Allgemein"
|
||||
|
||||
msgid "music"
|
||||
msgstr "Musik"
|
||||
|
||||
msgid "social media"
|
||||
msgstr "Soziale Medien"
|
||||
|
||||
msgid "images"
|
||||
msgstr "Bilder"
|
||||
|
||||
msgid "videos"
|
||||
msgstr "Videos"
|
||||
|
||||
msgid "it"
|
||||
msgstr "IT"
|
||||
|
||||
msgid "news"
|
||||
msgstr "Neuigkeiten"
|
||||
|
BIN
sources/searx/translations/en/LC_MESSAGES/messages.mo
Normal file
169
sources/searx/translations/en/LC_MESSAGES/messages.po
Normal file
|
@ -0,0 +1,169 @@
|
|||
# English translations for PROJECT.
|
||||
# Copyright (C) 2014 ORGANIZATION
|
||||
# This file is distributed under the same license as the PROJECT project.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, 2014.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PROJECT VERSION\n"
|
||||
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
|
||||
"POT-Creation-Date: 2014-03-18 17:10+0100\n"
|
||||
"PO-Revision-Date: 2014-01-30 15:22+0100\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: en <LL@li.org>\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=utf-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Generated-By: Babel 1.3\n"
|
||||
|
||||
#: searx/webapp.py:167
|
||||
msgid "{minutes} minute(s) ago"
|
||||
msgstr ""
|
||||
|
||||
#: searx/webapp.py:169
|
||||
msgid "{hours} hour(s), {minutes} minute(s) ago"
|
||||
msgstr ""
|
||||
|
||||
#: searx/engines/__init__.py:311
|
||||
msgid "Page loads (sec)"
|
||||
msgstr ""
|
||||
|
||||
#: searx/engines/__init__.py:315
|
||||
msgid "Number of results"
|
||||
msgstr ""
|
||||
|
||||
#: searx/engines/__init__.py:319
|
||||
msgid "Scores"
|
||||
msgstr ""
|
||||
|
||||
#: searx/engines/__init__.py:323
|
||||
msgid "Scores per result"
|
||||
msgstr ""
|
||||
|
||||
#: searx/engines/__init__.py:327
|
||||
msgid "Errors"
|
||||
msgstr ""
|
||||
|
||||
#: searx/templates/index.html:7
|
||||
msgid "about"
|
||||
msgstr ""
|
||||
|
||||
#: searx/templates/index.html:8
|
||||
msgid "preferences"
|
||||
msgstr ""
|
||||
|
||||
#: searx/templates/preferences.html:5
|
||||
msgid "Preferences"
|
||||
msgstr ""
|
||||
|
||||
#: searx/templates/preferences.html:9
|
||||
msgid "Default categories"
|
||||
msgstr ""
|
||||
|
||||
#: searx/templates/preferences.html:15
|
||||
msgid "Search language"
|
||||
msgstr ""
|
||||
|
||||
#: searx/templates/preferences.html:18
|
||||
msgid "Automatic"
|
||||
msgstr ""
|
||||
|
||||
#: searx/templates/preferences.html:26
|
||||
msgid "Interface language"
|
||||
msgstr ""
|
||||
|
||||
#: searx/templates/preferences.html:36
|
||||
msgid "Currently used search engines"
|
||||
msgstr ""
|
||||
|
||||
#: searx/templates/preferences.html:40
|
||||
msgid "Engine name"
|
||||
msgstr ""
|
||||
|
||||
#: searx/templates/preferences.html:41
|
||||
msgid "Category"
|
||||
msgstr ""
|
||||
|
||||
#: searx/templates/preferences.html:42 searx/templates/preferences.html:53
|
||||
msgid "Allow"
|
||||
msgstr ""
|
||||
|
||||
#: searx/templates/preferences.html:42 searx/templates/preferences.html:54
|
||||
msgid "Block"
|
||||
msgstr ""
|
||||
|
||||
#: searx/templates/preferences.html:62
|
||||
msgid ""
|
||||
"These settings are stored in your cookies, this allows us not to store "
|
||||
"this data about you."
|
||||
msgstr ""
|
||||
|
||||
#: searx/templates/preferences.html:64
|
||||
msgid ""
|
||||
"These cookies serve your sole convenience, we don't use these cookies to "
|
||||
"track you."
|
||||
msgstr ""
|
||||
|
||||
#: searx/templates/preferences.html:67
|
||||
msgid "save"
|
||||
msgstr ""
|
||||
|
||||
#: searx/templates/preferences.html:68
|
||||
msgid "back"
|
||||
msgstr ""
|
||||
|
||||
#: searx/templates/results.html:11
|
||||
msgid "Suggestions"
|
||||
msgstr ""
|
||||
|
||||
#: searx/templates/results.html:22
|
||||
msgid "Search URL"
|
||||
msgstr ""
|
||||
|
||||
#: searx/templates/results.html:26
|
||||
msgid "Download results"
|
||||
msgstr ""
|
||||
|
||||
#: searx/templates/results.html:62
|
||||
msgid "previous page"
|
||||
msgstr ""
|
||||
|
||||
#: searx/templates/results.html:73
|
||||
msgid "next page"
|
||||
msgstr ""
|
||||
|
||||
#: searx/templates/search.html:3
|
||||
msgid "Search for..."
|
||||
msgstr ""
|
||||
|
||||
#: searx/templates/stats.html:4
|
||||
msgid "Engine stats"
|
||||
msgstr ""
|
||||
|
||||
# categories - manually added
|
||||
# TODO - automatically add
|
||||
msgid "files"
|
||||
msgstr ""
|
||||
|
||||
msgid "general"
|
||||
msgstr ""
|
||||
|
||||
msgid "music"
|
||||
msgstr ""
|
||||
|
||||
msgid "social media"
|
||||
msgstr ""
|
||||
|
||||
msgid "images"
|
||||
msgstr ""
|
||||
|
||||
msgid "videos"
|
||||
msgstr ""
|
||||
|
||||
msgid "it"
|
||||
msgstr ""
|
||||
|
||||
msgid "news"
|
||||
msgstr ""
|
||||
|
BIN
sources/searx/translations/es/LC_MESSAGES/messages.mo
Normal file
175
sources/searx/translations/es/LC_MESSAGES/messages.po
Normal file
|
@ -0,0 +1,175 @@
|
|||
# English translations for .
|
||||
# Copyright (C) 2014 ORGANIZATION
|
||||
# This file is distributed under the same license as the project.
|
||||
#
|
||||
# Translators:
|
||||
# niazle, 2014
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: searx\n"
|
||||
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
|
||||
"POT-Creation-Date: 2014-03-18 17:10+0100\n"
|
||||
"PO-Revision-Date: 2014-03-04 20:40+0000\n"
|
||||
"Last-Translator: niazle\n"
|
||||
"Language-Team: Spanish "
|
||||
"(http://www.transifex.com/projects/p/searx/language/es/)\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=utf-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Generated-By: Babel 1.3\n"
|
||||
|
||||
#: searx/webapp.py:167
|
||||
msgid "{minutes} minute(s) ago"
|
||||
msgstr ""
|
||||
|
||||
#: searx/webapp.py:169
|
||||
msgid "{hours} hour(s), {minutes} minute(s) ago"
|
||||
msgstr ""
|
||||
|
||||
#: searx/engines/__init__.py:311
|
||||
msgid "Page loads (sec)"
|
||||
msgstr "Tiempo de carga (segundos)"
|
||||
|
||||
#: searx/engines/__init__.py:315
|
||||
msgid "Number of results"
|
||||
msgstr "Número de resultados"
|
||||
|
||||
#: searx/engines/__init__.py:319
|
||||
msgid "Scores"
|
||||
msgstr "Puntuaciones"
|
||||
|
||||
#: searx/engines/__init__.py:323
|
||||
msgid "Scores per result"
|
||||
msgstr "Puntuaciones por resultado"
|
||||
|
||||
#: searx/engines/__init__.py:327
|
||||
msgid "Errors"
|
||||
msgstr "Errores"
|
||||
|
||||
#: searx/templates/index.html:7
|
||||
msgid "about"
|
||||
msgstr "acerca de"
|
||||
|
||||
#: searx/templates/index.html:8
|
||||
msgid "preferences"
|
||||
msgstr "preferencias"
|
||||
|
||||
#: searx/templates/preferences.html:5
|
||||
msgid "Preferences"
|
||||
msgstr "Preferencias"
|
||||
|
||||
#: searx/templates/preferences.html:9
|
||||
msgid "Default categories"
|
||||
msgstr "Categorías predeterminadas"
|
||||
|
||||
#: searx/templates/preferences.html:15
|
||||
msgid "Search language"
|
||||
msgstr "Buscar idioma"
|
||||
|
||||
#: searx/templates/preferences.html:18
|
||||
msgid "Automatic"
|
||||
msgstr "Automático"
|
||||
|
||||
#: searx/templates/preferences.html:26
|
||||
msgid "Interface language"
|
||||
msgstr "Idioma de la interfaz"
|
||||
|
||||
#: searx/templates/preferences.html:36
|
||||
msgid "Currently used search engines"
|
||||
msgstr "Motores de búsqueda actualmente en uso"
|
||||
|
||||
#: searx/templates/preferences.html:40
|
||||
msgid "Engine name"
|
||||
msgstr "Nombre del motor de búsqueda"
|
||||
|
||||
#: searx/templates/preferences.html:41
|
||||
msgid "Category"
|
||||
msgstr "Categoría"
|
||||
|
||||
#: searx/templates/preferences.html:42 searx/templates/preferences.html:53
|
||||
msgid "Allow"
|
||||
msgstr "Permitir"
|
||||
|
||||
#: searx/templates/preferences.html:42 searx/templates/preferences.html:54
|
||||
msgid "Block"
|
||||
msgstr "Bloquear"
|
||||
|
||||
#: searx/templates/preferences.html:62
|
||||
msgid ""
|
||||
"These settings are stored in your cookies, this allows us not to store "
|
||||
"this data about you."
|
||||
msgstr ""
|
||||
"Esta configuración se guarda en sus cookies, lo que nos permite no "
|
||||
"almacenar dicha información sobre usted."
|
||||
|
||||
#: searx/templates/preferences.html:64
|
||||
msgid ""
|
||||
"These cookies serve your sole convenience, we don't use these cookies to "
|
||||
"track you."
|
||||
msgstr ""
|
||||
"Estas cookies son para su propia comodidad, no las utilizamos para "
|
||||
"rastrearle."
|
||||
|
||||
#: searx/templates/preferences.html:67
|
||||
msgid "save"
|
||||
msgstr "Guardar"
|
||||
|
||||
#: searx/templates/preferences.html:68
|
||||
msgid "back"
|
||||
msgstr "Atrás"
|
||||
|
||||
#: searx/templates/results.html:11
|
||||
msgid "Suggestions"
|
||||
msgstr "Sugerencias"
|
||||
|
||||
#: searx/templates/results.html:22
|
||||
msgid "Search URL"
|
||||
msgstr "Buscar URL"
|
||||
|
||||
#: searx/templates/results.html:26
|
||||
msgid "Download results"
|
||||
msgstr "Descargar resultados"
|
||||
|
||||
#: searx/templates/results.html:62
|
||||
msgid "previous page"
|
||||
msgstr "Página anterior"
|
||||
|
||||
#: searx/templates/results.html:73
|
||||
msgid "next page"
|
||||
msgstr "Página siguiente"
|
||||
|
||||
#: searx/templates/search.html:3
|
||||
msgid "Search for..."
|
||||
msgstr ""
|
||||
|
||||
#: searx/templates/stats.html:4
|
||||
msgid "Engine stats"
|
||||
msgstr "Estadísticas del motor de búsqueda"
|
||||
|
||||
# categories - manually added
|
||||
# TODO - automatically add
|
||||
msgid "files"
|
||||
msgstr "Archivos"
|
||||
|
||||
msgid "general"
|
||||
msgstr "General"
|
||||
|
||||
msgid "music"
|
||||
msgstr "Música"
|
||||
|
||||
msgid "social media"
|
||||
msgstr "Medios sociales"
|
||||
|
||||
msgid "images"
|
||||
msgstr "Imágenes"
|
||||
|
||||
msgid "videos"
|
||||
msgstr "Vídeos"
|
||||
|
||||
msgid "it"
|
||||
msgstr "TIC"
|
||||
|
||||
msgid "news"
|
||||
msgstr "noticias"
|
||||
|
BIN
sources/searx/translations/fr/LC_MESSAGES/messages.mo
Normal file
177
sources/searx/translations/fr/LC_MESSAGES/messages.po
Normal file
|
@ -0,0 +1,177 @@
|
|||
# English translations for .
|
||||
# Copyright (C) 2014 ORGANIZATION
|
||||
# This file is distributed under the same license as the project.
|
||||
#
|
||||
# Translators:
|
||||
# Benjamin Sonntag <benjamin@sonntag.fr>, 2014
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, 2014
|
||||
# rike <u@451f.org>, 2014
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: searx\n"
|
||||
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
|
||||
"POT-Creation-Date: 2014-03-18 17:10+0100\n"
|
||||
"PO-Revision-Date: 2014-03-16 07:40+0000\n"
|
||||
"Last-Translator: Benjamin Sonntag <benjamin@sonntag.fr>\n"
|
||||
"Language-Team: French "
|
||||
"(http://www.transifex.com/projects/p/searx/language/fr/)\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n > 1)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=utf-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Generated-By: Babel 1.3\n"
|
||||
|
||||
#: searx/webapp.py:167
|
||||
msgid "{minutes} minute(s) ago"
|
||||
msgstr ""
|
||||
|
||||
#: searx/webapp.py:169
|
||||
msgid "{hours} hour(s), {minutes} minute(s) ago"
|
||||
msgstr ""
|
||||
|
||||
#: searx/engines/__init__.py:311
|
||||
msgid "Page loads (sec)"
|
||||
msgstr "Chargement de la page (sec)"
|
||||
|
||||
#: searx/engines/__init__.py:315
|
||||
msgid "Number of results"
|
||||
msgstr "Nombre de résultats"
|
||||
|
||||
#: searx/engines/__init__.py:319
|
||||
msgid "Scores"
|
||||
msgstr "Score"
|
||||
|
||||
#: searx/engines/__init__.py:323
|
||||
msgid "Scores per result"
|
||||
msgstr "Score par résultat"
|
||||
|
||||
#: searx/engines/__init__.py:327
|
||||
msgid "Errors"
|
||||
msgstr "Erreurs"
|
||||
|
||||
#: searx/templates/index.html:7
|
||||
msgid "about"
|
||||
msgstr "À propos"
|
||||
|
||||
#: searx/templates/index.html:8
|
||||
msgid "preferences"
|
||||
msgstr "préférences"
|
||||
|
||||
#: searx/templates/preferences.html:5
|
||||
msgid "Preferences"
|
||||
msgstr "Préférences"
|
||||
|
||||
#: searx/templates/preferences.html:9
|
||||
msgid "Default categories"
|
||||
msgstr "Catégories par défaut"
|
||||
|
||||
#: searx/templates/preferences.html:15
|
||||
msgid "Search language"
|
||||
msgstr "Langue de recherche"
|
||||
|
||||
#: searx/templates/preferences.html:18
|
||||
msgid "Automatic"
|
||||
msgstr "Automatique"
|
||||
|
||||
#: searx/templates/preferences.html:26
|
||||
msgid "Interface language"
|
||||
msgstr "Langue de l'interface"
|
||||
|
||||
#: searx/templates/preferences.html:36
|
||||
msgid "Currently used search engines"
|
||||
msgstr "Moteurs actuellement utilisés"
|
||||
|
||||
#: searx/templates/preferences.html:40
|
||||
msgid "Engine name"
|
||||
msgstr "Nom du moteur"
|
||||
|
||||
#: searx/templates/preferences.html:41
|
||||
msgid "Category"
|
||||
msgstr "Catégorie"
|
||||
|
||||
#: searx/templates/preferences.html:42 searx/templates/preferences.html:53
|
||||
msgid "Allow"
|
||||
msgstr "Autoriser"
|
||||
|
||||
#: searx/templates/preferences.html:42 searx/templates/preferences.html:54
|
||||
msgid "Block"
|
||||
msgstr "Bloquer"
|
||||
|
||||
#: searx/templates/preferences.html:62
|
||||
msgid ""
|
||||
"These settings are stored in your cookies, this allows us not to store "
|
||||
"this data about you."
|
||||
msgstr ""
|
||||
"Ces paramètres sont stockés dans vos cookies ; ceci nous permet de ne pas"
|
||||
" collecter vos données."
|
||||
|
||||
#: searx/templates/preferences.html:64
|
||||
msgid ""
|
||||
"These cookies serve your sole convenience, we don't use these cookies to "
|
||||
"track you."
|
||||
msgstr ""
|
||||
"Ces cookies existent pour votre confort d'utilisation, nous ne les "
|
||||
"utilisons pas pour vous espionner."
|
||||
|
||||
#: searx/templates/preferences.html:67
|
||||
msgid "save"
|
||||
msgstr "enregistrer"
|
||||
|
||||
#: searx/templates/preferences.html:68
|
||||
msgid "back"
|
||||
msgstr "retour"
|
||||
|
||||
#: searx/templates/results.html:11
|
||||
msgid "Suggestions"
|
||||
msgstr "Suggestions"
|
||||
|
||||
#: searx/templates/results.html:22
|
||||
msgid "Search URL"
|
||||
msgstr "URL de recherche"
|
||||
|
||||
#: searx/templates/results.html:26
|
||||
msgid "Download results"
|
||||
msgstr "Télécharger les résultats"
|
||||
|
||||
#: searx/templates/results.html:62
|
||||
msgid "previous page"
|
||||
msgstr "page précédente"
|
||||
|
||||
#: searx/templates/results.html:73
|
||||
msgid "next page"
|
||||
msgstr "page suivante"
|
||||
|
||||
#: searx/templates/search.html:3
|
||||
msgid "Search for..."
|
||||
msgstr "Rechercher..."
|
||||
|
||||
#: searx/templates/stats.html:4
|
||||
msgid "Engine stats"
|
||||
msgstr "Statistiques du moteur"
|
||||
|
||||
# categories - manually added
|
||||
# TODO - automatically add
|
||||
msgid "files"
|
||||
msgstr "fichiers"
|
||||
|
||||
msgid "general"
|
||||
msgstr "général"
|
||||
|
||||
msgid "music"
|
||||
msgstr "musique"
|
||||
|
||||
msgid "social media"
|
||||
msgstr "réseaux sociaux"
|
||||
|
||||
msgid "images"
|
||||
msgstr "images"
|
||||
|
||||
msgid "videos"
|
||||
msgstr "vidéos"
|
||||
|
||||
msgid "it"
|
||||
msgstr "Informatique"
|
||||
|
||||
msgid "news"
|
||||
msgstr "actus"
|
||||
|
BIN
sources/searx/translations/hu/LC_MESSAGES/messages.mo
Normal file
171
sources/searx/translations/hu/LC_MESSAGES/messages.po
Normal file
|
@ -0,0 +1,171 @@
|
|||
# Hungarian translations for PROJECT.
|
||||
# Copyright (C) 2014 ORGANIZATION
|
||||
# This file is distributed under the same license as the PROJECT project.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, 2014.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PROJECT VERSION\n"
|
||||
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
|
||||
"POT-Creation-Date: 2014-03-18 17:10+0100\n"
|
||||
"PO-Revision-Date: 2014-01-21 23:33+0100\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: hu <LL@li.org>\n"
|
||||
"Plural-Forms: nplurals=1; plural=0\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=utf-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Generated-By: Babel 1.3\n"
|
||||
|
||||
#: searx/webapp.py:167
|
||||
msgid "{minutes} minute(s) ago"
|
||||
msgstr "{minutes} perce"
|
||||
|
||||
#: searx/webapp.py:169
|
||||
msgid "{hours} hour(s), {minutes} minute(s) ago"
|
||||
msgstr "{hours} óra, {minutes} perce"
|
||||
|
||||
#: searx/engines/__init__.py:311
|
||||
msgid "Page loads (sec)"
|
||||
msgstr "Válaszidők (sec)"
|
||||
|
||||
#: searx/engines/__init__.py:315
|
||||
msgid "Number of results"
|
||||
msgstr "Találatok száma"
|
||||
|
||||
#: searx/engines/__init__.py:319
|
||||
msgid "Scores"
|
||||
msgstr "Pontszámok"
|
||||
|
||||
#: searx/engines/__init__.py:323
|
||||
msgid "Scores per result"
|
||||
msgstr "Pontszámok találatonként"
|
||||
|
||||
#: searx/engines/__init__.py:327
|
||||
msgid "Errors"
|
||||
msgstr "Hibák"
|
||||
|
||||
#: searx/templates/index.html:7
|
||||
msgid "about"
|
||||
msgstr "rólunk"
|
||||
|
||||
#: searx/templates/index.html:8
|
||||
msgid "preferences"
|
||||
msgstr "beállítások"
|
||||
|
||||
#: searx/templates/preferences.html:5
|
||||
msgid "Preferences"
|
||||
msgstr "Beállítások"
|
||||
|
||||
#: searx/templates/preferences.html:9
|
||||
msgid "Default categories"
|
||||
msgstr "Alapértelmezett kategóriák"
|
||||
|
||||
#: searx/templates/preferences.html:15
|
||||
msgid "Search language"
|
||||
msgstr "Keresés nyelve"
|
||||
|
||||
#: searx/templates/preferences.html:18
|
||||
msgid "Automatic"
|
||||
msgstr "Automatikus"
|
||||
|
||||
#: searx/templates/preferences.html:26
|
||||
msgid "Interface language"
|
||||
msgstr "Felület nyelve"
|
||||
|
||||
#: searx/templates/preferences.html:36
|
||||
msgid "Currently used search engines"
|
||||
msgstr "Jelenleg használt keresők"
|
||||
|
||||
#: searx/templates/preferences.html:40
|
||||
msgid "Engine name"
|
||||
msgstr "Kereső neve"
|
||||
|
||||
#: searx/templates/preferences.html:41
|
||||
msgid "Category"
|
||||
msgstr "Kategória"
|
||||
|
||||
#: searx/templates/preferences.html:42 searx/templates/preferences.html:53
|
||||
msgid "Allow"
|
||||
msgstr "Engedélyezés"
|
||||
|
||||
#: searx/templates/preferences.html:42 searx/templates/preferences.html:54
|
||||
msgid "Block"
|
||||
msgstr "Tiltás"
|
||||
|
||||
#: searx/templates/preferences.html:62
|
||||
msgid ""
|
||||
"These settings are stored in your cookies, this allows us not to store "
|
||||
"this data about you."
|
||||
msgstr "Ezek a beállítások csak a böngésző cookie-jaiban tárolódnak."
|
||||
|
||||
#: searx/templates/preferences.html:64
|
||||
msgid ""
|
||||
"These cookies serve your sole convenience, we don't use these cookies to "
|
||||
"track you."
|
||||
msgstr ""
|
||||
"Ezek a cookie-k csak kényelmi funkciókat látnak el, nem használjuk a "
|
||||
"felhasználók követésére."
|
||||
|
||||
#: searx/templates/preferences.html:67
|
||||
msgid "save"
|
||||
msgstr "mentés"
|
||||
|
||||
#: searx/templates/preferences.html:68
|
||||
msgid "back"
|
||||
msgstr "vissza"
|
||||
|
||||
#: searx/templates/results.html:11
|
||||
msgid "Suggestions"
|
||||
msgstr "Javaslatok"
|
||||
|
||||
#: searx/templates/results.html:22
|
||||
msgid "Search URL"
|
||||
msgstr "Keresési URL"
|
||||
|
||||
#: searx/templates/results.html:26
|
||||
msgid "Download results"
|
||||
msgstr "Találatok letöltése"
|
||||
|
||||
#: searx/templates/results.html:62
|
||||
msgid "previous page"
|
||||
msgstr "előző oldal"
|
||||
|
||||
#: searx/templates/results.html:73
|
||||
msgid "next page"
|
||||
msgstr "következő oldal"
|
||||
|
||||
#: searx/templates/search.html:3
|
||||
msgid "Search for..."
|
||||
msgstr "Keresés..."
|
||||
|
||||
#: searx/templates/stats.html:4
|
||||
msgid "Engine stats"
|
||||
msgstr "Kereső statisztikák"
|
||||
|
||||
# categories - manually added
|
||||
# TODO - automatically add
|
||||
msgid "files"
|
||||
msgstr "fájlok"
|
||||
|
||||
msgid "general"
|
||||
msgstr "általános"
|
||||
|
||||
msgid "music"
|
||||
msgstr "zene"
|
||||
|
||||
msgid "social media"
|
||||
msgstr "közösségi média"
|
||||
|
||||
msgid "images"
|
||||
msgstr "képek"
|
||||
|
||||
msgid "videos"
|
||||
msgstr "videók"
|
||||
|
||||
msgid "it"
|
||||
msgstr "it"
|
||||
|
||||
msgid "news"
|
||||
msgstr "hírek"
|
||||
|