This commit is contained in:
Markus Heiser 2025-02-11 23:45:09 +11:00 committed by GitHub
commit 83d4e40a42
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
105 changed files with 6362 additions and 10468 deletions
.editorconfig
.github
Makefile
client/simple
docs
manage
searx
searxng_extra/update

View File

@ -16,11 +16,17 @@ max_line_length = 119
[*.html]
indent_size = 4
[*.css]
indent_size = 2
[*.less]
indent_size = 2
[*.js]
indent_size = 2
[*.json]
indent_size = 4
indent_size = 2
insert_final_newline = ignore
# Minified JavaScript files shouldn't be changed

View File

@ -12,11 +12,11 @@ updates:
prefix: "[upd] pypi:"
- package-ecosystem: "npm"
directory: "/searx/static/themes/simple"
directory: "/client/simple"
schedule:
interval: "weekly"
day: "friday"
open-pull-requests-limit: 5
target-branch: "master"
commit-message:
prefix: "[upd] npm:"
prefix: "[upd] web-client (simple):"

View File

@ -44,19 +44,8 @@ jobs:
with:
python-version: '3.12'
architecture: 'x64'
- name: Cache Python dependencies
id: cache-python
uses: actions/cache@v4
with:
path: |
./local
./.nvm
./node_modules
key: python-ubuntu-24.04-3.12-${{ hashFiles('requirements*.txt', 'setup.py','.nvmrc', 'package.json') }}
- name: Install node dependencies
run: make V=1 node.env
- name: Build themes
run: make V=1 themes.all
run: make themes.all
documentation:
name: Documentation

View File

@ -50,7 +50,7 @@ search.checker.%: install
$(Q)./manage pyenv.cmd searxng-checker -v "$(subst _, ,$(patsubst search.checker.%,%,$@))"
PHONY += test ci.test test.shell
ci.test: test.yamllint test.black test.types.ci test.pylint test.unit test.robot test.rst test.shell test.pybabel test.themes
ci.test: test.yamllint test.black test.types.ci test.pylint test.unit test.robot test.rst test.shell test.pybabel
test: test.yamllint test.black test.types.dev test.pylint test.unit test.robot test.rst test.shell
test.shell:
$(Q)shellcheck -x -s dash \
@ -85,7 +85,6 @@ MANAGE += pyenv pyenv.install pyenv.uninstall
MANAGE += format.python
MANAGE += test.yamllint test.pylint test.black test.pybabel test.unit test.coverage test.robot test.rst test.clean test.themes test.types.dev test.types.ci
MANAGE += themes.all themes.fix themes.test
MANAGE += themes.simple themes.simple.pygments themes.simple.fix
MANAGE += static.build.commit static.build.drop static.build.restore
MANAGE += nvm.install nvm.clean nvm.status nvm.nodejs

3
client/simple/.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
dist
node_modules
.stylelintcache

View File

@ -1,6 +1,9 @@
{
"extends": "stylelint-config-standard-less",
"formatter": "unix",
"plugins": [ "stylelint-prettier" ],
"extends": [ "stylelint-config-standard-less" ],
"rules": {
"prettier/prettier": true,
"declaration-empty-line-before": null,
"no-invalid-position-at-import-rule": null,
"property-no-vendor-prefix": null,

24
client/simple/README.rst Normal file
View File

@ -0,0 +1,24 @@
=====================
MEMO vite development
=====================
Local install::
# in folder ./client/simple/
$ npm install
Start development server::
$ ./manage vite.simple.dev
# in folder ./client/simple/
$ npm exec -- vite
Fix source code::
# in folder ./client/simple/
$ npm run fix
Fix & Build::
$ ./manage vite.simple.build

View File

@ -0,0 +1,34 @@
import globals from "globals";
import pluginJs from "@eslint/js";
/** @type {import('eslint').Linter.Config[]} */
export default [
pluginJs.configs.recommended,
// global "ignores"
// https://eslint.org/docs/latest/use/configure/configuration-files#globally-ignoring-files-with-ignores
{
ignores: ["node_modules/", "dist/"]
},
{
files: [
"**/*.js",
],
linterOptions: {
reportUnusedDisableDirectives: "error",
// noInlineConfig: true
},
languageOptions: {
sourceType: "module",
globals: {
...globals.browser,
}
},
rules: {
indent: ["error", 2],
},
},
];

5400
client/simple/package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,40 @@
{
"name": "simple",
"version": "1.0.0",
"type": "module",
"scripts": {
"clean": "rm -Rf node_modules",
"build": "node theme_icons.js && vite build",
"fix": "eslint --fix && stylelint --fix strict 'src/**/*.{css,scss,sass,less,styl,vue,svelte}'",
"icons.html": "node theme_icons.js"
},
"devDependencies": {
"@eslint/js": "^9.19.0",
"copy-webpack-plugin": "^12.0.2",
"css-loader": "^7.1.2",
"edge.js": "^6.2.1",
"eslint": "^9.19.0",
"filemanager-webpack-plugin": "^8.0.0",
"globals": "^15.14.0",
"ionicons": "^7.4.0",
"leaflet": "^1.9.4",
"less": "^4.2.2",
"less-loader": "^12.2.0",
"normalize.css": "^8.0.1",
"sharp": "^0.33.5",
"style-loader": "^4.0.0",
"stylelint": "^16.14.1",
"stylelint-config-standard": "^37.0.0",
"stylelint-config-standard-less": "^3.0.1",
"stylelint-prettier": "^5.0.3",
"svgo": "^3.3.2",
"vite": "^6.0.7",
"vite-plugin-static-copy": "^2.2.0",
"vite-plugin-stylelint": "^6.0.0",
"webpack": "^5.97.1",
"webpack-cli": "^6.0.1"
},
"dependencies": {
"autocomplete-js": "^2.7.1"
}
}

View File

Before

(image error) Size: 3.0 KiB

After

(image error) Size: 3.0 KiB

View File

Before

(image error) Size: 1.7 KiB

After

(image error) Size: 1.7 KiB

View File

Before

(image error) Size: 10 KiB

After

(image error) Size: 10 KiB

View File

@ -0,0 +1 @@
import "./head/00_init.js";

View File

@ -0,0 +1,8 @@
import "./main/00_toolkit.js";
import "./main/infinite_scroll.js";
import "./main/keyboard.js";
import "./main/mapresult.js";
import "./main/preferences.js";
import "./main/results.js";
import "./main/search.js";
import "../../node_modules/autocomplete-js/dist/autocomplete.js";

View File

@ -1,4 +1,4 @@
@import "../generated/pygments.less";
@import "../../generated/pygments.less";
.codelines {
margin: @results-margin 0 0 0;

View File

@ -55,7 +55,7 @@
--color-autocomplete-background: #fff;
--color-autocomplete-background-hover: #e3e3e3;
/// Answer Colors
--color-answer-font: #444; // same as --color-base-font
--color-answer-font: #444; // same as --color-base-font
--color-answer-background: #fff;
/// Results Colors
--color-result-background: #fff;
@ -284,7 +284,7 @@
/// Device Size
/// @desktop > @tablet
@tablet: 79.75em; // see https://github.com/searxng/searxng/issues/874
@tablet: 79.75em; // see https://github.com/searxng/searxng/issues/874
@phone: 50em;
@small-phone: 35em;
@ultra-small-phone: 20rem;
@ -293,12 +293,12 @@
@stacked-bar-chart: rgb(0, 0, 0);
/// Load fonts from this directory.
@icon-font-path: "../../../fonts/";
@icon-font-path: "../../../fonts/";
//** File name for all font files.
@icon-font-name: "glyphicons-halflings-regular";
@icon-font-name: "glyphicons-halflings-regular";
//** Element ID within SVG icon file.
@icon-font-svg-id: "glyphicons_halflingsregular";
@icon-font-svg-id: "glyphicons_halflingsregular";
// decoration of the select HTML elements
@select-light-svg-path: "../svg/select-light.svg";
@select-dark-svg-path: "../svg/select-dark.svg";
@select-light-svg-path: "../svg/select-light.svg";
@select-dark-svg-path: "../svg/select-dark.svg";

View File

@ -203,7 +203,9 @@ article.result-images .detail {
}
}
#results.image-detail-open.scrolling article.result-images[data-vim-selected] .detail {
#results.image-detail-open.scrolling
article.result-images[data-vim-selected]
.detail {
top: 0;
a.result-images-source img {

View File

@ -1,14 +1,17 @@
iframe[src^="https://w.soundcloud.com"] {
iframe[src^="https://w.soundcloud.com"]
{
height: 120px;
}
iframe[src^="https://www.deezer.com"] {
iframe[src^="https://www.deezer.com"]
{
// The real size is 92px, but 94px are needed to avoid an inner scrollbar of
// the embedded HTML.
height: 94px;
}
iframe[src^="https://www.mixcloud.com"] {
iframe[src^="https://www.mixcloud.com"]
{
// the embedded player from mixcloud has some quirks: initial there is an
// issue with an image URL that is blocked since it is an a Cross-Origin
// request. The alternative text (<img alt='Mixcloud Logo'> then cause an
@ -18,16 +21,19 @@ iframe[src^="https://www.mixcloud.com"] {
height: 250px;
}
iframe[src^="https://bandcamp.com/EmbeddedPlayer"] {
iframe[src^="https://bandcamp.com/EmbeddedPlayer"]
{
// show playlist
height: 350px;
}
iframe[src^="https://bandcamp.com/EmbeddedPlayer/track"] {
iframe[src^="https://bandcamp.com/EmbeddedPlayer/track"]
{
// hide playlist
height: 120px;
}
iframe[src^="https://genius.com/songs"] {
iframe[src^="https://genius.com/songs"]
{
height: 65px;
}

View File

@ -6,7 +6,7 @@
text-align: center;
.title {
background: url('../img/searxng.png') no-repeat;
background: url("../img/searxng.png") no-repeat;
min-height: 4rem;
margin: 4rem auto;
background-position: center;

View File

@ -9,7 +9,7 @@
display: none;
}
input[type=checked] {
input[type="checked"] {
position: absolute;
}

View File

@ -83,7 +83,9 @@ button.category_button {
}
// only used when JavaScript is disabled
.no-js #categories_container:has(button.category_button:focus-within) button.category_button {
.no-js
#categories_container:has(button.category_button:focus-within)
button.category_button {
&.selected {
color: var(--color-base-font);
border-bottom: none;

View File

@ -63,9 +63,11 @@ on the /search URL and when the "center alignment" preference is enabled.
}
#search_header {
grid-template-columns: calc(50% - 4.5rem - var(--center-page-width) / 2) 3rem var(--center-page-width);
grid-template-columns:
calc(50% - 4.5rem - var(--center-page-width) / 2)
3rem var(--center-page-width);
grid-template-areas: "na logo search" "na spacer categories";
column-gap: 1.2rem; // from search.less
column-gap: 1.2rem; // from search.less
width: 100%;
padding-left: 0;
padding-right: 0;
@ -94,7 +96,9 @@ on the /search URL and when the "center alignment" preference is enabled.
&:not(.only_template_images, .image-detail-open) {
// the gap is set in style.less
.ltr-margin-left(1.5rem);
grid-template-columns: calc(var(--center-page-width) - @results-gap - @results-sidebar-width) @results-sidebar-width;
grid-template-columns:
calc(var(--center-page-width) - @results-gap - @results-sidebar-width)
@results-sidebar-width;
#backToTop {
.ltr-left(calc(50% - @results-sidebar-width - @results-gap + 1rem + var(--center-page-width) / 2));

View File

@ -109,7 +109,11 @@
}
// Image detail
#results.image-detail-open article.result-images[data-vim-selected] .detail .result-images-labels p {
#results.image-detail-open
article.result-images[data-vim-selected]
.detail
.result-images-labels
p {
direction: rtl;
&.result-url {
@ -125,7 +129,13 @@
}
// select HTML element
@supports ((background-position-x: 100%) and ((appearance: none) or (-webkit-appearance: none) or (-moz-appearance: none))) {
@supports (
(background-position-x: 100%) and
(
(appearance: none) or (-webkit-appearance: none) or
(-moz-appearance: none)
)
) {
select {
border-width: 0 0 0 2rem;
background-position-x: -2rem;

View File

@ -544,12 +544,11 @@ article[data-vim-selected].category-social {
.ltr-margin-left(@results-offset);
display: grid;
grid-template:
"corrections sidebar" min-content
"answers sidebar" min-content
"urls sidebar" 1fr
"pagination sidebar" min-content
/ @results-width @results-sidebar-width
;
"corrections sidebar" min-content
"answers sidebar" min-content
"urls sidebar" 1fr
"pagination sidebar" min-content
/ @results-width @results-sidebar-width;
gap: 0 @results-gap;
}
@ -782,7 +781,7 @@ summary.title {
padding: 0.4rem;
margin-left: 0.5rem;
border-radius: 0.3rem;
display: none; // will be shown by JS.
display: none; // will be shown by JS.
}
}
@ -979,8 +978,7 @@ summary.title {
"sidebar" min-content
"urls" 1fr
"pagination" min-content
/ @results-width
;
/ @results-width;
gap: 0;
}
}

View File

@ -249,7 +249,7 @@ ul.tabs {
order: 2;
}
& > input[type=radio] {
& > input[type="radio"] {
display: none;
}
@ -347,14 +347,21 @@ select {
}
}
@supports ((background-position-x: 100%) and ((appearance: none) or (-webkit-appearance: none) or (-moz-appearance: none))) {
@supports (
(background-position-x: 100%) and
(
(appearance: none) or (-webkit-appearance: none) or
(-moz-appearance: none)
)
) {
select {
appearance: none;
-webkit-appearance: none;
-moz-appearance: none;
border-width: 0 2rem 0 0;
border-color: transparent;
background: data-uri('image/svg+xml;charset=UTF-8', @select-light-svg-path) no-repeat;
background: data-uri("image/svg+xml;charset=UTF-8", @select-light-svg-path)
no-repeat;
background-position-x: calc(100% + 2rem);
background-size: 2rem;
background-origin: content-box;
@ -376,12 +383,18 @@ select {
@media (prefers-color-scheme: dark) {
html.theme-auto select,
html.theme-dark select {
background-image: data-uri('image/svg+xml;charset=UTF-8', @select-dark-svg-path);
background-image: data-uri(
"image/svg+xml;charset=UTF-8",
@select-dark-svg-path
);
}
}
html.theme-dark select {
background-image: data-uri('image/svg+xml;charset=UTF-8', @select-dark-svg-path);
background-image: data-uri(
"image/svg+xml;charset=UTF-8",
@select-dark-svg-path
);
}
}
@ -461,7 +474,7 @@ input.checkbox-onoff.reversed-checkbox[type="checkbox"] {
/* -- checkbox -- */
@supports (transform: rotate(-45deg)) {
input[type=checkbox]:not(.checkbox-onoff) {
input[type="checkbox"]:not(.checkbox-onoff) {
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
@ -476,7 +489,7 @@ input.checkbox-onoff.reversed-checkbox[type="checkbox"] {
.rounded-corners(0.3em);
&::after {
content: '';
content: "";
width: 9px;
height: 5px;
position: absolute;
@ -497,14 +510,18 @@ input.checkbox-onoff.reversed-checkbox[type="checkbox"] {
}
// disabled : can't be focused, show only the check mark
input[type=checkbox][disabled]:not(.checkbox-onoff) {
input[type="checkbox"][disabled]:not(.checkbox-onoff) {
border: inherit;
background-color: transparent !important;
cursor: inherit;
}
// if not checked and possible to checked then display a "light" check mark on hover
input.checkbox[type=checkbox]:not(:checked, [disabled], .checkbox-onoff):hover::after {
input.checkbox[type="checkbox"]:not(
:checked,
[disabled],
.checkbox-onoff
):hover::after {
opacity: 0.5;
}
}

Binary file not shown.

After

(image error) Size: 989 B

View File

Before

(image error) Size: 196 B

After

(image error) Size: 196 B

View File

Before

(image error) Size: 184 B

After

(image error) Size: 184 B

2
client/simple/static/.gitattributes vendored Normal file
View File

@ -0,0 +1,2 @@
leaflet.css -diff
leaflet.js -diff

View File

@ -0,0 +1,70 @@
/**
* Generate icons.html for the jinja templates of the simple theme.
*/
import { argv } from "node:process";
import { dirname, resolve } from "node:path";
import { jinja_svg_sets } from "./tools/jinja_svg_catalog.js";
const HERE = dirname(argv[1]) + "/";
const dest = resolve(HERE, "../../searx/templates/simple/icons.html");
/** @type import("./tools/jinja_svg_catalog.js").JinjaMacro[] */
const searxng_jinja_macros = [
{ name: "icon", class: "ion-icon" },
{ name: "icon_small", class: "ion-icon-small" },
{ name: "icon_big", class: "ion-icon-big" },
];
/** @type import("./tools/jinja_svg_catalog.js").IconSet */
const simple_icons = [
{
base: resolve(HERE, "node_modules/ionicons/dist/svg"),
set: {
"alert": "alert-outline.svg",
"appstore": "apps-outline.svg",
"book": "book-outline.svg",
"close": "close-outline.svg",
"download": "download-outline.svg",
"ellipsis-vertical": "ellipsis-vertical-outline.svg",
"file-tray-full": "file-tray-full-outline.svg",
"film": "film-outline.svg",
"globe": "globe-outline.svg",
"heart": "heart-outline.svg",
"image": "image-outline.svg",
"information-circle": "information-circle-outline.svg",
"layers": "layers-outline.svg",
"leecher": "arrow-down.svg",
"location": "location-outline.svg",
"magnet": "magnet-outline.svg",
"musical-notes": "musical-notes-outline.svg",
"navigate-down": "chevron-down-outline.svg",
"navigate-left": "chevron-back-outline.svg",
"navigate-right": "chevron-forward-outline.svg",
"navigate-up": "chevron-up-outline.svg",
"newspaper": "newspaper-outline.svg",
"people": "people-outline.svg",
"play": "play-outline.svg",
"radio": "radio-outline.svg",
"save": "save-outline.svg",
"school": "school-outline.svg",
"search": "search-outline.svg",
"seeder": "swap-vertical.svg",
"settings": "settings-outline.svg",
"tv": "tv-outline.svg",
},
svgo_opts: {
multipass: true,
plugins: [
{ name: "removeTitle" },
{ name: "removeXMLNS" },
{ name: "addAttributesToSVGElement",
params: {
attributes: [
{
"aria-hidden": "true",
}]}}]},
}
];
jinja_svg_sets(dest, searxng_jinja_macros, simple_icons);

View File

@ -0,0 +1,78 @@
import fs from "fs";
import path from "path";
import sharp from "sharp";
import { optimize as svgo } from "svgo";
/**
* @typedef {object} Src2Dest - Mapping of src to dest
* @property {string} src - Name of the source file.
* @property {string} dest - Name of the destination file.
*/
/**
* Convert a list of SVG files to PNG.
*
* @param {Src2Dest[]} items - Array of SVG files (src: SVG, dest:PNG) to convert.
*/
async function svg2png (items) {
items.forEach(
async (item) => {
try {
fs.mkdir(path.dirname(item.dest), { recursive: true }, (err) => {
if (err)
throw err;
});
const info = await sharp(item.src).png({
force: true,
compressionLevel: 9,
palette: true,
}).toFile(item.dest);
console.log(
`[svg2png] created ${item.dest} -- bytes: ${info.size}, w:${info.width}px, h:${info.height}px`
);
} catch (err) {
console.error(`ERROR: ${item.dest} -- ${err}`);
throw(err);
}
}
);
}
/**
* Optimize SVG images for WEB.
*
* @param {import('svgo').Config} svgo_opts - Options passed to svgo.
* @param {Src2Dest[]} items - Array of SVG files (src:SVG, dest:SVG) to optimize.
*/
async function svg2svg(svgo_opts, items) {
items.forEach(
async (item) => {
try {
fs.mkdir(path.dirname(item.dest), { recursive: true }, (err) => {
if (err)
throw err;
});
const raw = fs.readFileSync(item.src, "utf8");
const opt = svgo(raw, svgo_opts);
fs.writeFileSync(item.dest, opt.data);
console.log(
`[svg2svg] optimized: ${item.dest} -- src: ${item.src}`
);
} catch (err) {
console.error(`ERROR: optimize src: ${item.src} -- ${err}`);
throw(err);
}
}
);
}
export { svg2png, svg2svg };

View File

@ -0,0 +1,26 @@
{{--
This is a EDGE https://edgejs.dev/ template to generate a HTML Jinja template
for the backend. Example output of this EDGE template:
- https://github.com/searxng/searxng/blob/master/searx/templates/simple/icons.html
--}}
{#
Catalog of SVG symbols that can be inserted into the HTML output of a Jinja
template. This file from:
client/simple/tools/icon_catalog.edge.html
#}
{%-
set catalog = {
@each((svg, name) in svg_catalog)
'{{{name}}}' : '{{{svg}}}',
@end
}
-%}
@each(macro in macros)
{% macro {{ macro.name }}(action, alt) -%}
{{ open_curly_brace }} catalog[action] | replace("{{__jinja_class_placeholder__}}", "{{ macro.class }}") | safe {{ close_curly_brace }}
{%- endmacro %}
@end

View File

@ -0,0 +1,130 @@
import fs from "fs";
import { resolve, dirname } from "path";
import { Edge } from 'edge.js';
import { optimize as svgo } from "svgo";
import { fileURLToPath } from 'url';
const __dirname = dirname(fileURLToPath(import.meta.url));
const __jinja_class_placeholder__ = "__jinja_class_placeholder__";
// -- types
/**
* @typedef {object} IconSet - A set of icons
* @property {object[]} set - Array of SVG icons, where property name is the
* name of the icon and value is the src of the SVG (relative to base).
* @property {string} base - Folder in which the SVG src files are located.
* @property {import("svgo").Config} svgo_opts - svgo options for this set.
*/
/**
* @typedef {object} IconSVG - Mapping of icon name to SVG source file.
* @property {string} name - Name of the icon isource file.
* @property {string} src - Name of the destination file.
* @property {import("svgo").Config} svgo_opts - Options passed to svgo.
*/
/**
* @typedef {object} JinjaMacro - Arguments to create a jinja macro
* @property {string} name - Name of the jinja macro.
* @property {string} class - SVG's class name (value of XML class attribute)
*/
// -- functions
/**
* Generate a jinja template with a catalog of SVG icons that can be
* used in in other HTML jinja templates.
*
* @param {string} dest - filename of the generate jinja template.
* @param {JinjaMacro} macros - Jinja macros to create.
* @param {IconSVG[]} items - Array of SVG items.
*/
function jinja_svg_catalog(dest, macros, items) {
const svg_catalog = {};
const edge_template = resolve(__dirname, "jinja_svg_catalog.html.edge");
items.forEach(
(item) => {
/** @type {import("svgo").Config} */
const svgo_opts = JSON.parse(JSON.stringify(item.svgo_opts));
svgo_opts.plugins.push({
name: "addAttributesToSVGElement",
params: {
attributes: [{ "class": __jinja_class_placeholder__, }]
}}
);
try {
const raw = fs.readFileSync(item.src, "utf8");
const opt = svgo(raw, svgo_opts);
svg_catalog[item.name] = opt.data;
} catch (err) {
console.error(`ERROR: jinja_svg_catalog processing ${item.name} src: ${item.src} -- ${err}`);
throw(err);
}
}
);
fs.mkdir(dirname(dest), { recursive: true }, (err) => {
if (err) throw err;
});
const ctx = {
svg_catalog: svg_catalog,
macros: macros,
edge_template: edge_template,
__jinja_class_placeholder__: __jinja_class_placeholder__,
// see https://github.com/edge-js/edge/issues/162
open_curly_brace : "{{",
close_curly_brace : "}}"
};
const jinjatmpl = Edge.create().renderRawSync(
fs.readFileSync(edge_template, "utf-8"),
ctx
);
fs.writeFileSync(dest, jinjatmpl);
console.log(`[jinja_svg_catalog] created: ${dest}`);
}
/**
* Calls jinja_svg_catalog for a collection of icon sets where each set has its
* own parameters.
*
* @param {string} dest - filename of the generate jinja template.
* @param {JinjaMacro} macros - Jinja macros to create.
* @param {IconSet[]} sets - Array of SVG sets.
*/
function jinja_svg_sets(dest, macros, sets) {
/** @type IconSVG[] */
const items = [];
const all = [];
for (const obj of sets) {
for (const [name, file] of Object.entries(obj.set)) {
if (all.includes(name)) {
throw new Error(`ERROR: ${name} has already been defined`);
}
items.push({
name: name,
src: resolve(obj.base, file),
svgo_opts: obj.svgo_opts,
});
}
jinja_svg_catalog(dest, macros, items);
}
}
// -- exports
export {
jinja_svg_sets,
jinja_svg_catalog,
};

View File

@ -0,0 +1,41 @@
/**
* Custom vite plugins to build the web-client components of the simple theme.
*
* HINT:
*
* This is an inital implementation for the migration of the build process
* from grunt to vite. For fully support (vite: build & serve) more work is
* needed.
*/
import { svg2png } from "./img.js";
import { svg2svg } from "./img.js";
/**
* Vite plugin to convert a list of SVG files to PNG.
*
* @param {import('./img.js').Src2Dest} items - Array of SVG files (src: SVG, dest:PNG) to convert.
*/
function plg_svg2png(items) {
return {
name: 'searxng-simple-svg2png',
apply: 'build', // or 'serve'
async writeBundle() { svg2png(items); },
};
}
/**
* Vite plugin to optimize SVG images for WEB.
*
* @param {import('svgo').Config} svgo_opts - Options passed to svgo.
* @param {import('./img.js').Src2Dest} items - Array of SVG files (src:SVG, dest:SVG) to optimize.
*/
function plg_svg2svg(svgo_opts, items) {
return {
name: 'searxng-simple-svg2png',
apply: 'build', // or 'serve'
async writeBundle() { svg2svg(items, svgo_opts); },
};
}
export { plg_svg2png, plg_svg2svg };

View File

@ -0,0 +1,185 @@
/**
* CONFIG: https://vite.dev/config/
*/
import { resolve } from "node:path";
import { defineConfig } from "vite";
import stylelint from "vite-plugin-stylelint";
import { viteStaticCopy } from "vite-plugin-static-copy";
import { plg_svg2png } from "./tools/plg.js";
import { plg_svg2svg } from "./tools/plg.js";
const ROOT = "../.."; // root of the git reposetory
const PATH = {
dist: resolve(ROOT, "searx/static/themes/simple"),
// dist: resolve(ROOT, "client/simple/dist"),
src: "src",
modules: "node_modules",
brand: "src/brand",
static: resolve(ROOT, "client/simple/static"),
leaflet: resolve(ROOT, "client/simple/node_modules/leaflet/dist"),
templates: resolve(ROOT, "searx/templates/simple"),
};
const svg2svg_opts = {
plugins: [
{ name: "preset-default" },
"sortAttrs",
"convertStyleToAttrs",
]
};
const svg2svg_favicon_opts = {
plugins: [
{ name: "preset-default" },
"sortAttrs",
]
};
export default defineConfig({
root: PATH.src,
mode: "production",
// mode: "development",
// FIXME: missing CCS sourcemaps!!
// see: https://github.com/vitejs/vite/discussions/13845#discussioncomment-11992084
//
// what I have tried so far (see config below):
//
// - build.sourcemap
// - esbuild.sourcemap
// - css.preprocessorOptions.less.sourceMap
css: {
devSourcemap: true,
preprocessorOptions: {
less: {
// FIXME: missing CCS sourcemaps!!
sourceMap: {
outputSourceFiles: true,
sourceMapURL: (name) => { const s = name.split('/'); return s[s.length - 1] + '.map'; },
},
// env: 'development',
// relativeUrls: true,
// javascriptEnabled: true,
},
},
}, // end: css
esbuild : {
// FIXME: missing CCS sourcemaps!!
sourcemap: true
},
build: {
manifest: "manifest.json",
emptyOutDir: true,
assetsDir: "",
outDir: PATH.dist,
// FIXME: missing CCS sourcemaps!!
sourcemap: true,
// https://vite.dev/config/build-options.html#build-cssminify
cssMinify: true,
// cssMinify: "esbuild",
minify: "esbuild",
rollupOptions: {
input: {
// build CSS files
"css/searxng.min.css": PATH.src + "/less/style-ltr.less",
"css/searxng-rtl.min.css": PATH.src + "/less/style-rtl.less",
"css/rss.min.css": PATH.src + "/less/rss.less",
// build JS files
"js/searxng.head.min": PATH.src + "/js/searxng.head.js",
"js/searxng.min": PATH.src + "/js/searxng.js",
},
// file naming conventions / pathnames are relative to outDir (PATH.dist)
output: {
entryFileNames: "[name].js",
chunkFileNames: "[name].js",
assetFileNames: "[name].[ext]",
// Vite does not support "rollupOptions.output.sourcemap".
// Please use "build.sourcemap" instead.
// sourcemap: true,
},
},
}, // end: build
plugins: [
stylelint({
build: true,
emitWarningAsError: true,
fix: true,
}),
// Leaflet
viteStaticCopy({
targets: [
{ src: PATH.leaflet + "/leaflet.{js,js.map}", dest: PATH.dist + "/js" },
{ src: PATH.leaflet + "/images/*.png", dest: PATH.dist + "/css/images/" },
{ src: PATH.leaflet + "/*.{css,css.map}", dest: PATH.dist + "/css" },
{ src: PATH.static + "/**/*", dest: PATH.dist },
]
}),
// -- svg images
plg_svg2svg(
[
{ src: PATH.src + "/svg/empty_favicon.svg", dest: PATH.dist + "/img/empty_favicon.svg" },
{ src: PATH.src + "/svg/select-dark.svg", dest: PATH.dist + "/img/select-dark.svg" },
{ src: PATH.src + "/svg/select-light.svg", dest: PATH.dist + "/img/select-light.svg" },
],
svg2svg_opts,
),
// SearXNG brand (static)
plg_svg2png(
[
{ src: PATH.brand + "/searxng-wordmark.svg", dest: PATH.dist + "/img/favicon.png" },
{ src: PATH.brand + "/searxng.svg", dest: PATH.dist + "/img/searxng.png" },
],
),
// -- svg
plg_svg2svg(
[
{ src: PATH.brand + "/searxng.svg", dest: PATH.dist + "/img/searxng.svg" },
{ src: PATH.brand + "/img_load_error.svg", dest: PATH.dist + "/img/img_load_error.svg" },
],
svg2svg_opts,
),
// -- favicon
plg_svg2svg(
[ { src: PATH.brand + "/searxng-wordmark.svg", dest: PATH.dist + "/img/favicon.svg" } ],
svg2svg_favicon_opts,
),
// -- simple templates
plg_svg2svg(
[
{ src: PATH.brand + "/searxng-wordmark.svg", dest: PATH.templates + "/searxng-wordmark.min.svg" },
],
svg2svg_opts
),
] // end: plugins
});

View File

@ -44,7 +44,7 @@
``center_alignment`` : default ``false``
When enabled, the results are centered instead of being in the left (or RTL)
side of the screen. This setting only affects the *desktop layout*
(:origin:`min-width: @tablet <searx/static/themes/simple/src/less/definitions.less>`)
(:origin:`min-width: @tablet <client/simple/src/less/definitions.less>`)
.. cache_url:

View File

@ -197,7 +197,7 @@ html_sidebars = {
],
}
singlehtml_sidebars = {"index": ["project.html", "localtoc.html"]}
html_logo = "../src/brand/searxng-wordmark.svg"
html_logo = "../client/simple/src/brand/searxng-wordmark.svg"
html_title = "SearXNG Documentation ({})".format(VERSION_STRING)
html_show_sourcelink = True

View File

@ -180,10 +180,13 @@ sources of the theme need to be rebuild. You can do that by running::
$ make themes.all
Alternatively to ``themes.all`` you can run *live builds* of the theme you are
modify (:ref:`make themes`)::
..
ToDo: vite server is not implemented yet / will be done in a follow up PR
$ LIVE_THEME=simple make run
Alternatively to ``themes.all`` you can run *live builds* of the theme you are
modify (:ref:`make themes`)::
$ LIVE_THEME=simple make run
.. _make format.python:

16
manage
View File

@ -35,6 +35,9 @@ source "$(dirname "${BASH_SOURCE[0]}")/utils/lib_go.sh"
# shellcheck source=utils/lib_redis.sh
source "$(dirname "${BASH_SOURCE[0]}")/utils/lib_redis.sh"
# shellcheck source=utils/lib_sxng_vite.sh
source "$(dirname "${BASH_SOURCE[0]}")/utils/lib_sxng_vite.sh"
PATH="${REPO_ROOT}/node_modules/.bin:${PATH}"
# config
@ -102,6 +105,7 @@ EOF
test.help
themes.help
static.help
vite.help
cat <<EOF
environment ...
SEARXNG_REDIS_URL : ${SEARXNG_REDIS_URL}
@ -310,6 +314,18 @@ format.python() {
dump_return $?
}
docs.prebuild() {
build_msg DOCS "build ${DOCS_BUILD}/includes"
(
set -e
[ "$VERBOSE" = "1" ] && set -x
mkdir -p "${DOCS_BUILD}/includes"
./utils/searxng.sh searxng.doc.rst > "${DOCS_BUILD}/includes/searxng.rst"
pyenv.cmd searxng_extra/docs_prebuild
)
dump_return $?
}
# shellcheck disable=SC2119
main() {

View File

@ -384,7 +384,7 @@ def extract_response_info(result):
def response(resp):
'''Scrap *results* from the response (see :ref:`engine results`).'''
'''Scrap *results* from the response (see :ref:`result types`).'''
results = []
if no_result_for_http_status and resp.status_code in no_result_for_http_status:

View File

@ -1 +0,0 @@
/node_modules

View File

@ -1,8 +0,0 @@
{
"proto": true,
"globals": {
"browser": true,
"jQuery": false,
"devel": true
}
}

Binary file not shown.

Binary file not shown.

View File

@ -1,68 +0,0 @@
import globals from "globals";
import path from "node:path";
import { fileURLToPath } from "node:url";
import js from "@eslint/js";
import { FlatCompat } from "@eslint/eslintrc";
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const compat = new FlatCompat({
baseDirectory: __dirname,
recommendedConfig: js.configs.recommended,
allConfig: js.configs.all
});
export default [...compat.extends("eslint:recommended"), {
languageOptions: {
globals: {
...globals.browser,
...globals.node,
},
ecmaVersion: 12,
sourceType: "commonjs",
},
rules: {
indent: ["error", 2],
"keyword-spacing": ["error", {
before: true,
after: true,
}],
"no-trailing-spaces": 2,
"space-before-function-paren": ["error", "always"],
"space-infix-ops": "error",
"comma-spacing": ["error", {
before: false,
after: true,
}],
"brace-style": ["error", "1tbs", {
allowSingleLine: true,
}],
curly: ["error", "multi-line"],
"block-spacing": ["error", "always"],
"dot-location": ["error", "property"],
"key-spacing": ["error", {
beforeColon: false,
afterColon: true,
}],
"spaced-comment": ["error", "always", {
line: {
markers: ["*package", "!", "/", ",", "="],
},
block: {
balanced: true,
markers: ["*package", "!", ",", ":", "::", "flow-include"],
exceptions: ["*"],
},
}],
},
}];

View File

@ -1,313 +0,0 @@
/* SPDX-License-Identifier: AGPL-3.0-or-later */
module.exports = function (grunt) {
const eachAsync = require('each-async');
function file_exists (filepath) {
// filter function to exit grunt task with error if a (src) file not exists
if (!grunt.file.exists(filepath)) {
grunt.fail.fatal('Could not find: ' + filepath, 42);
} else {
return true;
}
}
grunt.initConfig({
_brand: '../../../../src/brand',
_templates: '../../../templates',
pkg: grunt.file.readJSON('package.json'),
watch: {
scripts: {
files: ['gruntfile.js', 'eslint.config.mjs', '.stylelintrc.json', 'src/**'],
tasks: [
'eslint',
'stylelint',
'copy',
'uglify',
'less',
'image',
'svg2png',
'svg2jinja'
]
}
},
eslint: {
options: {
overrideConfigFile: 'eslint.config.mjs',
failOnError: true,
fix: grunt.option('fix')
},
target: [
'gruntfile.js',
'svg4web.svgo.js',
'src/js/main/*.js',
'src/js/head/*.js',
],
},
stylelint: {
options: {
formatter: 'unix',
fix: grunt.option('fix')
},
src: [
'src/less/**/*.less',
]
},
copy: {
js: {
expand: true,
cwd: './node_modules',
dest: './js/',
flatten: true,
filter: 'isFile',
timestamp: true,
src: [
'./leaflet/dist/leaflet.js',
]
},
css: {
expand: true,
cwd: './node_modules',
dest: './css/',
flatten: true,
filter: 'isFile',
timestamp: true,
src: [
'./leaflet/dist/leaflet.css',
]
},
leaflet_images: {
expand: true,
cwd: './node_modules',
dest: './css/images/',
flatten: true,
filter: 'isFile',
timestamp: true,
src: [
'./leaflet/dist/images/*.png',
]
},
},
uglify: {
options: {
output: {
comments: 'some'
},
ie8: false,
warnings: true,
compress: false,
mangle: true,
sourceMap: {
includeSources: true
}
},
dist: {
files: {
'js/searxng.head.min.js': ['src/js/head/*.js'],
'js/searxng.min.js': [
'src/js/main/*.js',
'./node_modules/autocomplete-js/dist/autocomplete.js',
'./node_modules/swiped-events/src/swiped-events.js'
]
}
}
},
less: {
production: {
options: {
paths: ["less"],
sourceMap: true,
sourceMapURL: (name) => { const s = name.split('/'); return s[s.length - 1] + '.map'; },
outputSourceFiles: true,
},
files: [
{
src: ['src/less/style-ltr.less'],
dest: 'css/searxng.min.css',
nonull: true,
filter: file_exists,
},
{
src: ['src/less/style-rtl.less'],
dest: 'css/searxng-rtl.min.css',
nonull: true,
filter: file_exists,
},
{
src: ['src/less/rss.less'],
dest: 'css/rss.min.css',
nonull: true,
filter: file_exists,
},
],
},
},
image: {
svg4web: {
options: {
svgo: ['--config', 'svg4web.svgo.js']
},
files: {
'<%= _templates %>/simple/searxng-wordmark.min.svg': '<%= _brand %>/searxng-wordmark.svg',
'img/searxng.svg': '<%= _brand %>/searxng.svg',
'img/img_load_error.svg': '<%= _brand %>/img_load_error.svg'
}
},
favicon: {
options: {
svgo: ['--config', 'svg4favicon.svgo.js']
},
files: {
'img/favicon.svg': '<%= _brand %>/searxng-wordmark.svg'
}
},
},
svg2png: {
favicon: {
files: {
'img/favicon.png': '<%= _brand %>/searxng-wordmark.svg',
'img/searxng.png': '<%= _brand %>/searxng.svg',
}
}
},
svg2jinja: {
all: {
src: {
'warning': 'node_modules/ionicons/dist/svg/alert-outline.svg',
'close': 'node_modules/ionicons/dist/svg/close-outline.svg',
'chevron-up-outline': 'node_modules/ionicons/dist/svg/chevron-up-outline.svg',
'chevron-right': 'node_modules/ionicons/dist/svg/chevron-forward-outline.svg',
'chevron-left': 'node_modules/ionicons/dist/svg/chevron-back-outline.svg',
'menu-outline': 'node_modules/ionicons/dist/svg/settings-outline.svg',
'ellipsis-vertical-outline': 'node_modules/ionicons/dist/svg/ellipsis-vertical-outline.svg',
'magnet-outline': 'node_modules/ionicons/dist/svg/magnet-outline.svg',
'globe-outline': 'node_modules/ionicons/dist/svg/globe-outline.svg',
'search-outline': 'node_modules/ionicons/dist/svg/search-outline.svg',
'image-outline': 'node_modules/ionicons/dist/svg/image-outline.svg',
'play-outline': 'node_modules/ionicons/dist/svg/play-outline.svg',
'newspaper-outline': 'node_modules/ionicons/dist/svg/newspaper-outline.svg',
'location-outline': 'node_modules/ionicons/dist/svg/location-outline.svg',
'musical-notes-outline': 'node_modules/ionicons/dist/svg/musical-notes-outline.svg',
'layers-outline': 'node_modules/ionicons/dist/svg/layers-outline.svg',
'school-outline': 'node_modules/ionicons/dist/svg/school-outline.svg',
'file-tray-full-outline': 'node_modules/ionicons/dist/svg/file-tray-full-outline.svg',
'people-outline': 'node_modules/ionicons/dist/svg/people-outline.svg',
'heart-outline': 'node_modules/ionicons/dist/svg/heart-outline.svg',
'information-circle-outline': 'src/svg/information-circle-outline.svg',
},
dest: '../../../templates/simple/icons.html',
},
},
});
grunt.registerMultiTask('svg2jinja', 'Create Jinja2 macro', function () {
const ejs = require('ejs'), svgo = require('svgo');
const icons = {}
for (const iconName in this.data.src) {
const svgFileName = this.data.src[iconName];
try {
const svgContent = grunt.file.read(svgFileName, { encoding: 'utf8' })
const svgoResult = svgo.optimize(svgContent, {
path: svgFileName,
multipass: true,
plugins: [
{
name: "removeTitle",
},
{
name: "removeXMLNS",
},
{
name: "addAttributesToSVGElement",
params: {
attributes: [
{ "class": "ionicon", "aria-hidden": "true" }
]
}
}
]
});
icons[iconName] = svgoResult.data.replace("'", "\\'");
} catch (err) {
grunt.log.error(err);
}
}
const template = `{# this file was generated by searx/static/themes/simple/gruntfile.js #}
{%- set icons = {
<% for (const iconName in icons) { %> '<%- iconName %>':'<%- icons[iconName] %>',
<% } %>
}
-%}
{% macro icon(action, alt) -%}
{{ icons[action] | replace("ionicon", "ion-icon") | safe }}
{%- endmacro %}
{% macro icon_small(action) -%}
{{ icons[action] | replace("ionicon", "ion-icon-small") | safe }}
{%- endmacro %}
{% macro icon_big(action, alt) -%}
{{ icons[action] | replace("ionicon", "ion-icon-big") | safe }}
{%- endmacro %}
`;
const result = ejs.render(template, { icons });
grunt.file.write(this.data.dest, result, { encoding: 'utf8' });
grunt.log.ok(this.data.dest + " created");
});
grunt.registerMultiTask('svg2png', 'Convert SVG to PNG', function () {
const sharp = require('sharp'), done = this.async();
eachAsync(this.files, async (file, _index, next) => {
try {
if (file.src.length != 1) {
next("this task supports only one source per destination");
}
const info = await sharp(file.src[0])
.png({
force: true,
compressionLevel: 9,
palette: true,
})
.toFile(file.dest);
grunt.log.ok(file.dest + ' created (' + info.size + ' bytes, ' + info.width + 'px * ' + info.height + 'px)');
next();
} catch (error) {
grunt.fatal(error);
next(error);
}
}, error => {
if (error) {
grunt.fatal(error);
done(error);
} else {
done();
}
});
});
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.loadNpmTasks('grunt-contrib-copy');
grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.loadNpmTasks('grunt-image');
grunt.loadNpmTasks('grunt-contrib-less');
grunt.loadNpmTasks('grunt-contrib-cssmin');
grunt.loadNpmTasks('grunt-stylelint');
grunt.loadNpmTasks('grunt-eslint');
grunt.registerTask('test', ['eslint', 'stylelint']);
grunt.registerTask('default', [
'eslint',
'stylelint',
'copy',
'uglify',
'less',
'image',
'svg2png',
'svg2jinja',
]);
};

Binary file not shown.

Before

(image error) Size: 989 B

After

(image error) Size: 966 B

Binary file not shown.

After

(image error) Size: 120 B

Binary file not shown.

After

(image error) Size: 108 B

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,29 @@
{
"src/js/searxng.head.js": {
"file": "js/searxng.head.min.js",
"name": "js/searxng.head.min",
"src": "src/js/searxng.head.js",
"isEntry": true
},
"src/js/searxng.js": {
"file": "js/searxng.min.js",
"name": "js/searxng.min",
"src": "src/js/searxng.js",
"isEntry": true
},
"src/less/rss.less": {
"file": "css/rss.min.css",
"src": "src/less/rss.less",
"isEntry": true
},
"src/less/style-ltr.less": {
"file": "css/searxng.min.css",
"src": "src/less/style-ltr.less",
"isEntry": true
},
"src/less/style-rtl.less": {
"file": "css/searxng-rtl.min.css",
"src": "src/less/style-rtl.less",
"isEntry": true
}
}

File diff suppressed because it is too large Load Diff

View File

@ -1,41 +0,0 @@
{
"devDependencies": {
"ejs": "^3.1.10",
"eslint": "^9.18.0",
"grunt": "^1.6.1",
"grunt-contrib-copy": "^1.0.0",
"grunt-contrib-cssmin": "^5.0.0",
"grunt-contrib-less": "^3.0.0",
"grunt-contrib-uglify": "^5.2.2",
"grunt-contrib-watch": "^1.1.0",
"grunt-eslint": "^25.0.0",
"grunt-image": "^6.4.0",
"grunt-stylelint": "^0.20.1",
"grunt-xmlmin": "^0.1.8",
"ionicons": "^7.4.0",
"less": "^4.2.2",
"sharp": "^0.33.5",
"stylelint": "^16.12.0",
"stylelint-config-standard": "^37.0.0",
"stylelint-config-standard-less": "^3.0.1",
"svgo": "^3.3.2"
},
"dependencies": {
"autocomplete-js": "^2.7.1",
"leaflet": "^1.9.4",
"normalize.css": "^8.0.1",
"swiped-events": "^1.2.0"
},
"scripts": {
"all": "npm install && grunt",
"build": "grunt",
"clean": "rm -Rf node_modules",
"eslint": "grunt eslint",
"eslint-fix": "grunt eslint --fix",
"fix": "grunt test --fix",
"stylelint": "grunt stylelint",
"stylelint-fix": "grunt stylelint --fix",
"test": "grunt test",
"watch": "grunt watch --fix"
}
}

Binary file not shown.

Before

(image error) Size: 679 B

View File

@ -1,16 +0,0 @@
/**
* @license
* SPDX-License-Identifier: AGPL-3.0-or-later
*
* svgo config: Optimize SVG for WEB usage
*/
module.exports = {
plugins: [
{
name: 'preset-default',
},
// make diff friendly
'sortAttrs',
],
};

View File

@ -1,18 +0,0 @@
/**
* @license
* SPDX-License-Identifier: AGPL-3.0-or-later
*
* svgo config: Optimize SVG for WEB usage
*/
module.exports = {
plugins: [
{
name: 'preset-default',
},
// make diff friendly
'sortAttrs',
// Optimize SVG for WEB usage
'convertStyleToAttrs',
],
};

View File

@ -46,15 +46,15 @@
<nav id="links_on_top">
{%- from 'simple/icons.html' import icon_big -%}
{%- block linkto_about -%}
<a href="{{ url_for('info', pagename='about') }}" class="link_on_top_about">{{ icon_big('information-circle-outline') }}<span>{{ _('About') }}</span></a>
<a href="{{ url_for('info', pagename='about') }}" class="link_on_top_about">{{ icon_big('information-circle') }}<span>{{ _('About') }}</span></a>
{%- endblock -%}
{%- block linkto_donate -%}
{%- if donation_url -%}
<a href="{{ donation_url }}" class="link_on_top_donate">{{ icon_big('heart-outline') }}<span>{{ _('Donate') }}</span></a>
<a href="{{ donation_url }}" class="link_on_top_donate">{{ icon_big('heart') }}<span>{{ _('Donate') }}</span></a>
{%- endif -%}
{%- endblock -%}
{%- block linkto_preferences -%}
<a href="{{ url_for('preferences') }}" class="link_on_top_preferences">{{ icon_big('menu-outline') }}<span>{{ _('Preferences') }}</span></a>
<a href="{{ url_for('preferences') }}" class="link_on_top_preferences">{{ icon_big('settings') }}<span>{{ _('Preferences') }}</span></a>
{%- endblock -%}
</nav>
{% block header %}

View File

@ -1,15 +1,19 @@
{% from 'simple/icons.html' import icon_big %}
{%- set category_icons = {
'general': 'search-outline',
'images': 'image-outline',
'videos': 'play-outline',
'news': 'newspaper-outline',
'map': 'location-outline',
'music': 'musical-notes-outline',
'it': 'layers-outline',
'science': 'school-outline',
'files': 'file-tray-full-outline',
'social media': 'people-outline',
'apps': 'appstore',
'dictionaries': 'book',
'files': 'file-tray-full',
'general': 'search',
'images': 'image',
'it': 'layers',
'map': 'location',
'music': 'musical-notes',
'news': 'newspaper',
'radio': 'radio',
'science': 'school',
'social media': 'people',
'TV': 'tv',
'videos': 'play',
} -%}
<div id="categories" class="search_categories">{{- '' -}}
<div id="categories_container">
@ -18,7 +22,7 @@
<div class="category category_checkbox">{{- '' -}}
<input type="checkbox" id="checkbox_{{ category|replace(' ', '_') }}" name="category_{{ category }}"{% if category in selected_categories %} checked="checked"{% endif %}>
<label for="checkbox_{{ category|replace(' ', '_') }}" class="tooltips">
{{- icon_big(category_icons[category]) if category in category_icons else icon_big('globe-outline') -}}
{{- icon_big(category_icons[category]) if category in category_icons else icon_big('globe') -}}
<div class="category_name">{{- _(category) -}}</div>
</label>
</div>
@ -27,7 +31,7 @@
{%- else -%}
{%- for category in categories -%}{{- '\n' -}}
<button type="submit" name="category_{{ category }}" class="category category_button {% if category in selected_categories %}selected{% endif %}">
{{- icon_big(category_icons[category]) if category in category_icons else icon_big('globe-outline') -}}
{{- icon_big(category_icons[category]) if category in category_icons else icon_big('globe') -}}
<div class="category_name">{{- _(category) -}}</div>{{- '' -}}
</button>{{- '' -}}
{%- endfor -%}

View File

@ -1,38 +1,55 @@
{# this file was generated by searx/static/themes/simple/gruntfile.js #}
{%- set icons = {
'warning':'<svg viewBox="0 0 512 512" class="ionicon" aria-hidden="true"><path d="M256 80c-8.66 0-16.58 7.36-16 16l8 216a8 8 0 008 8h0a8 8 0 008-8l8-216c.58-8.64-7.34-16-16-16z" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="32"/><circle cx="256" cy="416" r="16" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="32"/></svg>',
'close':'<svg viewBox="0 0 512 512" class="ionicon" aria-hidden="true"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="32" d="M368 368L144 144M368 144L144 368"/></svg>',
'chevron-up-outline':'<svg viewBox="0 0 512 512" class="ionicon" aria-hidden="true"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="48" d="M112 328l144-144 144 144"/></svg>',
'chevron-right':'<svg viewBox="0 0 512 512" class="ionicon" aria-hidden="true"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="48" d="M184 112l144 144-144 144"/></svg>',
'chevron-left':'<svg viewBox="0 0 512 512" class="ionicon" aria-hidden="true"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="48" d="M328 112L184 256l144 144"/></svg>',
'menu-outline':'<svg viewBox="0 0 512 512" class="ionicon" aria-hidden="true"><path d="M262.29 192.31a64 64 0 1057.4 57.4 64.13 64.13 0 00-57.4-57.4zM416.39 256a154.34 154.34 0 01-1.53 20.79l45.21 35.46a10.81 10.81 0 012.45 13.75l-42.77 74a10.81 10.81 0 01-13.14 4.59l-44.9-18.08a16.11 16.11 0 00-15.17 1.75A164.48 164.48 0 01325 400.8a15.94 15.94 0 00-8.82 12.14l-6.73 47.89a11.08 11.08 0 01-10.68 9.17h-85.54a11.11 11.11 0 01-10.69-8.87l-6.72-47.82a16.07 16.07 0 00-9-12.22 155.3 155.3 0 01-21.46-12.57 16 16 0 00-15.11-1.71l-44.89 18.07a10.81 10.81 0 01-13.14-4.58l-42.77-74a10.8 10.8 0 012.45-13.75l38.21-30a16.05 16.05 0 006-14.08c-.36-4.17-.58-8.33-.58-12.5s.21-8.27.58-12.35a16 16 0 00-6.07-13.94l-38.19-30A10.81 10.81 0 0149.48 186l42.77-74a10.81 10.81 0 0113.14-4.59l44.9 18.08a16.11 16.11 0 0015.17-1.75A164.48 164.48 0 01187 111.2a15.94 15.94 0 008.82-12.14l6.73-47.89A11.08 11.08 0 01213.23 42h85.54a11.11 11.11 0 0110.69 8.87l6.72 47.82a16.07 16.07 0 009 12.22 155.3 155.3 0 0121.46 12.57 16 16 0 0015.11 1.71l44.89-18.07a10.81 10.81 0 0113.14 4.58l42.77 74a10.8 10.8 0 01-2.45 13.75l-38.21 30a16.05 16.05 0 00-6.05 14.08c.33 4.14.55 8.3.55 12.47z" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="32"/></svg>',
'ellipsis-vertical-outline':'<svg viewBox="0 0 512 512" class="ionicon" aria-hidden="true"><circle cx="256" cy="256" r="32" fill="none" stroke="currentColor" stroke-miterlimit="10" stroke-width="32"/><circle cx="256" cy="416" r="32" fill="none" stroke="currentColor" stroke-miterlimit="10" stroke-width="32"/><circle cx="256" cy="96" r="32" fill="none" stroke="currentColor" stroke-miterlimit="10" stroke-width="32"/></svg>',
'magnet-outline':'<svg viewBox="0 0 512 512" class="ionicon" aria-hidden="true"><path d="M421.83 293.82A144 144 0 00218.18 90.17M353.94 225.94a48 48 0 00-67.88-67.88" fill="none" stroke="currentColor" stroke-miterlimit="10" stroke-width="32"/><path stroke="currentColor" stroke-linecap="round" stroke-miterlimit="10" stroke-width="32" d="M192 464v-48M90.18 421.82l33.94-33.94M48 320h48"/><path d="M286.06 158.06L172.92 271.19a32 32 0 01-45.25 0L105 248.57a32 32 0 010-45.26L218.18 90.17M421.83 293.82L308.69 407a32 32 0 01-45.26 0l-22.62-22.63a32 32 0 010-45.26l113.13-113.17M139.6 169.98l67.88 67.89M275.36 305.75l67.89 67.88" fill="none" stroke="currentColor" stroke-linejoin="round" stroke-width="32"/></svg>',
'globe-outline':'<svg viewBox="0 0 512 512" class="ionicon" aria-hidden="true"><path d="M256 48C141.13 48 48 141.13 48 256s93.13 208 208 208 208-93.13 208-208S370.87 48 256 48z" fill="none" stroke="currentColor" stroke-miterlimit="10" stroke-width="32"/><path d="M256 48c-58.07 0-112.67 93.13-112.67 208S197.93 464 256 464s112.67-93.13 112.67-208S314.07 48 256 48z" fill="none" stroke="currentColor" stroke-miterlimit="10" stroke-width="32"/><path d="M117.33 117.33c38.24 27.15 86.38 43.34 138.67 43.34s100.43-16.19 138.67-43.34M394.67 394.67c-38.24-27.15-86.38-43.34-138.67-43.34s-100.43 16.19-138.67 43.34" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="32"/><path fill="none" stroke="currentColor" stroke-miterlimit="10" stroke-width="32" d="M256 48v416M464 256H48"/></svg>',
'search-outline':'<svg viewBox="0 0 512 512" class="ionicon" aria-hidden="true"><path d="M221.09 64a157.09 157.09 0 10157.09 157.09A157.1 157.1 0 00221.09 64z" fill="none" stroke="currentColor" stroke-miterlimit="10" stroke-width="32"/><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-miterlimit="10" stroke-width="32" d="M338.29 338.29L448 448"/></svg>',
'image-outline':'<svg viewBox="0 0 512 512" class="ionicon" aria-hidden="true"><rect x="48" y="80" width="416" height="352" rx="48" ry="48" fill="none" stroke="currentColor" stroke-linejoin="round" stroke-width="32"/><circle cx="336" cy="176" r="32" fill="none" stroke="currentColor" stroke-miterlimit="10" stroke-width="32"/><path d="M304 335.79l-90.66-90.49a32 32 0 00-43.87-1.3L48 352M224 432l123.34-123.34a32 32 0 0143.11-2L464 368" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="32"/></svg>',
'play-outline':'<svg viewBox="0 0 512 512" class="ionicon" aria-hidden="true"><path d="M112 111v290c0 17.44 17 28.52 31 20.16l247.9-148.37c12.12-7.25 12.12-26.33 0-33.58L143 90.84c-14-8.36-31 2.72-31 20.16z" fill="none" stroke="currentColor" stroke-miterlimit="10" stroke-width="32"/></svg>',
'newspaper-outline':'<svg viewBox="0 0 512 512" class="ionicon" aria-hidden="true"><path d="M368 415.86V72a24.07 24.07 0 00-24-24H72a24.07 24.07 0 00-24 24v352a40.12 40.12 0 0040 40h328" fill="none" stroke="currentColor" stroke-linejoin="round" stroke-width="32"/><path d="M416 464h0a48 48 0 01-48-48V128h72a24 24 0 0124 24v264a48 48 0 01-48 48z" fill="none" stroke="currentColor" stroke-linejoin="round" stroke-width="32"/><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="32" d="M240 128h64M240 192h64M112 256h192M112 320h192M112 384h192"/><path d="M176 208h-64a16 16 0 01-16-16v-64a16 16 0 0116-16h64a16 16 0 0116 16v64a16 16 0 01-16 16z"/></svg>',
'location-outline':'<svg viewBox="0 0 512 512" class="ionicon" aria-hidden="true"><path d="M256 48c-79.5 0-144 61.39-144 137 0 87 96 224.87 131.25 272.49a15.77 15.77 0 0025.5 0C304 409.89 400 272.07 400 185c0-75.61-64.5-137-144-137z" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="32"/><circle cx="256" cy="192" r="48" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="32"/></svg>',
'musical-notes-outline':'<svg viewBox="0 0 512 512" class="ionicon" aria-hidden="true"><path d="M192 218v-6c0-14.84 10-27 24.24-30.59l174.59-46.68A20 20 0 01416 154v22" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="32"/><path d="M416 295.94v80c0 13.91-8.93 25.59-22 30l-22 8c-25.9 8.72-52-10.42-52-38h0a33.37 33.37 0 0123-32l51-18.15c13.07-4.4 22-15.94 22-29.85V58a10 10 0 00-12.6-9.61L204 102a16.48 16.48 0 00-12 16v226c0 13.91-8.93 25.6-22 30l-52 18c-13.88 4.68-22 17.22-22 32h0c0 27.58 26.52 46.55 52 38l22-8c13.07-4.4 22-16.08 22-30v-80" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="32"/></svg>',
'layers-outline':'<svg viewBox="0 0 512 512" class="ionicon" aria-hidden="true"><path d="M434.8 137.65l-149.36-68.1c-16.19-7.4-42.69-7.4-58.88 0L77.3 137.65c-17.6 8-17.6 21.09 0 29.09l148 67.5c16.89 7.7 44.69 7.7 61.58 0l148-67.5c17.52-8 17.52-21.1-.08-29.09zM160 308.52l-82.7 37.11c-17.6 8-17.6 21.1 0 29.1l148 67.5c16.89 7.69 44.69 7.69 61.58 0l148-67.5c17.6-8 17.6-21.1 0-29.1l-79.94-38.47" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="32"/><path d="M160 204.48l-82.8 37.16c-17.6 8-17.6 21.1 0 29.1l148 67.49c16.89 7.7 44.69 7.7 61.58 0l148-67.49c17.7-8 17.7-21.1.1-29.1L352 204.48" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="32"/></svg>',
'school-outline':'<svg viewBox="0 0 512 512" class="ionicon" aria-hidden="true"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="32" d="M32 192L256 64l224 128-224 128L32 192z"/><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="32" d="M112 240v128l144 80 144-80V240M480 368V192M256 320v128"/></svg>',
'file-tray-full-outline':'<svg viewBox="0 0 512 512" class="ionicon" aria-hidden="true"><path d="M384 80H128c-26 0-43 14-48 40L48 272v112a48.14 48.14 0 0048 48h320a48.14 48.14 0 0048-48V272l-32-152c-5-27-23-40-48-40z" fill="none" stroke="currentColor" stroke-linejoin="round" stroke-width="32"/><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="32" d="M48 272h144M320 272h144M192 272a64 64 0 00128 0M144 144h224M128 208h256"/></svg>',
'people-outline':'<svg viewBox="0 0 512 512" class="ionicon" aria-hidden="true"><path d="M402 168c-2.93 40.67-33.1 72-66 72s-63.12-31.32-66-72c-3-42.31 26.37-72 66-72s69 30.46 66 72z" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="32"/><path d="M336 304c-65.17 0-127.84 32.37-143.54 95.41-2.08 8.34 3.15 16.59 11.72 16.59h263.65c8.57 0 13.77-8.25 11.72-16.59C463.85 335.36 401.18 304 336 304z" fill="none" stroke="currentColor" stroke-miterlimit="10" stroke-width="32"/><path d="M200 185.94c-2.34 32.48-26.72 58.06-53 58.06s-50.7-25.57-53-58.06C91.61 152.15 115.34 128 147 128s55.39 24.77 53 57.94z" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="32"/><path d="M206 306c-18.05-8.27-37.93-11.45-59-11.45-52 0-102.1 25.85-114.65 76.2-1.65 6.66 2.53 13.25 9.37 13.25H154" fill="none" stroke="currentColor" stroke-linecap="round" stroke-miterlimit="10" stroke-width="32"/></svg>',
'heart-outline':'<svg viewBox="0 0 512 512" class="ionicon" aria-hidden="true"><path d="M352.92 80C288 80 256 144 256 144s-32-64-96.92-64c-52.76 0-94.54 44.14-95.08 96.81-1.1 109.33 86.73 187.08 183 252.42a16 16 0 0018 0c96.26-65.34 184.09-143.09 183-252.42-.54-52.67-42.32-96.81-95.08-96.81z" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="32"/></svg>',
'information-circle-outline':'<svg class="ionicon" viewBox="0 0 512 512" aria-hidden="true"><path d="M248 64C146.39 64 64 146.39 64 248s82.39 184 184 184 184-82.39 184-184S349.61 64 248 64z" fill="none" stroke="currentColor" stroke-miterlimit="10" stroke-width="32"/><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="32" d="M220 220h32v116"/><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-miterlimit="10" stroke-width="32" d="M208 340h88"/><path fill="currentColor" stroke="currentColor" stroke-linecap="round" d="M248 130a26 26 0 1026 26 26 26 0 00-26-26z"/></svg>',
{#
Catalog of SVG symbols that can be inserted into the HTML output of a Jinja
template. This file from:
client/simple/tools/icon_catalog.edge.html
#}
{%-
set catalog = {
'alert' : '<svg viewBox="0 0 512 512" aria-hidden="true" class="__jinja_class_placeholder__"><path d="M256 80c-8.66 0-16.58 7.36-16 16l8 216a8 8 0 008 8h0a8 8 0 008-8l8-216c.58-8.64-7.34-16-16-16z" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="32"/><circle cx="256" cy="416" r="16" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="32"/></svg>',
'appstore' : '<svg viewBox="0 0 512 512" aria-hidden="true" class="__jinja_class_placeholder__"><rect x="64" y="64" width="80" height="80" rx="40" ry="40" fill="none" stroke="currentColor" stroke-miterlimit="10" stroke-width="32"/><rect x="216" y="64" width="80" height="80" rx="40" ry="40" fill="none" stroke="currentColor" stroke-miterlimit="10" stroke-width="32"/><rect x="368" y="64" width="80" height="80" rx="40" ry="40" fill="none" stroke="currentColor" stroke-miterlimit="10" stroke-width="32"/><rect x="64" y="216" width="80" height="80" rx="40" ry="40" fill="none" stroke="currentColor" stroke-miterlimit="10" stroke-width="32"/><rect x="216" y="216" width="80" height="80" rx="40" ry="40" fill="none" stroke="currentColor" stroke-miterlimit="10" stroke-width="32"/><rect x="368" y="216" width="80" height="80" rx="40" ry="40" fill="none" stroke="currentColor" stroke-miterlimit="10" stroke-width="32"/><rect x="64" y="368" width="80" height="80" rx="40" ry="40" fill="none" stroke="currentColor" stroke-miterlimit="10" stroke-width="32"/><rect x="216" y="368" width="80" height="80" rx="40" ry="40" fill="none" stroke="currentColor" stroke-miterlimit="10" stroke-width="32"/><rect x="368" y="368" width="80" height="80" rx="40" ry="40" fill="none" stroke="currentColor" stroke-miterlimit="10" stroke-width="32"/></svg>',
'book' : '<svg viewBox="0 0 512 512" aria-hidden="true" class="__jinja_class_placeholder__"><path d="M256 160c16-63.16 76.43-95.41 208-96a15.94 15.94 0 0116 16v288a16 16 0 01-16 16c-128 0-177.45 25.81-208 64-30.37-38-80-64-208-64-9.88 0-16-8.05-16-17.93V80a15.94 15.94 0 0116-16c131.57.59 192 32.84 208 96zM256 160v288" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="32"/></svg>',
'close' : '<svg viewBox="0 0 512 512" aria-hidden="true" class="__jinja_class_placeholder__"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="32" d="M368 368L144 144M368 144L144 368"/></svg>',
'download' : '<svg viewBox="0 0 512 512" aria-hidden="true" class="__jinja_class_placeholder__"><path d="M336 176h40a40 40 0 0140 40v208a40 40 0 01-40 40H136a40 40 0 01-40-40V216a40 40 0 0140-40h40" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="32"/><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="32" d="M176 272l80 80 80-80M256 48v288"/></svg>',
'ellipsis-vertical' : '<svg viewBox="0 0 512 512" aria-hidden="true" class="__jinja_class_placeholder__"><circle cx="256" cy="256" r="32" fill="none" stroke="currentColor" stroke-miterlimit="10" stroke-width="32"/><circle cx="256" cy="416" r="32" fill="none" stroke="currentColor" stroke-miterlimit="10" stroke-width="32"/><circle cx="256" cy="96" r="32" fill="none" stroke="currentColor" stroke-miterlimit="10" stroke-width="32"/></svg>',
'file-tray-full' : '<svg viewBox="0 0 512 512" aria-hidden="true" class="__jinja_class_placeholder__"><path d="M384 80H128c-26 0-43 14-48 40L48 272v112a48.14 48.14 0 0048 48h320a48.14 48.14 0 0048-48V272l-32-152c-5-27-23-40-48-40z" fill="none" stroke="currentColor" stroke-linejoin="round" stroke-width="32"/><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="32" d="M48 272h144M320 272h144M192 272a64 64 0 00128 0M144 144h224M128 208h256"/></svg>',
'film' : '<svg viewBox="0 0 512 512" aria-hidden="true" class="__jinja_class_placeholder__"><rect x="48" y="96" width="416" height="320" rx="28" ry="28" fill="none" stroke="currentColor" stroke-linejoin="round" stroke-width="32"/><rect x="384" y="336" width="80" height="80" rx="28" ry="28" fill="none" stroke="currentColor" stroke-linejoin="round" stroke-width="32"/><rect x="384" y="256" width="80" height="80" rx="28" ry="28" fill="none" stroke="currentColor" stroke-linejoin="round" stroke-width="32"/><rect x="384" y="176" width="80" height="80" rx="28" ry="28" fill="none" stroke="currentColor" stroke-linejoin="round" stroke-width="32"/><rect x="384" y="96" width="80" height="80" rx="28" ry="28" fill="none" stroke="currentColor" stroke-linejoin="round" stroke-width="32"/><rect x="48" y="336" width="80" height="80" rx="28" ry="28" fill="none" stroke="currentColor" stroke-linejoin="round" stroke-width="32"/><rect x="48" y="256" width="80" height="80" rx="28" ry="28" fill="none" stroke="currentColor" stroke-linejoin="round" stroke-width="32"/><rect x="48" y="176" width="80" height="80" rx="28" ry="28" fill="none" stroke="currentColor" stroke-linejoin="round" stroke-width="32"/><rect x="48" y="96" width="80" height="80" rx="28" ry="28" fill="none" stroke="currentColor" stroke-linejoin="round" stroke-width="32"/><rect x="128" y="96" width="256" height="160" rx="28" ry="28" fill="none" stroke="currentColor" stroke-linejoin="round" stroke-width="32"/><rect x="128" y="256" width="256" height="160" rx="28" ry="28" fill="none" stroke="currentColor" stroke-linejoin="round" stroke-width="32"/></svg>',
'globe' : '<svg viewBox="0 0 512 512" aria-hidden="true" class="__jinja_class_placeholder__"><path d="M256 48C141.13 48 48 141.13 48 256s93.13 208 208 208 208-93.13 208-208S370.87 48 256 48z" fill="none" stroke="currentColor" stroke-miterlimit="10" stroke-width="32"/><path d="M256 48c-58.07 0-112.67 93.13-112.67 208S197.93 464 256 464s112.67-93.13 112.67-208S314.07 48 256 48z" fill="none" stroke="currentColor" stroke-miterlimit="10" stroke-width="32"/><path d="M117.33 117.33c38.24 27.15 86.38 43.34 138.67 43.34s100.43-16.19 138.67-43.34M394.67 394.67c-38.24-27.15-86.38-43.34-138.67-43.34s-100.43 16.19-138.67 43.34" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="32"/><path fill="none" stroke="currentColor" stroke-miterlimit="10" stroke-width="32" d="M256 48v416M464 256H48"/></svg>',
'heart' : '<svg viewBox="0 0 512 512" aria-hidden="true" class="__jinja_class_placeholder__"><path d="M352.92 80C288 80 256 144 256 144s-32-64-96.92-64c-52.76 0-94.54 44.14-95.08 96.81-1.1 109.33 86.73 187.08 183 252.42a16 16 0 0018 0c96.26-65.34 184.09-143.09 183-252.42-.54-52.67-42.32-96.81-95.08-96.81z" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="32"/></svg>',
'image' : '<svg viewBox="0 0 512 512" aria-hidden="true" class="__jinja_class_placeholder__"><rect x="48" y="80" width="416" height="352" rx="48" ry="48" fill="none" stroke="currentColor" stroke-linejoin="round" stroke-width="32"/><circle cx="336" cy="176" r="32" fill="none" stroke="currentColor" stroke-miterlimit="10" stroke-width="32"/><path d="M304 335.79l-90.66-90.49a32 32 0 00-43.87-1.3L48 352M224 432l123.34-123.34a32 32 0 0143.11-2L464 368" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="32"/></svg>',
'information-circle' : '<svg viewBox="0 0 512 512" aria-hidden="true" class="__jinja_class_placeholder__"><path d="M248 64C146.39 64 64 146.39 64 248s82.39 184 184 184 184-82.39 184-184S349.61 64 248 64z" fill="none" stroke="currentColor" stroke-miterlimit="10" stroke-width="32"/><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="32" d="M220 220h32v116"/><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-miterlimit="10" stroke-width="32" d="M208 340h88"/><path d="M248 130a26 26 0 1026 26 26 26 0 00-26-26z"/></svg>',
'layers' : '<svg viewBox="0 0 512 512" aria-hidden="true" class="__jinja_class_placeholder__"><path d="M434.8 137.65l-149.36-68.1c-16.19-7.4-42.69-7.4-58.88 0L77.3 137.65c-17.6 8-17.6 21.09 0 29.09l148 67.5c16.89 7.7 44.69 7.7 61.58 0l148-67.5c17.52-8 17.52-21.1-.08-29.09zM160 308.52l-82.7 37.11c-17.6 8-17.6 21.1 0 29.1l148 67.5c16.89 7.69 44.69 7.69 61.58 0l148-67.5c17.6-8 17.6-21.1 0-29.1l-79.94-38.47" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="32"/><path d="M160 204.48l-82.8 37.16c-17.6 8-17.6 21.1 0 29.1l148 67.49c16.89 7.7 44.69 7.7 61.58 0l148-67.49c17.7-8 17.7-21.1.1-29.1L352 204.48" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="32"/></svg>',
'leecher' : '<svg viewBox="0 0 512 512" aria-hidden="true" class="__jinja_class_placeholder__"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="48" d="M112 268l144 144 144-144M256 392V100"/></svg>',
'location' : '<svg viewBox="0 0 512 512" aria-hidden="true" class="__jinja_class_placeholder__"><path d="M256 48c-79.5 0-144 61.39-144 137 0 87 96 224.87 131.25 272.49a15.77 15.77 0 0025.5 0C304 409.89 400 272.07 400 185c0-75.61-64.5-137-144-137z" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="32"/><circle cx="256" cy="192" r="48" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="32"/></svg>',
'magnet' : '<svg viewBox="0 0 512 512" aria-hidden="true" class="__jinja_class_placeholder__"><path d="M421.83 293.82A144 144 0 00218.18 90.17M353.94 225.94a48 48 0 00-67.88-67.88" fill="none" stroke="currentColor" stroke-miterlimit="10" stroke-width="32"/><path stroke="currentColor" stroke-linecap="round" stroke-miterlimit="10" stroke-width="32" d="M192 464v-48M90.18 421.82l33.94-33.94M48 320h48"/><path d="M286.06 158.06L172.92 271.19a32 32 0 01-45.25 0L105 248.57a32 32 0 010-45.26L218.18 90.17M421.83 293.82L308.69 407a32 32 0 01-45.26 0l-22.62-22.63a32 32 0 010-45.26l113.13-113.17M139.6 169.98l67.88 67.89M275.36 305.75l67.89 67.88" fill="none" stroke="currentColor" stroke-linejoin="round" stroke-width="32"/></svg>',
'musical-notes' : '<svg viewBox="0 0 512 512" aria-hidden="true" class="__jinja_class_placeholder__"><path d="M192 218v-6c0-14.84 10-27 24.24-30.59l174.59-46.68A20 20 0 01416 154v22" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="32"/><path d="M416 295.94v80c0 13.91-8.93 25.59-22 30l-22 8c-25.9 8.72-52-10.42-52-38h0a33.37 33.37 0 0123-32l51-18.15c13.07-4.4 22-15.94 22-29.85V58a10 10 0 00-12.6-9.61L204 102a16.48 16.48 0 00-12 16v226c0 13.91-8.93 25.6-22 30l-52 18c-13.88 4.68-22 17.22-22 32h0c0 27.58 26.52 46.55 52 38l22-8c13.07-4.4 22-16.08 22-30v-80" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="32"/></svg>',
'navigate-down' : '<svg viewBox="0 0 512 512" aria-hidden="true" class="__jinja_class_placeholder__"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="48" d="M112 184l144 144 144-144"/></svg>',
'navigate-left' : '<svg viewBox="0 0 512 512" aria-hidden="true" class="__jinja_class_placeholder__"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="48" d="M328 112L184 256l144 144"/></svg>',
'navigate-right' : '<svg viewBox="0 0 512 512" aria-hidden="true" class="__jinja_class_placeholder__"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="48" d="M184 112l144 144-144 144"/></svg>',
'navigate-up' : '<svg viewBox="0 0 512 512" aria-hidden="true" class="__jinja_class_placeholder__"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="48" d="M112 328l144-144 144 144"/></svg>',
'newspaper' : '<svg viewBox="0 0 512 512" aria-hidden="true" class="__jinja_class_placeholder__"><path d="M368 415.86V72a24.07 24.07 0 00-24-24H72a24.07 24.07 0 00-24 24v352a40.12 40.12 0 0040 40h328" fill="none" stroke="currentColor" stroke-linejoin="round" stroke-width="32"/><path d="M416 464h0a48 48 0 01-48-48V128h72a24 24 0 0124 24v264a48 48 0 01-48 48z" fill="none" stroke="currentColor" stroke-linejoin="round" stroke-width="32"/><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="32" d="M240 128h64M240 192h64M112 256h192M112 320h192M112 384h192"/><path d="M176 208h-64a16 16 0 01-16-16v-64a16 16 0 0116-16h64a16 16 0 0116 16v64a16 16 0 01-16 16z"/></svg>',
'people' : '<svg viewBox="0 0 512 512" aria-hidden="true" class="__jinja_class_placeholder__"><path d="M402 168c-2.93 40.67-33.1 72-66 72s-63.12-31.32-66-72c-3-42.31 26.37-72 66-72s69 30.46 66 72z" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="32"/><path d="M336 304c-65.17 0-127.84 32.37-143.54 95.41-2.08 8.34 3.15 16.59 11.72 16.59h263.65c8.57 0 13.77-8.25 11.72-16.59C463.85 335.36 401.18 304 336 304z" fill="none" stroke="currentColor" stroke-miterlimit="10" stroke-width="32"/><path d="M200 185.94c-2.34 32.48-26.72 58.06-53 58.06s-50.7-25.57-53-58.06C91.61 152.15 115.34 128 147 128s55.39 24.77 53 57.94z" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="32"/><path d="M206 306c-18.05-8.27-37.93-11.45-59-11.45-52 0-102.1 25.85-114.65 76.2-1.65 6.66 2.53 13.25 9.37 13.25H154" fill="none" stroke="currentColor" stroke-linecap="round" stroke-miterlimit="10" stroke-width="32"/></svg>',
'play' : '<svg viewBox="0 0 512 512" aria-hidden="true" class="__jinja_class_placeholder__"><path d="M112 111v290c0 17.44 17 28.52 31 20.16l247.9-148.37c12.12-7.25 12.12-26.33 0-33.58L143 90.84c-14-8.36-31 2.72-31 20.16z" fill="none" stroke="currentColor" stroke-miterlimit="10" stroke-width="32"/></svg>',
'radio' : '<svg viewBox="0 0 512 512" aria-hidden="true" class="__jinja_class_placeholder__"><circle cx="256" cy="256.02" r="32"/><path d="M184.25 192.25a96 96 0 000 127.52M327.77 319.77a96 96 0 000-127.52M133.28 141.28a168 168 0 000 229.44M378.72 370.72a168 168 0 000-229.44M435 416a240.34 240.34 0 000-320M77 96a240.34 240.34 0 000 320" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="32"/></svg>',
'save' : '<svg viewBox="0 0 512 512" aria-hidden="true" class="__jinja_class_placeholder__"><path d="M380.93 57.37A32 32 0 00358.3 48H94.22A46.21 46.21 0 0048 94.22v323.56A46.21 46.21 0 0094.22 464h323.56A46.36 46.36 0 00464 417.78V153.7a32 32 0 00-9.37-22.63zM256 416a64 64 0 1164-64 63.92 63.92 0 01-64 64zm48-224H112a16 16 0 01-16-16v-64a16 16 0 0116-16h192a16 16 0 0116 16v64a16 16 0 01-16 16z" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="32"/></svg>',
'school' : '<svg viewBox="0 0 512 512" aria-hidden="true" class="__jinja_class_placeholder__"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="32" d="M32 192L256 64l224 128-224 128L32 192z"/><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="32" d="M112 240v128l144 80 144-80V240M480 368V192M256 320v128"/></svg>',
'search' : '<svg viewBox="0 0 512 512" aria-hidden="true" class="__jinja_class_placeholder__"><path d="M221.09 64a157.09 157.09 0 10157.09 157.09A157.1 157.1 0 00221.09 64z" fill="none" stroke="currentColor" stroke-miterlimit="10" stroke-width="32"/><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-miterlimit="10" stroke-width="32" d="M338.29 338.29L448 448"/></svg>',
'seeder' : '<svg viewBox="0 0 512 512" aria-hidden="true" class="__jinja_class_placeholder__"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="32" d="M464 208L352 96 240 208M352 113.13V416M48 304l112 112 112-112M160 398V96"/></svg>',
'settings' : '<svg viewBox="0 0 512 512" aria-hidden="true" class="__jinja_class_placeholder__"><path d="M262.29 192.31a64 64 0 1057.4 57.4 64.13 64.13 0 00-57.4-57.4zM416.39 256a154.34 154.34 0 01-1.53 20.79l45.21 35.46a10.81 10.81 0 012.45 13.75l-42.77 74a10.81 10.81 0 01-13.14 4.59l-44.9-18.08a16.11 16.11 0 00-15.17 1.75A164.48 164.48 0 01325 400.8a15.94 15.94 0 00-8.82 12.14l-6.73 47.89a11.08 11.08 0 01-10.68 9.17h-85.54a11.11 11.11 0 01-10.69-8.87l-6.72-47.82a16.07 16.07 0 00-9-12.22 155.3 155.3 0 01-21.46-12.57 16 16 0 00-15.11-1.71l-44.89 18.07a10.81 10.81 0 01-13.14-4.58l-42.77-74a10.8 10.8 0 012.45-13.75l38.21-30a16.05 16.05 0 006-14.08c-.36-4.17-.58-8.33-.58-12.5s.21-8.27.58-12.35a16 16 0 00-6.07-13.94l-38.19-30A10.81 10.81 0 0149.48 186l42.77-74a10.81 10.81 0 0113.14-4.59l44.9 18.08a16.11 16.11 0 0015.17-1.75A164.48 164.48 0 01187 111.2a15.94 15.94 0 008.82-12.14l6.73-47.89A11.08 11.08 0 01213.23 42h85.54a11.11 11.11 0 0110.69 8.87l6.72 47.82a16.07 16.07 0 009 12.22 155.3 155.3 0 0121.46 12.57 16 16 0 0015.11 1.71l44.89-18.07a10.81 10.81 0 0113.14 4.58l42.77 74a10.8 10.8 0 01-2.45 13.75l-38.21 30a16.05 16.05 0 00-6.05 14.08c.33 4.14.55 8.3.55 12.47z" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="32"/></svg>',
'tv' : '<svg viewBox="0 0 512 512" aria-hidden="true" class="__jinja_class_placeholder__"><rect x="32" y="96" width="448" height="272" rx="32.14" ry="32.14" fill="none" stroke="currentColor" stroke-linejoin="round" stroke-width="32"/><path stroke="currentColor" stroke-linecap="round" stroke-miterlimit="10" stroke-width="32" d="M128 416h256"/></svg>',
}
-%}
{% macro icon(action, alt) -%}
{{ icons[action] | replace("ionicon", "ion-icon") | safe }}
{{ catalog[action] | replace("__jinja_class_placeholder__", "ion-icon") | safe }}
{%- endmacro %}
{% macro icon_small(action) -%}
{{ icons[action] | replace("ionicon", "ion-icon-small") | safe }}
{% macro icon_small(action, alt) -%}
{{ catalog[action] | replace("__jinja_class_placeholder__", "ion-icon-small") | safe }}
{%- endmacro %}
{% macro icon_big(action, alt) -%}
{{ icons[action] | replace("ionicon", "ion-icon-big") | safe }}
{%- endmacro %}
{{ catalog[action] | replace("__jinja_class_placeholder__", "ion-icon-big") | safe }}
{%- endmacro %}

View File

@ -47,7 +47,7 @@
{%- macro result_sub_footer(result, proxify) -%}
<div class="engines">
{% for engine in result.engines %}<span>{{ engine }}</span>{% endfor %}
{{ icon_small('ellipsis-vertical-outline') + result_link(cache_url + result.url, _('cached'), "cache_link") }}&lrm; {% if proxify and proxify_results %} {{ result_link(proxify(result.url), _('proxied'), "proxyfied_link") }} {% endif %}
{{ icon_small('ellipsis-vertical') + result_link(cache_url + result.url, _('cached'), "cache_link") }}&lrm; {% if proxify and proxify_results %} {{ result_link(proxify(result.url), _('proxied'), "proxyfied_link") }} {% endif %}
</div>{{- '' -}}
<div class="break"></div>{{- '' -}}
{%- endmacro -%}

View File

@ -21,7 +21,7 @@
{%- macro checkbox(name, checked, disabled) -%}
{%- if checked == '?' -%}
{{- icon_small('warning') -}}
{{- icon_small('alert') -}}
{%- else -%}
<input type="checkbox" {%- if name %} name="{{ name }}" {%- endif %} value="None" {%- if checked %} checked {%- endif -%}{%- if disabled %} disabled {%- endif -%}>
{%- endif -%}
@ -128,7 +128,7 @@
<td class="{{ label }} column-reliability">{{- '' -}}
<a href="{{ url_for('stats', engine=engine_name|e) }}">{{- '' -}}
<span>
{{- icon_big('warning', 'The engine is not reliabled') }} {{ r -}}
{{- icon_big('alert', 'The engine is not reliabled') }} {{ r -}}
</span>{{- '' -}}
</a>{{- '' -}}
<div class="engine-tooltip" role="tooltip" id="{{engine_name}}_reliability">

View File

@ -57,7 +57,7 @@
</td>{{- '' -}}
<th class="name" data-engine-name="{{ search_engine.name }}">
{%- if search_engine.enable_http -%}
{{- icon_big('warning', 'No HTTPS') -}}
{{- icon_big('alert', 'No HTTPS') -}}
{%- endif -%}
<label for="{{ engine_id }}">
{{- ' ' -}}{{- search_engine.name -}}

View File

@ -6,8 +6,8 @@
{%- if result.embedded -%}
<small> &bull; <a class="text-info btn-collapse collapsed cursor-pointer media-loader disabled_if_nojs" data-toggle="collapse" data-target="#result-media-{{ index }}" data-btn-text-collapsed="{{ _('show media') }}" data-btn-text-not-collapsed="{{ _('hide media') }}">
{%- if result.mtype == 'audio' %}{{ icon_small('musical-notes-outline') -}}
{%- elif result.mtype == 'video' %} {{ icon_small('play-outline') -}}
{%- if result.mtype == 'audio' %}{{ icon_small('musical-notes') -}}
{%- elif result.mtype == 'video' %} {{ icon_small('play') -}}
{%- endif %} {{ _('show media') }}</a></small>
{%- endif -%}

View File

@ -7,8 +7,8 @@
</a>{{- "" -}}
<div class="detail swipe-horizontal">{{- "" -}}
<a class="result-detail-close" href="#">{{ icon('close') }}</a>{{- "" -}}
<a class="result-detail-previous" href="#">{{ icon('chevron-left') }}</a>{{- "" -}}
<a class="result-detail-next" href="#">{{ icon('chevron-right') }}</a>{{- "" -}}
<a class="result-detail-previous" href="#">{{ icon('navigate-left') }}</a>{{- "" -}}
<a class="result-detail-next" href="#">{{ icon('navigate-right') }}</a>{{- "" -}}
<a class="result-images-source" {% if results_on_new_tab %}target="_blank" rel="noopener noreferrer"{% else %}rel="noreferrer"{% endif %} href="{{ result.img_src }}">
<img src="" data-src="{{ image_proxify(result.img_src) }}" alt="{{ result.title|striptags }}">{{- "" -}}
</a>{{- "" -}}

View File

@ -40,7 +40,7 @@
</table>
{%- if (result.latitude and result.longitude) or result.boundingbox -%}
<small> <a class="btn-collapse collapsed searxng_init_map hide_if_nojs" data-target="#result-map-{{ index }}" data-btn-text-collapsed="{{ _('show map') }}" data-btn-text-not-collapsed="{{ _('hide map') }}" data-leaflet-target="osm-map-{{ index }}" data-map-lon="{{ result.longitude }}" data-map-lat="{{ result.latitude }}" {% if result.boundingbox %}data-map-boundingbox='{{ result.boundingbox|tojson|safe }}'{% endif %} {% if result.geojson %}data-map-geojson='{{ result.geojson|tojson|safe }}'{% endif %}>{{ icon_small( 'globe-outline') }} {{ _('show map') }}</a></small>
<small> <a class="btn-collapse collapsed searxng_init_map hide_if_nojs" data-target="#result-map-{{ index }}" data-btn-text-collapsed="{{ _('show map') }}" data-btn-text-not-collapsed="{{ _('hide map') }}" data-leaflet-target="osm-map-{{ index }}" data-map-lon="{{ result.longitude }}" data-map-lat="{{ result.latitude }}" {% if result.boundingbox %}data-map-boundingbox='{{ result.boundingbox|tojson|safe }}'{% endif %} {% if result.geojson %}data-map-geojson='{{ result.geojson|tojson|safe }}'{% endif %}>{{ icon_small( 'globe') }} {{ _('show map') }}</a></small>
{%- endif -%}
{{- result_sub_footer(result, proxify) -}}

View File

@ -3,15 +3,21 @@
{{ result_header(result, favicons, image_proxify) -}}
{{- result_sub_header(result) -}}
{% if result.magnetlink %}<p class="altlink"> &bull; {{ result_link(result.magnetlink, icon_big('magnet-outline') + _('magnet link'), "magnetlink") }}</p>{% endif %}
{% if result.torrentfile %}<p class="altlink"> &bull; {{ result_link(result.torrentfile, icon_big('download-alt') + _('torrent file'), "torrentfile") }}</p>{% endif %}
<p class="altlink">
{%- if result.magnetlink %}{{ result_link(result.magnetlink, icon_big('magnet') + _('magnet link'), "magnetlink") }}{%- endif -%}
{%- if result.torrentfile %}{{ result_link(result.torrentfile, icon_big('download-alt') + _('torrent file'), "torrentfile") }}{%- endif -%}
</p>
{% if result.seed is defined %}<p class="stat"> &bull; {{ icon_big('arrow-swap') }} {{ _('Seeder') }} <span class="badge">{{ result.seed }}</span> &bull; {{ _('Leecher') }} <span class="badge">{{ result.leech }}</span></p>{% endif %}
{%- if result.filesize %}<p class="stat">{{ icon_big('floppy-disk') }} {{ _('Filesize') }}<span class="badge">{{ result.filesize }}</span></p>{%- endif -%}
{%- if result.files %}<p class="stat">{{ icon_big('file') }} {{ _('Number of Files') }} <span class="badge">{{ result.files }}</span></p>{% endif -%}
{%- if result.content %}<p class="content">{{ result.content|safe }}</p>{% endif -%}
<p class="stat">
{%- if result.seed is defined %}
{{ icon_big('seeder') }} <span class="badge">{{ result.seed }} {{ _('Seeder') }} </span>
{{ icon_big('leecher') }} <span class="badge">{{ result.leech }} {{ _('Leecher') }}</span>
{% endif %}
</p>
<p class="stat">
{%- if result.filesize %}{{ icon_big('save') }} <span class="badge">{{ result.filesize }} {{ _('Filesize') }}</span>{%- endif -%}
{%- if result.files %}{{ icon_big('file') }} <span class="badge">{{ result.files }} {{ _('Number of Files') }}</span>{%- endif -%}
</p>
{%- if result.content %}<p class="content">{{ result.content|safe }}</p>{%- endif -%}
{{- result_sub_footer(result, proxify) -}}
{{- result_footer(result) }}
{{- result_footer(result) -}}

View File

@ -3,7 +3,7 @@
{{ result_header(result, favicons, image_proxify) }}
{{ result_sub_header(result) }}
{% if result.iframe_src -%}
<p class="altlink"> <a class="btn-collapse collapsed media-loader disabled_if_nojs" data-target="#result-video-{{ index }}" data-btn-text-collapsed="{{ _('show video') }}" data-btn-text-not-collapsed="{{ _('hide video') }}">{{ icon('film-outline') }} {{ _('show video') }}</a></p>
<p class="altlink"> <a class="btn-collapse collapsed media-loader disabled_if_nojs" data-target="#result-video-{{ index }}" data-btn-text-collapsed="{{ _('show video') }}" data-btn-text-not-collapsed="{{ _('hide video') }}">{{ icon('film') }} {{ _('show video') }}</a></p>
{%- endif %}
{%- if result.content %}
<p class="content">

View File

@ -74,7 +74,7 @@
{% endif %}
</div>
<div id="backToTop">
<a href="#" aria-label="{{ _('Back to top') }}">{{ icon_small('chevron-up-outline') }}</a>
<a href="#" aria-label="{{ _('Back to top') }}">{{ icon_small('navigate-up') }}</a>
</div>
{% if paging %}
<nav id="pagination" role="navigation">
@ -92,7 +92,7 @@
<input type="hidden" name="theme" value="{{ theme }}" >
{% if timeout_limit %}<input type="hidden" name="timeout_limit" value="{{ timeout_limit|e }}" >{% endif %}
{{- engine_data_form(engine_data) -}}
<button role="link" type="submit">{{ icon_small('chevron-left') }} {{ _('Previous page') }}</button>
<button role="link" type="submit">{{ icon_small('navigate-left') }} {{ _('Previous page') }}</button>
</div>
</form>
{% endif %}
@ -110,7 +110,7 @@
<input type="hidden" name="theme" value="{{ theme }}" >
{% if timeout_limit %}<input type="hidden" name="timeout_limit" value="{{ timeout_limit|e }}" >{% endif %}
{{- engine_data_form(engine_data) -}}
<button role="link" type="submit">{{ _('Next page') }} {{ icon_small('chevron-right') }}</button>
<button role="link" type="submit">{{ _('Next page') }} {{ icon_small('navigate-right') }}</button>
</div>
</form>
{%- endif -%}

View File

@ -8,7 +8,7 @@
<div class="search_box">
<input id="q" name="q" type="text" placeholder="{{ _('Search for...') }}" tabindex="1" autocomplete="off" autocapitalize="none" spellcheck="false" autocorrect="off" dir="auto" value="{{ q or '' }}">
<button id="clear_search" type="reset" aria-label="{{ _('clear') }}" class="hide_if_nojs"><span>{{ icon_big('close') }}</span><span class="show_if_nojs">{{ _('clear') }}</span></button>
<button id="send_search" type="submit" {%- if search_on_category_select -%}name="category_{{ selected_categories[0]|replace(' ', '_') }}"{%- endif -%} aria-label="{{ _('search') }}"><span class="hide_if_nojs">{{ icon_big('search-outline') }}</span><span class="show_if_nojs">{{ _('search') }}</span></button>
<button id="send_search" type="submit" {%- if search_on_category_select -%}name="category_{{ selected_categories[0]|replace(' ', '_') }}"{%- endif -%} aria-label="{{ _('search') }}"><span class="hide_if_nojs">{{ icon_big('search') }}</span><span class="show_if_nojs">{{ _('search') }}</span></button>
</div>
</div>
{% set display_tooltip = true %}

View File

@ -4,7 +4,7 @@
<div class="search_box">
<input id="q" name="q" type="text" placeholder="{{ _('Search for...') }}" autocomplete="off" autocapitalize="none" spellcheck="false" autocorrect="off" dir="auto" value="{{ q or '' }}">
<button id="clear_search" type="reset" aria-label="{{ _('clear') }}"><span class="hide_if_nojs">{{ icon_big('close') }}</span><span class="show_if_nojs">{{ _('clear') }}</span></button>
<button id="send_search" type="submit" aria-label="{{ _('search') }}"><span class="hide_if_nojs">{{ icon_big('search-outline') }}</span><span class="show_if_nojs">{{ _('search') }}</span></button>
<button id="send_search" type="submit" aria-label="{{ _('search') }}"><span class="hide_if_nojs">{{ icon_big('search') }}</span><span class="show_if_nojs">{{ _('search') }}</span></button>
</div>
</div>
</div>

View File

@ -7,7 +7,7 @@
{% if selected_engine_name %}
{{ column_name }}
{% elif column_order==sort_order %}
{{ column_name }} {{ icon_big('arrow-dropdown') }}
{{ icon_big('navigate-down') }} {{ column_name }}
{% else %}
<a href="{{ url_for('stats', sort=column_order) }}">{{ column_name }}</a>
{% endif %}

View File

@ -13,7 +13,7 @@ from pygments.formatters.html import HtmlFormatter
from searx import searx_dir
LESS_FILE = Path(searx_dir) / 'static/themes/simple/src/generated/pygments.less'
LESS_FILE = Path(searx_dir).parent / 'client/simple/generated/pygments.less'
HEADER = f"""\
/*

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