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] [*.html]
indent_size = 4 indent_size = 4
[*.css]
indent_size = 2
[*.less]
indent_size = 2
[*.js] [*.js]
indent_size = 2 indent_size = 2
[*.json] [*.json]
indent_size = 4 indent_size = 2
insert_final_newline = ignore insert_final_newline = ignore
# Minified JavaScript files shouldn't be changed # Minified JavaScript files shouldn't be changed

View File

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

View File

@ -44,19 +44,8 @@ jobs:
with: with:
python-version: '3.12' python-version: '3.12'
architecture: 'x64' 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 - name: Build themes
run: make V=1 themes.all run: make themes.all
documentation: documentation:
name: Documentation name: Documentation

View File

@ -50,7 +50,7 @@ search.checker.%: install
$(Q)./manage pyenv.cmd searxng-checker -v "$(subst _, ,$(patsubst search.checker.%,%,$@))" $(Q)./manage pyenv.cmd searxng-checker -v "$(subst _, ,$(patsubst search.checker.%,%,$@))"
PHONY += test ci.test test.shell 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: test.yamllint test.black test.types.dev test.pylint test.unit test.robot test.rst test.shell
test.shell: test.shell:
$(Q)shellcheck -x -s dash \ $(Q)shellcheck -x -s dash \
@ -85,7 +85,6 @@ MANAGE += pyenv pyenv.install pyenv.uninstall
MANAGE += format.python 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 += 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.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 += static.build.commit static.build.drop static.build.restore
MANAGE += nvm.install nvm.clean nvm.status nvm.nodejs 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": { "rules": {
"prettier/prettier": true,
"declaration-empty-line-before": null, "declaration-empty-line-before": null,
"no-invalid-position-at-import-rule": null, "no-invalid-position-at-import-rule": null,
"property-no-vendor-prefix": 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 { .codelines {
margin: @results-margin 0 0 0; margin: @results-margin 0 0 0;

View File

@ -55,7 +55,7 @@
--color-autocomplete-background: #fff; --color-autocomplete-background: #fff;
--color-autocomplete-background-hover: #e3e3e3; --color-autocomplete-background-hover: #e3e3e3;
/// Answer Colors /// Answer Colors
--color-answer-font: #444; // same as --color-base-font --color-answer-font: #444; // same as --color-base-font
--color-answer-background: #fff; --color-answer-background: #fff;
/// Results Colors /// Results Colors
--color-result-background: #fff; --color-result-background: #fff;
@ -284,7 +284,7 @@
/// Device Size /// Device Size
/// @desktop > @tablet /// @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; @phone: 50em;
@small-phone: 35em; @small-phone: 35em;
@ultra-small-phone: 20rem; @ultra-small-phone: 20rem;
@ -293,12 +293,12 @@
@stacked-bar-chart: rgb(0, 0, 0); @stacked-bar-chart: rgb(0, 0, 0);
/// Load fonts from this directory. /// Load fonts from this directory.
@icon-font-path: "../../../fonts/"; @icon-font-path: "../../../fonts/";
//** File name for all font files. //** File name for all font files.
@icon-font-name: "glyphicons-halflings-regular"; @icon-font-name: "glyphicons-halflings-regular";
//** Element ID within SVG icon file. //** Element ID within SVG icon file.
@icon-font-svg-id: "glyphicons_halflingsregular"; @icon-font-svg-id: "glyphicons_halflingsregular";
// decoration of the select HTML elements // decoration of the select HTML elements
@select-light-svg-path: "../svg/select-light.svg"; @select-light-svg-path: "../svg/select-light.svg";
@select-dark-svg-path: "../svg/select-dark.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; top: 0;
a.result-images-source img { 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; 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 real size is 92px, but 94px are needed to avoid an inner scrollbar of
// the embedded HTML. // the embedded HTML.
height: 94px; 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 // 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 // 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 // request. The alternative text (<img alt='Mixcloud Logo'> then cause an
@ -18,16 +21,19 @@ iframe[src^="https://www.mixcloud.com"] {
height: 250px; height: 250px;
} }
iframe[src^="https://bandcamp.com/EmbeddedPlayer"] { iframe[src^="https://bandcamp.com/EmbeddedPlayer"]
{
// show playlist // show playlist
height: 350px; height: 350px;
} }
iframe[src^="https://bandcamp.com/EmbeddedPlayer/track"] { iframe[src^="https://bandcamp.com/EmbeddedPlayer/track"]
{
// hide playlist // hide playlist
height: 120px; height: 120px;
} }
iframe[src^="https://genius.com/songs"] { iframe[src^="https://genius.com/songs"]
{
height: 65px; height: 65px;
} }

View File

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

View File

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

View File

@ -83,7 +83,9 @@ button.category_button {
} }
// only used when JavaScript is disabled // 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 { &.selected {
color: var(--color-base-font); color: var(--color-base-font);
border-bottom: none; border-bottom: none;

View File

@ -63,9 +63,11 @@ on the /search URL and when the "center alignment" preference is enabled.
} }
#search_header { #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"; 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%; width: 100%;
padding-left: 0; padding-left: 0;
padding-right: 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) { &:not(.only_template_images, .image-detail-open) {
// the gap is set in style.less // the gap is set in style.less
.ltr-margin-left(1.5rem); .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 { #backToTop {
.ltr-left(calc(50% - @results-sidebar-width - @results-gap + 1rem + var(--center-page-width) / 2)); .ltr-left(calc(50% - @results-sidebar-width - @results-gap + 1rem + var(--center-page-width) / 2));

View File

@ -109,7 +109,11 @@
} }
// Image detail // 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; direction: rtl;
&.result-url { &.result-url {
@ -125,7 +129,13 @@
} }
// select HTML element // 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 { select {
border-width: 0 0 0 2rem; border-width: 0 0 0 2rem;
background-position-x: -2rem; background-position-x: -2rem;

View File

@ -544,12 +544,11 @@ article[data-vim-selected].category-social {
.ltr-margin-left(@results-offset); .ltr-margin-left(@results-offset);
display: grid; display: grid;
grid-template: grid-template:
"corrections sidebar" min-content "corrections sidebar" min-content
"answers sidebar" min-content "answers sidebar" min-content
"urls sidebar" 1fr "urls sidebar" 1fr
"pagination sidebar" min-content "pagination sidebar" min-content
/ @results-width @results-sidebar-width / @results-width @results-sidebar-width;
;
gap: 0 @results-gap; gap: 0 @results-gap;
} }
@ -782,7 +781,7 @@ summary.title {
padding: 0.4rem; padding: 0.4rem;
margin-left: 0.5rem; margin-left: 0.5rem;
border-radius: 0.3rem; 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 "sidebar" min-content
"urls" 1fr "urls" 1fr
"pagination" min-content "pagination" min-content
/ @results-width / @results-width;
;
gap: 0; gap: 0;
} }
} }

View File

@ -249,7 +249,7 @@ ul.tabs {
order: 2; order: 2;
} }
& > input[type=radio] { & > input[type="radio"] {
display: none; 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 { select {
appearance: none; appearance: none;
-webkit-appearance: none; -webkit-appearance: none;
-moz-appearance: none; -moz-appearance: none;
border-width: 0 2rem 0 0; border-width: 0 2rem 0 0;
border-color: transparent; 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-position-x: calc(100% + 2rem);
background-size: 2rem; background-size: 2rem;
background-origin: content-box; background-origin: content-box;
@ -376,12 +383,18 @@ select {
@media (prefers-color-scheme: dark) { @media (prefers-color-scheme: dark) {
html.theme-auto select, html.theme-auto select,
html.theme-dark 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 { 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 -- */ /* -- checkbox -- */
@supports (transform: rotate(-45deg)) { @supports (transform: rotate(-45deg)) {
input[type=checkbox]:not(.checkbox-onoff) { input[type="checkbox"]:not(.checkbox-onoff) {
-webkit-appearance: none; -webkit-appearance: none;
-moz-appearance: none; -moz-appearance: none;
appearance: none; appearance: none;
@ -476,7 +489,7 @@ input.checkbox-onoff.reversed-checkbox[type="checkbox"] {
.rounded-corners(0.3em); .rounded-corners(0.3em);
&::after { &::after {
content: ''; content: "";
width: 9px; width: 9px;
height: 5px; height: 5px;
position: absolute; position: absolute;
@ -497,14 +510,18 @@ input.checkbox-onoff.reversed-checkbox[type="checkbox"] {
} }
// disabled : can't be focused, show only the check mark // 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; border: inherit;
background-color: transparent !important; background-color: transparent !important;
cursor: inherit; cursor: inherit;
} }
// if not checked and possible to checked then display a "light" check mark on hover // 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; 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`` ``center_alignment`` : default ``false``
When enabled, the results are centered instead of being in the left (or RTL) 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* 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: .. cache_url:

View File

@ -197,7 +197,7 @@ html_sidebars = {
], ],
} }
singlehtml_sidebars = {"index": ["project.html", "localtoc.html"]} 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_title = "SearXNG Documentation ({})".format(VERSION_STRING)
html_show_sourcelink = True 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 $ 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: .. _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 # shellcheck source=utils/lib_redis.sh
source "$(dirname "${BASH_SOURCE[0]}")/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}" PATH="${REPO_ROOT}/node_modules/.bin:${PATH}"
# config # config
@ -102,6 +105,7 @@ EOF
test.help test.help
themes.help themes.help
static.help static.help
vite.help
cat <<EOF cat <<EOF
environment ... environment ...
SEARXNG_REDIS_URL : ${SEARXNG_REDIS_URL} SEARXNG_REDIS_URL : ${SEARXNG_REDIS_URL}
@ -310,6 +314,18 @@ format.python() {
dump_return $? 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 # shellcheck disable=SC2119
main() { main() {

View File

@ -384,7 +384,7 @@ def extract_response_info(result):
def response(resp): def response(resp):
'''Scrap *results* from the response (see :ref:`engine results`).''' '''Scrap *results* from the response (see :ref:`result types`).'''
results = [] results = []
if no_result_for_http_status and resp.status_code in no_result_for_http_status: 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"> <nav id="links_on_top">
{%- from 'simple/icons.html' import icon_big -%} {%- from 'simple/icons.html' import icon_big -%}
{%- block linkto_about -%} {%- 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 -%} {%- endblock -%}
{%- block linkto_donate -%} {%- block linkto_donate -%}
{%- if donation_url -%} {%- 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 -%} {%- endif -%}
{%- endblock -%} {%- endblock -%}
{%- block linkto_preferences -%} {%- 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 -%} {%- endblock -%}
</nav> </nav>
{% block header %} {% block header %}

View File

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

View File

@ -1,38 +1,55 @@
{# this file was generated by searx/static/themes/simple/gruntfile.js #} {#
{%- set icons = { Catalog of SVG symbols that can be inserted into the HTML output of a Jinja
'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>', template. This file from:
'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>',
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) -%} {% macro icon(action, alt) -%}
{{ icons[action] | replace("ionicon", "ion-icon") | safe }} {{ catalog[action] | replace("__jinja_class_placeholder__", "ion-icon") | safe }}
{%- endmacro %} {%- endmacro %}
{% macro icon_small(action) -%} {% macro icon_small(action, alt) -%}
{{ icons[action] | replace("ionicon", "ion-icon-small") | safe }} {{ catalog[action] | replace("__jinja_class_placeholder__", "ion-icon-small") | safe }}
{%- endmacro %} {%- endmacro %}
{% macro icon_big(action, alt) -%} {% macro icon_big(action, alt) -%}
{{ icons[action] | replace("ionicon", "ion-icon-big") | safe }} {{ catalog[action] | replace("__jinja_class_placeholder__", "ion-icon-big") | safe }}
{%- endmacro %} {%- endmacro %}

View File

@ -47,7 +47,7 @@
{%- macro result_sub_footer(result, proxify) -%} {%- macro result_sub_footer(result, proxify) -%}
<div class="engines"> <div class="engines">
{% for engine in result.engines %}<span>{{ engine }}</span>{% endfor %} {% 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>{{- '' -}}
<div class="break"></div>{{- '' -}} <div class="break"></div>{{- '' -}}
{%- endmacro -%} {%- endmacro -%}

View File

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

View File

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

View File

@ -6,8 +6,8 @@
{%- if result.embedded -%} {%- 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') }}"> <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') -}} {%- if result.mtype == 'audio' %}{{ icon_small('musical-notes') -}}
{%- elif result.mtype == 'video' %} {{ icon_small('play-outline') -}} {%- elif result.mtype == 'video' %} {{ icon_small('play') -}}
{%- endif %} {{ _('show media') }}</a></small> {%- endif %} {{ _('show media') }}</a></small>
{%- endif -%} {%- endif -%}

View File

@ -7,8 +7,8 @@
</a>{{- "" -}} </a>{{- "" -}}
<div class="detail swipe-horizontal">{{- "" -}} <div class="detail swipe-horizontal">{{- "" -}}
<a class="result-detail-close" href="#">{{ icon('close') }}</a>{{- "" -}} <a class="result-detail-close" href="#">{{ icon('close') }}</a>{{- "" -}}
<a class="result-detail-previous" href="#">{{ icon('chevron-left') }}</a>{{- "" -}} <a class="result-detail-previous" href="#">{{ icon('navigate-left') }}</a>{{- "" -}}
<a class="result-detail-next" href="#">{{ icon('chevron-right') }}</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 }}"> <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 }}">{{- "" -}} <img src="" data-src="{{ image_proxify(result.img_src) }}" alt="{{ result.title|striptags }}">{{- "" -}}
</a>{{- "" -}} </a>{{- "" -}}

View File

@ -40,7 +40,7 @@
</table> </table>
{%- if (result.latitude and result.longitude) or result.boundingbox -%} {%- 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 -%} {%- endif -%}
{{- result_sub_footer(result, proxify) -}} {{- result_sub_footer(result, proxify) -}}

View File

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

View File

@ -3,7 +3,7 @@
{{ result_header(result, favicons, image_proxify) }} {{ result_header(result, favicons, image_proxify) }}
{{ result_sub_header(result) }} {{ result_sub_header(result) }}
{% if result.iframe_src -%} {% 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 %} {%- endif %}
{%- if result.content %} {%- if result.content %}
<p class="content"> <p class="content">

View File

@ -74,7 +74,7 @@
{% endif %} {% endif %}
</div> </div>
<div id="backToTop"> <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> </div>
{% if paging %} {% if paging %}
<nav id="pagination" role="navigation"> <nav id="pagination" role="navigation">
@ -92,7 +92,7 @@
<input type="hidden" name="theme" value="{{ theme }}" > <input type="hidden" name="theme" value="{{ theme }}" >
{% if timeout_limit %}<input type="hidden" name="timeout_limit" value="{{ timeout_limit|e }}" >{% endif %} {% if timeout_limit %}<input type="hidden" name="timeout_limit" value="{{ timeout_limit|e }}" >{% endif %}
{{- engine_data_form(engine_data) -}} {{- 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> </div>
</form> </form>
{% endif %} {% endif %}
@ -110,7 +110,7 @@
<input type="hidden" name="theme" value="{{ theme }}" > <input type="hidden" name="theme" value="{{ theme }}" >
{% if timeout_limit %}<input type="hidden" name="timeout_limit" value="{{ timeout_limit|e }}" >{% endif %} {% if timeout_limit %}<input type="hidden" name="timeout_limit" value="{{ timeout_limit|e }}" >{% endif %}
{{- engine_data_form(engine_data) -}} {{- 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> </div>
</form> </form>
{%- endif -%} {%- endif -%}

View File

@ -8,7 +8,7 @@
<div class="search_box"> <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 '' }}"> <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="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>
</div> </div>
{% set display_tooltip = true %} {% set display_tooltip = true %}

View File

@ -4,7 +4,7 @@
<div class="search_box"> <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 '' }}"> <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="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> </div>
</div> </div>

View File

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

View File

@ -13,7 +13,7 @@ from pygments.formatters.html import HtmlFormatter
from searx import searx_dir 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"""\ HEADER = f"""\
/* /*

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