diff --git a/manifest.json b/manifest.json index b89103b..3b9e512 100644 --- a/manifest.json +++ b/manifest.json @@ -11,8 +11,8 @@ }, "url": "https://asciimoo.github.io/searx/", "maintainer": { - "name": "beudbeud", - "email": "beudbeud@beudibox.fr" + "name": "opi", + "email": "opi@zeropi.net" }, "multi_instance": "false", "services": [ @@ -41,7 +41,7 @@ "default": "/searx" }, { - "name": "public_site", + "name": "is_public", "ask": { "en": "Is it a public Searx site ?", "fr": "Est-ce un site public ?" diff --git a/scripts/backup b/scripts/backup index eba70be..d4e95d4 100755 --- a/scripts/backup +++ b/scripts/backup @@ -1,4 +1,5 @@ #!/bin/bash +app="searx" # causes the shell to exit if any subcommand or pipeline returns a non-zero status set -e @@ -6,30 +7,15 @@ set -e # Source YNH helpers . /usr/share/yunohost/helpers -# This is a multi-instance app, meaning it can be installed several times independently -# The id of the app as stated in the manifest is available as $YNH_APP_ID -# The instance number is available as $YNH_APP_INSTANCE_NUMBER (equals "1", "2", ...) -# The app instance name is available as $YNH_APP_INSTANCE_NAME -# - the first time the app is installed, YNH_APP_INSTANCE_NAME = ynhexample -# - the second time the app is installed, YNH_APP_INSTANCE_NAME = ynhexample__2 -# - ynhexample__{N} for the subsequent installations, with N=3,4, ... -# The app instance name is probably what you are interested the most, since this is -# guaranteed to be unique. This is a good unique identifier to define installation path, -# db names, ... -app=$YNH_APP_INSTANCE_NAME - # Retrieve arguments -domain=$(sudo yunohost app setting $app domain) - -# Backup directory location for the app from where the script is executed and -# which will be compressed afterward -backup_dir=$YNH_APP_BACKUP_DIR +domain=$(ynh_app_setting_get "$app" domain) +path=$(ynh_app_setting_get "$app" path) +is_public=$(ynh_app_setting_get "$app" is_public) # Backup sources & data ynh_backup "/opt/yunohost/$app" "sources" # Copy Nginx conf -sudo mkdir -p ./conf ynh_backup "/etc/uwsgi/apps-available/$app.ini" "conf/searx.ini" ynh_backup "/opt/yunohost/$app/searx/settings.yml" "conf/settings.yml" ynh_backup "/etc/nginx/conf.d/$domain.d/$app.conf" "conf/nginx.conf" diff --git a/scripts/install b/scripts/install index 023012d..f4c551b 100644 --- a/scripts/install +++ b/scripts/install @@ -1,27 +1,30 @@ #!/bin/bash +app="searx" + +# causes the shell to exit if any subcommand or pipeline returns a non-zero status +set -e + +# Source app helpers +. /usr/share/yunohost/helpers # Retrieve arguments -domain=$1 -path=$2 -is_public=$3 +domain=$YNH_APP_ARG_DOMAIN +path=$YNH_APP_ARG_PATH +is_public=$YNH_APP_ARG_IS_PUBLIC + +# Force path to start with a / +if [ "${path:0:1}" != "/" ]; then + path="/$path" +fi + +# Remove trailing slash to path +path=${path%/} +#force location to be / or /foo +location=${path:-/} # Check domain/path availability -sudo yunohost app checkurl $domain$path -a searx -if [[ ! $? -eq 0 ]]; then - exit 1 -fi - -# Path need a trailing slash, and location does not. -# See conf/nginx.conf* usage -location=$path -if [[ ! $path == */ ]]; then - # no trailing slash, so add it - path=$path/ -fi -if [[ ! "$location" == "/" ]]; then - # remove possible trailing slash - location=${location%/} -fi +sudo yunohost app checkurl $domain$path -a $app \ + || (echo "Path not available: $domain$path" && exit 1) # Save specific settings sudo yunohost app setting searx is_public -v $is_public @@ -32,26 +35,26 @@ sudo apt-get install git build-essential libxslt-dev python-dev python-virtualen # Check Swap if [ $(sudo swapon -s | wc -l) = 1 ]; then - # It is NOT possible to setup a swap file on a tmpfs filesystem - mount | grep /tmp | grep tmpfs > /dev/null 2>&1 - if [ $? = 1 ]; - then - tmp_swap_file=/tmp/searx_swapfile - else - tmp_swap_file=/var/cache/searx_swapfile - fi - sudo dd if=/dev/zero of=$tmp_swap_file bs=1M count=256 - sudo chmod 600 $tmp_swap_file - sudo mkswap $tmp_swap_file - sudo swapon $tmp_swap_file + # It is NOT possible to setup a swap file on a tmpfs filesystem + mount | grep /tmp | grep tmpfs > /dev/null 2>&1 + if [ $? = 1 ]; + then + tmp_swap_file=/tmp/searx_swapfile + else + tmp_swap_file=/var/cache/searx_swapfile + fi + sudo dd if=/dev/zero of=$tmp_swap_file bs=1M count=256 + sudo chmod 600 $tmp_swap_file + sudo mkswap $tmp_swap_file + sudo swapon $tmp_swap_file fi -final_path=/opt/yunohost/searx +final_path=/opt/yunohost/$app # Init virtualenv if [ ! -d $final_path ]; then - sudo mkdir -p $final_path + sudo mkdir -p $final_path fi sudo cp -r ../sources/* $final_path sudo virtualenv --system-site-packages $final_path @@ -60,8 +63,8 @@ sudo bash -c "source $final_path/bin/activate && pip install -r $final_path/requ # Disable swapfile if [[ -v "$tmp_swap_file" ]]; then - sudo swapoff $tmp_swap_file - sudo rm -f $tmp_swap_file + sudo swapoff $tmp_swap_file + sudo rm -f $tmp_swap_file fi #Configuration Searx @@ -69,9 +72,9 @@ sudo cp ../conf/settings.yml $final_path/searx/ sudo sed -i -e "s/ultrasecretkey/`openssl rand -hex 16`/g" $final_path/searx/settings.yml if [ "$path" != "/" ]; then - sudo sed -i -e "s@ynhbaseurl@https://$domain$path/@g" $final_path/searx/settings.yml + sudo sed -i -e "s@ynhbaseurl@https://$domain$path/@g" $final_path/searx/settings.yml else - sudo sed -i -e "s@ynhbaseurl@False@g" $final_path/searx/settings.yml + sudo sed -i -e "s@ynhbaseurl@False@g" $final_path/searx/settings.yml fi # Set permissions to searx directory @@ -79,17 +82,17 @@ sudo useradd searx -d $final_path sudo chown searx:searx -R $final_path # Copy uwsgi config -sudo cp ../conf/searx.ini /etc/uwsgi/apps-available/ -sudo ln -s /etc/uwsgi/apps-available/searx.ini /etc/uwsgi/apps-enabled/ +sudo cp ../conf/searx.ini /etc/uwsgi/apps-available/$app.ini +sudo ln -s /etc/uwsgi/apps-available/searx.ini /etc/uwsgi/apps-enabled/$app.ini # Modify Nginx configuration file and copy it to Nginx conf directory sed -i "s@YNH_WWW_LOCATION@$location@g" ../conf/nginx.conf* sed -i "s@YNH_WWW_PATH@$path@g" ../conf/nginx.conf* if [ "$path" != "/" ]; then - sudo cp ../conf/nginx.conf-noroot /etc/nginx/conf.d/$domain.d/searx.conf + sudo cp ../conf/nginx.conf-noroot /etc/nginx/conf.d/$domain.d/$app.conf else - sudo cp ../conf/nginx.conf /etc/nginx/conf.d/$domain.d/searx.conf + sudo cp ../conf/nginx.conf /etc/nginx/conf.d/$domain.d/$app.conf fi # Fix permission @@ -99,11 +102,10 @@ fi ## Reload Nginx and regenerate SSOwat conf sudo service nginx reload sudo service uwsgi restart -sudo yunohost service add uwsgi -l /var/log/uwsgi/app/searx.log +sudo yunohost service add uwsgi -l /var/log/uwsgi/app/$app.log if [ "$is_public" = "Yes" ]; then - sudo yunohost app setting searx unprotected_uris -v "/" + sudo yunohost app setting $app unprotected_uris -v "/" fi -sudo yunohost app ssowatconf diff --git a/scripts/remove b/scripts/remove index 75adc9f..495cf5e 100644 --- a/scripts/remove +++ b/scripts/remove @@ -1,14 +1,30 @@ #!/bin/bash +app="searx" -domain=$(sudo yunohost app setting searx domain) +# Source app helpers +. /usr/share/yunohost/helpers -sudo rm -Rf /opt/yunohost/searx -sudo rm -f /etc/uwsgi/apps-enabled/searx.ini -sudo rm -f /etc/uwsgi/apps-available/searx.ini -sudo rm -f /etc/nginx/conf.d/$domain.d/searx.conf +# Retrieve arguments +domain=$(ynh_app_setting_get "$app" domain) + +# Remove files +sudo rm -Rf /opt/yunohost/$app +sudo rm -f /etc/uwsgi/apps-enabled/$app.ini +sudo rm -f /etc/uwsgi/apps-available/$app.ini +sudo rm -f /etc/nginx/conf.d/$domain.d/$app.conf + +# Stop uwsgi sudo service uwsgi stop sudo killall uwsgi + +# Remove user (kill attached process before) +if id -u searx > /dev/null 2>&1; then + sudo killall -KILL -u searx + sudo userdel --force searx +fi + +# Restart uwsgi sudo service uwsgi start + +# Reload Nginx sudo service nginx reload -sudo yunohost app ssowatconf -sudo userdel searx diff --git a/scripts/restore b/scripts/restore index e5fbdc5..b1aa27e 100755 --- a/scripts/restore +++ b/scripts/restore @@ -1,4 +1,5 @@ #!/bin/bash +app="searx" # causes the shell to exit if any subcommand or pipeline returns a non-zero status set -e @@ -6,22 +7,15 @@ set -e # Source YNH helpers . /usr/share/yunohost/helpers -# This is a multi-instance app, meaning it can be installed several times independently -# The id of the app as stated in the manifest is available as $YNH_APP_ID -# The instance number is available as $YNH_APP_INSTANCE_NUMBER (equals "1", "2", ...) -# The app instance name is available as $YNH_APP_INSTANCE_NAME -# - the first time the app is installed, YNH_APP_INSTANCE_NAME = ynhexample -# - the second time the app is installed, YNH_APP_INSTANCE_NAME = ynhexample__2 -# - ynhexample__{N} for the subsequent installations, with N=3,4, ... -# The app instance name is probably what you are interested the most, since this is -# guaranteed to be unique. This is a good unique identifier to define installation path, -# db names, ... -app=$YNH_APP_INSTANCE_NAME +# Retrieve arguments +domain=$(ynh_app_setting_get "$app" domain) +path=$(ynh_app_setting_get "$app" path) +is_public=$(ynh_app_setting_get "$app" is_public) -# Get old parameter of the app -domain=$(sudo yunohost app setting $app domain) -path=$(sudo yunohost app setting $app path) -is_public=$(sudo yunohost app setting $app is_public) +# Remove trailing slash to path +path=${path%/} +#force location to be / or /foo +location=${path:-/} # Check domain/path availability sudo yunohost app checkurl $domain$path -a $app @@ -30,7 +24,7 @@ if [[ ! $? -eq 0 ]]; then exit 1 fi -final_path=/opt/yunohost/searx +final_path=/opt/yunohost/$app if [ -d $final_path ]; then echo "There is already a directory: $final_path " | sudo tee /dev/stderr exit 1 @@ -45,21 +39,8 @@ fi # Run install script # sudo bash -c "./install $domain $path $is_public $app" - -# Path need a trailing slash, and location does not. -# See conf/nginx.conf* usage -location=$path -if [[ ! $path == */ ]]; then - # no trailing slash, so add it - path=$path/ -fi -if [[ ! "$location" == "/" ]]; then - # remove possible trailing slash - location=${location%/} -fi - # Save specific settings -sudo yunohost app setting searx is_public -v $is_public +sudo yunohost app setting $app is_public -v $is_public # Check depends installation sudo apt-get install git build-essential libxslt-dev python-dev python-virtualenv python-pybabel zlib1g-dev libffi-dev libssl-dev python-lxml uwsgi uwsgi-plugin-python -y @@ -82,7 +63,7 @@ then fi # Restore sources -final_path=/opt/yunohost/searx +final_path=/opt/yunohost/$app sudo cp -a "./sources" $final_path # Init virtualenv @@ -110,14 +91,13 @@ sudo ln -s "/etc/uwsgi/apps-available/$app.ini" /etc/uwsgi/apps-enabled/ # Nginx conf sudo cp "conf/nginx.conf" $nginx_conf -## Reload Nginx and regenerate SSOwat conf -sudo service nginx reload -sudo service uwsgi restart -sudo yunohost service add uwsgi -l /var/log/uwsgi/app/searx.log - if [ "$is_public" = "Yes" ]; then sudo yunohost app setting searx unprotected_uris -v "/" fi -sudo yunohost app ssowatconf + +## Reload services +sudo service nginx reload +sudo service uwsgi restart +sudo yunohost service add uwsgi -l /var/log/uwsgi/app/$app.log diff --git a/scripts/upgrade b/scripts/upgrade index a93414e..639f1d7 100644 --- a/scripts/upgrade +++ b/scripts/upgrade @@ -1,21 +1,21 @@ #!/bin/bash +app="searx" + +# causes the shell to exit if any subcommand or pipeline returns a non-zero status +set -e + +# Source app helpers +. /usr/share/yunohost/helpers # Retrieve arguments -domain=$(sudo yunohost app setting searx domain) -path=$(sudo yunohost app setting searx path) -is_public=$(sudo yunohost app setting searx is_public) +domain=$(ynh_app_setting_get "$app" domain) +path=$(ynh_app_setting_get "$app" path) +is_public=$(ynh_app_setting_get "$app" is_public) -# Path need a trailing slash, and location does not. -# See conf/nginx.conf usage -location=$path -if [[ ! $path == */ ]]; then - # no trailing slash, so add it - path=$path/ -fi -if [[ ! "$location" == "/" ]]; then - # remove possible trailing slash - location=${location%/} -fi +# Remove trailing slash to path +path=${path%/} +#force location to be / or /foo +location=${path:-/} # Check depends installation sudo apt-get install git build-essential libxslt-dev python-dev python-virtualenv python-pybabel zlib1g-dev libffi-dev libssl-dev python-lxml uwsgi uwsgi-plugin-python -y @@ -23,20 +23,20 @@ sudo apt-get install git build-essential libxslt-dev python-dev python-virtualen # Check Swap if [ $(sudo swapon -s | wc -l) = 1 ]; then - mount | grep /tmp | grep tmpfs > /dev/null 2>&1 - if [ $? = 1 ]; - then - tmp_swap_file=/tmp/searx_swapfile - else - tmp_swap_file=/var/cache/ - fi - sudo dd if=/dev/zero of=$tmp_swap_file bs=1M count=256 - sudo chmod 600 $tmp_swap_file - sudo mkswap $tmp_swap_file - sudo swapon $tmp_swap_file + mount | grep /tmp | grep tmpfs > /dev/null 2>&1 + if [ $? = 1 ]; + then + tmp_swap_file=/tmp/searx_swapfile + else + tmp_swap_file=/var/cache/ + fi + sudo dd if=/dev/zero of=$tmp_swap_file bs=1M count=256 + sudo chmod 600 $tmp_swap_file + sudo mkswap $tmp_swap_file + sudo swapon $tmp_swap_file fi -final_path=/opt/yunohost/searx +final_path=/opt/yunohost/$app sudo cp -r ../sources/* $final_path sudo bash -c "source $final_path/bin/activate && pip install -r $final_path/requirements-ynh.txt --upgrade" @@ -47,12 +47,6 @@ then sudo rm -f $tmp_swap_file fi -# Remove trailing "/" for next commands if installing on a subpath -if [ "$path" != "/" ]; -then - path=${path%/} -fi - #Configuration Searx sudo cp ../conf/settings.yml $final_path/searx/ sudo sed -i -e "s/ultrasecretkey/`openssl rand -hex 16`/g" $final_path/searx/settings.yml @@ -70,30 +64,29 @@ fi sudo chown searx:searx -R $final_path # Copy uwsgi config -sudo cp ../conf/searx.ini /etc/uwsgi/apps-available/ +sudo cp ../conf/searx.ini /etc/uwsgi/apps-available/$app.ini # Modify Nginx configuration file and copy it to Nginx conf directory sed -i "s@YNH_WWW_LOCATION@$location@g" ../conf/nginx.conf* sed -i "s@YNH_WWW_PATH@$path@g" ../conf/nginx.conf* if [ "$path" != "/" ]; then - sudo cp ../conf/nginx.conf-noroot /etc/nginx/conf.d/$domain.d/searx.conf + sudo cp ../conf/nginx.conf-noroot /etc/nginx/conf.d/$domain.d/$app.conf else - sudo cp ../conf/nginx.conf /etc/nginx/conf.d/$domain.d/searx.conf + sudo cp ../conf/nginx.conf /etc/nginx/conf.d/$domain.d/$app.conf fi # Fix permission #sudo find $final_path/ -type d -exec chmod 2755 {} \; #sudo find $final_path/ -type f -exec chmod g+r,o+r {} \; -## Reload Nginx and regenerate SSOwat conf -sudo service nginx reload -sudo service uwsgi restart - if [ "$is_public" = "Yes" ]; then sudo yunohost app setting searx skipped_uris -d sudo yunohost app setting searx unprotected_uris -v "/" fi -sudo yunohost app ssowatconf + +## Reload services +sudo service nginx reload +sudo service uwsgi restart diff --git a/sources/.coveragerc b/sources/.coveragerc new file mode 100644 index 0000000..4f50efc --- /dev/null +++ b/sources/.coveragerc @@ -0,0 +1,20 @@ +[run] +branch = True +source = + searx/engines + searx/__init__.py + searx/autocomplete.py + searx/https_rewrite.py + searx/languages.py + searx/search.py + searx/testing.py + searx/utils.py + searx/webapp.py + +[report] +show_missing = True +exclude_lines = + if __name__ == .__main__.: + +[html] +directory = coverage diff --git a/sources/.gitignore b/sources/.gitignore new file mode 100644 index 0000000..105f019 --- /dev/null +++ b/sources/.gitignore @@ -0,0 +1,17 @@ +.coverage +.installed.cfg +engines.cfg +env +robot_log.html +robot_output.xml +robot_report.html +test_basic/ +setup.cfg + +*.pyc +*/*.pyc +*~ + +node_modules/ + +.tx/ diff --git a/sources/.landscape.yaml b/sources/.landscape.yaml new file mode 100644 index 0000000..1bb3977 --- /dev/null +++ b/sources/.landscape.yaml @@ -0,0 +1,3 @@ +strictness: high +ignore-paths: + - bootstrap.py diff --git a/sources/.travis.yml b/sources/.travis.yml new file mode 100644 index 0000000..3bef5e5 --- /dev/null +++ b/sources/.travis.yml @@ -0,0 +1,32 @@ +sudo: false +cache: + - pip + - npm + - directories: + - $HOME/.cache/pip +language: python +python: + - "2.7" +before_install: + - "export DISPLAY=:99.0" + - "sh -e /etc/init.d/xvfb start" + - npm install less grunt-cli + - ( cd searx/static/themes/oscar;npm install; cd - ) +install: + - ./manage.sh update_dev_packages + - pip install coveralls +script: + - ./manage.sh pep8_check + - ./manage.sh styles + - ./manage.sh grunt_build + - ./manage.sh py_test_coverage + - ./manage.sh robot_tests +after_success: + coveralls +notifications: + irc: + channels: + - "irc.freenode.org#searx" + template: + - "%{repository}/#%{build_number}/%{branch} (%{author}): %{message} %{build_url}" + on_success: change diff --git a/sources/AUTHORS.rst b/sources/AUTHORS.rst index 3605332..5bc6807 100644 --- a/sources/AUTHORS.rst +++ b/sources/AUTHORS.rst @@ -44,3 +44,10 @@ generally made searx better: - Kirill Isakov - Guilhem Bonnefille - Marc Abonce Seguin + +- @jibe-b +- Christian Pietsch @pietsch +- @Maxqia +- Ashutosh Das @pyprism +- YuLun Shih @imZack +- Dmitry Mikhirev @mikhirev diff --git a/sources/CHANGELOG.rst b/sources/CHANGELOG.rst index 2e333f0..8907ab4 100644 --- a/sources/CHANGELOG.rst +++ b/sources/CHANGELOG.rst @@ -1,3 +1,41 @@ +0.9.0 2016.05.24 +================ + +- New search category: science +- New engines + + - Wolframalpha (science) + - Frinkiac (images) + - Arch Linux (it) + - BASE - Bielefeld Academic Search Engine (science) + - Dokuwiki (general) + - Nyaa.se (files, images, music, video) + - Reddit (general, images, news, social media) + - Torrentz.eu (files, music, video) + - Tokyo Toshokan (files, music, video) + - F-Droid (files) + - Erowid (general) + - Bitbucket (it) + - GitLab (it) + - Geektimes (it) + - Habrahabr (it) +- New plugins + + - Open links in new tab + - Vim hotkeys for better navigation +- Wikipedia/Mediawiki engine improvements +- Configurable instance name +- Configurable connection pool size +- Fixed broken google engine +- Better docker image +- Images in standard results +- Fixed and refactored user settings (Warning: backward incompatibility - you have to reset your custom engine preferences) +- Suspending engines on errors +- Simplified development/deployment tooling +- Translation updates +- Multilingual autocompleter +- Qwant autocompleter backend + 0.8.1 2015.12.22 ================ diff --git a/sources/README.rst b/sources/README.rst index c099315..6563fe8 100644 --- a/sources/README.rst +++ b/sources/README.rst @@ -18,7 +18,7 @@ Installation ``git clone git@github.com:asciimoo/searx.git && cd searx`` - install dependencies: ``./manage.sh update_packages`` - edit your - `settings.yml `__ + `settings.yml `__ (set your ``secret_key``!) - run ``python searx/webapp.py`` to start the application diff --git a/sources/requirements-ynh.txt b/sources/requirements-ynh.txt index 602a959..4d3a13d 100644 --- a/sources/requirements-ynh.txt +++ b/sources/requirements-ynh.txt @@ -11,3 +11,4 @@ pyopenssl==0.15.1 python-dateutil==2.4.2 pyyaml==3.11 requests==2.9.1 +cffi>=1.6 \ No newline at end of file diff --git a/sources/searx/engines/bing.py b/sources/searx/engines/bing.py index 171606c..6bdfd37 100644 --- a/sources/searx/engines/bing.py +++ b/sources/searx/engines/bing.py @@ -54,6 +54,12 @@ def response(resp): dom = html.fromstring(resp.text) + try: + results.append({'number_of_results': int(dom.xpath('//span[@class="sb_count"]/text()')[0] + .split()[0].replace(',', ''))}) + except: + pass + # parse results for result in dom.xpath('//div[@class="sa_cc"]'): link = result.xpath('.//h3/a')[0] @@ -66,10 +72,6 @@ def response(resp): 'title': title, 'content': content}) - # return results if something is found - if results: - return results - # parse results again if nothing is found yet for result in dom.xpath('//li[@class="b_algo"]'): link = result.xpath('.//h2/a')[0] diff --git a/sources/searx/engines/currency_convert.py b/sources/searx/engines/currency_convert.py index 26830a1..b0ffb49 100644 --- a/sources/searx/engines/currency_convert.py +++ b/sources/searx/engines/currency_convert.py @@ -9,13 +9,13 @@ categories = [] url = 'https://download.finance.yahoo.com/d/quotes.csv?e=.csv&f=sl1d1t1&s={query}=X' weight = 100 -parser_re = re.compile(u'^\W*(\d+(?:\.\d+)?)\W*([^.0-9].+)\W+in?\W+([^\.]+)\W*$', re.I) # noqa +parser_re = re.compile(u'.*?(\d+(?:\.\d+)?) ([^.0-9]+) (?:in|to) ([^.0-9]+)', re.I) # noqa db = 1 def normalize_name(name): - name = name.lower().replace('-', ' ') + name = name.lower().replace('-', ' ').rstrip('s') name = re.sub(' +', ' ', name) return unicodedata.normalize('NFKD', name).lower() diff --git a/sources/searx/engines/gigablast.py b/sources/searx/engines/gigablast.py index 1cc2431..6e4e24b 100644 --- a/sources/searx/engines/gigablast.py +++ b/sources/searx/engines/gigablast.py @@ -31,9 +31,9 @@ search_string = 'search?{query}'\ '&s={offset}'\ '&format=json'\ '&qh=0'\ - '&rxiwd={rxiwd}'\ '&qlang={lang}'\ - '&ff={safesearch}' + '&ff={safesearch}'\ + '&rxikd={rxikd}' # random number - 9 digits # specific xpath variables results_xpath = '//response//result' @@ -59,8 +59,7 @@ def request(query, params): search_path = search_string.format(query=urlencode({'q': query}), offset=offset, number_of_results=number_of_results, - rxiwd=1, - # rand=int(time()), + rxikd=str(time())[:9], lang=language, safesearch=safesearch) diff --git a/sources/searx/engines/yahoo.py b/sources/searx/engines/yahoo.py index 769e7e4..b8b40e4 100644 --- a/sources/searx/engines/yahoo.py +++ b/sources/searx/engines/yahoo.py @@ -77,6 +77,13 @@ def response(resp): dom = html.fromstring(resp.text) + try: + results_num = int(dom.xpath('//div[@class="compPagination"]/span[last()]/text()')[0] + .split()[0].replace(',', '')) + results.append({'number_of_results': results_num}) + except: + pass + # parse results for result in dom.xpath(results_xpath): try: diff --git a/sources/searx/plugins/__init__.py b/sources/searx/plugins/__init__.py index 87cc013..efb9b06 100644 --- a/sources/searx/plugins/__init__.py +++ b/sources/searx/plugins/__init__.py @@ -23,7 +23,8 @@ from searx.plugins import (https_rewrite, open_results_on_new_tab, self_info, search_on_category_select, - tracker_url_remover) + tracker_url_remover, + vim_hotkeys) required_attrs = (('name', str), ('description', str), @@ -77,3 +78,4 @@ plugins.register(open_results_on_new_tab) plugins.register(self_info) plugins.register(search_on_category_select) plugins.register(tracker_url_remover) +plugins.register(vim_hotkeys) diff --git a/sources/searx/plugins/vim_hotkeys.py b/sources/searx/plugins/vim_hotkeys.py new file mode 100644 index 0000000..e537a3a --- /dev/null +++ b/sources/searx/plugins/vim_hotkeys.py @@ -0,0 +1,10 @@ +from flask.ext.babel import gettext + +name = gettext('Vim-like hotkeys') +description = gettext('Navigate search results with Vim-like hotkeys ' + '(JavaScript required). ' + 'Press "h" key on main or result page to get help.') +default_on = False + +js_dependencies = ('plugins/js/vim_hotkeys.js',) +css_dependencies = ('plugins/css/vim_hotkeys.css',) diff --git a/sources/searx/poolrequests.py b/sources/searx/poolrequests.py index 13c6a90..f268df2 100644 --- a/sources/searx/poolrequests.py +++ b/sources/searx/poolrequests.py @@ -41,14 +41,18 @@ class HTTPAdapterWithConnParams(requests.adapters.HTTPAdapter): block=self._pool_block, **self._conn_params) +connect = settings['outgoing'].get('pool_connections', 100) # Magic number kept from previous code +maxsize = settings['outgoing'].get('pool_maxsize', requests.adapters.DEFAULT_POOLSIZE) # Picked from constructor if settings['outgoing'].get('source_ips'): - http_adapters = cycle(HTTPAdapterWithConnParams(pool_connections=100, source_address=(source_ip, 0)) + http_adapters = cycle(HTTPAdapterWithConnParams(pool_connections=connect, pool_maxsize=maxsize, + source_address=(source_ip, 0)) for source_ip in settings['outgoing']['source_ips']) - https_adapters = cycle(HTTPAdapterWithConnParams(pool_connections=100, source_address=(source_ip, 0)) + https_adapters = cycle(HTTPAdapterWithConnParams(pool_connections=connect, pool_maxsize=maxsize, + source_address=(source_ip, 0)) for source_ip in settings['outgoing']['source_ips']) else: - http_adapters = cycle((HTTPAdapterWithConnParams(pool_connections=100), )) - https_adapters = cycle((HTTPAdapterWithConnParams(pool_connections=100), )) + http_adapters = cycle((HTTPAdapterWithConnParams(pool_connections=connect, pool_maxsize=maxsize), )) + https_adapters = cycle((HTTPAdapterWithConnParams(pool_connections=connect, pool_maxsize=maxsize), )) class SessionSinglePool(requests.Session): diff --git a/sources/searx/preferences.py b/sources/searx/preferences.py index ad9e673..dd9133d 100644 --- a/sources/searx/preferences.py +++ b/sources/searx/preferences.py @@ -181,7 +181,7 @@ class EnginesSetting(SwitchableSetting): return [item[len('engine_'):].replace('_', ' ').replace(' ', '__') for item in items] def transform_values(self, values): - if len(values) == 1 and values[0] == '': + if len(values) == 1 and next(iter(values)) == '': return list() transformed_values = [] for value in values: @@ -229,6 +229,7 @@ class Preferences(object): self.engines = EnginesSetting('engines', choices=engines) self.plugins = PluginsSetting('plugins', choices=plugins) + self.unknown_params = {} def parse_cookies(self, input_data): for user_setting_name, user_setting in input_data.iteritems(): @@ -254,6 +255,8 @@ class Preferences(object): enabled_categories.append(user_setting_name[len('category_'):]) elif user_setting_name.startswith('plugin_'): disabled_plugins.append(user_setting_name) + else: + self.unknown_params[user_setting_name] = user_setting self.key_value_settings['categories'].parse_form(enabled_categories) self.engines.parse_form(disabled_engines) self.plugins.parse_form(disabled_plugins) @@ -268,4 +271,6 @@ class Preferences(object): user_setting.save(user_setting_name, resp) self.engines.save(resp) self.plugins.save(resp) + for k, v in self.unknown_params.items(): + resp.set_cookie(k, v, max_age=COOKIE_MAX_AGE) return resp diff --git a/sources/searx/results.py b/sources/searx/results.py index c3040b3..dcd966e 100644 --- a/sources/searx/results.py +++ b/sources/searx/results.py @@ -99,6 +99,7 @@ class ResultContainer(object): self._infobox_ids = {} self.suggestions = set() self.answers = set() + self.number_of_results = 0 def extend(self, engine_name, results): for result in list(results): @@ -111,6 +112,9 @@ class ResultContainer(object): elif 'infobox' in result: self._merge_infobox(result) results.remove(result) + elif 'number_of_results' in result: + self.number_of_results = max(self.number_of_results, result['number_of_results']) + results.remove(result) with RLock(): engines[engine_name].stats['search_count'] += 1 diff --git a/sources/searx/settings.yml b/sources/searx/settings.yml index ff85684..9308756 100644 --- a/sources/searx/settings.yml +++ b/sources/searx/settings.yml @@ -21,6 +21,8 @@ ui: outgoing: # communication with search engines request_timeout : 2.0 # seconds useragent_suffix : "" # suffix of searx_useragent, could contain informations like an email address to the administrator + pool_connections : 100 # Number of different hosts + pool_maxsize : 10 # Number of simultaneous requests by host # uncomment below section if you want to use a proxy # see http://docs.python-requests.org/en/latest/user/advanced/#proxies # SOCKS proxies are not supported : see https://github.com/kennethreitz/requests/pull/478 @@ -38,6 +40,17 @@ engines: engine : archlinux shortcut : al + - name : archive is + engine : xpath + search_url : https://archive.is/{query} + url_xpath : (//div[@class="TEXT-BLOCK"]/a)/@href + title_xpath : (//div[@class="TEXT-BLOCK"]/a) + content_xpath : //div[@class="TEXT-BLOCK"]/ul/li + categories : general + timeout : 7.0 + disabled : True + shortcut : ai + - name : base engine : base shortcut : bs @@ -221,8 +234,8 @@ engines: engine : xpath paging : True search_url : https://geektimes.ru/search/page{pageno}/?q={query} - url_xpath : //div[@class="search_results"]//a[@class="post_title"]/@href - title_xpath : //div[@class="search_results"]//a[@class="post_title"] + url_xpath : //div[@class="search_results"]//a[@class="post__title_link"]/@href + title_xpath : //div[@class="search_results"]//a[@class="post__title_link"] content_xpath : //div[@class="search_results"]//div[contains(@class, "content")] categories : it timeout : 4.0 diff --git a/sources/searx/static/plugins/css/vim_hotkeys.css b/sources/searx/static/plugins/css/vim_hotkeys.css new file mode 100644 index 0000000..2ccfdc1 --- /dev/null +++ b/sources/searx/static/plugins/css/vim_hotkeys.css @@ -0,0 +1,26 @@ +.vim-hotkeys-help { + position: fixed; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + z-index: 9999999; + overflow-y: auto; + max-height: 80%; + box-shadow: 0 0 1em; +} + +.dflex { + display: -webkit-box; /* OLD - iOS 6-, Safari 3.1-6 */ + display: -moz-box; /* OLD - Firefox 19- (buggy but mostly works) */ + display: -ms-flexbox; /* TWEENER - IE 10 */ + display: -webkit-flex; /* NEW - Chrome */ + display: flex; /* NEW, Spec - Opera 12.1, Firefox 20+ */ +} + +.iflex { + -webkit-box-flex: 1; /* OLD - iOS 6-, Safari 3.1-6 */ + -moz-box-flex: 1; /* OLD - Firefox 19- */ + -webkit-flex: 1; /* Chrome */ + -ms-flex: 1; /* IE 10 */ + flex: 1; /* NEW, Spec - Opera 12.1, Firefox 20+ */ +} diff --git a/sources/searx/static/plugins/js/vim_hotkeys.js b/sources/searx/static/plugins/js/vim_hotkeys.js new file mode 100644 index 0000000..61500d8 --- /dev/null +++ b/sources/searx/static/plugins/js/vim_hotkeys.js @@ -0,0 +1,336 @@ +$(document).ready(function() { + highlightResult('top')(); + + $('.result').on('click', function() { + highlightResult($(this))(); + }); + + var vimKeys = { + 27: { + key: 'Escape', + fun: removeFocus, + des: 'remove focus from the focused input', + cat: 'Control' + }, + 73: { + key: 'i', + fun: searchInputFocus, + des: 'focus on the search input', + cat: 'Control' + }, + 66: { + key: 'b', + fun: scrollPage(-window.innerHeight), + des: 'scroll one page up', + cat: 'Navigation' + }, + 70: { + key: 'f', + fun: scrollPage(window.innerHeight), + des: 'scroll one page down', + cat: 'Navigation' + }, + 85: { + key: 'u', + fun: scrollPage(-window.innerHeight / 2), + des: 'scroll half a page up', + cat: 'Navigation' + }, + 68: { + key: 'd', + fun: scrollPage(window.innerHeight / 2), + des: 'scroll half a page down', + cat: 'Navigation' + }, + 71: { + key: 'g', + fun: scrollPageTo(-document.body.scrollHeight, 'top'), + des: 'scroll to the top of the page', + cat: 'Navigation' + }, + 86: { + key: 'v', + fun: scrollPageTo(document.body.scrollHeight, 'bottom'), + des: 'scroll to the bottom of the page', + cat: 'Navigation' + }, + 75: { + key: 'k', + fun: highlightResult('up'), + des: 'select previous search result', + cat: 'Results' + }, + 74: { + key: 'j', + fun: highlightResult('down'), + des: 'select next search result', + cat: 'Results' + }, + 80: { + key: 'p', + fun: pageButtonClick(0), + des: 'go to previous page', + cat: 'Results' + }, + 78: { + key: 'n', + fun: pageButtonClick(1), + des: 'go to next page', + cat: 'Results' + }, + 79: { + key: 'o', + fun: openResult(false), + des: 'open search result', + cat: 'Results' + }, + 84: { + key: 't', + fun: openResult(true), + des: 'open the result in a new tab', + cat: 'Results' + }, + 82: { + key: 'r', + fun: reloadPage, + des: 'reload page from the server', + cat: 'Control' + }, + 72: { + key: 'h', + fun: toggleHelp, + des: 'toggle help window', + cat: 'Other' + } + }; + + $(document).keyup(function(e) { + // check for modifiers so we don't break browser's hotkeys + if (vimKeys.hasOwnProperty(e.keyCode) + && !e.ctrlKey + && !e.altKey + && !e.shiftKey + && !e.metaKey) + { + if (e.keyCode === 27) { + if (e.target.tagName.toLowerCase() === 'input') { + vimKeys[e.keyCode].fun(); + } + } else { + if (e.target === document.body) { + vimKeys[e.keyCode].fun(); + } + } + } + }); + + function highlightResult(which) { + return function() { + var current = $('.result[data-vim-selected]'); + if (current.length === 0) { + current = $('.result:first'); + if (current.length === 0) { + return; + } + } + + var next; + + if (typeof which !== 'string') { + next = which; + } else { + switch (which) { + case 'visible': + var top = $(window).scrollTop(); + var bot = top + $(window).height(); + var results = $('.result'); + + for (var i = 0; i < results.length; i++) { + next = $(results[i]); + var etop = next.offset().top; + var ebot = etop + next.height(); + + if ((ebot <= bot) && (etop > top)) { + break; + } + } + break; + case 'down': + next = current.next('.result'); + if (next.length === 0) { + next = $('.result:first'); + } + break; + case 'up': + next = current.prev('.result'); + if (next.length === 0) { + next = $('.result:last'); + } + break; + case 'bottom': + next = $('.result:last'); + break; + case 'top': + default: + next = $('.result:first'); + } + } + + if (next) { + current.removeAttr('data-vim-selected').removeClass('well well-sm'); + next.attr('data-vim-selected', 'true').addClass('well well-sm'); + scrollPageToSelected(); + } + } + } + + function reloadPage() { + document.location.reload(false); + } + + function removeFocus() { + if (document.activeElement) { + document.activeElement.blur(); + } + } + + function pageButtonClick(num) { + return function() { + var buttons = $('div#pagination button[type="submit"]'); + if (buttons.length !== 2) { + console.log('page navigation with this theme is not supported'); + return; + } + if (num >= 0 && num < buttons.length) { + buttons[num].click(); + } else { + console.log('pageButtonClick(): invalid argument'); + } + } + } + + function scrollPageToSelected() { + var sel = $('.result[data-vim-selected]'); + if (sel.length !== 1) { + return; + } + + var wnd = $(window); + + var wtop = wnd.scrollTop(); + var etop = sel.offset().top; + + var offset = 30; + + if (wtop > etop) { + wnd.scrollTop(etop - offset); + } else { + var ebot = etop + sel.height(); + var wbot = wtop + wnd.height(); + + if (wbot < ebot) { + wnd.scrollTop(ebot - wnd.height() + offset); + } + } + } + + function scrollPage(amount) { + return function() { + window.scrollBy(0, amount); + highlightResult('visible')(); + } + } + + function scrollPageTo(position, nav) { + return function() { + window.scrollTo(0, position); + highlightResult(nav)(); + } + } + + function searchInputFocus() { + $('input#q').focus(); + } + + function openResult(newTab) { + return function() { + var link = $('.result[data-vim-selected] .result_header a'); + if (link.length) { + var url = link.attr('href'); + if (newTab) { + window.open(url); + } else { + window.location.href = url; + } + } + }; + } + + function toggleHelp() { + var helpPanel = $('#vim-hotkeys-help'); + if (helpPanel.length) { + helpPanel.toggleClass('hidden'); + return; + } + + var categories = {}; + + for (var k in vimKeys) { + var key = vimKeys[k]; + categories[key.cat] = categories[key.cat] || []; + categories[key.cat].push(key); + } + + var sorted = Object.keys(categories).sort(function(a, b) { + return categories[b].length - categories[a].length; + }); + + if (sorted.length === 0) { + return; + } + + var html = '
'; + html += '
'; + + html += '
'; + html += '
'; + html += '

How to navigate searx with Vim-like hotkeys

'; + html += '
'; // col-sm-12 + html += '
'; // row + + for (var i = 0; i < sorted.length; i++) { + var cat = categories[sorted[i]]; + + var lastCategory = i === (sorted.length - 1); + var first = i % 2 === 0; + + if (first) { + html += '
'; + } + html += '
'; + + html += '
'; + html += '
' + cat[0].cat + '
'; + html += '
'; + html += '
    '; + + for (var cj in cat) { + html += '
  • ' + cat[cj].key + ' ' + cat[cj].des + '
  • '; + } + + html += '
'; + html += '
'; // panel-body + html += '
'; // panel + html += '
'; // col-sm-* + + if (!first || lastCategory) { + html += '
'; // row + } + } + + html += '
'; // container-fluid + html += '
'; // vim-hotkeys-help + + $('body').append(html); + } +}); diff --git a/sources/searx/static/themes/oscar/css/logicodev.min.css b/sources/searx/static/themes/oscar/css/logicodev.min.css new file mode 100644 index 0000000..4f9fffb --- /dev/null +++ b/sources/searx/static/themes/oscar/css/logicodev.min.css @@ -0,0 +1 @@ +.navbar-default .navbar-nav>.active>a,.navbar-default .navbar-nav>.active>a:hover,.navbar-default .navbar-nav>.active>a:focus{background:#29314d;color:#01d7d4}.navbar>li>a{padding:0;margin:0}.navbar-nav>li>a{background:#29314d;padding:0 8px;margin:0;line-height:30px}.navbar,.navbar-default{background-color:#29314d;border:none;border-top:4px solid #01d7d4;padding-top:5px;color:#f6f9fa!important;font-weight:700;font-size:1.1em;text-transform:lowercase;margin-bottom:24px;height:30px;line-height:30px;z-index:1}.navbar .navbar-nav>li>a,.navbar-default .navbar-nav>li>a{color:#f6f9fa}.navbar .navbar-brand,.navbar-default .navbar-brand{font-weight:700;color:#01d7d4;line-height:30px;padding:0 30px;margin:0}.navbar-default .navbar-nav>li>a:hover,.navbar-default .navbar-nav>li>a:focus{color:#01d7d4;background:#29314d}.navbar-toggle{margin-top:0}*{border-radius:0!important}html{position:relative;min-height:100%;color:#29314d}body{font-family:Roboto,Helvetica,Arial,sans-serif;margin-bottom:80px;background-color:#fff}body a{color:#08c}.footer{position:absolute;bottom:0;width:100%;height:60px;text-align:center;color:#999}input[type=checkbox]:checked+.label_hide_if_checked,input[type=checkbox]:checked+.label_hide_if_not_checked+.label_hide_if_checked{display:none}input[type=checkbox]:not(:checked)+.label_hide_if_not_checked,input[type=checkbox]:not(:checked)+.label_hide_if_checked+.label_hide_if_not_checked{display:none}.result_header{margin-top:6px;margin-bottom:4px;font-size:16px}.result_header .favicon{margin-bottom:-3px}.result_header a{color:#29314d;text-decoration:none}.result_header a:hover{color:#08c}.result_header a:visited{color:#684898}.result_header a .highlight{background-color:#f6f9fa}.result-content{margin-top:2px;margin-bottom:0;word-wrap:break-word;color:#666;font-size:13px}.result-content .highlight{font-weight:700}.external-link,.external-link a{color:#2ecc71}.external-link a,.external-link a a{margin-right:3px}.result-default,.result-code,.result-torrent,.result-videos,.result-map{clear:both;padding:2px 4px}.result-default:hover,.result-code:hover,.result-torrent:hover,.result-videos:hover,.result-map:hover{background-color:#f6f9fa}.result-images{float:left!important;width:24%;margin:.5%}.result-images a{display:block;width:100%;height:170px;background-size:cover}.img-thumbnail{margin:5px;max-height:128px;min-height:128px}.result-videos{clear:both}.result-videos hr{margin:5px 0 15px 0}.result-videos .collapse{width:100%}.result-videos .in{margin-bottom:8px}.result-torrent{clear:both}.result-torrent b{margin-right:5px;margin-left:5px}.result-torrent .seeders{color:#2ecc71}.result-torrent .leechers{color:#f35e77}.result-map{clear:both}.result-code{clear:both}.result-code .code-fork,.result-code .code-fork a{color:#666}.suggestion_item{margin:2px 5px}.result_download{margin-right:5px}#pagination{margin-top:30px;padding-bottom:60px}.label-default{color:#a4a4a4;background:0 0}.infobox .panel-heading{background-color:#f6f9fa}.infobox .panel-heading .panel-title{font-weight:700}.infobox p{font-family:"DejaVu Serif",Georgia,Cambria,"Times New Roman",Times,serif!important;font-style:italic}.infobox .btn{background-color:#2ecc71;border:none}.infobox .btn a{color:#fff;margin:5px}.infobox .infobox_part{margin-bottom:20px;word-wrap:break-word;table-layout:fixed}.infobox .infobox_part:last-child{margin-bottom:0}.search_categories,#categories{margin:10px 0 4px 0;text-transform:capitalize}.search_categories label,#categories label{border:none;box-shadow:none;font-size:13px;padding-bottom:2px;color:#a4a4a4;margin-bottom:5px}.search_categories label:hover,#categories label:hover{color:#29314d;background-color:transparent}.search_categories label:active,#categories label:active{box-shadow:none}.search_categories .active,#categories .active,.search_categories .btn-primary,#categories .btn-primary{color:#29314d;font-weight:700;border-bottom:5px solid #01d7d4;background-color:transparent}#categories{margin:0}#main-logo{margin-top:10vh;margin-bottom:25px}#main-logo>img{max-width:350px;width:80%}#q{box-shadow:none;border-right:none;border-color:#a4a4a4}#search_form .input-group-btn .btn{border-color:#a4a4a4}#search_form .input-group-btn .btn:hover{background-color:#2ecc71;color:#fff}.cursor-text{cursor:text!important}.cursor-pointer{cursor:pointer!important}pre,code{font-family:'Ubuntu Mono','Courier New','Lucida Console',monospace!important}.lineno{margin-right:5px}.highlight .hll{background-color:#ffc}.highlight{background:#f8f8f8}.highlight .c{color:#556366;font-style:italic}.highlight .err{border:1px solid #ffa92f}.highlight .k{color:#BE74D5;font-weight:700}.highlight .o{color:#d19a66}.highlight .cm{color:#556366;font-style:italic}.highlight .cp{color:#bc7a00}.highlight .c1{color:#556366;font-style:italic}.highlight .cs{color:#556366;font-style:italic}.highlight .gd{color:#a00000}.highlight .ge{font-style:italic}.highlight .gr{color:red}.highlight .gh{color:navy;font-weight:700}.highlight .gi{color:#00a000}.highlight .go{color:#888}.highlight .gp{color:navy;font-weight:700}.highlight .gs{font-weight:700}.highlight .gu{color:purple;font-weight:700}.highlight .gt{color:#04d}.highlight .kc{color:#BE74D5;font-weight:700}.highlight .kd{color:#BE74D5;font-weight:700}.highlight .kn{color:#BE74D5;font-weight:700}.highlight .kp{color:#be74d5}.highlight .kr{color:#BE74D5;font-weight:700}.highlight .kt{color:#d46c72}.highlight .m{color:#d19a66}.highlight .s{color:#86c372}.highlight .na{color:#7d9029}.highlight .nb{color:#be74d5}.highlight .nc{color:#61AFEF;font-weight:700}.highlight .no{color:#d19a66}.highlight .nd{color:#a2f}.highlight .ni{color:#999;font-weight:700}.highlight .ne{color:#D2413A;font-weight:700}.highlight .nf{color:#61afef}.highlight .nl{color:#a0a000}.highlight .nn{color:#61AFEF;font-weight:700}.highlight .nt{color:#BE74D5;font-weight:700}.highlight .nv{color:#dfc06f}.highlight .ow{color:#A2F;font-weight:700}.highlight .w{color:#d7dae0}.highlight .mf{color:#d19a66}.highlight .mh{color:#d19a66}.highlight .mi{color:#d19a66}.highlight .mo{color:#d19a66}.highlight .sb{color:#86c372}.highlight .sc{color:#86c372}.highlight .sd{color:#86C372;font-style:italic}.highlight .s2{color:#86c372}.highlight .se{color:#B62;font-weight:700}.highlight .sh{color:#86c372}.highlight .si{color:#B68;font-weight:700}.highlight .sx{color:#be74d5}.highlight .sr{color:#b68}.highlight .s1{color:#86c372}.highlight .ss{color:#dfc06f}.highlight .bp{color:#be74d5}.highlight .vc{color:#dfc06f}.highlight .vg{color:#dfc06f}.highlight .vi{color:#dfc06f}.highlight .il{color:#d19a66}.highlight .lineno{-webkit-touch-callout:none;-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;cursor:default;color:#556366}.highlight .lineno::selection{background:0 0}.highlight .lineno::-moz-selection{background:0 0}.highlight pre{background-color:#282C34;color:#D7DAE0;border:none;margin-bottom:25px;font-size:15px;padding:20px 10px}.highlight{font-weight:700} \ No newline at end of file diff --git a/sources/searx/static/themes/oscar/css/oscar.min.css b/sources/searx/static/themes/oscar/css/oscar.min.css deleted file mode 100644 index 60b5c37..0000000 --- a/sources/searx/static/themes/oscar/css/oscar.min.css +++ /dev/null @@ -1,88 +0,0 @@ -html{position:relative;min-height:100%} -body{margin-bottom:80px} -.footer{position:absolute;bottom:0;width:100%;height:60px} -input[type=checkbox]:checked+.label_hide_if_checked,input[type=checkbox]:checked+.label_hide_if_not_checked+.label_hide_if_checked{display:none} -input[type=checkbox]:not(:checked)+.label_hide_if_not_checked,input[type=checkbox]:not(:checked)+.label_hide_if_checked+.label_hide_if_not_checked{display:none} -.result_header{margin-bottom:5px;margin-top:20px}.result_header .favicon{margin-bottom:-3px} -.result_header a{vertical-align:bottom}.result_header a .highlight{font-weight:bold} -.result-content{margin-top:5px;word-wrap:break-word}.result-content .highlight{font-weight:bold} -.result-default{clear:both} -.result-images{float:left !important} -.img-thumbnail{margin:5px;max-height:128px;min-height:128px} -.result-videos{clear:both} -.result-torrents{clear:both} -.result-map{clear:both} -.result-code{clear:both} -.suggestion_item{margin:2px 5px} -.result_download{margin-right:5px} -#pagination{margin-top:30px;padding-bottom:50px} -.label-default{color:#aaa;background:#fff} -.infobox .infobox_part{margin-bottom:20px;word-wrap:break-word;table-layout:fixed} -.infobox .infobox_part:last-child{margin-bottom:0} -.search_categories{margin:10px 0;text-transform:capitalize} -.cursor-text{cursor:text !important} -.cursor-pointer{cursor:pointer !important} -.highlight .hll{background-color:#ffc} -.highlight{background:#f8f8f8} -.highlight .c{color:#408080;font-style:italic} -.highlight .err{border:1px solid #f00} -.highlight .k{color:#008000;font-weight:bold} -.highlight .o{color:#666} -.highlight .cm{color:#408080;font-style:italic} -.highlight .cp{color:#bc7a00} -.highlight .c1{color:#408080;font-style:italic} -.highlight .cs{color:#408080;font-style:italic} -.highlight .gd{color:#a00000} -.highlight .ge{font-style:italic} -.highlight .gr{color:#f00} -.highlight .gh{color:#000080;font-weight:bold} -.highlight .gi{color:#00a000} -.highlight .go{color:#888} -.highlight .gp{color:#000080;font-weight:bold} -.highlight .gs{font-weight:bold} -.highlight .gu{color:#800080;font-weight:bold} -.highlight .gt{color:#04d} -.highlight .kc{color:#008000;font-weight:bold} -.highlight .kd{color:#008000;font-weight:bold} -.highlight .kn{color:#008000;font-weight:bold} -.highlight .kp{color:#008000} -.highlight .kr{color:#008000;font-weight:bold} -.highlight .kt{color:#b00040} -.highlight .m{color:#666} -.highlight .s{color:#ba2121} -.highlight .na{color:#7d9029} -.highlight .nb{color:#008000} -.highlight .nc{color:#00f;font-weight:bold} -.highlight .no{color:#800} -.highlight .nd{color:#a2f} -.highlight .ni{color:#999;font-weight:bold} -.highlight .ne{color:#d2413a;font-weight:bold} -.highlight .nf{color:#00f} -.highlight .nl{color:#a0a000} -.highlight .nn{color:#00f;font-weight:bold} -.highlight .nt{color:#008000;font-weight:bold} -.highlight .nv{color:#19177c} -.highlight .ow{color:#a2f;font-weight:bold} -.highlight .w{color:#bbb} -.highlight .mf{color:#666} -.highlight .mh{color:#666} -.highlight .mi{color:#666} -.highlight .mo{color:#666} -.highlight .sb{color:#ba2121} -.highlight .sc{color:#ba2121} -.highlight .sd{color:#ba2121;font-style:italic} -.highlight .s2{color:#ba2121} -.highlight .se{color:#b62;font-weight:bold} -.highlight .sh{color:#ba2121} -.highlight .si{color:#b68;font-weight:bold} -.highlight .sx{color:#008000} -.highlight .sr{color:#b68} -.highlight .s1{color:#ba2121} -.highlight .ss{color:#19177c} -.highlight .bp{color:#008000} -.highlight .vc{color:#19177c} -.highlight .vg{color:#19177c} -.highlight .vi{color:#19177c} -.highlight .il{color:#666} -.highlight .lineno{-webkit-touch-callout:none;-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;cursor:default}.highlight .lineno::selection{background:transparent;} -.highlight .lineno::-moz-selection{background:transparent;} diff --git a/sources/searx/static/themes/oscar/css/pointhi.min.css b/sources/searx/static/themes/oscar/css/pointhi.min.css new file mode 100644 index 0000000..29f7497 --- /dev/null +++ b/sources/searx/static/themes/oscar/css/pointhi.min.css @@ -0,0 +1 @@ +html{position:relative;min-height:100%}body{margin-bottom:80px}.footer{position:absolute;bottom:0;width:100%;height:60px}input[type=checkbox]:checked+.label_hide_if_checked,input[type=checkbox]:checked+.label_hide_if_not_checked+.label_hide_if_checked{display:none}input[type=checkbox]:not(:checked)+.label_hide_if_not_checked,input[type=checkbox]:not(:checked)+.label_hide_if_checked+.label_hide_if_not_checked{display:none}.result_header{margin-bottom:5px;margin-top:20px}.result_header .favicon{margin-bottom:-3px}.result_header a{vertical-align:bottom}.result_header a .highlight{font-weight:700}.result-content{margin-top:5px;word-wrap:break-word}.result-content .highlight{font-weight:700}.result-default{clear:both}.result-images{float:left!important}.img-thumbnail{margin:5px;max-height:128px;min-height:128px}.result-videos{clear:both}.result-torrents{clear:both}.result-map{clear:both}.result-code{clear:both}.suggestion_item{margin:2px 5px}.result_download{margin-right:5px}#pagination{margin-top:30px;padding-bottom:50px}.label-default{color:#AAA;background:#FFF}.infobox .infobox_part{margin-bottom:20px;word-wrap:break-word;table-layout:fixed}.infobox .infobox_part:last-child{margin-bottom:0}.search_categories{margin:10px 0;text-transform:capitalize}.cursor-text{cursor:text!important}.cursor-pointer{cursor:pointer!important}.highlight .hll{background-color:#ffc}.highlight{background:#f8f8f8}.highlight .c{color:#408080;font-style:italic}.highlight .err{border:1px solid red}.highlight .k{color:green;font-weight:700}.highlight .o{color:#666}.highlight .cm{color:#408080;font-style:italic}.highlight .cp{color:#bc7a00}.highlight .c1{color:#408080;font-style:italic}.highlight .cs{color:#408080;font-style:italic}.highlight .gd{color:#a00000}.highlight .ge{font-style:italic}.highlight .gr{color:red}.highlight .gh{color:navy;font-weight:700}.highlight .gi{color:#00a000}.highlight .go{color:#888}.highlight .gp{color:navy;font-weight:700}.highlight .gs{font-weight:700}.highlight .gu{color:purple;font-weight:700}.highlight .gt{color:#04d}.highlight .kc{color:green;font-weight:700}.highlight .kd{color:green;font-weight:700}.highlight .kn{color:green;font-weight:700}.highlight .kp{color:green}.highlight .kr{color:green;font-weight:700}.highlight .kt{color:#b00040}.highlight .m{color:#666}.highlight .s{color:#ba2121}.highlight .na{color:#7d9029}.highlight .nb{color:green}.highlight .nc{color:#00F;font-weight:700}.highlight .no{color:#800}.highlight .nd{color:#a2f}.highlight .ni{color:#999;font-weight:700}.highlight .ne{color:#D2413A;font-weight:700}.highlight .nf{color:#00f}.highlight .nl{color:#a0a000}.highlight .nn{color:#00F;font-weight:700}.highlight .nt{color:green;font-weight:700}.highlight .nv{color:#19177c}.highlight .ow{color:#A2F;font-weight:700}.highlight .w{color:#bbb}.highlight .mf{color:#666}.highlight .mh{color:#666}.highlight .mi{color:#666}.highlight .mo{color:#666}.highlight .sb{color:#ba2121}.highlight .sc{color:#ba2121}.highlight .sd{color:#BA2121;font-style:italic}.highlight .s2{color:#ba2121}.highlight .se{color:#B62;font-weight:700}.highlight .sh{color:#ba2121}.highlight .si{color:#B68;font-weight:700}.highlight .sx{color:green}.highlight .sr{color:#b68}.highlight .s1{color:#ba2121}.highlight .ss{color:#19177c}.highlight .bp{color:green}.highlight .vc{color:#19177c}.highlight .vg{color:#19177c}.highlight .vi{color:#19177c}.highlight .il{color:#666}.highlight .lineno{-webkit-touch-callout:none;-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;cursor:default}.highlight .lineno::selection{background:0 0}.highlight .lineno::-moz-selection{background:0 0} \ No newline at end of file diff --git a/sources/searx/static/themes/oscar/gruntfile.js b/sources/searx/static/themes/oscar/gruntfile.js index c591e85..59d1b6d 100644 --- a/sources/searx/static/themes/oscar/gruntfile.js +++ b/sources/searx/static/themes/oscar/gruntfile.js @@ -36,18 +36,20 @@ module.exports = function(grunt) { less: { development: { options: { - paths: ["less/oscar"] + paths: ["less/pointhi", "less/logicodev"] //banner: '/*! less/oscar/oscar.css | <%= grunt.template.today("dd-mm-yyyy") %> | https://github.com/asciimoo/searx */\n' }, - files: {"css/oscar.css": "less/oscar/oscar.less"} + files: {"css/pointhi.css": "less/pointhi/oscar.less", + "css/logicodev.css": "less/logicodev/oscar.less"} }, production: { options: { - paths: ["less/oscar"], + paths: ["less/pointhi", "less/logicodev"], //banner: '/*! less/oscar/oscar.css | <%= grunt.template.today("dd-mm-yyyy") %> | https://github.com/asciimoo/searx */\n', cleancss: true }, - files: {"css/oscar.min.css": "less/oscar/oscar.less"} + files: {"css/pointhi.min.css": "less/pointhi/oscar.less", + "css/logicodev.min.css": "less/logicodev/oscar.less"} }, bootstrap: { options: { @@ -63,7 +65,7 @@ module.exports = function(grunt) { tasks: ['jshint', 'concat', 'uglify'] }, oscar_styles: { - files: ['less/oscar/**/*.less'], + files: ['less/pointhi/**/*.less'], tasks: ['less:development', 'less:production'] }, bootstrap_styles: { diff --git a/sources/searx/static/themes/oscar/img/logo_searx_a.png b/sources/searx/static/themes/oscar/img/logo_searx_a.png new file mode 100644 index 0000000..fe8b94f Binary files /dev/null and b/sources/searx/static/themes/oscar/img/logo_searx_a.png differ diff --git a/sources/searx/static/themes/oscar/img/logo_searx_a_n.png b/sources/searx/static/themes/oscar/img/logo_searx_a_n.png new file mode 100644 index 0000000..96e97cb Binary files /dev/null and b/sources/searx/static/themes/oscar/img/logo_searx_a_n.png differ diff --git a/sources/searx/static/themes/oscar/less/oscar/checkbox.less b/sources/searx/static/themes/oscar/less/logicodev/checkbox.less similarity index 100% rename from sources/searx/static/themes/oscar/less/oscar/checkbox.less rename to sources/searx/static/themes/oscar/less/logicodev/checkbox.less diff --git a/sources/searx/static/themes/oscar/less/logicodev/code.less b/sources/searx/static/themes/oscar/less/logicodev/code.less new file mode 100644 index 0000000..96486f5 --- /dev/null +++ b/sources/searx/static/themes/oscar/less/logicodev/code.less @@ -0,0 +1,103 @@ +pre, code{ + font-family: 'Ubuntu Mono', 'Courier New', 'Lucida Console', monospace !important; +} + +.lineno{ + margin-right: 5px; +} + +.highlight .hll { background-color: #ffffcc } +.highlight { background: #f8f8f8; } +.highlight .c { color: #556366; font-style: italic } /* Comment */ +.highlight .err { border: 1px solid @orange } /* Error */ +.highlight .k { color: #BE74D5; font-weight: bold } /* Keyword */ +.highlight .o { color: #D19A66 } /* Operator */ +.highlight .cm { color: #556366; font-style: italic } /* Comment.Multiline */ +.highlight .cp { color: #BC7A00 } /* Comment.Preproc */ +.highlight .c1 { color: #556366; font-style: italic } /* Comment.Single */ +.highlight .cs { color: #556366; font-style: italic } /* Comment.Special */ +.highlight .gd { color: #A00000 } /* Generic.Deleted */ +.highlight .ge { font-style: italic } /* Generic.Emph */ +.highlight .gr { color: #FF0000 } /* Generic.Error */ +.highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */ +.highlight .gi { color: #00A000 } /* Generic.Inserted */ +.highlight .go { color: #888888 } /* Generic.Output */ +.highlight .gp { color: #000080; font-weight: bold } /* Generic.Prompt */ +.highlight .gs { font-weight: bold } /* Generic.Strong */ +.highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */ +.highlight .gt { color: #0044DD } /* Generic.Traceback */ +.highlight .kc { color: #BE74D5; font-weight: bold } /* Keyword.Constant */ +.highlight .kd { color: #BE74D5; font-weight: bold } /* Keyword.Declaration */ +.highlight .kn { color: #BE74D5; font-weight: bold } /* Keyword.Namespace */ +.highlight .kp { color: #BE74D5 } /* Keyword.Pseudo */ +.highlight .kr { color: #BE74D5; font-weight: bold } /* Keyword.Reserved */ +.highlight .kt { color: #D46C72 } /* Keyword.Type */ +.highlight .m { color: #D19A66 } /* Literal.Number */ +.highlight .s { color: #86C372 } /* Literal.String */ +.highlight .na { color: #7D9029 } /* Name.Attribute */ +.highlight .nb { color: #BE74D5 } /* Name.Builtin */ +.highlight .nc { color: #61AFEF; font-weight: bold } /* Name.Class */ +.highlight .no { color: #D19A66 } /* Name.Constant */ +.highlight .nd { color: #AA22FF } /* Name.Decorator */ +.highlight .ni { color: #999999; font-weight: bold } /* Name.Entity */ +.highlight .ne { color: #D2413A; font-weight: bold } /* Name.Exception */ +.highlight .nf { color: #61AFEF } /* Name.Function */ +.highlight .nl { color: #A0A000 } /* Name.Label */ +.highlight .nn { color: #61AFEF; font-weight: bold } /* Name.Namespace */ +.highlight .nt { color: #BE74D5; font-weight: bold } /* Name.Tag */ +.highlight .nv { color: #DFC06F } /* Name.Variable */ +.highlight .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */ +.highlight .w { color: #D7DAE0 } /* Text.Whitespace */ +.highlight .mf { color: #D19A66 } /* Literal.Number.Float */ +.highlight .mh { color: #D19A66 } /* Literal.Number.Hex */ +.highlight .mi { color: #D19A66 } /* Literal.Number.Integer */ +.highlight .mo { color: #D19A66 } /* Literal.Number.Oct */ +.highlight .sb { color: #86C372 } /* Literal.String.Backtick */ +.highlight .sc { color: #86C372 } /* Literal.String.Char */ +.highlight .sd { color: #86C372; font-style: italic } /* Literal.String.Doc */ +.highlight .s2 { color: #86C372 } /* Literal.String.Double */ +.highlight .se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */ +.highlight .sh { color: #86C372 } /* Literal.String.Heredoc */ +.highlight .si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */ +.highlight .sx { color: #BE74D5 } /* Literal.String.Other */ +.highlight .sr { color: #BB6688 } /* Literal.String.Regex */ +.highlight .s1 { color: #86C372 } /* Literal.String.Single */ +.highlight .ss { color: #DFC06F } /* Literal.String.Symbol */ +.highlight .bp { color: #BE74D5 } /* Name.Builtin.Pseudo */ +.highlight .vc { color: #DFC06F } /* Name.Variable.Class */ +.highlight .vg { color: #DFC06F } /* Name.Variable.Global */ +.highlight .vi { color: #DFC06F } /* Name.Variable.Instance */ +.highlight .il { color: #D19A66 } /* Literal.Number.Integer.Long */ + +.highlight .lineno { + -webkit-touch-callout: none; + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + cursor: default; + color: #556366; + + &::selection { + background: transparent; /* WebKit/Blink Browsers */ + } + &::-moz-selection { + background: transparent; /* Gecko Browsers */ + } +} + +.highlight pre { + background-color: #282C34; + color: #D7DAE0; + border: none; + margin-bottom: 25px; + font-size: 15px; + padding: 20px 10px; +} + +.highlight { + font-weight: 700; +} + + diff --git a/sources/searx/static/themes/oscar/less/oscar/cursor.less b/sources/searx/static/themes/oscar/less/logicodev/cursor.less similarity index 100% rename from sources/searx/static/themes/oscar/less/oscar/cursor.less rename to sources/searx/static/themes/oscar/less/logicodev/cursor.less diff --git a/sources/searx/static/themes/oscar/less/logicodev/footer.less b/sources/searx/static/themes/oscar/less/logicodev/footer.less new file mode 100644 index 0000000..d23a0cc --- /dev/null +++ b/sources/searx/static/themes/oscar/less/logicodev/footer.less @@ -0,0 +1,30 @@ +// Sticky footer styles +*{ + border-radius: 0 !important; +} +html { + position: relative; + min-height: 100%; + color: @black; +} + +body { + /* Margin bottom by footer height */ + font-family: 'Roboto', Helvetica, Arial, sans-serif; + margin-bottom: 80px; + background-color: white; + + a{ + color: @blue; + } +} + +.footer { + position: absolute; + bottom: 0; + width: 100%; + /* Set the fixed height of the footer here */ + height: 60px; + text-align: center; + color: #999; +} diff --git a/sources/searx/static/themes/oscar/less/logicodev/infobox.less b/sources/searx/static/themes/oscar/less/logicodev/infobox.less new file mode 100644 index 0000000..0d488d7 --- /dev/null +++ b/sources/searx/static/themes/oscar/less/logicodev/infobox.less @@ -0,0 +1,37 @@ +.infobox { + + .panel-heading{ + background-color: @dim-gray; + + .panel-title{ + font-weight: 700; + } + } + + + p{ + font-family: "DejaVu Serif", Georgia, Cambria, "Times New Roman", Times, serif !important; + font-style: italic; + } + + .btn{ + background-color: @green; + border: none; + + a{ + color: white; + margin: 5px; + } + } + + .infobox_part { + margin-bottom: 20px; + word-wrap: break-word; + table-layout: fixed; + + } + + .infobox_part:last-child { + margin-bottom: 0; + } +} diff --git a/sources/searx/static/themes/oscar/less/logicodev/navbar.less b/sources/searx/static/themes/oscar/less/logicodev/navbar.less new file mode 100644 index 0000000..493c9dc --- /dev/null +++ b/sources/searx/static/themes/oscar/less/logicodev/navbar.less @@ -0,0 +1,54 @@ +.navbar-default .navbar-nav > .active > a, .navbar-default .navbar-nav > .active > a:hover, .navbar-default .navbar-nav > .active > a:focus{ + background: @black; + color: @light-green; +} + +.navbar > li > a { + padding: 0; + margin: 0; +} + +.navbar-nav > li > a { + background: @black; + padding: 0 8px; + margin: 0; + line-height: 30px; +} + +.navbar, .navbar-default{ + background-color: @black; + border: none; + border-top: 4px solid @light-green; + padding-top: 5px; + color: @dim-gray !important; + font-weight: 700; + font-size: 1.1em; + text-transform: lowercase; + margin-bottom: 24px; + height: 30px; + line-height: 30px; + + .navbar-nav > li > a{ + color: @dim-gray; + } + + .navbar-brand{ + font-weight: 700; + color: @light-green; + line-height: 30px; + padding: 0 30px; + margin: 0; + } + z-index: 1; +} + +// Hover color +// http://stackoverflow.com/users/114029/leniel-macaferi +.navbar-default .navbar-nav > li > a:hover, .navbar-default .navbar-nav > li > a:focus { + color: @light-green; + background: @black; +} + +.navbar-toggle { + margin-top: 0; +} diff --git a/sources/searx/static/themes/oscar/less/logicodev/oscar.less b/sources/searx/static/themes/oscar/less/logicodev/oscar.less new file mode 100644 index 0000000..fba596c --- /dev/null +++ b/sources/searx/static/themes/oscar/less/logicodev/oscar.less @@ -0,0 +1,17 @@ +@import "variables.less"; + +@import "navbar.less"; + +@import "footer.less"; + +@import "checkbox.less"; + +@import "results.less"; + +@import "infobox.less"; + +@import "search.less"; + +@import "cursor.less"; + +@import "code.less"; diff --git a/sources/searx/static/themes/oscar/less/logicodev/results.less b/sources/searx/static/themes/oscar/less/logicodev/results.less new file mode 100644 index 0000000..37a5a76 --- /dev/null +++ b/sources/searx/static/themes/oscar/less/logicodev/results.less @@ -0,0 +1,150 @@ +.result_header { + margin-top: 6px; + margin-bottom: 4px; + font-size: 16px; + + .favicon { + margin-bottom:-3px; + } + + a { + color: @black; + text-decoration: none; + + &:hover{ + color: @blue; + } + + &:visited{ + color: @violet; + } + + .highlight { + background-color: @dim-gray; + // Chrome hack: bold is different size than normal + // https://stackoverflow.com/questions/20713988/weird-text-alignment-issue-in-css-when-bolded-lucida-sans + } + } +} + +.result-content { + margin-top: 2px; + margin-bottom: 0; + word-wrap: break-word; + color: @dark-gray; + font-size: 13px; + + + .highlight { + font-weight:bold; + } + +} + +.external-link, .external-link a{ + color: @green; + + a{ + margin-right: 3px; + } +} + +// default formating of results +.result-default, .result-code, .result-torrent, .result-videos, .result-map { + clear: both; + padding: 2px 4px; + &:hover{ + background-color: @dim-gray; + } +} + + +// image formating of results +.result-images { + float: left !important; + width: 24%; + margin: .5%; + a{ + display: block; + width: 100%; + height: 170px; + background-size: cover; + } +} + +.img-thumbnail { + margin: 5px; + max-height: 128px; + min-height: 128px; +} + +// video formating of results +.result-videos { + clear: both; + + hr{ + margin: 5px 0 15px 0; + } + + .collapse{ + width: 100%; + } + + .in{ + margin-bottom: 8px; + } +} + +// torrent formating of results +.result-torrent { + clear: both; + + b{ + margin-right: 5px; + margin-left: 5px; + } + + .seeders{ + color: @green; + } + + .leechers{ + color: @red; + } +} + +// map formating of results +.result-map { + clear: both; +} + +// code formating of results +.result-code { + clear: both; + + .code-fork, .code-fork a{ + color: @dark-gray; + } + +} + +// suggestion +.suggestion_item { + margin: 2px 5px; +} + +// download result +.result_download { + margin-right: 5px; +} + +// page forward, backward +#pagination { + margin-top: 30px; + padding-bottom: 60px; +} + +.label-default { + color: @gray; + background: transparent; +} diff --git a/sources/searx/static/themes/oscar/less/logicodev/search.less b/sources/searx/static/themes/oscar/less/logicodev/search.less new file mode 100644 index 0000000..1bb71a7 --- /dev/null +++ b/sources/searx/static/themes/oscar/less/logicodev/search.less @@ -0,0 +1,59 @@ +.search_categories, #categories { + margin: 10px 0 4px 0; + text-transform: capitalize; + + label{ + border: none; + box-shadow: none; + font-size: 13px; + padding-bottom: 2px; + color: @gray; + margin-bottom: 5px; + + &:hover{ + color: @black; + background-color: transparent; + } + + &:active{ + box-shadow: none; + } + } + + .active, .btn-primary{ + color: @black; + font-weight: 700; + border-bottom: 5px solid @light-green; + background-color: transparent; + } + +} + +#categories{ + margin: 0; +} + +#main-logo{ + margin-top: 10vh; + margin-bottom: 25px; +} + +#main-logo > img { + max-width: 350px; + width: 80%; +} + +#q{ + box-shadow: none; + border-right: none; + border-color: @gray; +} + + #search_form .input-group-btn .btn{ + border-color: @gray; + } + + #search_form .input-group-btn .btn:hover{ + background-color: @green; + color: white; + } diff --git a/sources/searx/static/themes/oscar/less/logicodev/variables.less b/sources/searx/static/themes/oscar/less/logicodev/variables.less new file mode 100644 index 0000000..3ca05e7 --- /dev/null +++ b/sources/searx/static/themes/oscar/less/logicodev/variables.less @@ -0,0 +1,10 @@ +@black: #29314D; +@gray: #A4A4A4; +@dim-gray: #F6F9FA; +@dark-gray: #666; +@blue: #0088CC; +@red: #F35E77; +@violet: #684898; +@green: #2ecc71; +@light-green: #01D7D4; +@orange: #FFA92F; diff --git a/sources/searx/static/themes/oscar/less/pointhi/checkbox.less b/sources/searx/static/themes/oscar/less/pointhi/checkbox.less new file mode 100644 index 0000000..6428b36 --- /dev/null +++ b/sources/searx/static/themes/oscar/less/pointhi/checkbox.less @@ -0,0 +1,9 @@ +// Hide element if checkbox is checked +input[type=checkbox]:checked + .label_hide_if_checked, input[type=checkbox]:checked + .label_hide_if_not_checked + .label_hide_if_checked { + display:none; +} + +// Hide element if checkbox is not checked +input[type=checkbox]:not(:checked) + .label_hide_if_not_checked, input[type=checkbox]:not(:checked) + .label_hide_if_checked + .label_hide_if_not_checked { + display:none; +} diff --git a/sources/searx/static/themes/oscar/less/oscar/code.less b/sources/searx/static/themes/oscar/less/pointhi/code.less similarity index 100% rename from sources/searx/static/themes/oscar/less/oscar/code.less rename to sources/searx/static/themes/oscar/less/pointhi/code.less diff --git a/sources/searx/static/themes/oscar/less/pointhi/cursor.less b/sources/searx/static/themes/oscar/less/pointhi/cursor.less new file mode 100644 index 0000000..cbc1ea6 --- /dev/null +++ b/sources/searx/static/themes/oscar/less/pointhi/cursor.less @@ -0,0 +1,8 @@ +// display cursor +.cursor-text { + cursor: text !important; +} + +.cursor-pointer { + cursor: pointer !important; +} diff --git a/sources/searx/static/themes/oscar/less/oscar/footer.less b/sources/searx/static/themes/oscar/less/pointhi/footer.less similarity index 100% rename from sources/searx/static/themes/oscar/less/oscar/footer.less rename to sources/searx/static/themes/oscar/less/pointhi/footer.less diff --git a/sources/searx/static/themes/oscar/less/oscar/infobox.less b/sources/searx/static/themes/oscar/less/pointhi/infobox.less similarity index 100% rename from sources/searx/static/themes/oscar/less/oscar/infobox.less rename to sources/searx/static/themes/oscar/less/pointhi/infobox.less diff --git a/sources/searx/static/themes/oscar/less/oscar/oscar.less b/sources/searx/static/themes/oscar/less/pointhi/oscar.less similarity index 100% rename from sources/searx/static/themes/oscar/less/oscar/oscar.less rename to sources/searx/static/themes/oscar/less/pointhi/oscar.less diff --git a/sources/searx/static/themes/oscar/less/oscar/results.less b/sources/searx/static/themes/oscar/less/pointhi/results.less similarity index 100% rename from sources/searx/static/themes/oscar/less/oscar/results.less rename to sources/searx/static/themes/oscar/less/pointhi/results.less diff --git a/sources/searx/static/themes/oscar/less/oscar/search.less b/sources/searx/static/themes/oscar/less/pointhi/search.less similarity index 100% rename from sources/searx/static/themes/oscar/less/oscar/search.less rename to sources/searx/static/themes/oscar/less/pointhi/search.less diff --git a/sources/searx/templates/oscar/base.html b/sources/searx/templates/oscar/base.html index f63025e..649d91f 100644 --- a/sources/searx/templates/oscar/base.html +++ b/sources/searx/templates/oscar/base.html @@ -12,7 +12,11 @@ {% block title %}{% endblock %}{{ instance_name }} - + {% if cookies['oscar-style'] %} + + {% else %} + + {% endif %} {% for css in styles %} @@ -48,8 +52,8 @@ -
{% include 'oscar/navbar.html' %} +
{% block site_alert_error %} {% endblock %} @@ -75,7 +79,7 @@
{% block footer %} {% endblock %} -

{{ _('Powered by') }} searx - {{ searx_version }} - {{ _('a privacy-respecting, hackable metasearch engine') }}

+

{{ _('Powered by') }} searx - {{ searx_version }} - {{ _('a privacy-respecting, hackable metasearch engine') }}

diff --git a/sources/searx/templates/oscar/index.html b/sources/searx/templates/oscar/index.html index e58aa07..b941f5f 100644 --- a/sources/searx/templates/oscar/index.html +++ b/sources/searx/templates/oscar/index.html @@ -3,7 +3,14 @@
-

searx logosearx

+ {% if cookies['oscar-style'] == 'pointhi' %} +

searx logosearx

+ {% else %} +

+ searx logo + searx +

+ {% endif %}
diff --git a/sources/searx/templates/oscar/macros.html b/sources/searx/templates/oscar/macros.html index cf49ce8..a826b0e 100644 --- a/sources/searx/templates/oscar/macros.html +++ b/sources/searx/templates/oscar/macros.html @@ -17,7 +17,6 @@ {% macro result_sub_header(result) -%} {% if result.publishedDate %}{% endif %} - {{ icon('link') }} {{ _('cached') }} {% if result.magnetlink %}{{ icon('magnet') }} {{ _('magnet link') }}{% endif %} {% if result.torrentfile %}{{ icon('download-alt') }} {{ _('torrent file') }}{% endif %} {%- endmacro %} @@ -29,15 +28,19 @@ {% for engine in result.engines %} {{ engine }} {% endfor %} + {{ icon('link') }} {{ _('cached') }}
-

{{ result.pretty_url }}

+
{{ result.pretty_url }}
{%- endmacro %} {% macro result_footer_rtl(result) -%}
- {{ result.engine }} -

{{ result.pretty_url }}‎

+ {% for engine in result.engines %} + {{ engine }} + {% endfor %} + {{ icon('link') }} {{ _('cached') }} +
{{ result.pretty_url }}
{%- endmacro %} {% macro preferences_item_header(info, label, rtl) -%} diff --git a/sources/searx/templates/oscar/preferences.html b/sources/searx/templates/oscar/preferences.html index a2c493a..18308bd 100644 --- a/sources/searx/templates/oscar/preferences.html +++ b/sources/searx/templates/oscar/preferences.html @@ -110,6 +110,13 @@ {% endfor %} {{ preferences_item_footer(theme_info, theme_label, rtl) }} + + {{ preferences_item_header(_('Choose style for this theme'), _('Style'), rtl) }} + + {{ preferences_item_footer(_('Choose style for this theme'), _('Style'), rtl) }}
diff --git a/sources/searx/templates/oscar/results.html b/sources/searx/templates/oscar/results.html index 9f9bdf1..39cdff4 100644 --- a/sources/searx/templates/oscar/results.html +++ b/sources/searx/templates/oscar/results.html @@ -78,6 +78,16 @@