Commit 10a24bdc authored by Alexandre Flament's avatar Alexandre Flament

[enh] add simple theme (WIP)

parent 4f6586d8
searx/static/css/bootstrap.min.css -diff
searx/static/js/bootstrap.min.js -diff
searx/static/themes/oscar/css/logicodev.min.css -diff
searx/static/themes/oscar/css/leaflet.min.css -diff
searx/static/themes/oscar/css/pointhi.min.css -diff
searx/static/themes/oscar/js/searx.min.js -diff
searx/static/themes/simple/css/searx.min.css -diff
searx/static/themes/simple/css/searx-rtl.min.css -diff
searx/static/themes/simple/js/searx.min.js -diff
searx/static/themes/simple/js/searx.min.js.map -diff
......@@ -13,10 +13,11 @@ python:
before_install:
- "export DISPLAY=:99.0"
- "sh -e /etc/init.d/xvfb start"
- npm install less grunt-cli
- npm install less less-plugin-clean-css grunt-cli
- ( cd searx/static/themes/oscar;npm install; cd - )
- ( cd searx/static/themes/simple;npm install; cd - )
- mkdir -p ~/drivers; export PATH=~/drivers:$PATH;
- GECKODRIVER_URL="https://github.com/mozilla/geckodriver/releases/download/v0.11.1/geckodriver-v0.11.1-linux64.tar.gz";
- GECKODRIVER_URL="https://github.com/mozilla/geckodriver/releases/download/v0.14.0/geckodriver-v0.14.0-linux64.tar.gz";
- FILE=`mktemp`; wget "$GECKODRIVER_URL" -qO $FILE && tar xz -C ~/drivers -f $FILE geckodriver; rm $FILE; chmod 777 ~/drivers/geckodriver;
install:
- ./manage.sh update_dev_packages
......
......@@ -22,7 +22,7 @@ check_geckodriver() {
if [ -z $NOTFOUND ]; then
return
fi
GECKODRIVER_VERSION="v0.11.1"
GECKODRIVER_VERSION="v0.14.0"
PLATFORM=`python -c "import platform; print platform.system().lower(), platform.architecture()[0]"`
case $PLATFORM in
"linux 32bit" | "linux2 32bit") ARCH="linux32";;
......@@ -49,7 +49,7 @@ pep8_check() {
# ignored rules:
# E402 module level import not at top of file
# W503 line break before binary operator
pep8 --max-line-length=120 --ignore "E402,W503" "$SEARX_DIR" "$BASE_DIR/tests"
pep8 --exclude=searx/static --max-line-length=120 --ignore "E402,W503" "$SEARX_DIR" "$BASE_DIR/tests"
}
unit_tests() {
......@@ -79,7 +79,8 @@ tests() {
}
build_style() {
lessc -x "$BASE_DIR/searx/static/$1" "$BASE_DIR/searx/static/$2"
# lessc -x "$BASE_DIR/searx/static/$1" "$BASE_DIR/searx/static/$2"
lessc --clean-css="--s1 --advanced --compatibility=ie9" "$BASE_DIR/searx/static/$1" "$BASE_DIR/searx/static/$2"
}
styles() {
......@@ -92,10 +93,13 @@ styles() {
build_style themes/oscar/less/pointhi/oscar.less themes/oscar/css/pointhi.min.css
build_style themes/oscar/less/logicodev/oscar.less themes/oscar/css/logicodev.min.css
build_style themes/pix-art/less/style.less themes/pix-art/css/style.css
build_style themes/simple/less/style.less themes/simple/css/searx.min.css
build_style themes/simple/less/style-rtl.less themes/simple/css/searx-rtl.min.css
}
grunt_build() {
grunt --gruntfile "$SEARX_DIR/static/themes/oscar/gruntfile.js"
grunt --gruntfile "$SEARX_DIR/static/themes/simple/gruntfile.js"
}
locales() {
......
......@@ -7,6 +7,7 @@ regex = re.compile(r'10\.\d{4,9}/[^\s]+')
name = gettext('DOAI rewrite')
description = gettext('Avoid paywalls by redirecting to open-access versions of publications when available')
default_on = False
preference_section = 'privacy'
def extract_doi(url):
......
......@@ -31,6 +31,7 @@ if sys.version_info[0] == 3:
name = "HTTPS rewrite"
description = gettext('Rewrite HTTP links to HTTPS if possible')
default_on = True
preference_section = 'privacy'
if 'SEARX_HTTPS_REWRITE_PATH' in environ:
rules_path = environ['SEARX_rules_path']
......
......@@ -3,6 +3,7 @@ from flask_babel import gettext
name = gettext('Infinite scroll')
description = gettext('Automatically load next page when scrolling to bottom of current page')
default_on = False
preference_section = 'ui'
js_dependencies = ('plugins/js/infinite_scroll.js',)
css_dependencies = ('plugins/css/infinite_scroll.css',)
......@@ -19,5 +19,6 @@ name = gettext('Search on category select')
description = gettext('Perform search immediately if a category selected. '
'Disable to select multiple categories. (JavaScript required)')
default_on = True
preference_section = 'ui'
js_dependencies = ('plugins/js/search_on_category_select.js',)
......@@ -26,6 +26,7 @@ regexes = {re.compile(r'utm_[^&]+&?'),
name = gettext('Tracker URL remover')
description = gettext('Remove trackers arguments from the returned URL')
default_on = True
preference_section = 'privacy'
def on_result(request, search, result):
......
js/searx_src/autocomplete.js
This diff is collapsed.
This diff was suppressed by a .gitattributes entry.
This diff is collapsed.
This diff was suppressed by a .gitattributes entry.
/* Generated by grunt-webfont */
@font-face {
font-family:"ion";
src:url("../fonts/ion.eot?94af7082ea096aefe3a7b6642834716e");
src:url("../fonts/ion.eot?#iefix") format("embedded-opentype"),
url("../fonts/ion.woff2?94af7082ea096aefe3a7b6642834716e") format("woff2"),
url("../fonts/ion.woff?94af7082ea096aefe3a7b6642834716e") format("woff"),
url("../fonts/ion.ttf?94af7082ea096aefe3a7b6642834716e") format("truetype"),
url("../fonts/ion.svg?94af7082ea096aefe3a7b6642834716e#ion") format("svg");
font-weight:normal;
font-style:normal;
}
.ion-icon {
font-family:"ion";
display:inline-block;
vertical-align:middle;
line-height:1;
font-weight:normal;
font-style:normal;
speak:none;
text-decoration:inherit;
text-transform:none;
text-rendering:auto;
-webkit-font-smoothing:antialiased;
-moz-osx-font-smoothing:grayscale;
}
/* Icons */
.ion-navicon-round:before {
content:"\f101";
}
.ion-search:before {
content:"\f102";
}
.ion-play:before {
content:"\f103";
}
.ion-link:before {
content:"\f104";
}
.ion-chevron-up:before {
content:"\f105";
}
.ion-chevron-left:before {
content:"\f106";
}
.ion-chevron-right:before {
content:"\f107";
}
.ion-arrow-down-a:before {
content:"\f108";
}
.ion-arrow-up-a:before {
content:"\f109";
}
.ion-arrow-swap:before {
content:"\f10a";
}
.ion-arrow-dropdown:before {
content:"\f10b";
}
.ion-globe:before {
content:"\f10c";
}
.ion-time:before {
content:"\f10d";
}
.ion-location:before {
content:"\f10e";
}
.ion-warning:before {
content:"\f10f";
}
.ion-error:before {
content:"\f110";
}
.ion-film-outline:before {
content:"\f111";
}
.ion-music-note:before {
content:"\f112";
}
.ion-more-vertical:before {
content:"\f113";
}
.ion-magnet:before {
content:"\f114";
}
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>ion</title>
<style>
body {
margin:0;
padding:10px 20px;
background:#fff;
color:#222;
}
h1, div, footer {
font-family:"Helvetica Neue", Arial, sans-serif;
}
h1 {
margin:0 0 20px;
font-size:32px;
font-weight:normal;
}
h1 small {
font-size: 0.8em;
padding-left: 2em;
}
.icons {
margin-bottom:40px;
-webkit-column-count:5;
-moz-column-count:5;
column-count:5;
-webkit-column-gap:20px;
-moz-column-gap:20px;
column-gap:20px;
}
.icons__item,
.icons__item i {
line-height:2em;
cursor:pointer;
overflow:hidden;
}
.icons__item:hover {
color:#3c90be;
}
.icons__item i {
display:inline-block;
width:32px;
text-align:center;
}
.icons__item:hover i {
-webkit-transform:scale(1.5);
transform:scale(1.5);
}
footer {
margin-top:40px;
font-size:14px;
color:#999;
}
/* Generated by grunt-webfont */
@font-face {
font-family:"ion";
src:url("ion.eot?94af7082ea096aefe3a7b6642834716e");
src:url("ion.eot?#iefix") format("embedded-opentype"),
url("ion.woff2?94af7082ea096aefe3a7b6642834716e") format("woff2"),
url("ion.woff?94af7082ea096aefe3a7b6642834716e") format("woff"),
url("ion.ttf?94af7082ea096aefe3a7b6642834716e") format("truetype"),
url("ion.svg?94af7082ea096aefe3a7b6642834716e#ion") format("svg");
font-weight:normal;
font-style:normal;
}
.ion-icon {
font-family:"ion";
display:inline-block;
vertical-align:middle;
line-height:1;
font-weight:normal;
font-style:normal;
speak:none;
text-decoration:inherit;
text-transform:none;
text-rendering:auto;
-webkit-font-smoothing:antialiased;
-moz-osx-font-smoothing:grayscale;
}
/* Icons */
.ion-navicon-round:before {
content:"\f101";
}
.ion-search:before {
content:"\f102";
}
.ion-play:before {
content:"\f103";
}
.ion-link:before {
content:"\f104";
}
.ion-chevron-up:before {
content:"\f105";
}
.ion-chevron-left:before {
content:"\f106";
}
.ion-chevron-right:before {
content:"\f107";
}
.ion-arrow-down-a:before {
content:"\f108";
}
.ion-arrow-up-a:before {
content:"\f109";
}
.ion-arrow-swap:before {
content:"\f10a";
}
.ion-arrow-dropdown:before {
content:"\f10b";
}
.ion-globe:before {
content:"\f10c";
}
.ion-time:before {
content:"\f10d";
}
.ion-location:before {
content:"\f10e";
}
.ion-warning:before {
content:"\f10f";
}
.ion-error:before {
content:"\f110";
}
.ion-film-outline:before {
content:"\f111";
}
.ion-music-note:before {
content:"\f112";
}
.ion-more-vertical:before {
content:"\f113";
}
.ion-magnet:before {
content:"\f114";
}
</style>
</head>
<body>
<h1>ion</h1>
<div class="icons" id="icons">
<div class="icons__item" data-name="navicon-round"><i class="ion-icon ion-navicon-round"></i> ion-navicon-round</div>
<div class="icons__item" data-name="search"><i class="ion-icon ion-search"></i> ion-search</div>
<div class="icons__item" data-name="play"><i class="ion-icon ion-play"></i> ion-play</div>
<div class="icons__item" data-name="link"><i class="ion-icon ion-link"></i> ion-link</div>
<div class="icons__item" data-name="chevron-up"><i class="ion-icon ion-chevron-up"></i> ion-chevron-up</div>
<div class="icons__item" data-name="chevron-left"><i class="ion-icon ion-chevron-left"></i> ion-chevron-left</div>
<div class="icons__item" data-name="chevron-right"><i class="ion-icon ion-chevron-right"></i> ion-chevron-right</div>
<div class="icons__item" data-name="arrow-down-a"><i class="ion-icon ion-arrow-down-a"></i> ion-arrow-down-a</div>
<div class="icons__item" data-name="arrow-up-a"><i class="ion-icon ion-arrow-up-a"></i> ion-arrow-up-a</div>
<div class="icons__item" data-name="arrow-swap"><i class="ion-icon ion-arrow-swap"></i> ion-arrow-swap</div>
<div class="icons__item" data-name="arrow-dropdown"><i class="ion-icon ion-arrow-dropdown"></i> ion-arrow-dropdown</div>
<div class="icons__item" data-name="globe"><i class="ion-icon ion-globe"></i> ion-globe</div>
<div class="icons__item" data-name="time"><i class="ion-icon ion-time"></i> ion-time</div>
<div class="icons__item" data-name="location"><i class="ion-icon ion-location"></i> ion-location</div>
<div class="icons__item" data-name="warning"><i class="ion-icon ion-warning"></i> ion-warning</div>
<div class="icons__item" data-name="error"><i class="ion-icon ion-error"></i> ion-error</div>
<div class="icons__item" data-name="film-outline"><i class="ion-icon ion-film-outline"></i> ion-film-outline</div>
<div class="icons__item" data-name="music-note"><i class="ion-icon ion-music-note"></i> ion-music-note</div>
<div class="icons__item" data-name="more-vertical"><i class="ion-icon ion-more-vertical"></i> ion-more-vertical</div>
<div class="icons__item" data-name="magnet"><i class="ion-icon ion-magnet"></i> ion-magnet</div>
</div>
<h1>Usage</h1>
<pre><code>&lt;i class=&quot;ion-icon ion-<span id="name">name</span>&quot;&gt;&lt;/i&gt;</code></pre>
<footer>Generated by <a href="https://github.com/sapegin/grunt-webfont">grunt-webfont</a>.</footer>
<script>
(function() {
document.getElementById('icons').onclick = function(e) {
e = e || window.event;
var name = e.target.getAttribute('data-name') || e.target.parentNode.getAttribute('data-name');
document.getElementById('name').innerHTML = name;
}
})();
</script>
</body>
</html>
This diff is collapsed.
module.exports = function(grunt) {
const path = require('path');
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
watch: {
scripts: {
files: ['<%= jshint.files %>', 'less/*.less'],
tasks: ['jshint', 'concat', 'uglify', 'webfont', 'less:development', 'less:production']
}
},
concat: {
options: {
separator: ';'
},
dist: {
src: ['js/searx_src/*.js'],
dest: 'js/searx.js'
}
},
uglify: {
options: {
banner: '/*! simple/searx.min.js | <%= grunt.template.today("dd-mm-yyyy") %> | https://github.com/asciimoo/searx */\n',
preserveComments: 'some',
sourceMap: true
},
dist: {
files: {
'js/searx.min.js': ['<%= concat.dist.dest %>']
}
}
},
jshint: {
files: ['js/searx_src/*.js'],
options: {
proto: true,
// options here to override JSHint defaults
globals: {
browser: true,
jQuery: false,
devel: true
}
}
},
less: {
development: {
options: {
paths: ["less"],
banner: '/*! searx | <%= grunt.template.today("dd-mm-yyyy") %> | https://github.com/asciimoo/searx */\n'
},
files: {
"css/searx.css": "less/style.less",
"css/searx-rtl.css": "less/style-rtl.less"
}
},
production: {
options: {
paths: ["less"],
plugins: [
new (require('less-plugin-clean-css'))({
advanced: true,
compatibility: 'ie8'
})
],
banner: '/*! searx | <%= grunt.template.today("dd-mm-yyyy") %> | https://github.com/asciimoo/searx */\n'
},
files: {
"css/searx.min.css": "less/style.less",
"css/searx-rtl.min.css": "less/style-rtl.less"
}
},
},
webfont: {
icons: {
// src: 'node_modules/ionicons-npm/src/*.svg',
src: [
'node_modules/ionicons-npm/src/navicon-round.svg',
'node_modules/ionicons-npm/src/search.svg',
'node_modules/ionicons-npm/src/play.svg',
'node_modules/ionicons-npm/src/link.svg',
'node_modules/ionicons-npm/src/chevron-up.svg',
'node_modules/ionicons-npm/src/chevron-left.svg',
'node_modules/ionicons-npm/src/chevron-right.svg',
'node_modules/ionicons-npm/src/arrow-down-a.svg',
'node_modules/ionicons-npm/src/arrow-up-a.svg',
'node_modules/ionicons-npm/src/arrow-swap.svg',
'node_modules/ionicons-npm/src/telephone.svg',
'node_modules/ionicons-npm/src/android-arrow-dropdown.svg',
'node_modules/ionicons-npm/src/android-globe.svg',
'node_modules/ionicons-npm/src/android-time.svg',
'node_modules/ionicons-npm/src/location.svg',
'node_modules/ionicons-npm/src/alert-circled.svg',
'node_modules/ionicons-npm/src/android-alert.svg',
'node_modules/ionicons-npm/src/ios-film-outline.svg',
'node_modules/ionicons-npm/src/music-note.svg',
'node_modules/ionicons-npm/src/ion-close-round.svg',
'node_modules/ionicons-npm/src/android-more-vertical.svg',
'magnet.svg'
],
dest: 'fonts',
destLess: 'less',
options: {
font: 'ion',
hashes : true,
syntax: 'bem',
styles : 'font,icon',
types : 'eot,woff2,woff,ttf,svg',
order : 'eot,woff2,woff,ttf,svg',
stylesheets : ['css', 'less'],
relativeFontPath : '../fonts/',
autoHint : false,
normalize : false,
// ligatures : true,
optimize : true,
// fontHeight : 400,
rename : function(name) {
basename = path.basename(name);
if (basename === 'android-alert.svg') {
return 'error.svg';
}
if (basename === 'alert-circled.svg') {
return 'warning.svg';
}
if (basename === 'ion-close-round.svg') {
return 'close.svg';
}
return basename.replace(/(ios|md|android)-/i, '');
},
templateOptions: {
baseClass: 'ion-icon',
classPrefix: 'ion-'
}
}
}
}
});
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.loadNpmTasks('grunt-contrib-jshint');
grunt.loadNpmTasks('grunt-contrib-concat');
grunt.loadNpmTasks('grunt-contrib-less');
grunt.loadNpmTasks('grunt-contrib-cssmin');
grunt.loadNpmTasks('grunt-webfont');
grunt.registerTask('test', ['jshint']);
grunt.registerTask('default', ['jshint', 'concat', 'uglify', 'less:development', 'less:production']);
};
This diff is collapsed.
This diff is collapsed.
This diff was suppressed by a .gitattributes entry.
This diff was suppressed by a .gitattributes entry.
/**
* searx is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* searx is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with searx. If not, see < http://www.gnu.org/licenses/ >.
*
* (C) 2017 by Alexandre Flament, <alex@al-f.net>
*
*/
(function(w, d, searx) {
'use strict';
// not invented here tookit with bugs fixed elsewhere
// purposes : be just good enough and as small as possible
// from https://plainjs.com/javascript/events/live-binding-event-handlers-14/
if (w.Element) {
(function(ElementPrototype) {
ElementPrototype.matches = ElementPrototype.matches ||
ElementPrototype.matchesSelector ||
ElementPrototype.webkitMatchesSelector ||
ElementPrototype.msMatchesSelector ||
function(selector) {
var node = this, nodes = (node.parentNode || node.document).querySelectorAll(selector), i = -1;
while (nodes[++i] && nodes[i] != node);
return !!nodes[i];
};
})(Element.prototype);
}
function callbackSafe(callback, el, e) {
try {
callback.call(el, e);
} catch (exception) {
console.log(exception);
}
}
searx = searx || {};
searx.on = function(obj, eventType, callback, useCapture) {
useCapture = useCapture || false;
if (typeof obj !== 'string') {
// obj HTMLElement, HTMLDocument
obj.addEventListener(eventType, callback, useCapture);
} else {
// obj is a selector
d.addEventListener(eventType, function(e) {
var el = e.target || e.srcElement, found = false;
while (el && el.matches && el !== d && !(found = el.matches(obj))) el = el.parentElement;
if (found) callbackSafe(callback, el, e);
}, useCapture);
}
};
searx.ready = function(callback) {
if (document.readyState != 'loading') {
callback.call(w);
} else {
w.addEventListener('DOMContentLoaded', callback.bind(w));
}
};
searx.http = function(method, url, callback) {
var req = new XMLHttpRequest(),
resolve = function() {},
reject = function() {},
promise = {
then: function(callback) { resolve = callback; return promise; },
catch: function(callback) { reject = callback; return promise; }
};
try {
req.open(method, url, true);
// On load
req.onload = function() {
if (req.status == 200) {
resolve(req.response, req.responseType);
} else {
reject(Error(req.statusText));
}
};
// Handle network errors
req.onerror = function() {
reject(Error("Network Error"));
};
req.onabort = function() {
reject(Error("Transaction is aborted"));
};
// Make the request
req.send();
} catch (ex) {
reject(ex);
}
return promise;
};
searx.loadStyle = function(src) {
var path = searx.staticPath + src,
id = "style_" + src.replace('.', '_'),
s = d.getElementById(id);
if (s === null) {
s = d.createElement('link');
s.setAttribute('id', id);
s.setAttribute('rel', 'stylesheet');
s.setAttribute('type', 'text/css');
s.setAttribute('href', path);
d.body.appendChild(s);
}
};
searx.loadScript = function(src, callback) {
var path = searx.staticPath + src,
id = "script_" + src.replace('.', '_'),
s = d.getElementById(id);
if (s === null) {
s = d.createElement('script');
s.setAttribute('id', id);
s.setAttribute('src', path);
s.onload = callback;
s.onerror = function() {
s.setAttribute('error', '1');
};
d.body.appendChild(s);
} else if (!s.hasAttribute('error')) {
try {
callback.apply(s, []);
} catch (exception) {
console.log(exception);
}
} else {
console.log("callback not executed : script '" + path + "' not loaded.");
}
};
searx.on('.close', 'click', function(e) {
var el = e.target || e.srcElement;
this.parentNode.style.display="None";
});
return searx;
})(window, document, window.searx);
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment