first commit
40
README.md
Normal file
|
@ -0,0 +1,40 @@
|
|||
# Searxng_beetroot
|
||||
|
||||
Disroot theme for Searxng.
|
||||
|
||||
## How to use
|
||||
To use this theme, `git clone` it on your computer.
|
||||
|
||||
Create a `beetroot` folder in `/var/www/searx/searx/static/themes` and in `/var/www/searx/searx/templates`.
|
||||
|
||||
Then, copy the content of `beetroot_static` in `/var/www/searx/searx/static/themes/beetroot` and the content of `beetroot_template` in `/var/www/searx/searx/templates/beetroot`.
|
||||
|
||||
Enable the beetroot them by editing `/var/www/searx/searx/settings.yml` and changing:
|
||||
```
|
||||
default_theme : beetroot
|
||||
```
|
||||
|
||||
Restart searx: `service uwsgi restart`
|
||||
|
||||
|
||||
## How to edit/change this theme
|
||||
All changes need to be done to Simple theme and then compiled. So:
|
||||
- You have clone the upstream repo first: `git clone https://github.com/searxng/searxng.git searx`.
|
||||
- Copy the `beetroot_static/src/less/definitions.less` and the `beetroot_static/src/less/disroot.less` from the beetroot theme repo to the clone (in `static/themes/simple/src/less/`).
|
||||
- Edit the `static/themes/simple/src/less/definitions.less` and `static/themes/simple/src/less/disroot.less` files copied in the clone with the colors and rules you want.
|
||||
- Once finished, build the theme: in searx root-src folder, as the searx user, do `make themes.simple`.
|
||||
- Copy the content of the `static/themes/simple/css` folder obtained in the clone back to this repo (if you didn't change any images, you don't have to copy the `images` folder again). Don't forget to also copy `definitions.less` and `disroot.less`, if you changed those, back to the beetroot repo.
|
||||
|
||||
If you want to test in live mode all your changes to the `Simple` theme, do `LIVE_THEME=simple make run` from searx-src folder and edit the `static/themes/simple/src/less/definitions.less` and `static/themes/simple/src/less/disroot.less` files as you wish.
|
||||
|
||||
## Screenshots
|
||||
|
||||
### Light mode
|
||||
![Light mode](img/Light01.png)
|
||||
![Light mode](img/Light02.png)
|
||||
![Light mode](img/Light03.png)
|
||||
|
||||
### Dark mode
|
||||
![Dark mode](img/Dark01.png)
|
||||
![Dark mode](img/Dark02.png)
|
||||
![Dark mode](img/Dark03.png)
|
BIN
beetroot_static/css/images/layers-2x.png
Normal file
After Width: | Height: | Size: 1.2 KiB |
BIN
beetroot_static/css/images/layers.png
Normal file
After Width: | Height: | Size: 696 B |
BIN
beetroot_static/css/images/marker-icon-2x.png
Normal file
After Width: | Height: | Size: 2.4 KiB |
BIN
beetroot_static/css/images/marker-icon.png
Normal file
After Width: | Height: | Size: 1.4 KiB |
BIN
beetroot_static/css/images/marker-shadow.png
Normal file
After Width: | Height: | Size: 618 B |
656
beetroot_static/css/leaflet.css
Normal file
|
@ -0,0 +1,656 @@
|
|||
/* required styles */
|
||||
|
||||
.leaflet-pane,
|
||||
.leaflet-tile,
|
||||
.leaflet-marker-icon,
|
||||
.leaflet-marker-shadow,
|
||||
.leaflet-tile-container,
|
||||
.leaflet-pane > svg,
|
||||
.leaflet-pane > canvas,
|
||||
.leaflet-zoom-box,
|
||||
.leaflet-image-layer,
|
||||
.leaflet-layer {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
}
|
||||
.leaflet-container {
|
||||
overflow: hidden;
|
||||
}
|
||||
.leaflet-tile,
|
||||
.leaflet-marker-icon,
|
||||
.leaflet-marker-shadow {
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
user-select: none;
|
||||
-webkit-user-drag: none;
|
||||
}
|
||||
/* Prevents IE11 from highlighting tiles in blue */
|
||||
.leaflet-tile::selection {
|
||||
background: transparent;
|
||||
}
|
||||
/* Safari renders non-retina tile on retina better with this, but Chrome is worse */
|
||||
.leaflet-safari .leaflet-tile {
|
||||
image-rendering: -webkit-optimize-contrast;
|
||||
}
|
||||
/* hack that prevents hw layers "stretching" when loading new tiles */
|
||||
.leaflet-safari .leaflet-tile-container {
|
||||
width: 1600px;
|
||||
height: 1600px;
|
||||
-webkit-transform-origin: 0 0;
|
||||
}
|
||||
.leaflet-marker-icon,
|
||||
.leaflet-marker-shadow {
|
||||
display: block;
|
||||
}
|
||||
/* .leaflet-container svg: reset svg max-width decleration shipped in Joomla! (joomla.org) 3.x */
|
||||
/* .leaflet-container img: map is broken in FF if you have max-width: 100% on tiles */
|
||||
.leaflet-container .leaflet-overlay-pane svg {
|
||||
max-width: none !important;
|
||||
max-height: none !important;
|
||||
}
|
||||
.leaflet-container .leaflet-marker-pane img,
|
||||
.leaflet-container .leaflet-shadow-pane img,
|
||||
.leaflet-container .leaflet-tile-pane img,
|
||||
.leaflet-container img.leaflet-image-layer,
|
||||
.leaflet-container .leaflet-tile {
|
||||
max-width: none !important;
|
||||
max-height: none !important;
|
||||
width: auto;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.leaflet-container.leaflet-touch-zoom {
|
||||
-ms-touch-action: pan-x pan-y;
|
||||
touch-action: pan-x pan-y;
|
||||
}
|
||||
.leaflet-container.leaflet-touch-drag {
|
||||
-ms-touch-action: pinch-zoom;
|
||||
/* Fallback for FF which doesn't support pinch-zoom */
|
||||
touch-action: none;
|
||||
touch-action: pinch-zoom;
|
||||
}
|
||||
.leaflet-container.leaflet-touch-drag.leaflet-touch-zoom {
|
||||
-ms-touch-action: none;
|
||||
touch-action: none;
|
||||
}
|
||||
.leaflet-container {
|
||||
-webkit-tap-highlight-color: transparent;
|
||||
}
|
||||
.leaflet-container a {
|
||||
-webkit-tap-highlight-color: rgba(51, 181, 229, 0.4);
|
||||
}
|
||||
.leaflet-tile {
|
||||
filter: inherit;
|
||||
visibility: hidden;
|
||||
}
|
||||
.leaflet-tile-loaded {
|
||||
visibility: inherit;
|
||||
}
|
||||
.leaflet-zoom-box {
|
||||
width: 0;
|
||||
height: 0;
|
||||
-moz-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
z-index: 800;
|
||||
}
|
||||
/* workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=888319 */
|
||||
.leaflet-overlay-pane svg {
|
||||
-moz-user-select: none;
|
||||
}
|
||||
|
||||
.leaflet-pane { z-index: 400; }
|
||||
|
||||
.leaflet-tile-pane { z-index: 200; }
|
||||
.leaflet-overlay-pane { z-index: 400; }
|
||||
.leaflet-shadow-pane { z-index: 500; }
|
||||
.leaflet-marker-pane { z-index: 600; }
|
||||
.leaflet-tooltip-pane { z-index: 650; }
|
||||
.leaflet-popup-pane { z-index: 700; }
|
||||
|
||||
.leaflet-map-pane canvas { z-index: 100; }
|
||||
.leaflet-map-pane svg { z-index: 200; }
|
||||
|
||||
.leaflet-vml-shape {
|
||||
width: 1px;
|
||||
height: 1px;
|
||||
}
|
||||
.lvml {
|
||||
behavior: url(#default#VML);
|
||||
display: inline-block;
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
|
||||
/* control positioning */
|
||||
|
||||
.leaflet-control {
|
||||
position: relative;
|
||||
z-index: 800;
|
||||
pointer-events: visiblePainted; /* IE 9-10 doesn't have auto */
|
||||
pointer-events: auto;
|
||||
}
|
||||
.leaflet-top,
|
||||
.leaflet-bottom {
|
||||
position: absolute;
|
||||
z-index: 1000;
|
||||
pointer-events: none;
|
||||
}
|
||||
.leaflet-top {
|
||||
top: 0;
|
||||
}
|
||||
.leaflet-right {
|
||||
right: 0;
|
||||
}
|
||||
.leaflet-bottom {
|
||||
bottom: 0;
|
||||
}
|
||||
.leaflet-left {
|
||||
left: 0;
|
||||
}
|
||||
.leaflet-control {
|
||||
float: left;
|
||||
clear: both;
|
||||
}
|
||||
.leaflet-right .leaflet-control {
|
||||
float: right;
|
||||
}
|
||||
.leaflet-top .leaflet-control {
|
||||
margin-top: 10px;
|
||||
}
|
||||
.leaflet-bottom .leaflet-control {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.leaflet-left .leaflet-control {
|
||||
margin-left: 10px;
|
||||
}
|
||||
.leaflet-right .leaflet-control {
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
|
||||
/* zoom and fade animations */
|
||||
|
||||
.leaflet-fade-anim .leaflet-popup {
|
||||
opacity: 0;
|
||||
-webkit-transition: opacity 0.2s linear;
|
||||
-moz-transition: opacity 0.2s linear;
|
||||
transition: opacity 0.2s linear;
|
||||
}
|
||||
.leaflet-fade-anim .leaflet-map-pane .leaflet-popup {
|
||||
opacity: 1;
|
||||
}
|
||||
.leaflet-zoom-animated {
|
||||
-webkit-transform-origin: 0 0;
|
||||
-ms-transform-origin: 0 0;
|
||||
transform-origin: 0 0;
|
||||
}
|
||||
svg.leaflet-zoom-animated {
|
||||
will-change: transform;
|
||||
}
|
||||
|
||||
.leaflet-zoom-anim .leaflet-zoom-animated {
|
||||
-webkit-transition: -webkit-transform 0.25s cubic-bezier(0,0,0.25,1);
|
||||
-moz-transition: -moz-transform 0.25s cubic-bezier(0,0,0.25,1);
|
||||
transition: transform 0.25s cubic-bezier(0,0,0.25,1);
|
||||
}
|
||||
.leaflet-zoom-anim .leaflet-tile,
|
||||
.leaflet-pan-anim .leaflet-tile {
|
||||
-webkit-transition: none;
|
||||
-moz-transition: none;
|
||||
transition: none;
|
||||
}
|
||||
|
||||
.leaflet-zoom-anim .leaflet-zoom-hide {
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
|
||||
/* cursors */
|
||||
|
||||
.leaflet-interactive {
|
||||
cursor: pointer;
|
||||
}
|
||||
.leaflet-grab {
|
||||
cursor: -webkit-grab;
|
||||
cursor: -moz-grab;
|
||||
cursor: grab;
|
||||
}
|
||||
.leaflet-crosshair,
|
||||
.leaflet-crosshair .leaflet-interactive {
|
||||
cursor: crosshair;
|
||||
}
|
||||
.leaflet-popup-pane,
|
||||
.leaflet-control {
|
||||
cursor: auto;
|
||||
}
|
||||
.leaflet-dragging .leaflet-grab,
|
||||
.leaflet-dragging .leaflet-grab .leaflet-interactive,
|
||||
.leaflet-dragging .leaflet-marker-draggable {
|
||||
cursor: move;
|
||||
cursor: -webkit-grabbing;
|
||||
cursor: -moz-grabbing;
|
||||
cursor: grabbing;
|
||||
}
|
||||
|
||||
/* marker & overlays interactivity */
|
||||
.leaflet-marker-icon,
|
||||
.leaflet-marker-shadow,
|
||||
.leaflet-image-layer,
|
||||
.leaflet-pane > svg path,
|
||||
.leaflet-tile-container {
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.leaflet-marker-icon.leaflet-interactive,
|
||||
.leaflet-image-layer.leaflet-interactive,
|
||||
.leaflet-pane > svg path.leaflet-interactive,
|
||||
svg.leaflet-image-layer.leaflet-interactive path {
|
||||
pointer-events: visiblePainted; /* IE 9-10 doesn't have auto */
|
||||
pointer-events: auto;
|
||||
}
|
||||
|
||||
/* visual tweaks */
|
||||
|
||||
.leaflet-container {
|
||||
background: #ddd;
|
||||
outline-offset: 1px;
|
||||
}
|
||||
.leaflet-container a {
|
||||
color: #0078A8;
|
||||
}
|
||||
.leaflet-zoom-box {
|
||||
border: 2px dotted #38f;
|
||||
background: rgba(255,255,255,0.5);
|
||||
}
|
||||
|
||||
|
||||
/* general typography */
|
||||
.leaflet-container {
|
||||
font-family: "Helvetica Neue", Arial, Helvetica, sans-serif;
|
||||
font-size: 12px;
|
||||
font-size: 0.75rem;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
|
||||
/* general toolbar styles */
|
||||
|
||||
.leaflet-bar {
|
||||
box-shadow: 0 1px 5px rgba(0,0,0,0.65);
|
||||
border-radius: 4px;
|
||||
}
|
||||
.leaflet-bar a {
|
||||
background-color: #fff;
|
||||
border-bottom: 1px solid #ccc;
|
||||
width: 26px;
|
||||
height: 26px;
|
||||
line-height: 26px;
|
||||
display: block;
|
||||
text-align: center;
|
||||
text-decoration: none;
|
||||
color: black;
|
||||
}
|
||||
.leaflet-bar a,
|
||||
.leaflet-control-layers-toggle {
|
||||
background-position: 50% 50%;
|
||||
background-repeat: no-repeat;
|
||||
display: block;
|
||||
}
|
||||
.leaflet-bar a:hover,
|
||||
.leaflet-bar a:focus {
|
||||
background-color: #f4f4f4;
|
||||
}
|
||||
.leaflet-bar a:first-child {
|
||||
border-top-left-radius: 4px;
|
||||
border-top-right-radius: 4px;
|
||||
}
|
||||
.leaflet-bar a:last-child {
|
||||
border-bottom-left-radius: 4px;
|
||||
border-bottom-right-radius: 4px;
|
||||
border-bottom: none;
|
||||
}
|
||||
.leaflet-bar a.leaflet-disabled {
|
||||
cursor: default;
|
||||
background-color: #f4f4f4;
|
||||
color: #bbb;
|
||||
}
|
||||
|
||||
.leaflet-touch .leaflet-bar a {
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
line-height: 30px;
|
||||
}
|
||||
.leaflet-touch .leaflet-bar a:first-child {
|
||||
border-top-left-radius: 2px;
|
||||
border-top-right-radius: 2px;
|
||||
}
|
||||
.leaflet-touch .leaflet-bar a:last-child {
|
||||
border-bottom-left-radius: 2px;
|
||||
border-bottom-right-radius: 2px;
|
||||
}
|
||||
|
||||
/* zoom control */
|
||||
|
||||
.leaflet-control-zoom-in,
|
||||
.leaflet-control-zoom-out {
|
||||
font: bold 18px 'Lucida Console', Monaco, monospace;
|
||||
text-indent: 1px;
|
||||
}
|
||||
|
||||
.leaflet-touch .leaflet-control-zoom-in, .leaflet-touch .leaflet-control-zoom-out {
|
||||
font-size: 22px;
|
||||
}
|
||||
|
||||
|
||||
/* layers control */
|
||||
|
||||
.leaflet-control-layers {
|
||||
box-shadow: 0 1px 5px rgba(0,0,0,0.4);
|
||||
background: #fff;
|
||||
border-radius: 5px;
|
||||
}
|
||||
.leaflet-control-layers-toggle {
|
||||
background-image: url(images/layers.png);
|
||||
width: 36px;
|
||||
height: 36px;
|
||||
}
|
||||
.leaflet-retina .leaflet-control-layers-toggle {
|
||||
background-image: url(images/layers-2x.png);
|
||||
background-size: 26px 26px;
|
||||
}
|
||||
.leaflet-touch .leaflet-control-layers-toggle {
|
||||
width: 44px;
|
||||
height: 44px;
|
||||
}
|
||||
.leaflet-control-layers .leaflet-control-layers-list,
|
||||
.leaflet-control-layers-expanded .leaflet-control-layers-toggle {
|
||||
display: none;
|
||||
}
|
||||
.leaflet-control-layers-expanded .leaflet-control-layers-list {
|
||||
display: block;
|
||||
position: relative;
|
||||
}
|
||||
.leaflet-control-layers-expanded {
|
||||
padding: 6px 10px 6px 6px;
|
||||
color: #333;
|
||||
background: #fff;
|
||||
}
|
||||
.leaflet-control-layers-scrollbar {
|
||||
overflow-y: scroll;
|
||||
overflow-x: hidden;
|
||||
padding-right: 5px;
|
||||
}
|
||||
.leaflet-control-layers-selector {
|
||||
margin-top: 2px;
|
||||
position: relative;
|
||||
top: 1px;
|
||||
}
|
||||
.leaflet-control-layers label {
|
||||
display: block;
|
||||
font-size: 13px;
|
||||
font-size: 1.08333em;
|
||||
}
|
||||
.leaflet-control-layers-separator {
|
||||
height: 0;
|
||||
border-top: 1px solid #ddd;
|
||||
margin: 5px -10px 5px -6px;
|
||||
}
|
||||
|
||||
/* Default icon URLs */
|
||||
.leaflet-default-icon-path { /* used only in path-guessing heuristic, see L.Icon.Default */
|
||||
background-image: url(images/marker-icon.png);
|
||||
}
|
||||
|
||||
|
||||
/* attribution and scale controls */
|
||||
|
||||
.leaflet-container .leaflet-control-attribution {
|
||||
background: #fff;
|
||||
background: rgba(255, 255, 255, 0.8);
|
||||
margin: 0;
|
||||
}
|
||||
.leaflet-control-attribution,
|
||||
.leaflet-control-scale-line {
|
||||
padding: 0 5px;
|
||||
color: #333;
|
||||
line-height: 1.4;
|
||||
}
|
||||
.leaflet-control-attribution a {
|
||||
text-decoration: none;
|
||||
}
|
||||
.leaflet-control-attribution a:hover,
|
||||
.leaflet-control-attribution a:focus {
|
||||
text-decoration: underline;
|
||||
}
|
||||
.leaflet-attribution-flag {
|
||||
display: inline !important;
|
||||
vertical-align: baseline !important;
|
||||
width: 1em;
|
||||
height: 0.6669em;
|
||||
}
|
||||
.leaflet-left .leaflet-control-scale {
|
||||
margin-left: 5px;
|
||||
}
|
||||
.leaflet-bottom .leaflet-control-scale {
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
.leaflet-control-scale-line {
|
||||
border: 2px solid #777;
|
||||
border-top: none;
|
||||
line-height: 1.1;
|
||||
padding: 2px 5px 1px;
|
||||
white-space: nowrap;
|
||||
-moz-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
background: rgba(255, 255, 255, 0.8);
|
||||
text-shadow: 1px 1px #fff;
|
||||
}
|
||||
.leaflet-control-scale-line:not(:first-child) {
|
||||
border-top: 2px solid #777;
|
||||
border-bottom: none;
|
||||
margin-top: -2px;
|
||||
}
|
||||
.leaflet-control-scale-line:not(:first-child):not(:last-child) {
|
||||
border-bottom: 2px solid #777;
|
||||
}
|
||||
|
||||
.leaflet-touch .leaflet-control-attribution,
|
||||
.leaflet-touch .leaflet-control-layers,
|
||||
.leaflet-touch .leaflet-bar {
|
||||
box-shadow: none;
|
||||
}
|
||||
.leaflet-touch .leaflet-control-layers,
|
||||
.leaflet-touch .leaflet-bar {
|
||||
border: 2px solid rgba(0,0,0,0.2);
|
||||
background-clip: padding-box;
|
||||
}
|
||||
|
||||
|
||||
/* popup */
|
||||
|
||||
.leaflet-popup {
|
||||
position: absolute;
|
||||
text-align: center;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
.leaflet-popup-content-wrapper {
|
||||
padding: 1px;
|
||||
text-align: left;
|
||||
border-radius: 12px;
|
||||
}
|
||||
.leaflet-popup-content {
|
||||
margin: 13px 24px 13px 20px;
|
||||
line-height: 1.3;
|
||||
font-size: 13px;
|
||||
font-size: 1.08333em;
|
||||
min-height: 1px;
|
||||
}
|
||||
.leaflet-popup-content p {
|
||||
margin: 17px 0;
|
||||
margin: 1.3em 0;
|
||||
}
|
||||
.leaflet-popup-tip-container {
|
||||
width: 40px;
|
||||
height: 20px;
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
margin-top: -1px;
|
||||
margin-left: -20px;
|
||||
overflow: hidden;
|
||||
pointer-events: none;
|
||||
}
|
||||
.leaflet-popup-tip {
|
||||
width: 17px;
|
||||
height: 17px;
|
||||
padding: 1px;
|
||||
|
||||
margin: -10px auto 0;
|
||||
pointer-events: auto;
|
||||
|
||||
-webkit-transform: rotate(45deg);
|
||||
-moz-transform: rotate(45deg);
|
||||
-ms-transform: rotate(45deg);
|
||||
transform: rotate(45deg);
|
||||
}
|
||||
.leaflet-popup-content-wrapper,
|
||||
.leaflet-popup-tip {
|
||||
background: white;
|
||||
color: #333;
|
||||
box-shadow: 0 3px 14px rgba(0,0,0,0.4);
|
||||
}
|
||||
.leaflet-container a.leaflet-popup-close-button {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
border: none;
|
||||
text-align: center;
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
font: 16px/24px Tahoma, Verdana, sans-serif;
|
||||
color: #757575;
|
||||
text-decoration: none;
|
||||
background: transparent;
|
||||
}
|
||||
.leaflet-container a.leaflet-popup-close-button:hover,
|
||||
.leaflet-container a.leaflet-popup-close-button:focus {
|
||||
color: #585858;
|
||||
}
|
||||
.leaflet-popup-scrolled {
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.leaflet-oldie .leaflet-popup-content-wrapper {
|
||||
-ms-zoom: 1;
|
||||
}
|
||||
.leaflet-oldie .leaflet-popup-tip {
|
||||
width: 24px;
|
||||
margin: 0 auto;
|
||||
|
||||
-ms-filter: "progid:DXImageTransform.Microsoft.Matrix(M11=0.70710678, M12=0.70710678, M21=-0.70710678, M22=0.70710678)";
|
||||
filter: progid:DXImageTransform.Microsoft.Matrix(M11=0.70710678, M12=0.70710678, M21=-0.70710678, M22=0.70710678);
|
||||
}
|
||||
|
||||
.leaflet-oldie .leaflet-control-zoom,
|
||||
.leaflet-oldie .leaflet-control-layers,
|
||||
.leaflet-oldie .leaflet-popup-content-wrapper,
|
||||
.leaflet-oldie .leaflet-popup-tip {
|
||||
border: 1px solid #999;
|
||||
}
|
||||
|
||||
|
||||
/* div icon */
|
||||
|
||||
.leaflet-div-icon {
|
||||
background: #fff;
|
||||
border: 1px solid #666;
|
||||
}
|
||||
|
||||
|
||||
/* Tooltip */
|
||||
/* Base styles for the element that has a tooltip */
|
||||
.leaflet-tooltip {
|
||||
position: absolute;
|
||||
padding: 6px;
|
||||
background-color: #fff;
|
||||
border: 1px solid #fff;
|
||||
border-radius: 3px;
|
||||
color: #222;
|
||||
white-space: nowrap;
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
pointer-events: none;
|
||||
box-shadow: 0 1px 3px rgba(0,0,0,0.4);
|
||||
}
|
||||
.leaflet-tooltip.leaflet-interactive {
|
||||
cursor: pointer;
|
||||
pointer-events: auto;
|
||||
}
|
||||
.leaflet-tooltip-top:before,
|
||||
.leaflet-tooltip-bottom:before,
|
||||
.leaflet-tooltip-left:before,
|
||||
.leaflet-tooltip-right:before {
|
||||
position: absolute;
|
||||
pointer-events: none;
|
||||
border: 6px solid transparent;
|
||||
background: transparent;
|
||||
content: "";
|
||||
}
|
||||
|
||||
/* Directions */
|
||||
|
||||
.leaflet-tooltip-bottom {
|
||||
margin-top: 6px;
|
||||
}
|
||||
.leaflet-tooltip-top {
|
||||
margin-top: -6px;
|
||||
}
|
||||
.leaflet-tooltip-bottom:before,
|
||||
.leaflet-tooltip-top:before {
|
||||
left: 50%;
|
||||
margin-left: -6px;
|
||||
}
|
||||
.leaflet-tooltip-top:before {
|
||||
bottom: 0;
|
||||
margin-bottom: -12px;
|
||||
border-top-color: #fff;
|
||||
}
|
||||
.leaflet-tooltip-bottom:before {
|
||||
top: 0;
|
||||
margin-top: -12px;
|
||||
margin-left: -6px;
|
||||
border-bottom-color: #fff;
|
||||
}
|
||||
.leaflet-tooltip-left {
|
||||
margin-left: -6px;
|
||||
}
|
||||
.leaflet-tooltip-right {
|
||||
margin-left: 6px;
|
||||
}
|
||||
.leaflet-tooltip-left:before,
|
||||
.leaflet-tooltip-right:before {
|
||||
top: 50%;
|
||||
margin-top: -6px;
|
||||
}
|
||||
.leaflet-tooltip-left:before {
|
||||
right: 0;
|
||||
margin-right: -12px;
|
||||
border-left-color: #fff;
|
||||
}
|
||||
.leaflet-tooltip-right:before {
|
||||
left: 0;
|
||||
margin-left: -12px;
|
||||
border-right-color: #fff;
|
||||
}
|
||||
|
||||
/* Printing */
|
||||
|
||||
@media print {
|
||||
/* Prevent printers from removing background-images of controls. */
|
||||
.leaflet-control {
|
||||
-webkit-print-color-adjust: exact;
|
||||
print-color-adjust: exact;
|
||||
}
|
||||
}
|
1
beetroot_static/css/searxng-rtl.min.css
vendored
Normal file
1
beetroot_static/css/searxng-rtl.min.css.map
Normal file
1
beetroot_static/css/searxng.min.css
vendored
Normal file
1
beetroot_static/css/searxng.min.css.map
Normal file
307
beetroot_static/gruntfile.js
Normal file
|
@ -0,0 +1,307 @@
|
|||
/* 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', 'src/**'],
|
||||
tasks: [
|
||||
'eslint',
|
||||
'copy',
|
||||
'uglify',
|
||||
'less',
|
||||
'image',
|
||||
'svg2png',
|
||||
'svg2jinja'
|
||||
]
|
||||
}
|
||||
},
|
||||
eslint: {
|
||||
options: {
|
||||
overrideConfigFile: '.eslintrc.json',
|
||||
failOnError: true,
|
||||
fix: grunt.option('fix')
|
||||
},
|
||||
target: [
|
||||
'gruntfile.js',
|
||||
'svg4web.svgo.js',
|
||||
'src/js/main/*.js',
|
||||
'src/js/head/*.js',
|
||||
],
|
||||
},
|
||||
stylelint: {
|
||||
options: {
|
||||
formatter: 'unix',
|
||||
},
|
||||
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'
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
less: {
|
||||
production: {
|
||||
options: {
|
||||
paths: ["less"],
|
||||
plugins: [
|
||||
new (require('less-plugin-clean-css'))()
|
||||
],
|
||||
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,
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
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: [
|
||||
{ "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']);
|
||||
|
||||
grunt.registerTask('default', [
|
||||
'eslint',
|
||||
'stylelint',
|
||||
'copy',
|
||||
'uglify',
|
||||
'less',
|
||||
'image',
|
||||
'svg2png',
|
||||
'svg2jinja',
|
||||
]);
|
||||
};
|
BIN
beetroot_static/img/favicon.png
Normal file
After Width: | Height: | Size: 14 KiB |
86
beetroot_static/img/favicon.svg
Normal file
|
@ -0,0 +1,86 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
width="92mm"
|
||||
height="92mm"
|
||||
viewBox="0 0 92 92"
|
||||
version="1.1"
|
||||
id="svg283"
|
||||
sodipodi:docname="favicon.svg"
|
||||
inkscape:version="1.2.2 (b0a8486541, 2022-12-01)"
|
||||
inkscape:export-filename="favicon.png"
|
||||
inkscape:export-xdpi="72.058701"
|
||||
inkscape:export-ydpi="72.058701"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs287" />
|
||||
<sodipodi:namedview
|
||||
id="namedview285"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#000000"
|
||||
borderopacity="0.25"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#d1d1d1"
|
||||
inkscape:document-units="mm"
|
||||
showgrid="false"
|
||||
inkscape:zoom="2.2805933"
|
||||
inkscape:cx="187.45122"
|
||||
inkscape:cy="180.87399"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="995"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg283" />
|
||||
<g
|
||||
id="g12851-2"
|
||||
transform="matrix(0.27333337,0,0,0.27333337,-18.69294,-5.0517884)"
|
||||
style="stroke:#50152c;stroke-opacity:0.992157"
|
||||
inkscape:export-filename="/home/fekete/Nextcloud-Antilopa/Disroot/Artwork/Icons/new_pngs/search.png"
|
||||
inkscape:export-xdpi="1080.73"
|
||||
inkscape:export-ydpi="1080.73">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path3814-0-7-1"
|
||||
d="m 80.033739,36.455764 c -7.11959,15.242893 -10.17798,31.779192 -8.22563,48.814566 5.01677,43.77413 41.675291,79.3245 91.536091,95.16289 -6.62576,-22.40752 -5.34093,-44.9362 2.6395,-65.84431 C 118.24672,100.40622 84.338699,71.780528 80.033739,36.455764 Z"
|
||||
style="fill:#50142b;fill-opacity:0.992157;fill-rule:nonzero;stroke:#50152c;stroke-opacity:0.992157" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path3814-0-8"
|
||||
d="m 313.2893,37.799153 c 7.11959,15.242893 10.17798,31.779192 8.22563,48.814566 -5.01677,43.774131 -41.67531,79.324501 -91.53611,95.162891 6.62576,-22.40752 5.34093,-44.9362 -2.6395,-65.84431 47.73698,-14.18269 81.64502,-42.808383 85.94998,-78.133147 z"
|
||||
style="fill:#50142b;fill-opacity:0.992157;fill-rule:nonzero;stroke:#50152c;stroke-opacity:0.992157" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="rect3804-7"
|
||||
d="m 201.77833,175.2842 12.07511,-13.9057 c 4.0785,-4.69679 19.95774,2.45971 35.60368,16.04598 l 130.50177,113.32219 c 15.64593,13.58626 24.95835,28.30512 20.87985,33.00192 l -12.07512,13.9057 c -4.07849,4.69679 -19.95774,-2.45971 -35.60367,-16.04598 L 222.65818,208.28612 C 207.01224,194.69986 197.69983,179.981 201.77833,175.2842 Z"
|
||||
style="fill:#50142b;fill-opacity:0.992157;fill-rule:nonzero;stroke:#50152c;stroke-opacity:0.992157" />
|
||||
<circle
|
||||
r="107.58125"
|
||||
cy="149.35568"
|
||||
cx="196.89389"
|
||||
id="path2987-9"
|
||||
style="fill:#50142b;fill-opacity:0.992157;fill-rule:nonzero;stroke:#50152c;stroke-opacity:0.992157" />
|
||||
<circle
|
||||
r="72.430138"
|
||||
cy="149.10315"
|
||||
cx="196.64131"
|
||||
id="path3757-9-0"
|
||||
style="fill:#ffffff;fill-opacity:0.992157;fill-rule:nonzero;stroke:#50152c;stroke-width:0.713454;stroke-opacity:0.992157" />
|
||||
<circle
|
||||
r="27.274118"
|
||||
cy="150.79912"
|
||||
cx="197.85327"
|
||||
id="path3800-2"
|
||||
style="fill:#50132a;fill-opacity:1;fill-rule:nonzero;stroke:#50152c;stroke-opacity:0.992157" />
|
||||
<circle
|
||||
r="5.5558391"
|
||||
cy="141.34952"
|
||||
cx="208.98526"
|
||||
id="path3802-3"
|
||||
style="fill:#ffffff;fill-opacity:0.992157;fill-rule:nonzero;stroke:#50152c;stroke-opacity:0.992157" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 3.7 KiB |
85
beetroot_static/img/img_load_error.svg
Normal file
|
@ -0,0 +1,85 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
width="92mm"
|
||||
height="92mm"
|
||||
viewBox="0 0 92 92"
|
||||
version="1.1"
|
||||
id="svg283"
|
||||
sodipodi:docname="favicon (copie).svg"
|
||||
inkscape:version="1.2.2 (b0a8486541, 2022-12-01)"
|
||||
inkscape:export-filename="favicon.png"
|
||||
inkscape:export-xdpi="72.058701"
|
||||
inkscape:export-ydpi="72.058701"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs287" />
|
||||
<sodipodi:namedview
|
||||
id="namedview285"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#000000"
|
||||
borderopacity="0.25"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#d1d1d1"
|
||||
inkscape:document-units="mm"
|
||||
showgrid="false"
|
||||
inkscape:zoom="2.2805933"
|
||||
inkscape:cx="187.67046"
|
||||
inkscape:cy="181.75095"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="995"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="g12851-2" />
|
||||
<g
|
||||
id="g12851-2"
|
||||
transform="matrix(0.27333337,0,0,0.27333337,-18.69294,-5.0517884)"
|
||||
style="stroke:#50152c;stroke-opacity:0.992157"
|
||||
inkscape:export-filename="/home/fekete/Nextcloud-Antilopa/Disroot/Artwork/Icons/new_pngs/search.png"
|
||||
inkscape:export-xdpi="1080.73"
|
||||
inkscape:export-ydpi="1080.73">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path3814-0-7-1"
|
||||
d="m 80.033739,36.455764 c -7.11959,15.242893 -10.17798,31.779192 -8.22563,48.814566 5.01677,43.77413 41.675291,79.3245 91.536091,95.16289 -6.62576,-22.40752 -5.34093,-44.9362 2.6395,-65.84431 C 118.24672,100.40622 84.338699,71.780528 80.033739,36.455764 Z"
|
||||
style="fill:#50142b;fill-opacity:0.992157;fill-rule:nonzero;stroke:#50152c;stroke-opacity:0.992157" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path3814-0-8"
|
||||
d="m 313.2893,37.799153 c 7.11959,15.242893 10.17798,31.779192 8.22563,48.814566 -5.01677,43.774131 -41.67531,79.324501 -91.53611,95.162891 6.62576,-22.40752 5.34093,-44.9362 -2.6395,-65.84431 47.73698,-14.18269 81.64502,-42.808383 85.94998,-78.133147 z"
|
||||
style="fill:#50142b;fill-opacity:0.992157;fill-rule:nonzero;stroke:#50152c;stroke-opacity:0.992157" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="rect3804-7"
|
||||
d="m 201.77833,175.2842 12.07511,-13.9057 c 4.0785,-4.69679 19.95774,2.45971 35.60368,16.04598 l 130.50177,113.32219 c 15.64593,13.58626 24.95835,28.30512 20.87985,33.00192 l -12.07512,13.9057 c -4.07849,4.69679 -19.95774,-2.45971 -35.60367,-16.04598 L 222.65818,208.28612 C 207.01224,194.69986 197.69983,179.981 201.77833,175.2842 Z"
|
||||
style="fill:#50142b;fill-opacity:0.992157;fill-rule:nonzero;stroke:#50152c;stroke-opacity:0.992157" />
|
||||
<circle
|
||||
r="107.58125"
|
||||
cy="149.35568"
|
||||
cx="196.89389"
|
||||
id="path2987-9"
|
||||
style="fill:#50142b;fill-opacity:0.992157;fill-rule:nonzero;stroke:#50152c;stroke-opacity:0.992157" />
|
||||
<circle
|
||||
r="72.430138"
|
||||
cy="149.10315"
|
||||
cx="196.64131"
|
||||
id="path3757-9-0"
|
||||
style="fill:#ffffff;fill-opacity:0.992157;fill-rule:nonzero;stroke:#50152c;stroke-width:0.713454;stroke-opacity:0.992157" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-weight:bold;font-size:25.055px;font-family:'Liberation Sans';-inkscape-font-specification:'Liberation Sans Bold';text-align:center;text-anchor:middle;fill:#50162d;stroke-width:6.19641"
|
||||
x="199.42154"
|
||||
y="198.21521"
|
||||
id="text402"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan400"
|
||||
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:150.33px;font-family:'Liberation Sans';-inkscape-font-specification:'Liberation Sans, Bold';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;stroke-width:6.19641"
|
||||
x="199.42154"
|
||||
y="198.21521">?</tspan></text>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 4.1 KiB |
BIN
beetroot_static/img/searxng.png
Normal file
After Width: | Height: | Size: 27 KiB |
65
beetroot_static/img/searxng.svg
Normal file
|
@ -0,0 +1,65 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
width="853.677"
|
||||
height="146.304"
|
||||
viewBox="0 0 225.869 38.71"
|
||||
version="1.1"
|
||||
id="svg6"
|
||||
sodipodi:docname="searxng.svg"
|
||||
inkscape:version="1.2.2 (b0a8486541, 2022-12-01)"
|
||||
inkscape:export-filename="searxng.png"
|
||||
inkscape:export-xdpi="96"
|
||||
inkscape:export-ydpi="96"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs10" />
|
||||
<sodipodi:namedview
|
||||
id="namedview8"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#000000"
|
||||
borderopacity="0.25"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#d1d1d1"
|
||||
showgrid="false"
|
||||
inkscape:zoom="1.017006"
|
||||
inkscape:cx="426.74283"
|
||||
inkscape:cy="81.120468"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="995"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg6" />
|
||||
<g
|
||||
aria-label="SearXNG"
|
||||
style="line-height:1.25;fill:#50162d;fill-opacity:1"
|
||||
font-style="normal"
|
||||
font-weight="400"
|
||||
font-size="50.8px"
|
||||
font-family="sans-serif"
|
||||
fill="#487cff"
|
||||
fill-opacity="1"
|
||||
stroke="none"
|
||||
stroke-width=".264583"
|
||||
id="g4">
|
||||
<path
|
||||
d="M56.494 102.704q-1.168-1.22-3.048-2.032-1.88-.813-4.42-.813-3.15 0-5.08 1.32-1.93 1.27-1.93 3.455 0 2.337 3.708 3.607l7.671 2.641q3.963 1.321 5.842 3.404 1.88 2.083 1.88 5.13 0 4.065-2.185 7.011-2.184 2.896-5.943 4.42-3.76 1.524-8.484 1.524-5.334 0-9.042-1.778-3.709-1.829-5.537-5.131-.204-.356-.204-.711 0-.356.407-.61l4.013-2.438q.356-.254.762-.254.61 0 1.118.66 1.32 1.626 2.387 2.54 1.118.864 2.693 1.321 1.625.457 4.165.457 3.2 0 5.182-1.168 1.981-1.22 1.981-3.76 0-1.27-.914-2.082-.915-.864-2.947-1.575l-7.417-2.49q-3.657-1.218-5.588-3.555-1.88-2.388-1.88-5.436 0-3.759 2.134-6.655 2.134-2.895 5.69-4.47 3.607-1.575 7.874-1.575 4.369 0 7.67 1.575 3.354 1.524 5.182 3.962.407.508.407.762t-.356.458l-4.52 2.997q-.052.05-.204.05-.305 0-1.067-.761zM77.004 132.37q-3.607 0-6.401-1.472-2.794-1.474-4.318-4.115-1.524-2.693-1.524-6.198 0-4.165 1.981-7.874 2.032-3.759 5.537-5.994 3.556-2.286 7.925-2.286 5.334 0 8.484 3.15 3.15 3.149 3.15 8.686 0 1.473-.204 2.845-.101.406-.355.61-.204.152-.813.152h-17.12q-.813 0-.813 2.184 0 2.388 1.524 3.709 1.575 1.27 4.064 1.27 1.93 0 3.607-.813 1.677-.813 3.302-2.54.254-.254.508-.254.153 0 .66.203l3.353 1.575q.61.203.61.66 0 .254-.254.66-2.946 3.303-5.893 4.573-2.895 1.27-7.01 1.27zm6.451-16.56q1.22 0 1.22-1.981 0-1.93-1.169-3.251-1.168-1.372-3.251-1.372-2.54 0-4.521 1.93-1.93 1.88-2.235 4.674zM109.411 129.374q-3.048 2.997-8.331 2.997-3.556 0-5.588-1.829t-2.032-4.775q0-3.607 2.387-5.893 2.388-2.337 5.995-3.353 3.657-1.067 7.569-1.168l1.829-.153q.965 0 1.117-.965l.153-1.067q.05-.254.05-.812 0-3.048-3.505-3.048-4.013 0-5.943 3.15-.254.355-.66.355-.305 0-.458-.051l-4.927-1.168q-.508-.102-.508-.66 0-.509.254-1.017 3.352-5.486 12.649-5.486 5.486 0 8.026 1.93 2.591 1.93 2.591 5.334 0 .457-.102 1.473l-2.54 17.78q-.05.66-.203.813-.152.102-.711.102h-5.232q-.508 0-.66-.305-.153-.305-.204-1.016l.05-1.32q0-.407-.253-.407-.254 0-.813.559zm2.184-9.754v-.305q0-.203-.101-.254-.102-.101-.407-.05l-1.828.152q-2.947.203-5.487 1.473t-2.54 3.912q0 1.219.864 1.98.914.712 2.438.712 1.321 0 2.49-.356 1.168-.406 2.031-1.066 1.88-1.423 2.083-2.896zM123.864 131.863q-.61 0-.915-.356-.254-.355-.152-.914l3.505-24.943q.05-.457.152-.559.153-.152.56-.152h6.044q.915 0 .712 1.067l-.356 2.286v.203q0 .355.203.355.153 0 .457-.304 1.778-1.88 3.963-2.998 2.184-1.117 3.962-1.117 1.067 0 1.575.152.508.153.457.61l-.813 5.69q-.05.558-.203.71-.101.153-.406.102-1.727-.254-3.455-.254-1.32 0-2.794.711-1.473.66-2.54 1.778-1.016 1.067-1.168 2.134l-2.083 14.834q-.101.66-.355.812-.204.153-.966.153zM176.481 130.085q.457.813.457 1.219 0 .305-.254.457-.254.102-.762.102h-7.06q-.61 0-.966-.153-.305-.152-.508-.61l-5.639-11.734q-.254-.508-.508-.508-.152 0-.559.559l-9.042 11.836q-.254.407-.61.508-.304.102-1.066.102h-5.944q-1.016 0-1.016-.66 0-.458.762-1.525l13.005-16.306q.559-.61.559-1.067 0-.356-.102-.559l-8.484-16.56q-.152-.255-.152-.509 0-.508.762-.508h7.417q.66 0 .914.153.254.152.508.66l4.928 10.363q.152.407.355.407.204 0 .508-.407l8.027-10.566q.305-.407.559-.508.304-.102.965-.102h6.553q.61 0 .61.559 0 .406-.305.914l-12.599 15.647q-.508.66-.508.914 0 .203.153.508zM218.113 94.17q.355 0 .457.202.101.153.05.56l-5.13 36.372q-.05.356-.254.457-.153.102-.559.102h-5.182q-.66 0-1.168-.813l-13.106-22.708q-.153-.254-.305-.254-.305 0-.356.56l-3.15 22.402q-.1.508-.304.66-.153.153-.711.153h-5.588q-.813 0-.712-1.118l5.08-35.814q.102-.508.204-.61.152-.152.66-.152h6.147q.508 0 .762.254.305.203.559.711l11.988 21.184q.254.406.508.406.407 0 .458-.61l2.946-21.284q.05-.407.203-.508.203-.153.66-.153zM236.44 132.37q-4.572 0-7.925-1.93-3.353-1.93-5.131-5.435-1.727-3.556-1.727-8.331 0-6.3 2.489-11.532 2.49-5.283 7.061-8.382 4.572-3.099 10.516-3.099 4.064 0 7.163 1.575 3.15 1.575 4.876 4.166 1.728 2.54 1.83 5.435 0 .508-.102.762-.051.203-.254.254l-6.96 1.016h-.05q-.204 0-.356-.254-.102-.254-.254-1.016-.356-2.54-1.93-4.115-1.525-1.574-4.319-1.574-3.607 0-5.994 2.641-2.337 2.642-3.455 6.807-1.117 4.115-1.117 8.586 0 4.368 1.625 6.299 1.677 1.88 4.877 1.88 3.099 0 5.233-1.728 2.133-1.727 3.15-4.216l.304-1.423q.152-.254.152-.355 0-.305-.61-.305h-6.248q-.304 0-.406-.102-.102-.152-.05-.558l.456-4.166q.051-.559.508-.559l14.53.051q.609 0 .761.203.203.153.102.66l-2.49 17.577q-.05.66-.812.66h-1.524q-.457 0-.711-.152-.204-.152-.356-.61l-.864-3.708q-.05-.254-.355-.254t-.66.407q-1.677 2.083-4.37 3.454-2.692 1.372-6.603 1.372z"
|
||||
style="-inkscape-font-specification:'Libre Franklin';fill:#50162d;fill-opacity:1"
|
||||
transform="translate(-29.722 -93.661)"
|
||||
font-style="normal"
|
||||
font-variant="normal"
|
||||
font-weight="400"
|
||||
font-stretch="normal"
|
||||
font-size="50.8px"
|
||||
font-family="Libre Franklin"
|
||||
fill="#487cff"
|
||||
fill-opacity="1"
|
||||
stroke-width=".264583"
|
||||
id="path2" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 6.1 KiB |
6
beetroot_static/js/leaflet.js
Normal file
2
beetroot_static/js/searxng.head.min.js
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
(function(t,e){"use strict";var s=e.currentScript||function(){var t=e.getElementsByTagName("script");return t[t.length-1]}();t.searxng={settings:JSON.parse(atob(s.getAttribute("client_settings")))};var n=e.getElementsByTagName("html")[0];n.classList.remove("no-js");n.classList.add("js")})(window,document);
|
||||
//# sourceMappingURL=searxng.head.min.js.map
|
1
beetroot_static/js/searxng.head.min.js.map
Normal file
|
@ -0,0 +1 @@
|
|||
{"version":3,"file":"searxng.head.min.js","sources":["../src/js/head/00_init.js"],"sourcesContent":["/* SPDX-License-Identifier: AGPL-3.0-or-later */\n(function (w, d) {\n 'use strict';\n\n // add data- properties\n var script = d.currentScript || (function () {\n var scripts = d.getElementsByTagName('script');\n return scripts[scripts.length - 1];\n })();\n\n w.searxng = {\n settings: JSON.parse(atob(script.getAttribute('client_settings')))\n };\n\n // update the css\n var hmtlElement = d.getElementsByTagName(\"html\")[0];\n hmtlElement.classList.remove('no-js');\n hmtlElement.classList.add('js');\n\n})(window, document);\n"],"names":["w","d","script","currentScript","scripts","getElementsByTagName","length","searxng","settings","JSON","parse","atob","getAttribute","hmtlElement","classList","remove","add","window","document"],"mappings":"CACA,SAAWA,EAAGC,gBAIZ,IAAIC,EAASD,EAAEE,eAAkB,WAC/B,IAAIC,EAAUH,EAAEI,qBAAqB,UACrC,OAAOD,EAAQA,EAAQE,OAAS,GAFD,GAKjCN,EAAEO,QAAU,CACVC,SAAUC,KAAKC,MAAMC,KAAKT,EAAOU,aAAa,sBAIhD,IAAIC,EAAcZ,EAAEI,qBAAqB,QAAQ,GACjDQ,EAAYC,UAAUC,OAAO,SAC7BF,EAAYC,UAAUE,IAAI,OAhB5B,CAkBGC,OAAQC"}
|
18
beetroot_static/js/searxng.min.js
vendored
Normal file
1
beetroot_static/js/searxng.min.js.map
Normal file
39
beetroot_static/package.json
Normal file
|
@ -0,0 +1,39 @@
|
|||
{
|
||||
"devDependencies": {
|
||||
"eslint": "^8.18.0",
|
||||
"grunt": "~1.6.1",
|
||||
"grunt-contrib-copy": "^1.0.0",
|
||||
"grunt-contrib-cssmin": "^4.0.0",
|
||||
"grunt-contrib-less": "~3.0.0",
|
||||
"grunt-contrib-uglify": "~5.2.1",
|
||||
"grunt-xmlmin": "~0.1.8",
|
||||
"grunt-contrib-watch": "~1.1.0",
|
||||
"grunt-eslint": "^24.0.0",
|
||||
"grunt-stylelint": "^0.16.0",
|
||||
"grunt-image": "^6.4.0",
|
||||
"ionicons": "^6.0.2",
|
||||
"less": "^4.1.3",
|
||||
"less-plugin-clean-css": "^1.5.1",
|
||||
"sharp": "^0.31.0",
|
||||
"stylelint": "^13.13.1",
|
||||
"stylelint-config-standard": "^22.0.0",
|
||||
"ejs": "^3.1.8",
|
||||
"svgo": "^3.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"autocomplete-js": "2.7.1",
|
||||
"leaflet": "^1.8.0",
|
||||
"normalize.css": "^8.0.1"
|
||||
},
|
||||
"scripts": {
|
||||
"all": "npm install && grunt",
|
||||
"build": "grunt",
|
||||
"test": "grunt test",
|
||||
"eslint": "grunt eslint",
|
||||
"eslint-fix": "grunt eslint --fix",
|
||||
"watch": "grunt watch",
|
||||
"clean": "rm -Rf node_modules package-lock.json",
|
||||
"stylelint": "grunt stylelint",
|
||||
"stylelint-fix": "grunt stylelint --fix"
|
||||
}
|
||||
}
|
99
beetroot_static/src/generated/pygments.less
Normal file
|
@ -0,0 +1,99 @@
|
|||
/*
|
||||
this file is generated automatically by searxng_extra/update/update_pygments.py
|
||||
using pygments version 2.14.0
|
||||
*/
|
||||
|
||||
.code-highlight .linenos {
|
||||
-webkit-touch-callout: none;
|
||||
-webkit-user-select: none;
|
||||
-khtml-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
cursor: default;
|
||||
|
||||
&::selection {
|
||||
background: transparent; /* WebKit/Blink Browsers */
|
||||
}
|
||||
&::-moz-selection {
|
||||
background: transparent; /* Gecko Browsers */
|
||||
}
|
||||
|
||||
margin-right: 8px;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.code-highlight pre { line-height: 125%; }
|
||||
.code-highlight td.linenos .normal { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }
|
||||
.code-highlight span.linenos { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }
|
||||
.code-highlight td.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }
|
||||
.code-highlight span.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }
|
||||
.code-highlight .hll { background-color: #ffffcc }
|
||||
.code-highlight { background: #f8f8f8; }
|
||||
.code-highlight .c { color: #3D7B7B; font-style: italic } /* Comment */
|
||||
.code-highlight .err { border: 1px solid #FF0000 } /* Error */
|
||||
.code-highlight .k { color: #008000; font-weight: bold } /* Keyword */
|
||||
.code-highlight .o { color: #666666 } /* Operator */
|
||||
.code-highlight .ch { color: #3D7B7B; font-style: italic } /* Comment.Hashbang */
|
||||
.code-highlight .cm { color: #3D7B7B; font-style: italic } /* Comment.Multiline */
|
||||
.code-highlight .cp { color: #9C6500 } /* Comment.Preproc */
|
||||
.code-highlight .cpf { color: #3D7B7B; font-style: italic } /* Comment.PreprocFile */
|
||||
.code-highlight .c1 { color: #3D7B7B; font-style: italic } /* Comment.Single */
|
||||
.code-highlight .cs { color: #3D7B7B; font-style: italic } /* Comment.Special */
|
||||
.code-highlight .gd { color: #A00000 } /* Generic.Deleted */
|
||||
.code-highlight .ge { font-style: italic } /* Generic.Emph */
|
||||
.code-highlight .gr { color: #E40000 } /* Generic.Error */
|
||||
.code-highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */
|
||||
.code-highlight .gi { color: #008400 } /* Generic.Inserted */
|
||||
.code-highlight .go { color: #717171 } /* Generic.Output */
|
||||
.code-highlight .gp { color: #000080; font-weight: bold } /* Generic.Prompt */
|
||||
.code-highlight .gs { font-weight: bold } /* Generic.Strong */
|
||||
.code-highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */
|
||||
.code-highlight .gt { color: #0044DD } /* Generic.Traceback */
|
||||
.code-highlight .kc { color: #008000; font-weight: bold } /* Keyword.Constant */
|
||||
.code-highlight .kd { color: #008000; font-weight: bold } /* Keyword.Declaration */
|
||||
.code-highlight .kn { color: #008000; font-weight: bold } /* Keyword.Namespace */
|
||||
.code-highlight .kp { color: #008000 } /* Keyword.Pseudo */
|
||||
.code-highlight .kr { color: #008000; font-weight: bold } /* Keyword.Reserved */
|
||||
.code-highlight .kt { color: #B00040 } /* Keyword.Type */
|
||||
.code-highlight .m { color: #666666 } /* Literal.Number */
|
||||
.code-highlight .s { color: #BA2121 } /* Literal.String */
|
||||
.code-highlight .na { color: #687822 } /* Name.Attribute */
|
||||
.code-highlight .nb { color: #008000 } /* Name.Builtin */
|
||||
.code-highlight .nc { color: #0000FF; font-weight: bold } /* Name.Class */
|
||||
.code-highlight .no { color: #880000 } /* Name.Constant */
|
||||
.code-highlight .nd { color: #AA22FF } /* Name.Decorator */
|
||||
.code-highlight .ni { color: #717171; font-weight: bold } /* Name.Entity */
|
||||
.code-highlight .ne { color: #CB3F38; font-weight: bold } /* Name.Exception */
|
||||
.code-highlight .nf { color: #0000FF } /* Name.Function */
|
||||
.code-highlight .nl { color: #767600 } /* Name.Label */
|
||||
.code-highlight .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */
|
||||
.code-highlight .nt { color: #008000; font-weight: bold } /* Name.Tag */
|
||||
.code-highlight .nv { color: #19177C } /* Name.Variable */
|
||||
.code-highlight .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */
|
||||
.code-highlight .w { color: #bbbbbb } /* Text.Whitespace */
|
||||
.code-highlight .mb { color: #666666 } /* Literal.Number.Bin */
|
||||
.code-highlight .mf { color: #666666 } /* Literal.Number.Float */
|
||||
.code-highlight .mh { color: #666666 } /* Literal.Number.Hex */
|
||||
.code-highlight .mi { color: #666666 } /* Literal.Number.Integer */
|
||||
.code-highlight .mo { color: #666666 } /* Literal.Number.Oct */
|
||||
.code-highlight .sa { color: #BA2121 } /* Literal.String.Affix */
|
||||
.code-highlight .sb { color: #BA2121 } /* Literal.String.Backtick */
|
||||
.code-highlight .sc { color: #BA2121 } /* Literal.String.Char */
|
||||
.code-highlight .dl { color: #BA2121 } /* Literal.String.Delimiter */
|
||||
.code-highlight .sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */
|
||||
.code-highlight .s2 { color: #BA2121 } /* Literal.String.Double */
|
||||
.code-highlight .se { color: #AA5D1F; font-weight: bold } /* Literal.String.Escape */
|
||||
.code-highlight .sh { color: #BA2121 } /* Literal.String.Heredoc */
|
||||
.code-highlight .si { color: #A45A77; font-weight: bold } /* Literal.String.Interpol */
|
||||
.code-highlight .sx { color: #008000 } /* Literal.String.Other */
|
||||
.code-highlight .sr { color: #A45A77 } /* Literal.String.Regex */
|
||||
.code-highlight .s1 { color: #BA2121 } /* Literal.String.Single */
|
||||
.code-highlight .ss { color: #19177C } /* Literal.String.Symbol */
|
||||
.code-highlight .bp { color: #008000 } /* Name.Builtin.Pseudo */
|
||||
.code-highlight .fm { color: #0000FF } /* Name.Function.Magic */
|
||||
.code-highlight .vc { color: #19177C } /* Name.Variable.Class */
|
||||
.code-highlight .vg { color: #19177C } /* Name.Variable.Global */
|
||||
.code-highlight .vi { color: #19177C } /* Name.Variable.Instance */
|
||||
.code-highlight .vm { color: #19177C } /* Name.Variable.Magic */
|
||||
.code-highlight .il { color: #666666 } /* Literal.Number.Integer.Long */
|
20
beetroot_static/src/js/head/00_init.js
Normal file
|
@ -0,0 +1,20 @@
|
|||
/* SPDX-License-Identifier: AGPL-3.0-or-later */
|
||||
(function (w, d) {
|
||||
'use strict';
|
||||
|
||||
// add data- properties
|
||||
var script = d.currentScript || (function () {
|
||||
var scripts = d.getElementsByTagName('script');
|
||||
return scripts[scripts.length - 1];
|
||||
})();
|
||||
|
||||
w.searxng = {
|
||||
settings: JSON.parse(atob(script.getAttribute('client_settings')))
|
||||
};
|
||||
|
||||
// update the css
|
||||
var hmtlElement = d.getElementsByTagName("html")[0];
|
||||
hmtlElement.classList.remove('no-js');
|
||||
hmtlElement.classList.add('js');
|
||||
|
||||
})(window, document);
|
165
beetroot_static/src/js/main/00_toolkit.js
Normal file
|
@ -0,0 +1,165 @@
|
|||
/**
|
||||
* @license
|
||||
* (C) Copyright Contributors to the SearXNG project.
|
||||
* (C) Copyright Contributors to the searx project (2014 - 2021).
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
window.searxng = (function (w, d) {
|
||||
|
||||
'use strict';
|
||||
|
||||
// not invented here tookit with bugs fixed elsewhere
|
||||
// purposes : be just good enough and as small as possible
|
||||
|
||||
// from https://plainjs.com/javascript/events/live-binding-event-handlers-14/
|
||||
if (w.Element) {
|
||||
(function (ElementPrototype) {
|
||||
ElementPrototype.matches = ElementPrototype.matches ||
|
||||
ElementPrototype.matchesSelector ||
|
||||
ElementPrototype.webkitMatchesSelector ||
|
||||
ElementPrototype.msMatchesSelector ||
|
||||
function (selector) {
|
||||
var node = this, nodes = (node.parentNode || node.document).querySelectorAll(selector), i = -1;
|
||||
while (nodes[++i] && nodes[i] != node);
|
||||
return !!nodes[i];
|
||||
};
|
||||
})(Element.prototype);
|
||||
}
|
||||
|
||||
function callbackSafe (callback, el, e) {
|
||||
try {
|
||||
callback.call(el, e);
|
||||
} catch (exception) {
|
||||
console.log(exception);
|
||||
}
|
||||
}
|
||||
|
||||
var searxng = window.searxng || {};
|
||||
|
||||
searxng.on = function (obj, eventType, callback, useCapture) {
|
||||
useCapture = useCapture || false;
|
||||
if (typeof obj !== 'string') {
|
||||
// obj HTMLElement, HTMLDocument
|
||||
obj.addEventListener(eventType, callback, useCapture);
|
||||
} else {
|
||||
// obj is a selector
|
||||
d.addEventListener(eventType, function (e) {
|
||||
var el = e.target || e.srcElement, found = false;
|
||||
while (el && el.matches && el !== d && !(found = el.matches(obj))) el = el.parentElement;
|
||||
if (found) callbackSafe(callback, el, e);
|
||||
}, useCapture);
|
||||
}
|
||||
};
|
||||
|
||||
searxng.ready = function (callback) {
|
||||
if (document.readyState != 'loading') {
|
||||
callback.call(w);
|
||||
} else {
|
||||
w.addEventListener('DOMContentLoaded', callback.bind(w));
|
||||
}
|
||||
};
|
||||
|
||||
searxng.http = function (method, url, data = null) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
try {
|
||||
var req = new XMLHttpRequest();
|
||||
req.open(method, url, true);
|
||||
req.timeout = 20000;
|
||||
|
||||
// On load
|
||||
req.onload = function () {
|
||||
if (req.status == 200) {
|
||||
resolve(req.response, req.responseType);
|
||||
} else {
|
||||
reject(Error(req.statusText));
|
||||
}
|
||||
};
|
||||
|
||||
// Handle network errors
|
||||
req.onerror = function () {
|
||||
reject(Error("Network Error"));
|
||||
};
|
||||
|
||||
req.onabort = function () {
|
||||
reject(Error("Transaction is aborted"));
|
||||
};
|
||||
|
||||
req.ontimeout = function () {
|
||||
reject(Error("Timeout"));
|
||||
}
|
||||
|
||||
// Make the request
|
||||
if (data) {
|
||||
req.send(data)
|
||||
} else {
|
||||
req.send();
|
||||
}
|
||||
} catch (ex) {
|
||||
reject(ex);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
searxng.loadStyle = function (src) {
|
||||
var path = searxng.settings.theme_static_path + "/" + src,
|
||||
id = "style_" + src.replace('.', '_'),
|
||||
s = d.getElementById(id);
|
||||
if (s === null) {
|
||||
s = d.createElement('link');
|
||||
s.setAttribute('id', id);
|
||||
s.setAttribute('rel', 'stylesheet');
|
||||
s.setAttribute('type', 'text/css');
|
||||
s.setAttribute('href', path);
|
||||
d.body.appendChild(s);
|
||||
}
|
||||
};
|
||||
|
||||
searxng.loadScript = function (src, callback) {
|
||||
var path = searxng.settings.theme_static_path + "/" + src,
|
||||
id = "script_" + src.replace('.', '_'),
|
||||
s = d.getElementById(id);
|
||||
if (s === null) {
|
||||
s = d.createElement('script');
|
||||
s.setAttribute('id', id);
|
||||
s.setAttribute('src', path);
|
||||
s.onload = callback;
|
||||
s.onerror = function () {
|
||||
s.setAttribute('error', '1');
|
||||
};
|
||||
d.body.appendChild(s);
|
||||
} else if (!s.hasAttribute('error')) {
|
||||
try {
|
||||
callback.apply(s, []);
|
||||
} catch (exception) {
|
||||
console.log(exception);
|
||||
}
|
||||
} else {
|
||||
console.log("callback not executed : script '" + path + "' not loaded.");
|
||||
}
|
||||
};
|
||||
|
||||
searxng.insertBefore = function (newNode, referenceNode) {
|
||||
referenceNode.parentNode.insertBefore(newNode, referenceNode);
|
||||
};
|
||||
|
||||
searxng.insertAfter = function (newNode, referenceNode) {
|
||||
referenceNode.parentNode.insertAfter(newNode, referenceNode.nextSibling);
|
||||
};
|
||||
|
||||
searxng.on('.close', 'click', function () {
|
||||
this.parentNode.classList.add('invisible');
|
||||
});
|
||||
|
||||
function getEndpoint () {
|
||||
for (var className of d.getElementsByTagName('body')[0].classList.values()) {
|
||||
if (className.endsWith('_endpoint')) {
|
||||
return className.split('_')[0];
|
||||
}
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
searxng.endpoint = getEndpoint();
|
||||
|
||||
return searxng;
|
||||
})(window, document);
|
88
beetroot_static/src/js/main/infinite_scroll.js
Normal file
|
@ -0,0 +1,88 @@
|
|||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
/* global searxng */
|
||||
|
||||
searxng.ready(function () {
|
||||
'use strict';
|
||||
|
||||
searxng.infinite_scroll_supported = (
|
||||
'IntersectionObserver' in window &&
|
||||
'IntersectionObserverEntry' in window &&
|
||||
'intersectionRatio' in window.IntersectionObserverEntry.prototype);
|
||||
|
||||
if (searxng.endpoint !== 'results') {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!searxng.infinite_scroll_supported) {
|
||||
console.log('IntersectionObserver not supported');
|
||||
return;
|
||||
}
|
||||
|
||||
let d = document;
|
||||
var onlyImages = d.getElementById('results').classList.contains('only_template_images');
|
||||
|
||||
function newLoadSpinner () {
|
||||
var loader = d.createElement('div');
|
||||
loader.classList.add('loader');
|
||||
return loader;
|
||||
}
|
||||
|
||||
function replaceChildrenWith (element, children) {
|
||||
element.textContent = '';
|
||||
children.forEach(child => element.appendChild(child));
|
||||
}
|
||||
|
||||
function loadNextPage (callback) {
|
||||
var form = d.querySelector('#pagination form.next_page');
|
||||
if (!form) {
|
||||
return
|
||||
}
|
||||
replaceChildrenWith(d.querySelector('#pagination'), [ newLoadSpinner() ]);
|
||||
var formData = new FormData(form);
|
||||
searxng.http('POST', d.querySelector('#search').getAttribute('action'), formData).then(
|
||||
function (response) {
|
||||
var nextPageDoc = new DOMParser().parseFromString(response, 'text/html');
|
||||
var articleList = nextPageDoc.querySelectorAll('#urls article');
|
||||
var paginationElement = nextPageDoc.querySelector('#pagination');
|
||||
d.querySelector('#pagination').remove();
|
||||
if (articleList.length > 0 && !onlyImages) {
|
||||
// do not add <hr> element when there are only images
|
||||
d.querySelector('#urls').appendChild(d.createElement('hr'));
|
||||
}
|
||||
articleList.forEach(articleElement => {
|
||||
d.querySelector('#urls').appendChild(articleElement);
|
||||
});
|
||||
if (paginationElement) {
|
||||
d.querySelector('#results').appendChild(paginationElement);
|
||||
callback();
|
||||
}
|
||||
}
|
||||
).catch(
|
||||
function (err) {
|
||||
console.log(err);
|
||||
var e = d.createElement('div');
|
||||
e.textContent = searxng.settings.translations.error_loading_next_page;
|
||||
e.classList.add('dialog-error');
|
||||
e.setAttribute('role', 'alert');
|
||||
replaceChildrenWith(d.querySelector('#pagination'), [ e ]);
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
if (searxng.settings.infinite_scroll && searxng.infinite_scroll_supported) {
|
||||
const intersectionObserveOptions = {
|
||||
rootMargin: "20rem",
|
||||
};
|
||||
const observedSelector = 'article.result:last-child';
|
||||
const observer = new IntersectionObserver(entries => {
|
||||
const paginationEntry = entries[0];
|
||||
if (paginationEntry.isIntersecting) {
|
||||
observer.unobserve(paginationEntry.target);
|
||||
loadNextPage(() => observer.observe(d.querySelector(observedSelector), intersectionObserveOptions));
|
||||
}
|
||||
});
|
||||
observer.observe(d.querySelector(observedSelector), intersectionObserveOptions);
|
||||
}
|
||||
|
||||
});
|
421
beetroot_static/src/js/main/keyboard.js
Normal file
|
@ -0,0 +1,421 @@
|
|||
/* SPDX-License-Identifier: AGPL-3.0-or-later */
|
||||
/* global searxng */
|
||||
|
||||
searxng.ready(function () {
|
||||
|
||||
function isElementInDetail (el) {
|
||||
while (el !== undefined) {
|
||||
if (el.classList.contains('detail')) {
|
||||
return true;
|
||||
}
|
||||
if (el.classList.contains('result')) {
|
||||
// we found a result, no need to go to the root of the document:
|
||||
// el is not inside a <div class="detail"> element
|
||||
return false;
|
||||
}
|
||||
el = el.parentNode;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function getResultElement (el) {
|
||||
while (el !== undefined) {
|
||||
if (el.classList.contains('result')) {
|
||||
return el;
|
||||
}
|
||||
el = el.parentNode;
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function isImageResult (resultElement) {
|
||||
return resultElement && resultElement.classList.contains('result-images');
|
||||
}
|
||||
|
||||
searxng.on('.result', 'click', function (e) {
|
||||
if (!isElementInDetail(e.target)) {
|
||||
highlightResult(this)(true, true);
|
||||
let resultElement = getResultElement(e.target);
|
||||
if (isImageResult(resultElement)) {
|
||||
e.preventDefault();
|
||||
searxng.selectImage(resultElement);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
searxng.on('.result a', 'focus', function (e) {
|
||||
if (!isElementInDetail(e.target)) {
|
||||
let resultElement = getResultElement(e.target);
|
||||
if (resultElement && resultElement.getAttribute("data-vim-selected") === null) {
|
||||
highlightResult(resultElement)(true);
|
||||
}
|
||||
if (isImageResult(resultElement)) {
|
||||
searxng.selectImage(resultElement);
|
||||
}
|
||||
}
|
||||
}, true);
|
||||
|
||||
var vimKeys = {
|
||||
27: {
|
||||
key: 'Escape',
|
||||
fun: removeFocus,
|
||||
des: 'remove focus from the focused input',
|
||||
cat: 'Control'
|
||||
},
|
||||
73: {
|
||||
key: 'i',
|
||||
fun: searchInputFocus,
|
||||
des: 'focus on the search input',
|
||||
cat: 'Control'
|
||||
},
|
||||
66: {
|
||||
key: 'b',
|
||||
fun: scrollPage(-window.innerHeight),
|
||||
des: 'scroll one page up',
|
||||
cat: 'Navigation'
|
||||
},
|
||||
70: {
|
||||
key: 'f',
|
||||
fun: scrollPage(window.innerHeight),
|
||||
des: 'scroll one page down',
|
||||
cat: 'Navigation'
|
||||
},
|
||||
85: {
|
||||
key: 'u',
|
||||
fun: scrollPage(-window.innerHeight / 2),
|
||||
des: 'scroll half a page up',
|
||||
cat: 'Navigation'
|
||||
},
|
||||
68: {
|
||||
key: 'd',
|
||||
fun: scrollPage(window.innerHeight / 2),
|
||||
des: 'scroll half a page down',
|
||||
cat: 'Navigation'
|
||||
},
|
||||
71: {
|
||||
key: 'g',
|
||||
fun: scrollPageTo(-document.body.scrollHeight, 'top'),
|
||||
des: 'scroll to the top of the page',
|
||||
cat: 'Navigation'
|
||||
},
|
||||
86: {
|
||||
key: 'v',
|
||||
fun: scrollPageTo(document.body.scrollHeight, 'bottom'),
|
||||
des: 'scroll to the bottom of the page',
|
||||
cat: 'Navigation'
|
||||
},
|
||||
75: {
|
||||
key: 'k',
|
||||
fun: highlightResult('up'),
|
||||
des: 'select previous search result',
|
||||
cat: 'Results'
|
||||
},
|
||||
74: {
|
||||
key: 'j',
|
||||
fun: highlightResult('down'),
|
||||
des: 'select next search result',
|
||||
cat: 'Results'
|
||||
},
|
||||
80: {
|
||||
key: 'p',
|
||||
fun: GoToPreviousPage(),
|
||||
des: 'go to previous page',
|
||||
cat: 'Results'
|
||||
},
|
||||
78: {
|
||||
key: 'n',
|
||||
fun: GoToNextPage(),
|
||||
des: 'go to next page',
|
||||
cat: 'Results'
|
||||
},
|
||||
79: {
|
||||
key: 'o',
|
||||
fun: openResult(false),
|
||||
des: 'open search result',
|
||||
cat: 'Results'
|
||||
},
|
||||
84: {
|
||||
key: 't',
|
||||
fun: openResult(true),
|
||||
des: 'open the result in a new tab',
|
||||
cat: 'Results'
|
||||
},
|
||||
82: {
|
||||
key: 'r',
|
||||
fun: reloadPage,
|
||||
des: 'reload page from the server',
|
||||
cat: 'Control'
|
||||
},
|
||||
72: {
|
||||
key: 'h',
|
||||
fun: toggleHelp,
|
||||
des: 'toggle help window',
|
||||
cat: 'Other'
|
||||
}
|
||||
};
|
||||
|
||||
if (searxng.settings.hotkeys) {
|
||||
searxng.on(document, "keydown", function (e) {
|
||||
// check for modifiers so we don't break browser's hotkeys
|
||||
if (Object.prototype.hasOwnProperty.call(vimKeys, e.keyCode) && !e.ctrlKey && !e.altKey && !e.shiftKey && !e.metaKey) {
|
||||
var tagName = e.target.tagName.toLowerCase();
|
||||
if (e.keyCode === 27) {
|
||||
vimKeys[e.keyCode].fun(e);
|
||||
} else {
|
||||
if (e.target === document.body || tagName === 'a' || tagName === 'button') {
|
||||
e.preventDefault();
|
||||
vimKeys[e.keyCode].fun();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function highlightResult (which) {
|
||||
return function (noScroll, keepFocus) {
|
||||
var current = document.querySelector('.result[data-vim-selected]'),
|
||||
effectiveWhich = which;
|
||||
if (current === null) {
|
||||
// no selection : choose the first one
|
||||
current = document.querySelector('.result');
|
||||
if (current === null) {
|
||||
// no first one : there are no results
|
||||
return;
|
||||
}
|
||||
// replace up/down actions by selecting first one
|
||||
if (which === "down" || which === "up") {
|
||||
effectiveWhich = current;
|
||||
}
|
||||
}
|
||||
|
||||
var next, results = document.querySelectorAll('.result');
|
||||
|
||||
if (typeof effectiveWhich !== 'string') {
|
||||
next = effectiveWhich;
|
||||
} else {
|
||||
switch (effectiveWhich) {
|
||||
case 'visible':
|
||||
var top = document.documentElement.scrollTop || document.body.scrollTop;
|
||||
var bot = top + document.documentElement.clientHeight;
|
||||
|
||||
for (var i = 0; i < results.length; i++) {
|
||||
next = results[i];
|
||||
var etop = next.offsetTop;
|
||||
var ebot = etop + next.clientHeight;
|
||||
|
||||
if ((ebot <= bot) && (etop > top)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'down':
|
||||
next = current.nextElementSibling;
|
||||
if (next === null) {
|
||||
next = results[0];
|
||||
}
|
||||
break;
|
||||
case 'up':
|
||||
next = current.previousElementSibling;
|
||||
if (next === null) {
|
||||
next = results[results.length - 1];
|
||||
}
|
||||
break;
|
||||
case 'bottom':
|
||||
next = results[results.length - 1];
|
||||
break;
|
||||
case 'top':
|
||||
/* falls through */
|
||||
default:
|
||||
next = results[0];
|
||||
}
|
||||
}
|
||||
|
||||
if (next) {
|
||||
current.removeAttribute('data-vim-selected');
|
||||
next.setAttribute('data-vim-selected', 'true');
|
||||
if (!keepFocus) {
|
||||
var link = next.querySelector('h3 a') || next.querySelector('a');
|
||||
if (link !== null) {
|
||||
link.focus();
|
||||
}
|
||||
}
|
||||
if (!noScroll) {
|
||||
scrollPageToSelected();
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function reloadPage () {
|
||||
document.location.reload(true);
|
||||
}
|
||||
|
||||
function removeFocus (e) {
|
||||
const tagName = e.target.tagName.toLowerCase();
|
||||
if (document.activeElement && (tagName === 'input' || tagName === 'select' || tagName === 'textarea')) {
|
||||
document.activeElement.blur();
|
||||
} else {
|
||||
searxng.closeDetail();
|
||||
}
|
||||
}
|
||||
|
||||
function pageButtonClick (css_selector) {
|
||||
return function () {
|
||||
var button = document.querySelector(css_selector);
|
||||
if (button) {
|
||||
button.click();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function GoToNextPage () {
|
||||
return pageButtonClick('nav#pagination .next_page button[type="submit"]');
|
||||
}
|
||||
|
||||
function GoToPreviousPage () {
|
||||
return pageButtonClick('nav#pagination .previous_page button[type="submit"]');
|
||||
}
|
||||
|
||||
function scrollPageToSelected () {
|
||||
var sel = document.querySelector('.result[data-vim-selected]');
|
||||
if (sel === null) {
|
||||
return;
|
||||
}
|
||||
var wtop = document.documentElement.scrollTop || document.body.scrollTop,
|
||||
wheight = document.documentElement.clientHeight,
|
||||
etop = sel.offsetTop,
|
||||
ebot = etop + sel.clientHeight,
|
||||
offset = 120;
|
||||
// first element ?
|
||||
if ((sel.previousElementSibling === null) && (ebot < wheight)) {
|
||||
// set to the top of page if the first element
|
||||
// is fully included in the viewport
|
||||
window.scroll(window.scrollX, 0);
|
||||
return;
|
||||
}
|
||||
if (wtop > (etop - offset)) {
|
||||
window.scroll(window.scrollX, etop - offset);
|
||||
} else {
|
||||
var wbot = wtop + wheight;
|
||||
if (wbot < (ebot + offset)) {
|
||||
window.scroll(window.scrollX, ebot - wheight + offset);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function scrollPage (amount) {
|
||||
return function () {
|
||||
window.scrollBy(0, amount);
|
||||
highlightResult('visible')();
|
||||
};
|
||||
}
|
||||
|
||||
function scrollPageTo (position, nav) {
|
||||
return function () {
|
||||
window.scrollTo(0, position);
|
||||
highlightResult(nav)();
|
||||
};
|
||||
}
|
||||
|
||||
function searchInputFocus () {
|
||||
window.scrollTo(0, 0);
|
||||
var q = document.querySelector('#q');
|
||||
q.focus();
|
||||
if (q.setSelectionRange) {
|
||||
var len = q.value.length;
|
||||
q.setSelectionRange(len, len);
|
||||
}
|
||||
}
|
||||
|
||||
function openResult (newTab) {
|
||||
return function () {
|
||||
var link = document.querySelector('.result[data-vim-selected] h3 a');
|
||||
if (link === null) {
|
||||
link = document.querySelector('.result[data-vim-selected] > a');
|
||||
}
|
||||
if (link !== null) {
|
||||
var url = link.getAttribute('href');
|
||||
if (newTab) {
|
||||
window.open(url);
|
||||
} else {
|
||||
window.location.href = url;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function initHelpContent (divElement) {
|
||||
var categories = {};
|
||||
|
||||
for (var k in vimKeys) {
|
||||
var key = vimKeys[k];
|
||||
categories[key.cat] = categories[key.cat] || [];
|
||||
categories[key.cat].push(key);
|
||||
}
|
||||
|
||||
var sorted = Object.keys(categories).sort(function (a, b) {
|
||||
return categories[b].length - categories[a].length;
|
||||
});
|
||||
|
||||
if (sorted.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
var html = '<a href="#" class="close" aria-label="close" title="close">×</a>';
|
||||
html += '<h3>How to navigate searx with Vim-like hotkeys</h3>';
|
||||
html += '<table>';
|
||||
|
||||
for (var i = 0; i < sorted.length; i++) {
|
||||
var cat = categories[sorted[i]];
|
||||
|
||||
var lastCategory = i === (sorted.length - 1);
|
||||
var first = i % 2 === 0;
|
||||
|
||||
if (first) {
|
||||
html += '<tr>';
|
||||
}
|
||||
html += '<td>';
|
||||
|
||||
html += '<h4>' + cat[0].cat + '</h4>';
|
||||
html += '<ul class="list-unstyled">';
|
||||
|
||||
for (var cj in cat) {
|
||||
html += '<li><kbd>' + cat[cj].key + '</kbd> ' + cat[cj].des + '</li>';
|
||||
}
|
||||
|
||||
html += '</ul>';
|
||||
html += '</td>'; // col-sm-*
|
||||
|
||||
if (!first || lastCategory) {
|
||||
html += '</tr>'; // row
|
||||
}
|
||||
}
|
||||
|
||||
html += '</table>';
|
||||
|
||||
divElement.innerHTML = html;
|
||||
}
|
||||
|
||||
function toggleHelp () {
|
||||
var helpPanel = document.querySelector('#vim-hotkeys-help');
|
||||
if (helpPanel === undefined || helpPanel === null) {
|
||||
// first call
|
||||
helpPanel = document.createElement('div');
|
||||
helpPanel.id = 'vim-hotkeys-help';
|
||||
helpPanel.className = 'dialog-modal';
|
||||
initHelpContent(helpPanel);
|
||||
initHelpContent(helpPanel);
|
||||
initHelpContent(helpPanel);
|
||||
var body = document.getElementsByTagName('body')[0];
|
||||
body.appendChild(helpPanel);
|
||||
} else {
|
||||
// togggle hidden
|
||||
helpPanel.classList.toggle('invisible');
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
searxng.scrollPageToSelected = scrollPageToSelected;
|
||||
searxng.selectNext = highlightResult('down');
|
||||
searxng.selectPrevious = highlightResult('up');
|
||||
});
|
74
beetroot_static/src/js/main/mapresult.js
Normal file
|
@ -0,0 +1,74 @@
|
|||
/* SPDX-License-Identifier: AGPL-3.0-or-later */
|
||||
/* global L */
|
||||
(function (w, d, searxng) {
|
||||
'use strict';
|
||||
|
||||
searxng.ready(function () {
|
||||
searxng.on('.searxng_init_map', 'click', function (event) {
|
||||
// no more request
|
||||
this.classList.remove("searxng_init_map");
|
||||
|
||||
//
|
||||
var leaflet_target = this.dataset.leafletTarget;
|
||||
var map_lon = parseFloat(this.dataset.mapLon);
|
||||
var map_lat = parseFloat(this.dataset.mapLat);
|
||||
var map_zoom = parseFloat(this.dataset.mapZoom);
|
||||
var map_boundingbox = JSON.parse(this.dataset.mapBoundingbox);
|
||||
var map_geojson = JSON.parse(this.dataset.mapGeojson);
|
||||
|
||||
searxng.loadStyle('css/leaflet.css');
|
||||
searxng.loadScript('js/leaflet.js', function () {
|
||||
var map_bounds = null;
|
||||
if (map_boundingbox) {
|
||||
var southWest = L.latLng(map_boundingbox[0], map_boundingbox[2]);
|
||||
var northEast = L.latLng(map_boundingbox[1], map_boundingbox[3]);
|
||||
map_bounds = L.latLngBounds(southWest, northEast);
|
||||
}
|
||||
|
||||
// init map
|
||||
var map = L.map(leaflet_target);
|
||||
// create the tile layer with correct attribution
|
||||
var osmMapnikUrl = 'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png';
|
||||
var osmMapnikAttrib = 'Map data © <a href="https://openstreetmap.org">OpenStreetMap</a> contributors';
|
||||
var osmMapnik = new L.TileLayer(osmMapnikUrl, {minZoom: 1, maxZoom: 19, attribution: osmMapnikAttrib});
|
||||
var osmWikimediaUrl = 'https://maps.wikimedia.org/osm-intl/{z}/{x}/{y}.png';
|
||||
var osmWikimediaAttrib = 'Wikimedia maps | Maps data © <a href="https://openstreetmap.org">OpenStreetMap contributors</a>';
|
||||
var osmWikimedia = new L.TileLayer(osmWikimediaUrl, {minZoom: 1, maxZoom: 19, attribution: osmWikimediaAttrib});
|
||||
// init map view
|
||||
if (map_bounds) {
|
||||
// TODO hack: https://github.com/Leaflet/Leaflet/issues/2021
|
||||
// Still useful ?
|
||||
setTimeout(function () {
|
||||
map.fitBounds(map_bounds, {
|
||||
maxZoom: 17
|
||||
});
|
||||
}, 0);
|
||||
} else if (map_lon && map_lat) {
|
||||
if (map_zoom) {
|
||||
map.setView(new L.latLng(map_lat, map_lon), map_zoom);
|
||||
} else {
|
||||
map.setView(new L.latLng(map_lat, map_lon), 8);
|
||||
}
|
||||
}
|
||||
|
||||
map.addLayer(osmMapnik);
|
||||
|
||||
var baseLayers = {
|
||||
"OSM Mapnik": osmMapnik,
|
||||
"OSM Wikimedia": osmWikimedia,
|
||||
};
|
||||
|
||||
L.control.layers(baseLayers).addTo(map);
|
||||
|
||||
if (map_geojson) {
|
||||
L.geoJson(map_geojson).addTo(map);
|
||||
} /* else if(map_bounds) {
|
||||
L.rectangle(map_bounds, {color: "#ff7800", weight: 3, fill:false}).addTo(map);
|
||||
} */
|
||||
});
|
||||
|
||||
// this event occour only once per element
|
||||
event.preventDefault();
|
||||
});
|
||||
});
|
||||
})(window, document, window.searxng);
|
30
beetroot_static/src/js/main/preferences.js
Normal file
|
@ -0,0 +1,30 @@
|
|||
/* SPDX-License-Identifier: AGPL-3.0-or-later */
|
||||
(function (w, d, searxng) {
|
||||
'use strict';
|
||||
|
||||
if (searxng.endpoint !== 'preferences') {
|
||||
return;
|
||||
}
|
||||
|
||||
searxng.ready(function () {
|
||||
let engine_descriptions = null;
|
||||
function load_engine_descriptions () {
|
||||
if (engine_descriptions == null) {
|
||||
searxng.http("GET", "engine_descriptions.json").then(function (content) {
|
||||
engine_descriptions = JSON.parse(content);
|
||||
for (const [engine_name, description] of Object.entries(engine_descriptions)) {
|
||||
let elements = d.querySelectorAll('[data-engine-name="' + engine_name + '"] .engine-description');
|
||||
for (const element of elements) {
|
||||
let source = ' (<i>' + searxng.settings.translations.Source + ': ' + description[1] + '</i>)';
|
||||
element.innerHTML = description[0] + source;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
for (const el of d.querySelectorAll('[data-engine-name]')) {
|
||||
searxng.on(el, 'mouseenter', load_engine_descriptions);
|
||||
}
|
||||
});
|
||||
})(window, document, window.searxng);
|
103
beetroot_static/src/js/main/results.js
Normal file
|
@ -0,0 +1,103 @@
|
|||
/* SPDX-License-Identifier: AGPL-3.0-or-later */
|
||||
(function (w, d, searxng) {
|
||||
'use strict';
|
||||
|
||||
if (searxng.endpoint !== 'results') {
|
||||
return;
|
||||
}
|
||||
|
||||
searxng.ready(function () {
|
||||
d.querySelectorAll('#urls img.image').forEach(
|
||||
img =>
|
||||
img.addEventListener(
|
||||
'error', () => {
|
||||
img.style.display = 'none';
|
||||
img.error = null;
|
||||
}
|
||||
));
|
||||
|
||||
searxng.on('.btn-collapse', 'click', function () {
|
||||
var btnLabelCollapsed = this.getAttribute('data-btn-text-collapsed');
|
||||
var btnLabelNotCollapsed = this.getAttribute('data-btn-text-not-collapsed');
|
||||
var target = this.getAttribute('data-target');
|
||||
var targetElement = d.querySelector(target);
|
||||
var html = this.innerHTML;
|
||||
if (this.classList.contains('collapsed')) {
|
||||
html = html.replace(btnLabelCollapsed, btnLabelNotCollapsed);
|
||||
} else {
|
||||
html = html.replace(btnLabelNotCollapsed, btnLabelCollapsed);
|
||||
}
|
||||
this.innerHTML = html;
|
||||
this.classList.toggle('collapsed');
|
||||
targetElement.classList.toggle('invisible');
|
||||
});
|
||||
|
||||
searxng.on('.media-loader', 'click', function () {
|
||||
var target = this.getAttribute('data-target');
|
||||
var iframe_load = d.querySelector(target + ' > iframe');
|
||||
var srctest = iframe_load.getAttribute('src');
|
||||
if (srctest === null || srctest === undefined || srctest === false) {
|
||||
iframe_load.setAttribute('src', iframe_load.getAttribute('data-src'));
|
||||
}
|
||||
});
|
||||
|
||||
searxng.selectImage = function (resultElement) {
|
||||
/* eslint no-unused-vars: 0 */
|
||||
if (resultElement) {
|
||||
// load full size image in background
|
||||
const imgElement = resultElement.querySelector('.result-images-source img');
|
||||
const thumbnailElement = resultElement.querySelector('.image_thumbnail');
|
||||
const detailElement = resultElement.querySelector('.detail');
|
||||
if (imgElement) {
|
||||
const imgSrc = imgElement.getAttribute('data-src');
|
||||
if (imgSrc) {
|
||||
const loader = d.createElement('div');
|
||||
const imgLoader = new Image();
|
||||
|
||||
loader.classList.add('loader');
|
||||
detailElement.appendChild(loader);
|
||||
|
||||
imgLoader.onload = e => {
|
||||
imgElement.src = imgSrc;
|
||||
loader.remove();
|
||||
};
|
||||
imgLoader.onerror = e => {
|
||||
loader.remove();
|
||||
};
|
||||
imgLoader.src = imgSrc;
|
||||
imgElement.src = thumbnailElement.src;
|
||||
imgElement.removeAttribute('data-src');
|
||||
}
|
||||
}
|
||||
}
|
||||
d.getElementById('results').classList.add('image-detail-open');
|
||||
searxng.scrollPageToSelected();
|
||||
}
|
||||
|
||||
searxng.closeDetail = function (e) {
|
||||
d.getElementById('results').classList.remove('image-detail-open');
|
||||
searxng.scrollPageToSelected();
|
||||
}
|
||||
searxng.on('.result-detail-close', 'click', e => {
|
||||
e.preventDefault();
|
||||
searxng.closeDetail();
|
||||
});
|
||||
searxng.on('.result-detail-previous', 'click', e => searxng.selectPrevious(false));
|
||||
searxng.on('.result-detail-next', 'click', e => searxng.selectNext(false));
|
||||
|
||||
w.addEventListener('scroll', function () {
|
||||
var e = d.getElementById('backToTop'),
|
||||
scrollTop = document.documentElement.scrollTop || document.body.scrollTop,
|
||||
results = d.getElementById('results');
|
||||
if (e !== null) {
|
||||
if (scrollTop >= 100) {
|
||||
results.classList.add('scrolling');
|
||||
} else {
|
||||
results.classList.remove('scrolling');
|
||||
}
|
||||
}
|
||||
}, true);
|
||||
|
||||
});
|
||||
|
||||
})(window, document, window.searxng);
|
138
beetroot_static/src/js/main/search.js
Normal file
|
@ -0,0 +1,138 @@
|
|||
/* SPDX-License-Identifier: AGPL-3.0-or-later */
|
||||
/* global AutoComplete */
|
||||
(function (w, d, searxng) {
|
||||
'use strict';
|
||||
|
||||
var qinput_id = "q", qinput;
|
||||
|
||||
const isMobile = window.matchMedia("only screen and (max-width: 50em)").matches;
|
||||
|
||||
function submitIfQuery () {
|
||||
if (qinput.value.length > 0) {
|
||||
var search = document.getElementById('search');
|
||||
setTimeout(search.submit.bind(search), 0);
|
||||
}
|
||||
}
|
||||
|
||||
function createClearButton (qinput) {
|
||||
var cs = document.getElementById('clear_search');
|
||||
var updateClearButton = function () {
|
||||
if (qinput.value.length === 0) {
|
||||
cs.classList.add("empty");
|
||||
} else {
|
||||
cs.classList.remove("empty");
|
||||
}
|
||||
};
|
||||
|
||||
// update status, event listener
|
||||
updateClearButton();
|
||||
cs.addEventListener('click', function (ev) {
|
||||
qinput.value = '';
|
||||
qinput.focus();
|
||||
updateClearButton();
|
||||
ev.preventDefault();
|
||||
});
|
||||
qinput.addEventListener('keyup', updateClearButton, false);
|
||||
}
|
||||
|
||||
searxng.ready(function () {
|
||||
qinput = d.getElementById(qinput_id);
|
||||
|
||||
if (qinput !== null) {
|
||||
// clear button
|
||||
createClearButton(qinput);
|
||||
|
||||
// autocompleter
|
||||
if (searxng.settings.autocomplete_provider) {
|
||||
searxng.autocomplete = AutoComplete.call(w, {
|
||||
Url: "./autocompleter",
|
||||
EmptyMessage: searxng.settings.translations.no_item_found,
|
||||
HttpMethod: searxng.settings.http_method,
|
||||
HttpHeaders: {
|
||||
"Content-type": "application/x-www-form-urlencoded",
|
||||
"X-Requested-With": "XMLHttpRequest"
|
||||
},
|
||||
MinChars: searxng.settings.autocomplete_min,
|
||||
Delay: 300,
|
||||
_Position: function () {},
|
||||
_Open: function () {
|
||||
var params = this;
|
||||
Array.prototype.forEach.call(this.DOMResults.getElementsByTagName("li"), function (li) {
|
||||
if (li.getAttribute("class") != "locked") {
|
||||
li.onmousedown = function () {
|
||||
params._Select(li);
|
||||
};
|
||||
}
|
||||
});
|
||||
},
|
||||
}, "#" + qinput_id);
|
||||
}
|
||||
|
||||
/*
|
||||
Monkey patch autocomplete.js to fix a bug
|
||||
With the POST method, the values are not URL encoded: query like "1 + 1" are sent as "1 1" since space are URL encoded as plus.
|
||||
See HTML specifications:
|
||||
* HTML5: https://url.spec.whatwg.org/#concept-urlencoded-serializer
|
||||
* HTML4: https://www.w3.org/TR/html401/interact/forms.html#h-17.13.4.1
|
||||
|
||||
autocomplete.js does not URL encode the name and values:
|
||||
https://github.com/autocompletejs/autocomplete.js/blob/87069524f3b95e68f1b54d8976868e0eac1b2c83/src/autocomplete.ts#L665
|
||||
|
||||
The monkey patch overrides the compiled version of the ajax function.
|
||||
See https://github.com/autocompletejs/autocomplete.js/blob/87069524f3b95e68f1b54d8976868e0eac1b2c83/dist/autocomplete.js#L143-L158
|
||||
The patch changes only the line 156 from
|
||||
params.Request.send(params._QueryArg() + "=" + params._Pre());
|
||||
to
|
||||
params.Request.send(encodeURIComponent(params._QueryArg()) + "=" + encodeURIComponent(params._Pre()));
|
||||
|
||||
Related to:
|
||||
* https://github.com/autocompletejs/autocomplete.js/issues/78
|
||||
* https://github.com/searxng/searxng/issues/1695
|
||||
*/
|
||||
AutoComplete.prototype.ajax = function (params, request, timeout) {
|
||||
if (timeout === void 0) { timeout = true; }
|
||||
if (params.$AjaxTimer) {
|
||||
window.clearTimeout(params.$AjaxTimer);
|
||||
}
|
||||
if (timeout === true) {
|
||||
params.$AjaxTimer = window.setTimeout(AutoComplete.prototype.ajax.bind(null, params, request, false), params.Delay);
|
||||
} else {
|
||||
if (params.Request) {
|
||||
params.Request.abort();
|
||||
}
|
||||
params.Request = request;
|
||||
params.Request.send(encodeURIComponent(params._QueryArg()) + "=" + encodeURIComponent(params._Pre()));
|
||||
}
|
||||
};
|
||||
|
||||
if (!isMobile && document.querySelector('.index_endpoint')) {
|
||||
qinput.focus();
|
||||
}
|
||||
}
|
||||
|
||||
// vanilla js version of search_on_category_select.js
|
||||
if (qinput !== null && d.querySelector('.help') != null && searxng.settings.search_on_category_select) {
|
||||
d.querySelector('.help').className = 'invisible';
|
||||
|
||||
searxng.on('#categories input', 'change', function () {
|
||||
var i, categories = d.querySelectorAll('#categories input[type="checkbox"]');
|
||||
for (i = 0; i < categories.length; i++) {
|
||||
if (categories[i] !== this && categories[i].checked) {
|
||||
categories[i].click();
|
||||
}
|
||||
}
|
||||
if (! this.checked) {
|
||||
this.click();
|
||||
}
|
||||
submitIfQuery();
|
||||
return false;
|
||||
});
|
||||
|
||||
searxng.on(d.getElementById('safesearch'), 'change', submitIfQuery);
|
||||
searxng.on(d.getElementById('time_range'), 'change', submitIfQuery);
|
||||
searxng.on(d.getElementById('language'), 'change', submitIfQuery);
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
})(window, document, window.searxng);
|
19
beetroot_static/src/less/animations.less
Normal file
|
@ -0,0 +1,19 @@
|
|||
.dialog-modal {
|
||||
animation-name: dialogmodal;
|
||||
animation-duration: 0.13s;
|
||||
|
||||
@keyframes dialogmodal {
|
||||
0% {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
50% {
|
||||
opacity: 0.5;
|
||||
transform: translate(-50%, -50%) scale(1.05);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
input.checkbox-onoff[type="checkbox"]::before {
|
||||
transition: left 0.25s;
|
||||
}
|
75
beetroot_static/src/less/autocomplete.less
Normal file
|
@ -0,0 +1,75 @@
|
|||
/*! Autocomplete.js v2.6.3 | license MIT | (c) 2017, Baptiste Donaux | http://autocomplete-js.com */
|
||||
|
||||
.autocomplete {
|
||||
position: absolute;
|
||||
width: @search-width;
|
||||
max-height: 0;
|
||||
overflow-y: hidden;
|
||||
.ltr-text-align-left();
|
||||
|
||||
.rounded-corners;
|
||||
|
||||
&:active,
|
||||
&:focus,
|
||||
&:hover {
|
||||
background-color: var(--color-autocomplete-background);
|
||||
}
|
||||
|
||||
&:empty {
|
||||
display: none;
|
||||
}
|
||||
|
||||
> ul {
|
||||
list-style-type: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
|
||||
> li {
|
||||
cursor: pointer;
|
||||
padding: 0.5rem 1rem;
|
||||
|
||||
&.active,
|
||||
&:active,
|
||||
&:focus,
|
||||
&:hover {
|
||||
background-color: var(--color-autocomplete-background-hover);
|
||||
|
||||
a:active,
|
||||
a:focus,
|
||||
a:hover {
|
||||
text-decoration: none;
|
||||
}
|
||||
}
|
||||
|
||||
&.locked {
|
||||
cursor: inherit;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.open {
|
||||
display: block;
|
||||
background-color: var(--color-autocomplete-background);
|
||||
color: var(--color-autocomplete-font);
|
||||
max-height: 32rem;
|
||||
overflow-y: auto;
|
||||
z-index: 100;
|
||||
margin-top: 3.5rem;
|
||||
border-radius: 0.8rem;
|
||||
box-shadow: 0 2px 8px rgb(34 38 46 / 25%);
|
||||
|
||||
&:empty {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: @phone) {
|
||||
.autocomplete {
|
||||
width: 100%;
|
||||
|
||||
> ul > li {
|
||||
padding: 1rem;
|
||||
}
|
||||
}
|
||||
}
|
9
beetroot_static/src/less/code.less
Normal file
|
@ -0,0 +1,9 @@
|
|||
.code-highlight pre {
|
||||
overflow: auto;
|
||||
background-color: inherit;
|
||||
color: inherit;
|
||||
border: inherit;
|
||||
}
|
||||
|
||||
// stylelint-disable no-invalid-position-at-import-rule
|
||||
@import "../generated/pygments.less";
|
279
beetroot_static/src/less/definitions.less
Normal file
|
@ -0,0 +1,279 @@
|
|||
/*
|
||||
* SearXNG, A privacy-respecting, hackable metasearch engine
|
||||
*
|
||||
* To change the colors of the site, simple edit this variables
|
||||
*/
|
||||
|
||||
/// Light Theme
|
||||
:root {
|
||||
/// Base Colors
|
||||
--color-base-font: #444;
|
||||
--color-base-font-rgb: 68, 68, 68;
|
||||
--color-base-background: #fff;
|
||||
--color-base-background-mobile: #f2f5f8;
|
||||
--color-url-font: var(--disroot-green);
|
||||
--color-url-visited-font: var(--disroot-blueish);
|
||||
/// Header Colors
|
||||
--color-header-background: var(--disroot-purple);
|
||||
--color-header-border: #ddd;
|
||||
/// Footer Colors
|
||||
--color-footer-background: #fdfbff;
|
||||
--color-footer-border: #ddd;
|
||||
/// Sidebar Colors
|
||||
--color-sidebar-border: #ddd;
|
||||
--color-sidebar-font: #000;
|
||||
--color-sidebar-background: #fff;
|
||||
/// BackToTop Colors
|
||||
--color-backtotop-font: #444;
|
||||
--color-backtotop-border: #ddd;
|
||||
--color-backtotop-background: #fff;
|
||||
/// Button Colors
|
||||
--color-btn-background: var(--disroot-purple);
|
||||
--color-btn-font: #fff;
|
||||
--color-show-btn-background: #bbb;
|
||||
--color-show-btn-font: #000;
|
||||
/// Search Input Colors
|
||||
--color-search-border: #bbb;
|
||||
--color-search-shadow: 0 2px 8px rgb(34 38 46 / 25%);
|
||||
--color-search-background: #fff;
|
||||
--color-search-font: #222;
|
||||
--color-search-background-hover: #3050ff;
|
||||
/// Modal Colors
|
||||
--color-error: #db3434;
|
||||
--color-error-background: lighten(#db3434, 40%);
|
||||
--color-warning: #dbba34;
|
||||
--color-warning-background: lighten(#dbba34, 40%);
|
||||
--color-success: #42db34;
|
||||
--color-success-background: lighten(#42db34, 40%);
|
||||
/// Categories Colors
|
||||
--color-categories-item-selected-font: var(--disroot-purple-even-lighter);
|
||||
--color-categories-item-border-selected: var(--disroot-purple-even-lighter);
|
||||
/// Autocomplete Colors
|
||||
--color-autocomplete-font: #000;
|
||||
--color-autocomplete-border: #bbb;
|
||||
--color-autocomplete-shadow: 0 2px 8px rgb(34 38 46 / 25%);
|
||||
--color-autocomplete-background: #fff;
|
||||
--color-autocomplete-background-hover: #e3e3e3;
|
||||
/// Answer Colors
|
||||
--color-answer-font: #444; // same as --color-base-font
|
||||
--color-answer-background: #fff;
|
||||
/// Results Colors
|
||||
--color-result-background: #fff;
|
||||
--color-result-border: #ddd;
|
||||
--color-result-url-font: #000;
|
||||
--color-result-vim-selected: #f7f7f7;
|
||||
--color-result-vim-arrow: var(--disroot-purple);
|
||||
--color-result-description-highlight-font: #000;
|
||||
--color-result-link-font: var(--disroot-purple);
|
||||
--color-result-link-font-highlight: var(--disroot-purple-even-lighter);
|
||||
--color-result-link-visited-font: var(--disroot-green);
|
||||
--color-result-publishdate-font: #777;
|
||||
--color-result-engines-font: #545454;
|
||||
--color-result-search-url-border: #ddd;
|
||||
--color-result-search-url-font: #000;
|
||||
// Images Colors
|
||||
--color-result-image-span-font: #444;
|
||||
--color-result-image-span-font-selected: #fff;
|
||||
--color-result-image-background: #fff;
|
||||
/// Settings Colors
|
||||
--color-settings-tr-hover: #ebebeb;
|
||||
--color-settings-engine-description-font: #545454;
|
||||
--color-settings-engine-group-background: #0001;
|
||||
/// Detail modal
|
||||
--color-result-detail-font: #fff;
|
||||
--color-result-detail-label-font: lightgray;
|
||||
--color-result-detail-background: #242424;
|
||||
--color-result-detail-hr: #555;
|
||||
--color-result-detail-link: #8af;
|
||||
--color-result-detail-loader-border: rgba(255, 255, 255, 0.2);
|
||||
--color-result-detail-loader-borderleft: rgba(0, 0, 0, 0);
|
||||
/// Toolkit Colors
|
||||
--color-toolkit-badge-font: #fff;
|
||||
--color-toolkit-badge-background: #545454;
|
||||
--color-toolkit-kbd-font: #fff;
|
||||
--color-toolkit-kbd-background: #000;
|
||||
--color-toolkit-dialog-border: #ddd;
|
||||
--color-toolkit-dialog-background: #fff;
|
||||
--color-toolkit-tabs-label-border: #fff;
|
||||
--color-toolkit-tabs-section-border: #ddd;
|
||||
--color-toolkit-select-background: #e1e1e1;
|
||||
--color-toolkit-select-border: #ddd;
|
||||
--color-toolkit-select-background-hover: #bbb;
|
||||
--color-toolkit-input-text-font: #222;
|
||||
--color-toolkit-checkbox-onoff-off-background: #ddd;
|
||||
--color-toolkit-checkbox-onoff-on-background: #ddd;
|
||||
--color-toolkit-checkbox-onoff-on-mark-background: var(--disroot-purple);
|
||||
--color-toolkit-checkbox-onoff-on-mark-color: #fff;
|
||||
--color-toolkit-checkbox-onoff-off-mark-background: #aaa;
|
||||
--color-toolkit-checkbox-onoff-off-mark-color: #fff;
|
||||
--color-toolkit-checkbox-label-background: #ddd;
|
||||
--color-toolkit-checkbox-label-border: #ddd;
|
||||
--color-toolkit-checkbox-input-border: var(--disroot-purple);
|
||||
--color-toolkit-engine-tooltip-border: #ddd;
|
||||
--color-toolkit-engine-tooltip-background: #fff;
|
||||
--color-toolkit-loader-border: rgba(0, 0, 0, 0.2);
|
||||
--color-toolkit-loader-borderleft: rgba(255, 255, 255, 0);
|
||||
--color-doc-code: #300;
|
||||
--color-doc-code-background: #fdd;
|
||||
}
|
||||
|
||||
.dark-themes() {
|
||||
/// Base Colors
|
||||
--color-base-font: #bbb;
|
||||
--color-base-font-rgb: 187, 187, 187;
|
||||
--color-base-background: #222428;
|
||||
--color-base-background-mobile: #222428;
|
||||
--color-url-font: var(--disroot-green);
|
||||
--color-url-visited-font: var(--disroot-blueish-lighter);
|
||||
/// Header Colors
|
||||
--color-header-background: var(--disroot-purple-darker);
|
||||
--color-header-border: #333;
|
||||
/// Footer Colors
|
||||
--color-footer-background: #1e1e22;
|
||||
--color-footer-border: #333;
|
||||
/// Sidebar Colors
|
||||
--color-sidebar-border: #555;
|
||||
--color-sidebar-font: #fff;
|
||||
--color-sidebar-background: #292c34;
|
||||
/// BackToTop Colors
|
||||
--color-backtotop-font: #bbb;
|
||||
--color-backtotop-border: #333;
|
||||
--color-backtotop-background: #2b2e36;
|
||||
/// Button Colors
|
||||
--color-btn-background: var(--disroot-purple);
|
||||
--color-btn-font: #222;
|
||||
--color-show-btn-background: #555;
|
||||
--color-show-btn-font: #fff;
|
||||
/// Search Input Colors
|
||||
--color-search-border: #555;
|
||||
--color-search-shadow: 0 2px 8px rgb(34 38 46 / 25%);
|
||||
--color-search-background: #2b2e36;
|
||||
--color-search-font: #fff;
|
||||
--color-search-background-hover: #58f;
|
||||
/// Modal Colors
|
||||
--color-error: #f55b5b;
|
||||
--color-error-background: darken(#db3434, 40%);
|
||||
--color-warning: #f1d561;
|
||||
--color-warning-background: darken(#dbba34, 40%);
|
||||
--color-success: #79f56e;
|
||||
--color-success-background: darken(#42db34, 40%);
|
||||
/// Categories Colors
|
||||
--color-categories-item-selected-font: var(--disroot-purple-even-lighter);
|
||||
--color-categories-item-border-selected: var(--disroot-purple-even-lighter);
|
||||
/// Autocomplete Colors
|
||||
--color-autocomplete-font: #fff;
|
||||
--color-autocomplete-border: #555;
|
||||
--color-autocomplete-shadow: 0 2px 8px rgb(34 38 46 / 25%);
|
||||
--color-autocomplete-background: #2b2e36;
|
||||
--color-autocomplete-background-hover: #1e1e22;
|
||||
/// Answer Colors
|
||||
--color-answer-font: #bbb; // same as --color-base-font
|
||||
--color-answer-background: #26292f;
|
||||
/// Results Colors
|
||||
--color-result-background: #26292f;
|
||||
--color-result-border: #333;
|
||||
--color-result-url-font: #fff;
|
||||
--color-result-vim-selected: #1f1f23cc;
|
||||
--color-result-vim-arrow: var(--disroot-purple);
|
||||
--color-result-description-highlight-font: #fff;
|
||||
--color-result-link-font: var(--disroot-purple-lighter);
|
||||
--color-result-link-font-highlight: var(--disroot-purple-even-lighter);
|
||||
--color-result-link-visited-font: var(--disroot-green);
|
||||
--color-result-publishdate-font: #888;
|
||||
--color-result-engines-font: #a4a4a4;
|
||||
--color-result-search-url-border: #555;
|
||||
--color-result-search-url-font: #fff;
|
||||
/// Detail modal : same as the light version
|
||||
--color-result-detail-font: #fff;
|
||||
--color-result-detail-label-font: lightgray;
|
||||
--color-result-detail-background: #1a1a1c;
|
||||
--color-result-detail-hr: #555;
|
||||
--color-result-detail-link: #8af;
|
||||
--color-result-detail-loader-border: rgba(255, 255, 255, 0.2);
|
||||
--color-result-detail-loader-borderleft: rgba(0, 0, 0, 0);
|
||||
// Images Colors
|
||||
--color-result-image-span-font: #bbb;
|
||||
--color-result-image-span-font-selected: #222;
|
||||
--color-result-image-background: #222;
|
||||
/// Settings Colors
|
||||
--color-settings-tr-hover: #2c2c32;
|
||||
--color-settings-engine-description-font: darken(#dcdcdc, 30%);
|
||||
--color-settings-engine-group-background: #1b1b21;
|
||||
/// Toolkit Colors
|
||||
--color-toolkit-badge-font: #fff;
|
||||
--color-toolkit-badge-background: #555;
|
||||
--color-toolkit-kbd-font: #000;
|
||||
--color-toolkit-kbd-background: #fff;
|
||||
--color-toolkit-dialog-border: #555;
|
||||
--color-toolkit-dialog-background: #1e1e22;
|
||||
--color-toolkit-tabs-label-border: #222;
|
||||
--color-toolkit-tabs-section-border: #555;
|
||||
--color-toolkit-select-background: #313338;
|
||||
--color-toolkit-select-border: #555;
|
||||
--color-toolkit-select-background-hover: #373b49;
|
||||
--color-toolkit-input-text-font: #fff;
|
||||
--color-toolkit-checkbox-onoff-off-background: #313338;
|
||||
--color-toolkit-checkbox-onoff-on-background: #313338;
|
||||
--color-toolkit-checkbox-onoff-on-mark-background: var(--disroot-purple);
|
||||
--color-toolkit-checkbox-onoff-on-mark-color: #222;
|
||||
--color-toolkit-checkbox-onoff-off-mark-background: #ddd;
|
||||
--color-toolkit-checkbox-onoff-off-mark-color: #222;
|
||||
--color-toolkit-checkbox-label-background: #222;
|
||||
--color-toolkit-checkbox-label-border: #333;
|
||||
--color-toolkit-checkbox-input-border: var(--disroot-purple-lighter);
|
||||
--color-toolkit-engine-tooltip-border: #333;
|
||||
--color-toolkit-engine-tooltip-background: #222;
|
||||
--color-toolkit-loader-border: rgba(255, 255, 255, 0.2);
|
||||
--color-toolkit-loader-borderleft: rgba(0, 0, 0, 0);
|
||||
--color-doc-code: #fdd;
|
||||
--color-doc-code-background: #300;
|
||||
}
|
||||
|
||||
@import "disroot.less";
|
||||
|
||||
/// Dark Theme (autoswitch based on device pref)
|
||||
@media (prefers-color-scheme: dark) {
|
||||
:root.theme-auto {
|
||||
.dark-themes();
|
||||
}
|
||||
}
|
||||
|
||||
// Dark Theme by preferences
|
||||
:root.theme-dark {
|
||||
.dark-themes();
|
||||
}
|
||||
|
||||
/// General Size
|
||||
@results-width: 45rem;
|
||||
@results-sidebar-width: 25rem;
|
||||
@results-offset: 10rem;
|
||||
@results-tablet-offset: 0.5rem;
|
||||
@results-gap: 5rem;
|
||||
@results-margin: 0.125rem;
|
||||
@result-padding: 1rem;
|
||||
@results-image-row-height: 12rem;
|
||||
@results-image-row-height-phone: 6rem;
|
||||
@search-width: 44rem;
|
||||
// heigh of #search, see detail.less
|
||||
@search-height: 7.6rem;
|
||||
|
||||
/// Device Size
|
||||
/// @desktop > @tablet
|
||||
@tablet: 79.75em; // see https://github.com/searxng/searxng/issues/874
|
||||
@phone: 50em;
|
||||
@small-phone: 35em;
|
||||
@ultra-small-phone: 20rem;
|
||||
|
||||
/// From style.less
|
||||
@stacked-bar-chart: rgb(0, 0, 0);
|
||||
|
||||
/// Load fonts from this directory.
|
||||
@icon-font-path: "../../../fonts/";
|
||||
//** File name for all font files.
|
||||
@icon-font-name: "glyphicons-halflings-regular";
|
||||
//** Element ID within SVG icon file.
|
||||
@icon-font-svg-id: "glyphicons_halflingsregular";
|
||||
|
||||
// decoration of the select HTML elements
|
||||
@select-light-svg-path: "../svg/select-light.svg";
|
||||
@select-dark-svg-path: "../svg/select-dark.svg";
|
248
beetroot_static/src/less/detail.less
Normal file
|
@ -0,0 +1,248 @@
|
|||
#main_results #results.image-detail-open.only_template_images {
|
||||
width: min(98%, 59.25rem) !important;
|
||||
}
|
||||
|
||||
#main_results #results.only_template_images.image-detail-open #backToTop {
|
||||
.ltr-left(56.75rem) !important;
|
||||
.ltr-right(inherit);
|
||||
}
|
||||
|
||||
article.result-images .detail {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#results.image-detail-open article.result-images[data-vim-selected] .detail {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
position: fixed;
|
||||
.ltr-left(60rem);
|
||||
.ltr-right(0);
|
||||
top: @search-height;
|
||||
transition: top 0.064s ease-in 0s;
|
||||
bottom: 0;
|
||||
background: var(--color-result-detail-background);
|
||||
border: 1px solid var(--color-result-detail-background);
|
||||
z-index: 10000;
|
||||
padding: 4rem 3rem 3rem 3rem;
|
||||
|
||||
a.result-images-source {
|
||||
display: block;
|
||||
flex: 1;
|
||||
text-align: left;
|
||||
width: 100%;
|
||||
border: none;
|
||||
text-decoration: none;
|
||||
|
||||
img {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
border: none;
|
||||
object-fit: contain;
|
||||
width: inherit;
|
||||
height: inherit;
|
||||
max-width: 100%;
|
||||
min-height: inherit;
|
||||
max-height: calc(100vh - 25rem - 7rem);
|
||||
background: inherit;
|
||||
}
|
||||
}
|
||||
|
||||
.result-images-labels {
|
||||
color: var(--color-result-detail-font);
|
||||
max-height: 16rem;
|
||||
min-height: 16rem;
|
||||
|
||||
hr {
|
||||
border-top: 1px solid var(--color-result-detail-hr);
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
h4 {
|
||||
height: 2rem;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
|
||||
p {
|
||||
color: var(--color-result-detail-label-font);
|
||||
font-size: 0.9rem;
|
||||
|
||||
span {
|
||||
display: inline-block;
|
||||
width: 12rem;
|
||||
}
|
||||
}
|
||||
|
||||
h4,
|
||||
p,
|
||||
a {
|
||||
.ltr-text-align-left();
|
||||
}
|
||||
|
||||
p.result-content {
|
||||
height: 2rem;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
p.result-url {
|
||||
white-space: nowrap;
|
||||
overflow-x: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
p.result-content:hover,
|
||||
p.result-url:hover {
|
||||
position: relative;
|
||||
overflow: inherit !important;
|
||||
background: var(--color-result-detail-background);
|
||||
text-overflow: inherit !important;
|
||||
}
|
||||
|
||||
a,
|
||||
a:visited,
|
||||
a:hover,
|
||||
a:active {
|
||||
color: var(--color-result-detail-link);
|
||||
}
|
||||
|
||||
a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
}
|
||||
|
||||
a.result-detail-close {
|
||||
top: 1rem;
|
||||
.ltr-left(1rem);
|
||||
padding: 0.4rem;
|
||||
}
|
||||
|
||||
a.result-detail-previous {
|
||||
top: 1rem;
|
||||
.ltr-right(6rem);
|
||||
// center the icon by moving it slightly on the left
|
||||
padding-top: 0.4rem;
|
||||
.ltr-padding-right(0.5rem);
|
||||
padding-bottom: 0.4rem;
|
||||
.ltr-padding-left(0.3rem);
|
||||
}
|
||||
|
||||
a.result-detail-next {
|
||||
top: 1rem;
|
||||
.ltr-right(2rem);
|
||||
padding: 0.4rem;
|
||||
}
|
||||
|
||||
a.result-detail-close,
|
||||
a.result-detail-next,
|
||||
a.result-detail-previous {
|
||||
border-radius: 50%;
|
||||
display: block;
|
||||
width: 1.5rem;
|
||||
height: 1.5rem;
|
||||
position: absolute;
|
||||
filter: opacity(40%);
|
||||
z-index: 2000002;
|
||||
|
||||
span {
|
||||
display: block;
|
||||
width: 1.5rem;
|
||||
height: 1.5rem;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
|
||||
a.result-detail-next,
|
||||
a.result-detail-previous {
|
||||
span::before {
|
||||
// vertical center small icons
|
||||
vertical-align: sub;
|
||||
}
|
||||
}
|
||||
|
||||
a.result-detail-close,
|
||||
a.result-detail-close:visited,
|
||||
a.result-detail-close:hover,
|
||||
a.result-detail-close:active,
|
||||
a.result-detail-previous,
|
||||
a.result-detail-previous:visited,
|
||||
a.result-detail-previous:hover,
|
||||
a.result-detail-previous:active,
|
||||
a.result-detail-next,
|
||||
a.result-detail-next:visited,
|
||||
a.result-detail-next:hover,
|
||||
a.result-detail-next:active {
|
||||
color: var(--color-result-detail-font);
|
||||
background: var(--color-result-detail-background);
|
||||
border: 1px solid var(--color-result-detail-font);
|
||||
}
|
||||
|
||||
a.result-detail-close:focus,
|
||||
a.result-detail-close:hover,
|
||||
a.result-detail-previous:focus,
|
||||
a.result-detail-previous:hover,
|
||||
a.result-detail-next:focus,
|
||||
a.result-detail-next:hover {
|
||||
filter: opacity(80%);
|
||||
}
|
||||
|
||||
.loader {
|
||||
position: absolute;
|
||||
top: 1rem;
|
||||
.ltr-right(50%);
|
||||
border-top: 0.5em solid var(--color-result-detail-loader-border);
|
||||
border-right: 0.5em solid var(--color-result-detail-loader-border);
|
||||
border-bottom: 0.5em solid var(--color-result-detail-loader-border);
|
||||
border-left: 0.5em solid var(--color-result-detail-loader-borderleft);
|
||||
}
|
||||
}
|
||||
|
||||
#results.image-detail-open.scrolling article.result-images[data-vim-selected] .detail {
|
||||
top: 0;
|
||||
|
||||
a.result-images-source img {
|
||||
max-height: calc(100vh - 25rem);
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: @tablet) {
|
||||
#results.image-detail-open article.result-images[data-vim-selected] .detail {
|
||||
top: 0;
|
||||
.ltr-left(0);
|
||||
|
||||
a.result-images-source {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
|
||||
img {
|
||||
width: 100%;
|
||||
max-height: calc(100vh - 24rem);
|
||||
}
|
||||
}
|
||||
|
||||
a.result-detail-next {
|
||||
.ltr-right(1rem);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: @phone) {
|
||||
#results.image-detail-open article.result-images[data-vim-selected] .detail {
|
||||
top: 0;
|
||||
.ltr-left(0);
|
||||
padding: 1rem;
|
||||
|
||||
a.result-images-source img {
|
||||
width: 100%;
|
||||
max-height: calc(100vh - 20rem);
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.result-images-labels p span {
|
||||
width: inherit;
|
||||
.ltr-margin-right(1rem);
|
||||
}
|
||||
}
|
||||
}
|
51
beetroot_static/src/less/disroot.less
Normal file
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
* Disroot flavor
|
||||
*/
|
||||
|
||||
:root {
|
||||
--disroot-purple: #50162d;
|
||||
--disroot-purple-lighter: #80264a;
|
||||
--disroot-purple-even-lighter: #e7518e;
|
||||
--disroot-purple-darker: #201c1c;
|
||||
--disroot-green: #8eb726;
|
||||
--disroot-green-lighter: #afcf60;
|
||||
--disroot-green-even-lighter: #cde78c;
|
||||
--disroot-green-darker: #71911e;
|
||||
--disroot-blueish: #1f5c60;
|
||||
--disroot-blueish-lighter: #38989f;
|
||||
}
|
||||
|
||||
// Category color
|
||||
.category label {
|
||||
color: #c0bbbb;
|
||||
}
|
||||
|
||||
// Navbar links in right corner only on results page
|
||||
// (needed when using disroot color as navbar background)
|
||||
.results_endpoint #links_on_top a,
|
||||
.results_endpoint #links_on_top a:active *,
|
||||
.results_endpoint #links_on_top a:hover *,
|
||||
.results_endpoint #links_on_top a:link *,
|
||||
.results_endpoint #links_on_top a:visited * {
|
||||
color: #fff !important;
|
||||
}
|
||||
|
||||
// Navbar magnifying glass color
|
||||
#search_logo svg g circle,
|
||||
#search_logo svg g path {
|
||||
stroke: var(--disroot-purple-even-lighter);
|
||||
}
|
||||
|
||||
#search_logo svg g rect {
|
||||
fill: var(--disroot-purple-even-lighter);
|
||||
}
|
||||
|
||||
// Have a slightly more bright disroot purple color on logo png
|
||||
// when in dark mode
|
||||
.theme-dark .index .title {
|
||||
filter: brightness(1.25);
|
||||
}
|
||||
|
||||
.theme-dark img.logo {
|
||||
filter: brightness(1.25);
|
||||
}
|
33
beetroot_static/src/less/embedded.less
Normal file
|
@ -0,0 +1,33 @@
|
|||
iframe[src^="https://w.soundcloud.com"] {
|
||||
height: 120px;
|
||||
}
|
||||
|
||||
iframe[src^="https://www.deezer.com"] {
|
||||
// The real size is 92px, but 94px are needed to avoid an inner scrollbar of
|
||||
// the embedded HTML.
|
||||
height: 94px;
|
||||
}
|
||||
|
||||
iframe[src^="https://www.mixcloud.com"] {
|
||||
// the embedded player from mixcloud has some quirks: initial there is an
|
||||
// issue with an image URL that is blocked since it is an a Cross-Origin
|
||||
// request. The alternative text (<img alt='Mixcloud Logo'> then cause an
|
||||
// scrollbar in the inner of the iframe we can't avoid. Another quirk comes
|
||||
// when pressing the play button, somtimes the shown player has an height of
|
||||
// 200px, somtimes 250px.
|
||||
height: 250px;
|
||||
}
|
||||
|
||||
iframe[src^="https://bandcamp.com/EmbeddedPlayer"] {
|
||||
// show playlist
|
||||
height: 350px;
|
||||
}
|
||||
|
||||
iframe[src^="https://bandcamp.com/EmbeddedPlayer/track"] {
|
||||
// hide playlist
|
||||
height: 120px;
|
||||
}
|
||||
|
||||
iframe[src^="https://genius.com/songs"] {
|
||||
height: 65px;
|
||||
}
|
51
beetroot_static/src/less/index.less
Normal file
|
@ -0,0 +1,51 @@
|
|||
#main_index {
|
||||
margin-top: 26vh;
|
||||
}
|
||||
|
||||
.index {
|
||||
text-align: center;
|
||||
|
||||
.title {
|
||||
background: url('../img/searxng.png') no-repeat;
|
||||
min-height: 4rem;
|
||||
margin: 4rem auto;
|
||||
background-position: center;
|
||||
background-size: contain;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 4em;
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
#search,
|
||||
#search_header {
|
||||
margin: 0 auto;
|
||||
background: inherit;
|
||||
border: inherit;
|
||||
padding: 0;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.search_filters {
|
||||
display: block;
|
||||
margin: 1em 0;
|
||||
}
|
||||
|
||||
.category label {
|
||||
padding: 6px 10px;
|
||||
border-bottom: initial !important;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: @tablet) {
|
||||
div.title {
|
||||
h1 {
|
||||
font-size: 1em;
|
||||
}
|
||||
}
|
||||
|
||||
#main_index {
|
||||
margin-top: 6em;
|
||||
}
|
||||
}
|
9
beetroot_static/src/less/info.less
Normal file
|
@ -0,0 +1,9 @@
|
|||
.info-page {
|
||||
code {
|
||||
font-family: monospace;
|
||||
color: var(--color-doc-code);
|
||||
background-color: var(--color-doc-code-background);
|
||||
padding: 2px 5px;
|
||||
.rounded-corners(5px);
|
||||
}
|
||||
}
|
40
beetroot_static/src/less/mixins.less
Normal file
|
@ -0,0 +1,40 @@
|
|||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
// Mixins
|
||||
.text-size-adjust (@property: 100%) {
|
||||
-webkit-text-size-adjust: @property;
|
||||
-ms-text-size-adjust: @property;
|
||||
-moz-text-size-adjust: @property;
|
||||
text-size-adjust: @property;
|
||||
}
|
||||
|
||||
.rounded-corners (@radius: 10px) {
|
||||
border-radius: @radius;
|
||||
}
|
||||
|
||||
.rounded-right-corners (@radius: 0 10px 10px 0) {
|
||||
border-radius: @radius;
|
||||
}
|
||||
|
||||
.rounded-corners-tiny (@radius: 5px) {
|
||||
border-radius: @radius;
|
||||
}
|
||||
|
||||
// disable user selection
|
||||
.disable-user-select () {
|
||||
-webkit-touch-callout: none;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.show-content-button() {
|
||||
padding: 5px 10px;
|
||||
.rounded-corners-tiny;
|
||||
background: var(--color-show-btn-background);
|
||||
color: var(--color-show-btn-font);
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
background: var(--color-btn-background);
|
||||
color: var(--color-btn-font);
|
||||
}
|
||||
}
|
48
beetroot_static/src/less/new_issue.less
Normal file
|
@ -0,0 +1,48 @@
|
|||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
.stats_endpoint {
|
||||
.github-issue-button {
|
||||
display: block;
|
||||
padding: 8px 16px;
|
||||
font-family: sans-serif;
|
||||
font-size: 16px;
|
||||
color: white;
|
||||
background-color: #238636;
|
||||
border: #2ea043;
|
||||
border-radius: 10px !important;
|
||||
box-shadow: rgba(0, 0, 0, 0) 0 0 0 0;
|
||||
}
|
||||
|
||||
.github-issue-button:hover {
|
||||
background-color: #2ea043;
|
||||
}
|
||||
|
||||
.issue-hide {
|
||||
display: none;
|
||||
}
|
||||
|
||||
input[type=checked] {
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
label {
|
||||
margin: 1rem 1rem 1rem 0;
|
||||
}
|
||||
|
||||
.step_content {
|
||||
margin: 1rem 1rem 1rem 2rem;
|
||||
}
|
||||
|
||||
.step1,
|
||||
.step2 {
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
.step1_delay {
|
||||
transition: visibility 0s linear 4s;
|
||||
}
|
||||
|
||||
#step1:checked ~ .step1,
|
||||
#step2:checked ~ .step2 {
|
||||
visibility: visible;
|
||||
}
|
||||
}
|
196
beetroot_static/src/less/preferences.less
Normal file
|
@ -0,0 +1,196 @@
|
|||
#tab-content-query table td,
|
||||
#tab-content-query table th {
|
||||
.ltr-text-align-right() !important;
|
||||
height: 3rem;
|
||||
}
|
||||
|
||||
#main_preferences {
|
||||
form {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
fieldset {
|
||||
margin: 8px;
|
||||
border: none;
|
||||
}
|
||||
|
||||
legend {
|
||||
margin: 0;
|
||||
padding: 5px 0 0 0;
|
||||
display: block;
|
||||
.ltr-float-left();
|
||||
width: 300px;
|
||||
}
|
||||
|
||||
.value {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
.ltr-float-left();
|
||||
width: 15em;
|
||||
|
||||
select,
|
||||
input[type="text"] {
|
||||
font-size: inherit !important;
|
||||
margin-top: 0;
|
||||
.ltr-margin-right(1rem);
|
||||
margin-bottom: 0;
|
||||
.ltr-margin-left(0);
|
||||
}
|
||||
|
||||
select {
|
||||
width: 14rem;
|
||||
}
|
||||
|
||||
input[type="text"] {
|
||||
width: 13.25rem;
|
||||
color: var(--color-toolkit-input-text-font);
|
||||
border: none;
|
||||
background: none repeat scroll 0 0 var(--color-toolkit-select-background);
|
||||
padding: 0.2rem 0.4rem;
|
||||
height: 2rem;
|
||||
.rounded-corners-tiny;
|
||||
|
||||
&:hover,
|
||||
&:focus {
|
||||
background-color: var(--color-toolkit-select-background-hover);
|
||||
}
|
||||
}
|
||||
|
||||
select:focus,
|
||||
input:focus {
|
||||
outline: none;
|
||||
box-shadow: 0 0 1px 1px var(--color-btn-background);
|
||||
}
|
||||
}
|
||||
|
||||
.description {
|
||||
margin: 0;
|
||||
padding: 5px 0 0 0;
|
||||
.ltr-float-right();
|
||||
width: 50%;
|
||||
color: var(--color-settings-engine-description-font);
|
||||
font-size: 90%;
|
||||
}
|
||||
|
||||
table {
|
||||
border-collapse: collapse;
|
||||
}
|
||||
|
||||
table td {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.category {
|
||||
.ltr-margin-right(0.5rem);
|
||||
|
||||
label {
|
||||
border: 2px solid transparent;
|
||||
padding: 0.2rem 0.4rem;
|
||||
.rounded-corners-tiny;
|
||||
}
|
||||
}
|
||||
|
||||
.category input[type="checkbox"]:checked + label {
|
||||
border: 2px solid var(--color-categories-item-border-selected);
|
||||
}
|
||||
|
||||
table.table_engines {
|
||||
td {
|
||||
height: 3.75rem;
|
||||
}
|
||||
|
||||
th.name {
|
||||
/* stylelint-disable */
|
||||
label {
|
||||
cursor: pointer;
|
||||
}
|
||||
/* stylelint-enable */
|
||||
|
||||
.engine-tooltip {
|
||||
margin-top: 1.8rem;
|
||||
.ltr-left(calc((100% - 85em) / 2 + 10em));
|
||||
max-width: 40rem;
|
||||
|
||||
.engine-description {
|
||||
margin-top: 0.5rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.engine-group {
|
||||
.ltr-text-align-left();
|
||||
font-weight: normal;
|
||||
background: var(--color-settings-engine-group-background);
|
||||
}
|
||||
|
||||
.name,
|
||||
.shortcut {
|
||||
.ltr-text-align-left();
|
||||
}
|
||||
}
|
||||
|
||||
table.cookies {
|
||||
width: 100%;
|
||||
direction: ltr;
|
||||
|
||||
th,
|
||||
td {
|
||||
text-align: left;
|
||||
font-family: monospace;
|
||||
font-size: 1rem;
|
||||
padding: 0.5em;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
td:first-child {
|
||||
word-break: keep-all;
|
||||
width: 14rem;
|
||||
padding-right: 1rem;
|
||||
}
|
||||
|
||||
td:last-child {
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
& > tbody > tr:nth-child(even) > th,
|
||||
& > tbody > tr:nth-child(even) > td {
|
||||
background-color: var(--color-settings-tr-hover);
|
||||
}
|
||||
}
|
||||
|
||||
.preferences_back {
|
||||
background: none repeat scroll 0 0 var(--color-btn-background);
|
||||
color: var(--color-btn-font);
|
||||
border: 0 none;
|
||||
.rounded-corners;
|
||||
|
||||
cursor: pointer;
|
||||
display: inline-block;
|
||||
margin: 2px 4px;
|
||||
padding: 0.7em;
|
||||
|
||||
a {
|
||||
color: var(--color-settings-return-font);
|
||||
}
|
||||
|
||||
a::first-letter {
|
||||
text-transform: uppercase;
|
||||
}
|
||||
}
|
||||
|
||||
div.selectable_url {
|
||||
pre {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: @tablet) {
|
||||
.preferences_back {
|
||||
clear: both;
|
||||
}
|
||||
|
||||
.engine-tooltip {
|
||||
.ltr-left(10em) !important;
|
||||
}
|
||||
}
|
7
beetroot_static/src/less/result_templates.less
Normal file
|
@ -0,0 +1,7 @@
|
|||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
.osm-map-box {
|
||||
height: 300px;
|
||||
width: 100%;
|
||||
margin: 10px 0;
|
||||
}
|
340
beetroot_static/src/less/search.less
Normal file
|
@ -0,0 +1,340 @@
|
|||
/*
|
||||
* SearXNG, A privacy-respecting, hackable metasearch engine
|
||||
*/
|
||||
|
||||
#search {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
#search_header {
|
||||
padding-top: 1.5em;
|
||||
.ltr-padding-right(2em);
|
||||
.ltr-padding-left(@results-offset - 3rem);
|
||||
margin: 0;
|
||||
background: var(--color-header-background);
|
||||
border-bottom: 1px solid var(--color-header-border);
|
||||
display: grid;
|
||||
column-gap: 1.2rem;
|
||||
row-gap: 1rem;
|
||||
grid-template-columns: 3rem 1fr;
|
||||
grid-template-areas:
|
||||
"logo search"
|
||||
"spacer categories";
|
||||
}
|
||||
|
||||
.category {
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
.ltr-margin-right(1rem);
|
||||
padding: 0;
|
||||
|
||||
input {
|
||||
display: none;
|
||||
}
|
||||
|
||||
label {
|
||||
svg {
|
||||
padding-right: 0.2rem;
|
||||
}
|
||||
|
||||
cursor: pointer;
|
||||
padding: 0.2rem 0;
|
||||
display: inline-flex;
|
||||
text-transform: capitalize;
|
||||
font-size: 0.9em;
|
||||
border-bottom: 2px solid transparent;
|
||||
.disable-user-select;
|
||||
|
||||
div.category_name {
|
||||
margin: auto 0;
|
||||
}
|
||||
}
|
||||
|
||||
input[type="checkbox"]:checked + label {
|
||||
color: var(--color-categories-item-selected-font);
|
||||
border-bottom: 2px solid var(--color-categories-item-border-selected);
|
||||
}
|
||||
}
|
||||
|
||||
#search_logo {
|
||||
grid-area: logo;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
svg {
|
||||
flex: 1;
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
margin: 0.5rem 0 auto 0;
|
||||
}
|
||||
}
|
||||
|
||||
.search_categories {
|
||||
grid-area: categories;
|
||||
|
||||
.help {
|
||||
display: none;
|
||||
}
|
||||
|
||||
&:hover .help {
|
||||
display: block;
|
||||
position: absolute;
|
||||
background: var(--color-base-background);
|
||||
padding: 1rem 0.6rem 0.6rem 0;
|
||||
z-index: 1000;
|
||||
width: 100%;
|
||||
left: -0.1rem;
|
||||
}
|
||||
}
|
||||
|
||||
#search_view {
|
||||
grid-area: search;
|
||||
}
|
||||
|
||||
.search_box {
|
||||
border-radius: 0.8rem;
|
||||
width: @search-width;
|
||||
display: inline-flex;
|
||||
flex-direction: row;
|
||||
white-space: nowrap;
|
||||
box-shadow: var(--color-search-shadow);
|
||||
}
|
||||
|
||||
#clear_search {
|
||||
display: block;
|
||||
border-collapse: separate;
|
||||
box-sizing: border-box;
|
||||
width: 1.8rem;
|
||||
margin: 0;
|
||||
padding: 0.8rem 0.2rem;
|
||||
background: none repeat scroll 0 0 var(--color-search-background);
|
||||
border: none;
|
||||
outline: none;
|
||||
color: var(--color-search-font);
|
||||
font-size: 1.1rem;
|
||||
z-index: 10000;
|
||||
|
||||
&:hover {
|
||||
color: var(--color-search-background-hover);
|
||||
}
|
||||
|
||||
&.empty * {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
html.no-js #clear_search.hide_if_nojs {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#q,
|
||||
#send_search {
|
||||
display: block;
|
||||
margin: 0;
|
||||
padding: 0.8rem;
|
||||
background: none repeat scroll 0 0 var(--color-search-background);
|
||||
border: none;
|
||||
outline: none;
|
||||
color: var(--color-search-font);
|
||||
font-size: 1.1rem;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
#q {
|
||||
width: 100%;
|
||||
.ltr-padding-left(1rem);
|
||||
.ltr-padding-right(0) !important;
|
||||
.ltr-rounded-left-corners(0.8rem);
|
||||
}
|
||||
|
||||
#q::-ms-clear,
|
||||
#q::-webkit-search-cancel-button {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#send_search {
|
||||
.ltr-rounded-right-corners(0.8rem);
|
||||
|
||||
&:hover {
|
||||
cursor: pointer;
|
||||
background-color: var(--color-search-background-hover);
|
||||
color: var(--color-search-background);
|
||||
}
|
||||
}
|
||||
|
||||
.no-js #clear_search,
|
||||
.no-js #send_search {
|
||||
width: auto !important;
|
||||
.ltr-border-left(1px solid var(--color-search-border));
|
||||
}
|
||||
|
||||
.search_filters {
|
||||
margin-top: 0.6rem;
|
||||
.ltr-margin-right(0);
|
||||
margin-bottom: 0;
|
||||
.ltr-margin-left(@results-offset + 0.6rem);
|
||||
display: flex;
|
||||
overflow-x: auto;
|
||||
overscroll-behavior-inline: contain;
|
||||
|
||||
select {
|
||||
background-color: inherit;
|
||||
|
||||
&:hover,
|
||||
&:focus {
|
||||
color: var(--color-base-font);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: @tablet) {
|
||||
#search_header {
|
||||
padding: 1.5em @results-tablet-offset 0 @results-tablet-offset;
|
||||
column-gap: @results-tablet-offset;
|
||||
}
|
||||
|
||||
.search_filters {
|
||||
margin-top: 0.6rem;
|
||||
.ltr-margin-right(0);
|
||||
margin-bottom: 0;
|
||||
.ltr-margin-left(@results-tablet-offset + 3rem);
|
||||
}
|
||||
|
||||
#categories {
|
||||
font-size: 90%;
|
||||
clear: both;
|
||||
|
||||
.checkbox_container {
|
||||
margin: auto;
|
||||
margin-top: 2px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: @tablet) and (hover: none) {
|
||||
#main_index,
|
||||
#main_results {
|
||||
#categories_container {
|
||||
width: max-content;
|
||||
|
||||
.category {
|
||||
display: inline-block;
|
||||
width: auto;
|
||||
}
|
||||
}
|
||||
|
||||
#categories {
|
||||
width: 100%;
|
||||
.ltr-text-align-left();
|
||||
overflow-x: scroll;
|
||||
overflow-y: hidden;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: @phone) {
|
||||
#search_header {
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
padding: 0.1rem 0 0 0;
|
||||
column-gap: 0;
|
||||
row-gap: 0;
|
||||
grid-template-areas:
|
||||
"logo search"
|
||||
"categories categories";
|
||||
}
|
||||
|
||||
.search_logo {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.search_box {
|
||||
width: 98%;
|
||||
display: flex;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
#q {
|
||||
width: 100%;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.search_filters {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.category {
|
||||
display: inline-block;
|
||||
width: auto;
|
||||
margin: 0;
|
||||
|
||||
label {
|
||||
padding: 1rem !important;
|
||||
margin: 0 !important;
|
||||
|
||||
svg {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#search_view:focus-within {
|
||||
display: block;
|
||||
background-color: var(--color-search-background);
|
||||
position: absolute;
|
||||
top: 0;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
z-index: 10000;
|
||||
|
||||
.search_box {
|
||||
border-bottom: 1px solid var(--color-search-border);
|
||||
width: 100%;
|
||||
border-radius: 0;
|
||||
box-shadow: none;
|
||||
|
||||
#send_search {
|
||||
.ltr-margin-right(0) !important; // Delete when send_search button is disabled on mobile.
|
||||
}
|
||||
|
||||
* {
|
||||
border: none;
|
||||
border-radius: 0;
|
||||
box-shadow: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#main_results #q:placeholder-shown ~ #send_search {
|
||||
.ltr-margin-right(2.6rem);
|
||||
transition: margin 0.1s;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: @ultra-small-phone) {
|
||||
#search_header {
|
||||
grid-template-areas:
|
||||
"search search"
|
||||
"categories categories";
|
||||
}
|
||||
|
||||
#search_logo {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
#categories {
|
||||
.disable-user-select;
|
||||
|
||||
&::-webkit-scrollbar {
|
||||
width: 0;
|
||||
height: 0;
|
||||
}
|
||||
}
|
||||
|
||||
#categories_container {
|
||||
position: relative;
|
||||
}
|
106
beetroot_static/src/less/stats.less
Normal file
|
@ -0,0 +1,106 @@
|
|||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
.engine-stats {
|
||||
border-spacing: 0;
|
||||
border-collapse: collapse;
|
||||
|
||||
tr td,
|
||||
tr th {
|
||||
border-bottom: 1px solid var(--color-result-border);
|
||||
padding: 0.25rem;
|
||||
}
|
||||
|
||||
table.engine-tooltip {
|
||||
border-spacing: 0;
|
||||
border-collapse: collapse;
|
||||
|
||||
td,
|
||||
th {
|
||||
border: none;
|
||||
}
|
||||
}
|
||||
|
||||
.engine-name {
|
||||
width: 20rem;
|
||||
}
|
||||
|
||||
.engine-score {
|
||||
width: 7rem;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.engine-reliability {
|
||||
text-align: right;
|
||||
}
|
||||
}
|
||||
|
||||
table.engine-error th.engine-error-type,
|
||||
table.engine-error td.engine-error-type,
|
||||
failed-test {
|
||||
width: 10rem;
|
||||
}
|
||||
|
||||
.engine-errors {
|
||||
margin-top: 3rem;
|
||||
|
||||
table.engine-error {
|
||||
max-width: 1280px;
|
||||
margin: 1rem 0 3rem 0;
|
||||
border: 1px solid var(--color-result-border);
|
||||
.ltr-text-align-left();
|
||||
|
||||
tr th,
|
||||
tr td {
|
||||
padding: 0.5rem;
|
||||
}
|
||||
|
||||
& span.log_parameters {
|
||||
border-right: 1px solid solid var(--color-result-border);
|
||||
padding: 0 1rem 0 0;
|
||||
margin: 0 0 0 0.5rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.bar-chart-value {
|
||||
width: 3em;
|
||||
display: inline-block;
|
||||
text-align: right;
|
||||
padding-right: 0.5rem;
|
||||
}
|
||||
|
||||
.bar-chart-graph {
|
||||
width: calc(100% - 5rem);
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.bar-chart-bar {
|
||||
border: 3px solid #5bc0de;
|
||||
margin: 1px 0;
|
||||
}
|
||||
|
||||
.bar-chart-serie1 {
|
||||
border: 3px solid #5bc0de;
|
||||
margin: 1px 0;
|
||||
float: left;
|
||||
}
|
||||
|
||||
.bar-chart-serie2 {
|
||||
border: 3px solid #deb15b;
|
||||
margin: 1px 0;
|
||||
float: left;
|
||||
}
|
||||
|
||||
.bar0 {
|
||||
width: 0;
|
||||
border: 0;
|
||||
}
|
||||
|
||||
.generate-bar(100);
|
||||
|
||||
.generate-bar(@n, @i: 1) when (@i =< @n) {
|
||||
.bar@{i} {
|
||||
width: (@i * 100% / @n);
|
||||
}
|
||||
.generate-bar(@n, (@i + 1));
|
||||
}
|
118
beetroot_static/src/less/style-center.less
Normal file
|
@ -0,0 +1,118 @@
|
|||
/*
|
||||
--center-page-width overrides the less variable @results-width when the results are centered
|
||||
see the CSS rules for #results in style.less ( grid-template-columns and gap).
|
||||
|
||||
In this file, the --center-page-width values comes from the Oscar theme (Bootstrap 3).
|
||||
|
||||
All rules starts with ".center-aligment-yes #main_results" to be enabled only
|
||||
on the /search URL and when the "center alignment" preference is enabled.
|
||||
*/
|
||||
|
||||
@media screen and (min-width: @phone) {
|
||||
.center-aligment-yes #main_results {
|
||||
--center-page-width: 48rem;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (min-width: 62rem) {
|
||||
.center-aligment-yes #main_results {
|
||||
--center-page-width: 60rem;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (min-width: @tablet) {
|
||||
.center-aligment-yes #main_results {
|
||||
--center-page-width: 73rem;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (min-width: @phone) and (max-width: @tablet) {
|
||||
// any change must be reset in @media screen and (min-width: @tablet) { ... }
|
||||
.center-aligment-yes #main_results {
|
||||
#results {
|
||||
grid-template-columns: 60% calc(40% - @results-gap);
|
||||
margin-left: 0;
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
#urls {
|
||||
.ltr-margin-left(3rem);
|
||||
}
|
||||
|
||||
#sidebar {
|
||||
.ltr-margin-right(1rem);
|
||||
}
|
||||
|
||||
#backToTop {
|
||||
.ltr-left(calc(60% + 1rem));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (min-width: @tablet) {
|
||||
.center-aligment-yes #main_results {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
|
||||
#search {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
#search_header {
|
||||
grid-template-columns: calc(50% - 4.5rem - var(--center-page-width) / 2) 3rem var(--center-page-width);
|
||||
grid-template-areas: "na logo search" "na spacer categories";
|
||||
column-gap: 1.2rem; // from search.less
|
||||
width: 100%;
|
||||
padding-left: 0;
|
||||
padding-right: 0;
|
||||
}
|
||||
|
||||
.search_filters {
|
||||
.ltr-margin-left(0.5rem);
|
||||
width: var(--center-page-width);
|
||||
}
|
||||
|
||||
#results {
|
||||
// from style.less (when screen width = @tablet, reset layout from tablet)
|
||||
.ltr-margin-right(2rem);
|
||||
.ltr-margin-left(@results-offset);
|
||||
//
|
||||
|
||||
&.only_template_images,
|
||||
&.image-detail-open {
|
||||
// * grid-template-columns and .ltr-margin-left are set in style.less
|
||||
// * With .image-detail-open.only_template_images, the width is set in detail.less
|
||||
// * #results is going to be centered because of the #main_results rules,
|
||||
// align-self aligns the results on the left or right according to the language.
|
||||
align-self: flex-start;
|
||||
}
|
||||
|
||||
&:not(.only_template_images):not(.image-detail-open) {
|
||||
// the gap is set in style.less
|
||||
.ltr-margin-left(1.5rem);
|
||||
grid-template-columns: calc(var(--center-page-width) - @results-gap - @results-sidebar-width) @results-sidebar-width;
|
||||
|
||||
#backToTop {
|
||||
.ltr-left(calc(50% - @results-sidebar-width - @results-gap + 1rem + var(--center-page-width) / 2));
|
||||
}
|
||||
}
|
||||
|
||||
.result .content {
|
||||
max-width: inherit;
|
||||
}
|
||||
}
|
||||
|
||||
// from style.less (when screen width = @tablet, reset layout from tablet)
|
||||
#urls {
|
||||
.ltr-margin-left(0);
|
||||
}
|
||||
|
||||
#sidebar {
|
||||
.ltr-margin-right(0);
|
||||
}
|
||||
}
|
||||
}
|
85
beetroot_static/src/less/style-ltr.less
Normal file
|
@ -0,0 +1,85 @@
|
|||
.ltr-left(@offset) {
|
||||
left: @offset;
|
||||
}
|
||||
|
||||
.ltr-right(@offset) {
|
||||
right: @offset;
|
||||
}
|
||||
|
||||
.ltr-margin-right(@offset) {
|
||||
margin-right: @offset;
|
||||
}
|
||||
|
||||
.ltr-margin-left(@offset) {
|
||||
margin-left: @offset;
|
||||
}
|
||||
|
||||
.ltr-border-right(@offset) {
|
||||
border-right: @offset;
|
||||
}
|
||||
|
||||
.ltr-border-left(@offset) {
|
||||
border-left: @offset;
|
||||
}
|
||||
|
||||
.ltr-padding-right(@offset) {
|
||||
padding-right: @offset;
|
||||
}
|
||||
|
||||
.ltr-padding-left(@offset) {
|
||||
padding-left: @offset;
|
||||
}
|
||||
|
||||
.ltr-float-left() {
|
||||
float: left;
|
||||
}
|
||||
|
||||
.ltr-float-right() {
|
||||
float: right;
|
||||
}
|
||||
|
||||
.ltr-text-align-right() {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.ltr-rounded-left-corners(@radius) {
|
||||
border-radius: @radius 0 0 @radius;
|
||||
}
|
||||
|
||||
.ltr-rounded-top-left-corners(@radius) {
|
||||
border-radius: @radius 0 0 0;
|
||||
}
|
||||
|
||||
.ltr-rounded-bottom-left-corners(@radius) {
|
||||
border-radius: 0 0 0 @radius;
|
||||
}
|
||||
|
||||
.ltr-rounded-right-corners(@radius) {
|
||||
border-radius: 0 @radius @radius 0;
|
||||
}
|
||||
|
||||
.ltr-rounded-top-right-corners(@radius) {
|
||||
border-radius: 0 @radius 0 0;
|
||||
}
|
||||
|
||||
.ltr-rounded-bottom-right-corners(@radius) {
|
||||
border-radius: 0 0 @radius 0;
|
||||
}
|
||||
|
||||
.ltr-text-align-left() {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.ltr-border-left-width(@offset) {
|
||||
border-left-width: @offset;
|
||||
}
|
||||
|
||||
.ltr-border-right-width(@offset) {
|
||||
border-right-width: @offset;
|
||||
}
|
||||
|
||||
.ltr-transform() {
|
||||
transform: scale(1, 1);
|
||||
}
|
||||
|
||||
@import "style.less";
|
155
beetroot_static/src/less/style-rtl.less
Normal file
|
@ -0,0 +1,155 @@
|
|||
.ltr-left(@offset) {
|
||||
right: @offset;
|
||||
}
|
||||
|
||||
.ltr-right(@offset) {
|
||||
left: @offset;
|
||||
}
|
||||
|
||||
.ltr-margin-right(@offset) {
|
||||
margin-left: @offset;
|
||||
}
|
||||
|
||||
.ltr-margin-left(@offset) {
|
||||
margin-right: @offset;
|
||||
}
|
||||
|
||||
.ltr-border-right(@offset) {
|
||||
border-left: @offset;
|
||||
}
|
||||
|
||||
.ltr-border-left(@offset) {
|
||||
border-right: @offset;
|
||||
}
|
||||
|
||||
.ltr-padding-right(@offset) {
|
||||
padding-left: @offset;
|
||||
}
|
||||
|
||||
.ltr-padding-left(@offset) {
|
||||
padding-right: @offset;
|
||||
}
|
||||
|
||||
.ltr-float-left() {
|
||||
float: right;
|
||||
}
|
||||
|
||||
.ltr-float-right() {
|
||||
float: left;
|
||||
}
|
||||
|
||||
.ltr-text-align-right() {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.ltr-rounded-left-corners(@radius) {
|
||||
border-radius: 0 @radius @radius 0;
|
||||
}
|
||||
|
||||
.ltr-rounded-top-left-corners(@radius) {
|
||||
border-radius: 0 @radius 0 0;
|
||||
}
|
||||
|
||||
.ltr-rounded-bottom-left-corners(@radius) {
|
||||
border-radius: 0 0 @radius 0;
|
||||
}
|
||||
|
||||
.ltr-rounded-right-corners(@radius) {
|
||||
border-radius: @radius 0 0 @radius;
|
||||
}
|
||||
|
||||
.ltr-rounded-top-right-corners(@radius) {
|
||||
border-radius: @radius 0 0 0;
|
||||
}
|
||||
|
||||
.ltr-rounded-bottom-right-corners(@radius) {
|
||||
border-radius: 0 0 0 @radius;
|
||||
}
|
||||
|
||||
.ltr-text-align-left() {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.ltr-border-left-width(@offset) {
|
||||
border-right-width: @offset;
|
||||
}
|
||||
|
||||
.ltr-border-right-width(@offset) {
|
||||
border-left-width: @offset;
|
||||
}
|
||||
|
||||
.ltr-transform() {
|
||||
transform: scale(-1, 1);
|
||||
}
|
||||
|
||||
@import "style.less";
|
||||
|
||||
#q,
|
||||
#sidebar .infobox dt bdi {
|
||||
direction: rtl;
|
||||
}
|
||||
|
||||
// URL are displayed LTR but align on the right
|
||||
#urls {
|
||||
direction: initial;
|
||||
text-align: right;
|
||||
|
||||
.result .url_wrapper {
|
||||
justify-content: end;
|
||||
}
|
||||
}
|
||||
|
||||
// Image flexbox
|
||||
#main_results div#results.only_template_images #urls {
|
||||
direction: rtl;
|
||||
}
|
||||
|
||||
// Image detail
|
||||
#results.image-detail-open article.result-images[data-vim-selected] .detail .result-images-labels p {
|
||||
direction: rtl;
|
||||
|
||||
&.result-url {
|
||||
// Display URL using the LTR direction
|
||||
direction: ltr;
|
||||
|
||||
span {
|
||||
// And put the label on the right
|
||||
direction: rtl;
|
||||
float: right;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// select HTML element
|
||||
@supports ((background-position-x: 100%) and ((appearance: none) or (-webkit-appearance: none) or (-moz-appearance: none))) {
|
||||
select {
|
||||
border-width: 0 0 0 2rem;
|
||||
background-position-x: -2rem;
|
||||
}
|
||||
}
|
||||
|
||||
// vim hotkey helps is not translated
|
||||
#vim-hotkeys-help table {
|
||||
direction: ltr;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
// Logo on the right
|
||||
#main_preferences h1,
|
||||
#main_stats h1 {
|
||||
background-position-x: 100%;
|
||||
}
|
||||
|
||||
// patch of stats.less
|
||||
.bar-chart-serie1,
|
||||
.bar-chart-serie2 {
|
||||
float: right;
|
||||
}
|
||||
|
||||
.engine-stats .engine-name,
|
||||
.engine-stats .engine-score,
|
||||
.engine-stats .result-count,
|
||||
.engine-stats .response-time,
|
||||
.engine-stats .engine-reliability {
|
||||
text-align: right;
|
||||
}
|
1077
beetroot_static/src/less/style.less
Normal file
639
beetroot_static/src/less/toolkit.less
Normal file
|
@ -0,0 +1,639 @@
|
|||
// other solution : http://stackoverflow.com/questions/1577598/how-to-hide-parts-of-html-when-javascript-is-disabled/13857783#13857783
|
||||
|
||||
// stylelint-disable no-descending-specificity
|
||||
|
||||
html.no-js .hide_if_nojs {
|
||||
display: none;
|
||||
}
|
||||
|
||||
html.js .show_if_nojs {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.center {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.right {
|
||||
float: right;
|
||||
}
|
||||
|
||||
.left {
|
||||
float: left;
|
||||
}
|
||||
|
||||
.invisible {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
.list-unstyled {
|
||||
list-style-type: none;
|
||||
|
||||
li {
|
||||
margin-top: 4px;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
}
|
||||
|
||||
.danger {
|
||||
background-color: var(--color-error-background);
|
||||
}
|
||||
|
||||
.warning {
|
||||
background: var(--color-warning-background);
|
||||
}
|
||||
|
||||
.success {
|
||||
background: var(--color-success-background);
|
||||
}
|
||||
|
||||
.badge {
|
||||
display: inline-block;
|
||||
color: var(--color-toolkit-badge-font);
|
||||
background-color: var(--color-toolkit-badge-background);
|
||||
text-align: center;
|
||||
white-space: nowrap;
|
||||
vertical-align: baseline;
|
||||
min-width: 10px;
|
||||
padding: 1px 5px;
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
// kbd
|
||||
kbd {
|
||||
padding: 2px 4px;
|
||||
margin: 1px;
|
||||
font-size: 90%;
|
||||
color: var(--color-toolkit-kbd-font);
|
||||
background: var(--color-toolkit-kbd-background);
|
||||
}
|
||||
|
||||
// table
|
||||
table {
|
||||
width: 100%;
|
||||
|
||||
&.striped {
|
||||
tr {
|
||||
border-bottom: 1px solid var(--color-settings-tr-hover);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
th {
|
||||
padding: 0.4em;
|
||||
}
|
||||
|
||||
td {
|
||||
padding: 0 4px;
|
||||
}
|
||||
|
||||
tr {
|
||||
&:hover {
|
||||
background: var(--color-settings-tr-hover) !important;
|
||||
}
|
||||
}
|
||||
|
||||
// pre
|
||||
.pre() {
|
||||
display: block;
|
||||
font-size: 0.8em;
|
||||
word-break: break-all;
|
||||
margin: 0.1em;
|
||||
user-select: all;
|
||||
}
|
||||
|
||||
div.selectable_url {
|
||||
display: block;
|
||||
border: 1px solid var(--color-result-search-url-border);
|
||||
padding: 4px;
|
||||
color: var(--color-result-search-url-font);
|
||||
margin: 0.1em;
|
||||
overflow: hidden;
|
||||
height: 1.2em;
|
||||
line-height: 1.2em;
|
||||
.rounded-corners-tiny;
|
||||
|
||||
pre {
|
||||
.pre();
|
||||
}
|
||||
}
|
||||
|
||||
// dialog
|
||||
.dialog() {
|
||||
position: relative;
|
||||
display: flex;
|
||||
padding: 1rem;
|
||||
margin: 0 0 1em 0;
|
||||
border: 1px solid var(--color-toolkit-dialog-border);
|
||||
.ltr-text-align-left();
|
||||
.rounded-corners;
|
||||
|
||||
.close {
|
||||
.ltr-float-right();
|
||||
position: relative;
|
||||
top: -3px;
|
||||
color: inherit;
|
||||
font-size: 1.5em;
|
||||
}
|
||||
|
||||
ul,
|
||||
ol,
|
||||
p {
|
||||
margin: 1px 0 0 0;
|
||||
}
|
||||
|
||||
table {
|
||||
width: auto;
|
||||
}
|
||||
|
||||
tr {
|
||||
vertical-align: text-top;
|
||||
|
||||
&:hover {
|
||||
background: transparent !important;
|
||||
}
|
||||
}
|
||||
|
||||
td {
|
||||
padding: 0 1em 0 0;
|
||||
padding-top: 0;
|
||||
.ltr-padding-right(1rem);
|
||||
padding-bottom: 0;
|
||||
.ltr-padding-left(0);
|
||||
}
|
||||
|
||||
h4 {
|
||||
margin-top: 0.3em;
|
||||
margin-bottom: 0.3em;
|
||||
}
|
||||
}
|
||||
|
||||
.dialog-error {
|
||||
.dialog();
|
||||
|
||||
color: var(--color-error);
|
||||
background: var(--color-error-background);
|
||||
border-color: var(--color-error);
|
||||
}
|
||||
|
||||
.dialog-warning {
|
||||
.dialog();
|
||||
|
||||
color: var(--color-warning);
|
||||
background: var(--color-warning-background);
|
||||
border-color: var(--color-warning);
|
||||
}
|
||||
|
||||
.dialog-modal {
|
||||
.dialog();
|
||||
|
||||
display: block;
|
||||
background: var(--color-toolkit-dialog-background);
|
||||
position: fixed;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
margin: 0 auto;
|
||||
transform: translate(-50%, -50%);
|
||||
z-index: 10000000;
|
||||
|
||||
h3 {
|
||||
margin-top: 0;
|
||||
}
|
||||
}
|
||||
|
||||
// btn-collapse
|
||||
.btn-collapse {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
//
|
||||
.scrollx {
|
||||
overflow-x: auto;
|
||||
overflow-y: hidden;
|
||||
display: block;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
border: none;
|
||||
}
|
||||
|
||||
/* -- tabs -- */
|
||||
.tabs .tabs > label {
|
||||
font-size: 90%;
|
||||
}
|
||||
|
||||
ul.tabs {
|
||||
border-bottom: 1px solid var(--color-toolkit-tabs-section-border);
|
||||
list-style: none;
|
||||
padding-left: 0;
|
||||
|
||||
li {
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
|
||||
.tabs {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
width: 100%;
|
||||
min-width: 100%;
|
||||
|
||||
& > * {
|
||||
order: 2;
|
||||
}
|
||||
|
||||
& > input[type=radio] {
|
||||
display: none;
|
||||
}
|
||||
|
||||
& > label,
|
||||
& > li > a {
|
||||
order: 1;
|
||||
padding: 0.7em;
|
||||
margin: 0 0.7em;
|
||||
letter-spacing: 0.5px;
|
||||
text-transform: uppercase;
|
||||
border: solid var(--color-toolkit-tabs-label-border);
|
||||
border-width: 0 0 2px 0;
|
||||
color: unset;
|
||||
|
||||
.disable-user-select();
|
||||
|
||||
cursor: pointer;
|
||||
|
||||
&.active {
|
||||
border-bottom: 2px solid var(--color-categories-item-border-selected);
|
||||
background: var(--color-categories-item-selected);
|
||||
color: var(--color-categories-item-selected-font);
|
||||
}
|
||||
}
|
||||
|
||||
& > label:hover,
|
||||
& > li > a:hover {
|
||||
border-bottom: 2px solid var(--color-categories-item-border-selected);
|
||||
}
|
||||
|
||||
& > section {
|
||||
min-width: 100%;
|
||||
padding: 0.7rem 0;
|
||||
box-sizing: border-box;
|
||||
border-top: 1px solid var(--color-toolkit-tabs-section-border);
|
||||
display: none;
|
||||
}
|
||||
|
||||
// default selection
|
||||
& > label:last-of-type {
|
||||
border-bottom: 2px solid var(--color-categories-item-border-selected);
|
||||
background: var(--color-categories-item-selected);
|
||||
color: var(--color-categories-item-selected-font);
|
||||
letter-spacing: -0.1px;
|
||||
}
|
||||
|
||||
& > section:last-of-type {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
html body .tabs > input:checked {
|
||||
~ section {
|
||||
display: none;
|
||||
}
|
||||
|
||||
~ label {
|
||||
position: inherited;
|
||||
background: inherit;
|
||||
border-bottom: 2px solid transparent;
|
||||
font-weight: normal;
|
||||
color: inherit;
|
||||
|
||||
&:hover {
|
||||
border-bottom: 2px solid var(--color-categories-item-border-selected);
|
||||
}
|
||||
}
|
||||
|
||||
+ label {
|
||||
border-bottom: 2px solid var(--color-categories-item-border-selected);
|
||||
background: var(--color-categories-item-selected);
|
||||
color: var(--color-categories-item-selected-font);
|
||||
}
|
||||
|
||||
+ label + section {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
/* -- select -- */
|
||||
select {
|
||||
height: 2.4rem;
|
||||
margin-top: 0;
|
||||
.ltr-margin-right(1rem);
|
||||
margin-bottom: 0;
|
||||
.ltr-margin-left(0);
|
||||
padding: 0.2rem !important;
|
||||
color: var(--color-search-font);
|
||||
font-size: 0.9rem;
|
||||
z-index: 2;
|
||||
|
||||
&:hover,
|
||||
&:focus {
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
||||
@supports ((background-position-x: 100%) and ((appearance: none) or (-webkit-appearance: none) or (-moz-appearance: none))) {
|
||||
select {
|
||||
appearance: none;
|
||||
-webkit-appearance: none;
|
||||
-moz-appearance: none;
|
||||
border-width: 0 2rem 0 0;
|
||||
border-color: transparent;
|
||||
background: data-uri('image/svg+xml;charset=UTF-8', @select-light-svg-path) no-repeat;
|
||||
background-position-x: calc(100% + 2rem);
|
||||
background-size: 2rem;
|
||||
background-origin: content-box;
|
||||
background-color: var(--color-toolkit-select-background);
|
||||
outline: medium none;
|
||||
text-overflow: ellipsis;
|
||||
.rounded-corners-tiny;
|
||||
|
||||
&:hover,
|
||||
&:focus {
|
||||
background-color: var(--color-toolkit-select-background-hover);
|
||||
}
|
||||
|
||||
option {
|
||||
background-color: var(--color-base-background);
|
||||
}
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
html.theme-auto select,
|
||||
html.theme-dark select {
|
||||
background-image: data-uri('image/svg+xml;charset=UTF-8', @select-dark-svg-path);
|
||||
}
|
||||
}
|
||||
|
||||
html.theme-dark select {
|
||||
background-image: data-uri('image/svg+xml;charset=UTF-8', @select-dark-svg-path);
|
||||
}
|
||||
}
|
||||
|
||||
/* -- checkbox-onoff -- */
|
||||
input.checkbox-onoff[type="checkbox"] {
|
||||
-webkit-appearance: none;
|
||||
-moz-appearance: none;
|
||||
appearance: none;
|
||||
cursor: pointer;
|
||||
display: inline-block;
|
||||
width: 2.5em;
|
||||
height: 0.7em;
|
||||
box-shadow: none !important;
|
||||
margin: 0 16px;
|
||||
border-radius: 10px;
|
||||
position: relative;
|
||||
|
||||
/* focus & hover */
|
||||
&:focus,
|
||||
&:hover {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
&:focus::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
width: 3.5em;
|
||||
height: 1.65em;
|
||||
border: 1px solid var(--color-btn-background);
|
||||
border-radius: 12px;
|
||||
box-shadow: var(--color-btn-background) 0 0 3px;
|
||||
z-index: 10000;
|
||||
top: -0.55em;
|
||||
left: -0.6em;
|
||||
}
|
||||
|
||||
&::before {
|
||||
position: absolute;
|
||||
top: -0.5em;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
font-size: 0.75em;
|
||||
width: 1.875em;
|
||||
height: 1.875em;
|
||||
border-radius: 50%;
|
||||
}
|
||||
}
|
||||
|
||||
/* check mark
|
||||
reversed-checkbox displays unchecked checkedboxes as checked, and vice versa.
|
||||
see https://github.com/searxng/searxng/blob/3408d061aab9abc6168fec9bbc6deab71b236dac/searx/templates/simple/preferences.html#L313
|
||||
*/
|
||||
input.checkbox-onoff[type="checkbox"],
|
||||
.reversed-checkbox input.checkbox-onoff[type="checkbox"]:checked {
|
||||
background: var(--color-toolkit-checkbox-onoff-off-background);
|
||||
|
||||
&::before {
|
||||
left: -0.5em;
|
||||
content: "\2715";
|
||||
color: var(--color-toolkit-checkbox-onoff-off-mark-color);
|
||||
background: var(--color-toolkit-checkbox-onoff-off-mark-background);
|
||||
}
|
||||
}
|
||||
|
||||
input.checkbox-onoff[type="checkbox"]:checked,
|
||||
.reversed-checkbox input.checkbox-onoff[type="checkbox"] {
|
||||
background: var(--color-toolkit-checkbox-onoff-on-background);
|
||||
|
||||
&::before {
|
||||
left: calc(100% - 1.5em);
|
||||
content: "\2713";
|
||||
color: var(--color-toolkit-checkbox-onoff-on-mark-color);
|
||||
background: var(--color-toolkit-checkbox-onoff-on-mark-background);
|
||||
}
|
||||
}
|
||||
|
||||
/* -- checkbox -- */
|
||||
@supports (transform: rotate(-45deg)) {
|
||||
input[type=checkbox]:not(.checkbox-onoff) {
|
||||
-webkit-appearance: none;
|
||||
-moz-appearance: none;
|
||||
appearance: none;
|
||||
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
top: 0;
|
||||
left: 0;
|
||||
border: 2px solid var(--color-toolkit-checkbox-input-border);
|
||||
.rounded-corners(0.3em);
|
||||
|
||||
&::after {
|
||||
content: '';
|
||||
width: 9px;
|
||||
height: 5px;
|
||||
position: absolute;
|
||||
top: 3px;
|
||||
left: 2px;
|
||||
border: 3px solid var(--color-toolkit-checkbox-label-border);
|
||||
border-top: none;
|
||||
border-right: none;
|
||||
background: transparent;
|
||||
opacity: 0;
|
||||
transform: rotate(-45deg);
|
||||
}
|
||||
|
||||
&:checked::after {
|
||||
border-color: var(--color-toolkit-checkbox-input-border);
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
// disabled : can't be focused, show only the check mark
|
||||
input[type=checkbox][disabled]:not(.checkbox-onoff) {
|
||||
border: inherit;
|
||||
background-color: transparent !important;
|
||||
cursor: inherit;
|
||||
}
|
||||
|
||||
// if not checked and possible to checked then display a "light" check mark on hover
|
||||
input.checkbox[type=checkbox]:not(:checked):not([disabled]):not(.checkbox-onoff):hover::after {
|
||||
opacity: 0.5;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: @phone) {
|
||||
.tabs > label {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
/* -- loader -- */
|
||||
.loader,
|
||||
.loader::after {
|
||||
border-radius: 50%;
|
||||
width: 2em;
|
||||
height: 2em;
|
||||
}
|
||||
|
||||
.loader {
|
||||
margin: 1em auto;
|
||||
font-size: 10px;
|
||||
position: relative;
|
||||
text-indent: -9999em;
|
||||
border-top: 0.5em solid var(--color-toolkit-loader-border);
|
||||
border-right: 0.5em solid var(--color-toolkit-loader-border);
|
||||
border-bottom: 0.5em solid var(--color-toolkit-loader-border);
|
||||
border-left: 0.5em solid var(--color-toolkit-loader-borderleft);
|
||||
-webkit-transform: translateZ(0);
|
||||
-ms-transform: translateZ(0);
|
||||
transform: translateZ(0);
|
||||
-webkit-animation: load8 1.2s infinite linear;
|
||||
animation: load8 1.2s infinite linear;
|
||||
}
|
||||
|
||||
@-webkit-keyframes load8 {
|
||||
0% {
|
||||
-webkit-transform: rotate(0deg);
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
|
||||
100% {
|
||||
-webkit-transform: rotate(360deg);
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes load8 {
|
||||
0% {
|
||||
-webkit-transform: rotate(0deg);
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
|
||||
100% {
|
||||
-webkit-transform: rotate(360deg);
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
|
||||
/* -- engine-tooltip -- */
|
||||
.engine-tooltip {
|
||||
display: none;
|
||||
position: absolute;
|
||||
padding: 0.5rem 1rem;
|
||||
margin: 0 0 0 2rem;
|
||||
border: 1px solid var(--color-toolkit-engine-tooltip-border);
|
||||
background: var(--color-toolkit-engine-tooltip-background);
|
||||
font-size: 14px;
|
||||
font-weight: normal;
|
||||
z-index: 1000000;
|
||||
text-align: left;
|
||||
.rounded-corners;
|
||||
}
|
||||
|
||||
th:hover .engine-tooltip,
|
||||
td:hover .engine-tooltip,
|
||||
.engine-tooltip:hover {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
/* -- stacked bar chart -- */
|
||||
.stacked-bar-chart {
|
||||
margin: 0;
|
||||
padding: 0 0.125rem 0 4rem;
|
||||
width: 100%;
|
||||
width: -moz-available;
|
||||
width: -webkit-fill-available;
|
||||
width: fill;
|
||||
flex-direction: row;
|
||||
flex-wrap: nowrap;
|
||||
align-items: center;
|
||||
display: inline-flex;
|
||||
}
|
||||
|
||||
.stacked-bar-chart-value {
|
||||
width: 3rem;
|
||||
display: inline-block;
|
||||
position: absolute;
|
||||
padding: 0 0.5rem;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.stacked-bar-chart-base {
|
||||
display: flex;
|
||||
flex-shrink: 0;
|
||||
flex-grow: 0;
|
||||
flex-basis: unset;
|
||||
}
|
||||
|
||||
.stacked-bar-chart-median {
|
||||
.stacked-bar-chart-base();
|
||||
|
||||
background: var(--color-base-font);
|
||||
border: 1px solid rgba(var(--color-base-font-rgb), 0.9);
|
||||
padding: 0.3rem 0;
|
||||
}
|
||||
|
||||
.stacked-bar-chart-rate80 {
|
||||
.stacked-bar-chart-base();
|
||||
|
||||
background: transparent;
|
||||
border: 1px solid rgba(var(--color-base-font-rgb), 0.3);
|
||||
padding: 0.3rem 0;
|
||||
}
|
||||
|
||||
.stacked-bar-chart-rate95 {
|
||||
.stacked-bar-chart-base();
|
||||
|
||||
background: transparent;
|
||||
border-bottom: 1px dotted rgba(var(--color-base-font-rgb), 0.5);
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.stacked-bar-chart-rate100 {
|
||||
.stacked-bar-chart-base();
|
||||
|
||||
background: transparent;
|
||||
border-left: 1px solid rgba(var(--color-base-font-rgb), 0.9);
|
||||
padding: 0.4rem 0;
|
||||
width: 1px;
|
||||
}
|
46
beetroot_static/src/less/toolkit_loader.less
Normal file
|
@ -0,0 +1,46 @@
|
|||
.loader,
|
||||
.loader::after {
|
||||
border-radius: 50%;
|
||||
width: 10em;
|
||||
height: 10em;
|
||||
}
|
||||
|
||||
.loader {
|
||||
margin: 60px auto;
|
||||
font-size: 10px;
|
||||
position: relative;
|
||||
text-indent: -9999em;
|
||||
border-top: 1.1em solid rgba(255, 255, 255, 0.2);
|
||||
border-right: 1.1em solid rgba(255, 255, 255, 0.2);
|
||||
border-bottom: 1.1em solid rgba(255, 255, 255, 0.2);
|
||||
border-left: 1.1em solid #fff;
|
||||
-webkit-transform: translateZ(0);
|
||||
-ms-transform: translateZ(0);
|
||||
transform: translateZ(0);
|
||||
-webkit-animation: load8 1.1s infinite linear;
|
||||
animation: load8 1.1s infinite linear;
|
||||
}
|
||||
|
||||
@-webkit-keyframes load8 {
|
||||
0% {
|
||||
-webkit-transform: rotate(0deg);
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
|
||||
100% {
|
||||
-webkit-transform: rotate(360deg);
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes load8 {
|
||||
0% {
|
||||
-webkit-transform: rotate(0deg);
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
|
||||
100% {
|
||||
-webkit-transform: rotate(360deg);
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
6
beetroot_static/src/svg/information-circle-outline.svg
Normal file
|
@ -0,0 +1,6 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" class="ionicon" viewBox="0 0 512 512">
|
||||
<title>Information Circle</title>
|
||||
<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>
|
After Width: | Height: | Size: 679 B |
4
beetroot_static/src/svg/select-dark.svg
Normal file
|
@ -0,0 +1,4 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="512" height="512" viewBox="0 0 512 512">
|
||||
<g><polygon fill="#ddd" points="128,192 256,320 384,192"/></g>
|
||||
</svg>
|
After Width: | Height: | Size: 196 B |
4
beetroot_static/src/svg/select-light.svg
Normal file
|
@ -0,0 +1,4 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="512" height="512" viewBox="0 0 512 512">
|
||||
<g><polygon points="128,192 256,320 384,192"/></g>
|
||||
</svg>
|
After Width: | Height: | Size: 184 B |
16
beetroot_static/svg4favicon.svgo.js
Normal file
|
@ -0,0 +1,16 @@
|
|||
/**
|
||||
* @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',
|
||||
],
|
||||
};
|
19
beetroot_static/svg4web.svgo.js
Normal file
|
@ -0,0 +1,19 @@
|
|||
/**
|
||||
* @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',
|
||||
'removeXMLNS'
|
||||
],
|
||||
};
|
9
beetroot_template/404.html
Normal file
|
@ -0,0 +1,9 @@
|
|||
{% extends "simple/base.html" %}
|
||||
{% block content %}
|
||||
<div class="center">
|
||||
<h1>{{ _('Page not found') }}</h1>
|
||||
{% autoescape false %}
|
||||
<p>{{ _('Go to %(search_page)s.', search_page='<a href="{}">{}</a>'.format(url_for('index'), _('search page'))) }}</p>
|
||||
{% endautoescape %}
|
||||
</div>
|
||||
{% endblock %}
|
83
beetroot_template/base.html
Normal file
|
@ -0,0 +1,83 @@
|
|||
<!DOCTYPE html>
|
||||
<html class="no-js theme-{{ preferences.get_value('simple_style') or 'auto' }} center-aligment-{{ preferences.get_value('center_alignment') and 'yes' or 'no' }}" lang="{{ locale_rfc5646 }}" {% if rtl %} dir="rtl"{% endif %}>
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="description" content="SearXNG — a privacy-respecting, open metasearch engine">
|
||||
<meta name="keywords" content="SearXNG, search, search engine, metasearch, meta search">
|
||||
<meta name="generator" content="searxng/{{ searx_version }}">
|
||||
<meta name="referrer" content="no-referrer">
|
||||
<meta name="robots" content="noarchive">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<meta name="HandheldFriendly" content="True">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge, chrome=1">
|
||||
<title>{% block title %}{% endblock %}{{ instance_name }}</title>
|
||||
{% block meta %}{% endblock %}
|
||||
{% if rtl %}
|
||||
<link rel="stylesheet" href="{{ url_for('static', filename='css/searxng-rtl.min.css') }}" type="text/css" media="screen" />
|
||||
{% else %}
|
||||
<link rel="stylesheet" href="{{ url_for('static', filename='css/searxng.min.css') }}" type="text/css" media="screen" />
|
||||
{% endif %}
|
||||
{% block styles %}{% endblock %}
|
||||
<!--[if gte IE 9]>-->
|
||||
<script src="{{ url_for('static', filename='js/searxng.head.min.js') }}" client_settings="{{ client_settings }}"></script>
|
||||
<!--<![endif]-->
|
||||
{% block head %}
|
||||
<link title="{{ instance_name }}" type="application/opensearchdescription+xml" rel="search" href="{{ opensearch_url }}"/>
|
||||
{% endblock %}
|
||||
<link rel="icon" href="{{ url_for('static', filename='img/favicon.png') }}" sizes="any">
|
||||
<link rel="icon" href="{{ url_for('static', filename='img/favicon.svg') }}" type="image/svg+xml">
|
||||
</head>
|
||||
<body class="{{ endpoint }}_endpoint" >
|
||||
<main id="main_{{ self._TemplateReference__context.name|replace("simple/", "")|replace(".html", "") }}" class="{{body_class}}">
|
||||
{% if errors %}
|
||||
<div class="dialog-error" role="alert">
|
||||
<a href="#" class="close" aria-label="close" title="close">×</a>
|
||||
<ul>
|
||||
{% for message in errors %}
|
||||
<li>{{ message }}</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<nav id="links_on_top">
|
||||
{%- from 'simple/icons.html' import icon_big -%}
|
||||
{%- block linkto_about -%}
|
||||
<a href="{{ url_for('info', pagename='about') }}" class="link_on_top_about">{{ icon_big('information-circle-outline') }}<span>{{ _('About') }}</span></a>
|
||||
{%- endblock -%}
|
||||
{%- block linkto_donate -%}
|
||||
{%- if donation_url -%}
|
||||
<a href="{{ donation_url }}" class="link_on_top_donate">{{ icon_big('heart-outline') }}<span>{{ _('Donate') }}</span></a>
|
||||
{%- endif -%}
|
||||
{%- endblock -%}
|
||||
{%- block linkto_preferences -%}
|
||||
<a href="{{ url_for('preferences') }}" class="link_on_top_preferences">{{ icon_big('menu-outline') }}<span>{{ _('Preferences') }}</span></a>
|
||||
{%- endblock -%}
|
||||
</nav>
|
||||
{% block header %}
|
||||
{% endblock %}
|
||||
{% block content %}
|
||||
{% endblock %}
|
||||
</main>
|
||||
<footer>
|
||||
<p>
|
||||
{{ _('Powered by') }} <a href="{{ url_for('info', pagename='about') }}">searxng</a> - {{ searx_version }} — {{ _('a privacy-respecting, open metasearch engine') }}<br/>
|
||||
<a href="{{ searx_git_url }}">{{ _('Source code') }}</a>
|
||||
| <a href="{{ get_setting('brand.issue_url') }}">{{ _('Issue tracker') }}</a>
|
||||
{% if enable_metrics %}| <a href="{{ url_for('stats') }}">{{ _('Engine stats') }}</a>{% endif %}
|
||||
{% if get_setting('brand.public_instances') %}
|
||||
| <a href="{{ get_setting('brand.public_instances') }}">{{ _('Public instances') }}</a>
|
||||
{% endif %}
|
||||
{% if get_setting('general.privacypolicy_url') %}
|
||||
| <a href="{{ get_setting('general.privacypolicy_url') }}">{{ _('Privacy policy') }}</a>
|
||||
{% endif %}
|
||||
{% if get_setting('general.contact_url') %}
|
||||
| <a href="{{ get_setting('general.contact_url') }}">{{ _('Contact instance maintainer') }}</a>
|
||||
{% endif %}
|
||||
</p>
|
||||
</footer>
|
||||
<!--[if gte IE 9]>-->
|
||||
<script src="{{ url_for('static', filename='js/searxng.min.js') }}"></script>
|
||||
<!--<![endif]-->
|
||||
</body>
|
||||
</html>
|
26
beetroot_template/categories.html
Normal file
|
@ -0,0 +1,26 @@
|
|||
{% from 'simple/icons.html' import icon_big %}
|
||||
{%- set category_icons = {
|
||||
'general': 'search-outline',
|
||||
'images': 'image-outline',
|
||||
'videos': 'play-outline',
|
||||
'news': 'newspaper-outline',
|
||||
'map': 'location-outline',
|
||||
'music': 'musical-notes-outline',
|
||||
'it': 'layers-outline',
|
||||
'science': 'school-outline',
|
||||
'files': 'file-tray-full-outline',
|
||||
'social media': 'people-outline',
|
||||
} -%}
|
||||
<div id="categories" class="search_categories">{{- '' -}}
|
||||
<div id="categories_container">
|
||||
{%- for category in categories_as_tabs -%}
|
||||
<div class="category"><input type="checkbox" id="checkbox_{{ category|replace(' ', '_') }}" name="category_{{ category }}"{% if category in selected_categories %} checked="checked"{% endif %}/>
|
||||
<label for="checkbox_{{ category|replace(' ', '_') }}" class="tooltips">
|
||||
{{- icon_big(category_icons[category]) if category in category_icons else icon_big('globe-outline') -}}
|
||||
<div class="category_name">{{- _(category) -}}</div>
|
||||
</label>
|
||||
</div>
|
||||
{%- endfor -%}
|
||||
{%- if display_tooltip %}<div class="help">{{ _('Click on the magnifier to perform search') }}</div>{% endif -%}
|
||||
</div>{{- '' -}}
|
||||
</div>
|
12
beetroot_template/filters/languages.html
Normal file
|
@ -0,0 +1,12 @@
|
|||
<select class="language" id="language" name="language" aria-label="{{ _('Search language') }}">{{- '' -}}
|
||||
<option value="all" {% if current_language == 'all' %}selected="selected"{% endif %}>{{ _('Default language') }}</option>
|
||||
<option value="auto" {% if current_language == 'auto' %}selected="selected"{% endif %}>
|
||||
{{- _('Auto-detect') -}}
|
||||
{%- if current_language == 'auto' %} ({{ search_language }}){%- endif -%}
|
||||
</option>
|
||||
{%- for lang_id,lang_name,country_name,english_name,flag in language_codes | sort(attribute=1) -%}
|
||||
<option value="{{ lang_id }}" {% if lang_id == current_language %}selected="selected"{% endif %}>
|
||||
{% if flag %}{{ flag }} {% endif%} {{- lang_name }} {% if country_name %}({{ country_name }}) {% endif %}
|
||||
</option>
|
||||
{%- endfor -%}
|
||||
</select>
|
5
beetroot_template/filters/safesearch.html
Normal file
|
@ -0,0 +1,5 @@
|
|||
<select name="safesearch" id="safesearch" class="safesearch" aria-label="{{ _('SafeSearch') }}">
|
||||
<option value="2" {% if safesearch == '2' %}selected="selected"{% endif %} aria-label="{{ _('Strict') }}">{{ _("SafeSearch") + ": " + _('Strict') }}</option>
|
||||
<option value="1" {% if safesearch == '1' %}selected="selected"{% endif %} aria-label="{{ _('Moderate') }}">{{ _("SafeSearch") + ": " + _('Moderate') }}</option>
|
||||
<option value="0" {% if safesearch == '0' %}selected="selected"{% endif %} aria-label="{{ _('None') }}">{{ _("SafeSearch") + ": " + _('None') }}</option>
|
||||
</select>
|
17
beetroot_template/filters/time_range.html
Normal file
|
@ -0,0 +1,17 @@
|
|||
<select name="time_range" id="time_range" class="time_range" aria-label="{{ _('Time range') }}">{{- '' -}}
|
||||
<option id="time-range-anytime" value="" {{ "selected" if time_range=="" or not time_range else ""}}>
|
||||
{{- _('Anytime') -}}
|
||||
</option>{{- '' -}}
|
||||
<option id="time-range-day" value="day" {{ "selected" if time_range=="day" else ""}}>
|
||||
{{- _('Last day') -}}
|
||||
</option>{{- '' -}}
|
||||
<option id="time-range-week" value="week" {{ "selected" if time_range=="week" else ""}}>
|
||||
{{- _('Last week') -}}
|
||||
</option>{{- '' -}}
|
||||
<option id="time-range-month" value="month" {{ "selected" if time_range=="month" else ""}}>
|
||||
{{- _('Last month') -}}
|
||||
</option>{{- '' -}}
|
||||
<option id="time-range-year" value="year" {{ "selected" if time_range=="year" else ""}}>
|
||||
{{- _('Last year') -}}
|
||||
</option>{{- '' -}}
|
||||
</select>
|
38
beetroot_template/icons.html
Normal file
|
@ -0,0 +1,38 @@
|
|||
{# this file was generated by searx/static/themes/simple/gruntfile.js #}
|
||||
{%- set icons = {
|
||||
'warning':'<svg class="ionicon" viewBox="0 0 512 512" aria-hidden="true"><path d="M256 80c-8.66 0-16.58 7.36-16 16l8 216a8 8 0 008 8h0a8 8 0 008-8l8-216c.58-8.64-7.34-16-16-16z" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="32"/><circle cx="256" cy="416" r="16" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="32"/></svg>',
|
||||
'close':'<svg class="ionicon" viewBox="0 0 512 512" 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 class="ionicon" viewBox="0 0 512 512" 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 class="ionicon" viewBox="0 0 512 512" 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 class="ionicon" viewBox="0 0 512 512" 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 class="ionicon" viewBox="0 0 512 512" 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 class="ionicon" viewBox="0 0 512 512" 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 class="ionicon" viewBox="0 0 512 512" 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 class="ionicon" viewBox="0 0 512 512" 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 class="ionicon" viewBox="0 0 512 512" 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 class="ionicon" viewBox="0 0 512 512" 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 class="ionicon" viewBox="0 0 512 512" 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 class="ionicon" viewBox="0 0 512 512" 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 class="ionicon" viewBox="0 0 512 512" 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 class="ionicon" viewBox="0 0 512 512" 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 class="ionicon" viewBox="0 0 512 512" 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 class="ionicon" viewBox="0 0 512 512" 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 class="ionicon" viewBox="0 0 512 512" 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 class="ionicon" viewBox="0 0 512 512" 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 class="ionicon" viewBox="0 0 512 512" 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>',
|
||||
|
||||
}
|
||||
-%}
|
||||
|
||||
{% 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 %}
|
8
beetroot_template/index.html
Normal file
|
@ -0,0 +1,8 @@
|
|||
{% extends "simple/base.html" %}
|
||||
{% from 'simple/icons.html' import icon_big %}
|
||||
{% block content %}
|
||||
<div class="index">
|
||||
<div class="title"><h1>SearXNG</h1></div>
|
||||
{% include 'simple/simple_search.html' %}
|
||||
</div>
|
||||
{% endblock %}
|
16
beetroot_template/info.html
Normal file
|
@ -0,0 +1,16 @@
|
|||
{% extends 'simple/page_with_header.html' %}
|
||||
{% block title %}{{ active_page.title }} - {% endblock %}
|
||||
{% block linkto_about %}{% endblock %}
|
||||
{% block linkto_donate %}{% endblock %}
|
||||
{% block content %}
|
||||
<ul class="tabs">
|
||||
{% for pagename, locale, page in all_pages %}
|
||||
<li>
|
||||
<a href="{{ url_for('info', pagename=pagename, locale=locale) }}" {% if pagename == active_pagename %}class="active"{% endif %}>{{page.title}}</a>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
<div class="info-page {{pagename}}">
|
||||
{{- active_page.html | safe -}}
|
||||
</div>
|
||||
{% endblock %}
|
50
beetroot_template/infobox.html
Normal file
|
@ -0,0 +1,50 @@
|
|||
<aside class="infobox" aria-label="{{ infobox.infobox }}">
|
||||
<h2><bdi>{{ infobox.infobox }}</bdi></h2>
|
||||
{% if infobox.img_src %}<img src="{{ image_proxify(infobox.img_src) }}" title="{{ infobox.infobox|striptags }}" alt="{{ infobox.infobox|striptags }}">{%- endif -%}
|
||||
<p><bdi>{{ infobox.content | safe }}</bdi></p>
|
||||
{% if infobox.attributes %}
|
||||
<div class="attributes">
|
||||
{% for attribute in infobox.attributes %}
|
||||
<dl>
|
||||
<dt><bdi>{{ attribute.label }} :</bdi></dt>
|
||||
{%- if attribute.image -%}
|
||||
<dd><img src="{{ image_proxify(attribute.image.src) }}" alt="{{ attribute.image.alt }}"></dd>
|
||||
{%- else -%}
|
||||
<dd><bdi>{{ attribute.value }}</bdi></dd>
|
||||
{%- endif -%}
|
||||
</dl>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if infobox.urls %}
|
||||
<div class="urls">
|
||||
<ul>
|
||||
{%- for url in infobox.urls -%}
|
||||
<li class="url"><bdi><a href="{{ url.url }}" {% if results_on_new_tab %}target="_blank" rel="noopener noreferrer"{% else %}rel="noreferrer"{% endif %}>{{ url.title }}</a></bdi></li>
|
||||
{%- endfor -%}
|
||||
</ul>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if infobox.relatedTopics %}
|
||||
<div class="relatedTopics">
|
||||
{% for topic in infobox.relatedTopics %}
|
||||
<div>
|
||||
<h3><bdi>{{ topic.name }}</bdi></h3>
|
||||
{% for suggestion in topic.suggestions %}
|
||||
<form method="{{ method or 'POST' }}" action="{{ url_for('search') }}">
|
||||
<input type="hidden" name="q" value="{{ suggestion }}">
|
||||
<input type="hidden" name="time_range" value="{{ time_range }}">
|
||||
<input type="hidden" name="language" value="{{ current_language }}">
|
||||
<input type="hidden" name="safesearch" value="{{ safesearch }}">
|
||||
<input type="hidden" name="theme" value="{{ theme }}">
|
||||
{% if timeout_limit %}<input type="hidden" name="timeout_limit" value="{{ timeout_limit|e }}" >{% endif %}
|
||||
<input type="submit" value="{{ suggestion }}" />
|
||||
</form>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endif %}
|
||||
</aside>
|
84
beetroot_template/macros.html
Normal file
|
@ -0,0 +1,84 @@
|
|||
{% from 'simple/icons.html' import icon_small %}
|
||||
|
||||
<!-- Draw favicon -->
|
||||
{% macro draw_favicon(favicon) -%}
|
||||
<img width="14" height="14" class="favicon" src="{{ url_for('static', filename='themes/simple/img/icons/' + favicon + '.png') }}" alt="{{ favicon }}">
|
||||
{%- endmacro %}
|
||||
|
||||
{% macro result_open_link(url, classes='') -%}
|
||||
<a href="{{ url }}" {% if classes %}class="{{ classes }}" {% endif %}{% if results_on_new_tab %}target="_blank" rel="noopener noreferrer"{% else %}rel="noreferrer"{% endif %}>
|
||||
{%- endmacro %}
|
||||
|
||||
{%- macro result_close_link() -%}
|
||||
</a>
|
||||
{%- endmacro %}
|
||||
|
||||
{%- macro result_link(url, title, classes='') -%}
|
||||
{{ result_open_link(url, classes) }}{{ title }}{{ result_close_link() }}
|
||||
{%- endmacro -%}
|
||||
|
||||
<!-- Draw result header -->
|
||||
{% macro result_header(result, favicons, image_proxify) -%}
|
||||
<article class="result {% if result['template'] %}result-{{ result.template|replace('.html', '') }}{% else %}result-default{% endif %} {% if result['category'] %}category-{{ result['category'] }}{% endif %}{% for e in result.engines %} {{ e }}{% endfor %}">
|
||||
{{- result_open_link(result.url, "url_wrapper") -}}
|
||||
{%- for part in get_pretty_url(result.parsed_url) -%}
|
||||
<span class="url_o{{loop.index}}"><span class="url_i{{loop.index}}">{{- part -}}</span></span>
|
||||
{%- endfor %}
|
||||
{{- result_close_link() -}}
|
||||
{%- if result.img_src %}{{ result_open_link(result.url) }}<img class="image" src="{{ image_proxify(result.img_src) }}" title="{{ result.title|striptags }}" loading="lazy" width="200" height="200">{{ result_close_link() }}{% endif -%}
|
||||
{%- if result.thumbnail %}{{ result_open_link(result.url) }}<img class="thumbnail" src="{{ image_proxify(result.thumbnail) }}" title="{{ result.title|striptags }}" loading="lazy" width="200" height="200">{{ result_close_link() }}{% endif -%}
|
||||
<h3>{{ result_link(result.url, result.title|safe) }}</h3>
|
||||
{%- endmacro -%}
|
||||
|
||||
<!-- Draw result sub header -->
|
||||
{%- macro result_sub_header(result) -%}
|
||||
{%- if result.publishedDate %}<time class="published_date" datetime="{{ result.pubdate }}" >{{ result.publishedDate }}</time>{% endif -%}
|
||||
{%- if result.length %}<div class="result_length">{{ _('Length') }}: {{ result.length }}</div>{% endif -%}
|
||||
{%- if result.author %}<div class="result_author">{{ _('Author') }}: {{ result.author }}</div>{% endif -%}
|
||||
{%- if result.metadata %}<div class="highlight">{{ result.metadata|safe }}</div>{% endif -%}
|
||||
{%- endmacro -%}
|
||||
|
||||
<!-- Draw result sub footer -->
|
||||
{%- macro result_sub_footer(result, proxify) -%}
|
||||
<div class="engines">
|
||||
{% for engine in result.engines %}<span>{{ engine }}</span>{% endfor %}
|
||||
{{ result_link(cache_url + result.url, icon_small('ellipsis-vertical-outline') + _('cached'), "cache_link") }}‎ {% if proxify and proxify_results %} {{ result_link(proxify(result.url), icon('link') + _('proxied'), "proxyfied_link") }} {% endif %}
|
||||
</div>{{- '' -}}
|
||||
<div class="break"></div>{{- '' -}}
|
||||
{%- endmacro -%}
|
||||
|
||||
<!-- Draw result footer -->
|
||||
{%- macro result_footer(result) -%}
|
||||
</article>
|
||||
{%- endmacro -%}
|
||||
|
||||
<!-- -->
|
||||
{%- macro tabs_open() -%}
|
||||
<div class="tabs" role="tablist">
|
||||
{%- endmacro -%}
|
||||
|
||||
{%- macro tab_header(name, id, label, checked) -%}
|
||||
<input type="radio" name="{{ name }}" id="tab-{{ id }}" {% if checked is sameas true %}checked="checked"{% endif %} />
|
||||
<label id="tab-label-{{ label }}" for="tab-{{ id }}" role="tab" aria-controls="tab-content-{{ id }}">{{ label }}</label>
|
||||
<section id="tab-content-{{ id }}" role="tabpanel" aria-labelledby="tab-label-{{ label }}" aria-hidden="false">
|
||||
{%- endmacro -%}
|
||||
|
||||
{%- macro tab_footer() -%}
|
||||
</section>
|
||||
{%- endmacro -%}
|
||||
|
||||
{%- macro tabs_close() -%}
|
||||
</div>
|
||||
{%- endmacro -%}
|
||||
|
||||
{%- macro checkbox_onoff(name, checked) -%}
|
||||
<input type="checkbox" name="{{ name }}" id="{{ name }}" value="None" class="checkbox-onoff" {% if checked %}checked{% endif %} />
|
||||
{%- endmacro -%}
|
||||
|
||||
{%- macro checkbox(name, checked, disabled) -%}
|
||||
{%- if checked == '?' -%}
|
||||
{{- icon_small('warning') -}}
|
||||
{%- else -%}
|
||||
<input type="checkbox"{% if name %} name="{{ name }}"{% endif %} value="None"{% if checked %} checked{% endif %}{% if disabled %} disabled{% endif %} />
|
||||
{%- endif -%}
|
||||
{%- endmacro -%}
|
5
beetroot_template/messages/no_cookies.html
Normal file
|
@ -0,0 +1,5 @@
|
|||
{% from 'simple/icons.html' import icon %}
|
||||
<div class="alert alert-info fade in" role="alert">
|
||||
<strong class="lead">{{ icon('info-sign') }} {{ _('Information!') }}</strong>
|
||||
{{ _('currently, there are no cookies defined.') }}
|
||||
</div>
|
23
beetroot_template/messages/no_results.html
Normal file
|
@ -0,0 +1,23 @@
|
|||
{% from 'simple/icons.html' import icon_big %}
|
||||
{% if unresponsive_engines %}
|
||||
<div class="dialog-error" role="alert">
|
||||
{{ icon_big('warning') }}
|
||||
<div>
|
||||
<p><strong>{{ _('Error!') }}</strong> {{ _('Engines cannot retrieve results.') }}</p>
|
||||
{% for engine_name, error_type in unresponsive_engines %}
|
||||
<p>{{- '' -}}
|
||||
{{- engine_name }} (
|
||||
<a href="{{ url_for('stats', engine=engine_name|e) }}" title="{{ _('View error logs and submit a bug report') }}">
|
||||
{{- error_type -}}
|
||||
</a> ){{- '' -}}
|
||||
</p>
|
||||
{%- endfor %}
|
||||
<p><small>{{ _('Please, try again later or find another SearXNG instance.') }} (<a href="{{ get_setting('brand.public_instances') }}">{{ _('Public instances') }}</a>) </small></p>
|
||||
</div>
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="dialog-error" role="alert">
|
||||
<p><strong>{{ _('Sorry!') }}</strong></p>
|
||||
<p>{{ _("we didn't find any results. Please use another query or search in more categories.") }}</p>
|
||||
</div>
|
||||
{% endif %}
|
75
beetroot_template/new_issue.html
Normal file
|
@ -0,0 +1,75 @@
|
|||
{% macro new_issue(engine_name, engine_reliability) %}
|
||||
<form action="{{ get_setting('brand.new_issue_url') }}" method="GET">
|
||||
<input name="title" type="hidden" value="Bug: {{ engine_name }} engine">
|
||||
<input name="labels" type="hidden" value="bug">
|
||||
<input name="template" type="hidden" value="bug-report.md">
|
||||
<textarea name="body" class="issue-hide">{{- '' -}}
|
||||
|
||||
**Version of SearXNG, commit number if you are using on master branch and stipulate if you forked SearXNG**
|
||||
{% if searx_git_url and searx_git_url != 'unknow' %}
|
||||
Repository: {{ searx_git_url }}
|
||||
Branch: {{ searx_git_branch }}
|
||||
Version: {{ searx_version }}
|
||||
<!-- Check if these values are correct -->
|
||||
|
||||
{% else %}
|
||||
<!-- If you are running on master branch using git execute this command
|
||||
in order to fetch the latest commit ID:
|
||||
```
|
||||
git log -1
|
||||
```
|
||||
If you are using searxng-docker then look at the bottom of the SearXNG page
|
||||
and check for the version after "Powered by SearXNG"
|
||||
|
||||
Please also stipulate if you are using a forked version of SearxNG and
|
||||
include a link to the fork source code.
|
||||
-->
|
||||
{% endif %}
|
||||
**How did you install SearXNG?**
|
||||
<!-- Did you install SearXNG using the official wiki or using searxng-docker
|
||||
or manually by executing the searx/webapp.py file? -->
|
||||
**What happened?**
|
||||
<!-- A clear and concise description of what the bug is. -->
|
||||
|
||||
**How To Reproduce**
|
||||
<!-- How can we reproduce this issue? (as minimally and as precisely as possible) -->
|
||||
|
||||
**Expected behavior**
|
||||
<!-- A clear and concise description of what you expected to happen. -->
|
||||
|
||||
**Screenshots & Logs**
|
||||
<!-- If applicable, add screenshots, logs to help explain your problem. -->
|
||||
|
||||
**Additional context**
|
||||
<!-- Add any other context about the problem here. -->
|
||||
|
||||
**Technical report**
|
||||
|
||||
{% for error in engine_reliability.errors %}
|
||||
{% if secondary %}Warning{% else %}Error{% endif %}
|
||||
{{'\n '}}* Error: {{ error.exception_classname or error.log_message }}
|
||||
{{' '}}* Percentage: {{ error.percentage }}
|
||||
{{' '}}* Parameters: `{{ error.log_parameters }}`
|
||||
{{' '}}* File name: `{{ error.filename }}:{{ error.line_no }}`
|
||||
{{' '}}* Function: `{{ error.function }}`
|
||||
{{' '}}* Code: `{{ error.code }}`
|
||||
{{'\n'-}}
|
||||
{%- endfor -%}
|
||||
{%- for test_name, results in engine_reliability.checker.items() -%}
|
||||
{%- if loop.first %}Checker{% endif -%}
|
||||
{{-'\n '}}* {{ test_name }}: {% for result in results%}`{{ result }}`,{% endfor -%}
|
||||
{%- endfor -%}
|
||||
</textarea>
|
||||
<input type="checkbox" id="step1">
|
||||
<label for="step1">{{ _('Start submiting a new issue on GitHub') }}</label>
|
||||
<div class="step1 step_content">
|
||||
<p><a href="{{ get_setting('brand.issue_url') }}?q=is%3Aissue+Bug:%20{{ engine_name }}" target="_blank" rel="noreferrer noreferrer">{{ _('Please check for existing bugs about this engine on GitHub') }}</a></p>
|
||||
</div>
|
||||
<input class="step1 step1_delay" type="checkbox" id="step2">
|
||||
<label class="step1 step1_delay" for="step2" >{{ _('I confirm there is no existing bug about the issue I encounter') }}</label>
|
||||
<div class="step2 step_content">
|
||||
<p>{{ _('If this is a public instance, please specify the URL in the bug report') }}</p>
|
||||
<button type="submit" class="github-issue-button" title="{{ get_setting('brand.new_issue_url') }}">{{ _('Submit a new issue on Github including the above information') }}</button>
|
||||
</div>
|
||||
</form>
|
||||
{% endmacro %}
|
21
beetroot_template/opensearch.xml
Normal file
|
@ -0,0 +1,21 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/" xmlns:moz="http://www.mozilla.org/2006/browser/search/">
|
||||
<ShortName>{{ instance_name }}</ShortName>
|
||||
<LongName>SearXNG metasearch</LongName>
|
||||
<Description>SearXNG is a metasearch engine that respects your privacy.</Description>
|
||||
<InputEncoding>UTF-8</InputEncoding>
|
||||
<Image type="image/png">{{ url_for('static', filename='img/favicon.png', _external=True) }}</Image>
|
||||
{% if opensearch_method == 'GET' %}
|
||||
<Url rel="results" type="text/html" method="{{ opensearch_method }}" template="{{ url_for('search', _external=True) }}?q={searchTerms}"/>
|
||||
{% else %}
|
||||
<Url rel="results" type="text/html" method="{{ opensearch_method }}" template="{{ url_for('search', _external=True) }}">
|
||||
<Param name="q" value="{searchTerms}" />
|
||||
</Url>
|
||||
{% endif %}
|
||||
{% if autocomplete %}
|
||||
<Url rel="suggestions" type="application/x-suggestions+json" method="{{ opensearch_method }}" template="{{ url_for('autocompleter', _external=True) }}?q={searchTerms}"/>
|
||||
{% endif %}
|
||||
<Url rel="self" type="application/opensearchdescription+xml" method="{{ opensearch_method }}" template="{{ opensearch_url }}" />
|
||||
<Query role="example" searchTerms="SearXNG" />
|
||||
<moz:SearchForm>{{ url_for('search', _external=True) }}</moz:SearchForm>
|
||||
</OpenSearchDescription>
|
53
beetroot_template/opensearch_response_rss.xml
Normal file
|
@ -0,0 +1,53 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<rss version="2.0"
|
||||
xmlns:opensearch="http://a9.com/-/spec/opensearch/1.1/"
|
||||
xmlns:atom="http://www.w3.org/2005/Atom">
|
||||
<channel>
|
||||
<title>Searx search: {{ q|e }}</title>
|
||||
<link>{{ url_for('search', _external=True) }}?q={{ q|e }}</link>
|
||||
<description>Search results for "{{ q|e }}" - searx</description>
|
||||
<opensearch:totalResults>{{ number_of_results }}</opensearch:totalResults>
|
||||
<opensearch:startIndex>1</opensearch:startIndex>
|
||||
<opensearch:itemsPerPage>{{ number_of_results }}</opensearch:itemsPerPage>
|
||||
<atom:link rel="search" type="application/opensearchdescription+xml" href="{{ opensearch_url }}"/>
|
||||
<opensearch:Query role="request" searchTerms="{{ q|e }}" startPage="1" />
|
||||
{% if error_message %}
|
||||
<item>
|
||||
<title>Error</title>
|
||||
<description>{{ error_message|e }}</description>
|
||||
</item>
|
||||
{% endif %}
|
||||
{% for r in results %}
|
||||
<item>
|
||||
<title>{{ r.title }}</title>
|
||||
<link>{{ r.url }}</link>
|
||||
<description>{{ r.content }}</description>
|
||||
{% if r.pubdate %}<pubDate>{{ r.pubdate }}</pubDate>{% endif %}
|
||||
</item>
|
||||
{% endfor %}
|
||||
{% if answers %}
|
||||
{% for a in answers %}
|
||||
<item>
|
||||
<title>{{ a }}</title>
|
||||
<type>answer</type>
|
||||
</item>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% if corrections %}
|
||||
{% for a in corrections %}
|
||||
<item>
|
||||
<title>{{ a }}</title>
|
||||
<type>correction</type>
|
||||
</item>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% if suggestions %}
|
||||
{% for a in suggestions %}
|
||||
<item>
|
||||
<title>{{ a }}</title>
|
||||
<type>suggestion</type>
|
||||
</item>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
</channel>
|
||||
</rss>
|
5
beetroot_template/page_with_header.html
Normal file
|
@ -0,0 +1,5 @@
|
|||
{% set body_class = "page_with_header" %}
|
||||
{% extends "simple/base.html" %}
|
||||
{% block header %}
|
||||
<a href="{{ url_for('index') }}"><img class="logo" src="{{ url_for('static', filename='img/searxng.png') }}" alt="SearXNG"></a>
|
||||
{% endblock %}
|
441
beetroot_template/preferences.html
Normal file
|
@ -0,0 +1,441 @@
|
|||
{% from 'simple/macros.html' import tabs_open, tabs_close, tab_header, tab_footer, checkbox_onoff, checkbox %}
|
||||
{% from 'simple/icons.html' import icon_big %}
|
||||
|
||||
{% extends "simple/page_with_header.html" %}
|
||||
|
||||
{%- macro plugin_preferences(section) -%}
|
||||
{%- for plugin in plugins -%}
|
||||
{%- if plugin.preference_section == section -%}
|
||||
<fieldset>{{- '' -}}
|
||||
<legend>{{ _(plugin.name) }}</legend>{{- '' -}}
|
||||
<div class="value">
|
||||
{{- checkbox_onoff('plugin_' + plugin.id, plugin.id not in allowed_plugins) -}}
|
||||
</div>{{- '' -}}
|
||||
<div class="description">
|
||||
{{- _(plugin.description) -}}
|
||||
</div>{{- '' -}}
|
||||
</fieldset>
|
||||
{%- endif -%}
|
||||
{%- endfor -%}
|
||||
{%- endmacro -%}
|
||||
|
||||
{% macro engine_about(search_engine) -%}
|
||||
{% if search_engine.about is defined %}
|
||||
{% set about = search_engine.about %}
|
||||
<div class="engine-tooltip" role="tooltip">{{- "" -}}
|
||||
<p class="engine-description"></p>{{- "" -}}
|
||||
<p><a href="{{about.website}}" rel="noreferrer">{{about.website}}</a></p>
|
||||
{%- if about.wikidata_id -%}<p><a href="https://www.wikidata.org/wiki/{{about.wikidata_id}}" rel="noreferrer">wikidata.org/wiki/{{about.wikidata_id}}</a></p>{%- endif -%}
|
||||
{%- if search_engine.enable_http %}<p>{{ icon_big('exclamation-sign', 'No HTTPS') }}{{ _('No HTTPS')}}</p>{% endif -%}
|
||||
{%- if reliabilities.get(search_engine.name, {}).errors or reliabilities.get(search_engine.name, {}).checker -%}
|
||||
<a href="{{ url_for('stats', engine=search_engine.name|e) }}" title="{{ _('View error logs and submit a bug report') }}">
|
||||
{{ _('View error logs and submit a bug report') -}}
|
||||
</a>
|
||||
{%- endif -%}
|
||||
|
||||
</div>
|
||||
{%- endif -%}
|
||||
{%- endmacro %}
|
||||
|
||||
{%- macro engine_time(engine_name) -%}
|
||||
<td class="{{ label }}">{{- "" -}}
|
||||
{%- if stats[engine_name].time != None -%}
|
||||
<span class="stacked-bar-chart-value">{{- stats[engine_name].time -}}</span>{{- "" -}}
|
||||
<span class="stacked-bar-chart" aria-labelledby="{{engine_name}}_chart" aria-hidden="true">
|
||||
{%- if max_rate95 is not none and max_rate95 > 0 -%}
|
||||
<div class="stacked-bar-chart-median bar{{ (100 * (stats[engine_name].time / max_rate95))|round }}"></div>{{- "" -}}
|
||||
<div class="stacked-bar-chart-rate80 bar{{ (100 * ((stats[engine_name].rate80 - stats[engine_name].time) / max_rate95))|round }}"></div>{{- "" -}}
|
||||
<div class="stacked-bar-chart-rate95 bar{{ (100 * ((stats[engine_name].rate95 - stats[engine_name].rate80) / max_rate95))|round }}"></div>{{- "" -}}
|
||||
<span class="stacked-bar-chart-rate100"></span>
|
||||
{%- endif -%}
|
||||
</span>{{- "" -}}
|
||||
<div class="engine-tooltip text-left" role="tooltip" id="{{engine_name}}_graph">{{- "" -}}
|
||||
<p>{{ _('Median') }}: {{ stats[engine_name].time }}</p>{{- "" -}}
|
||||
<p>{{ _('P80') }}: {{ stats[engine_name].rate80 }}</p>{{- "" -}}
|
||||
<p>{{ _('P95') }}: {{ stats[engine_name].rate95 }}</p>{{- "" -}}
|
||||
</div>
|
||||
{%- endif -%}
|
||||
</td>
|
||||
{%- endmacro -%}
|
||||
|
||||
{%- macro engine_reliability(engine_name) -%}
|
||||
{% set r = reliabilities.get(engine_name, {}).get('reliablity', None) %}
|
||||
{% set checker_result = reliabilities.get(engine_name, {}).get('checker', []) %}
|
||||
{% set errors = reliabilities.get(engine_name, {}).get('errors', []) %}
|
||||
{% if r != None %}
|
||||
{% if r <= 50 %}{% set label = 'danger' %}
|
||||
{% elif r < 80 %}{% set label = 'warning' %}
|
||||
{% elif r < 90 %}{% set label = '' %}
|
||||
{% else %}{% set label = 'success' %}
|
||||
{% endif %}
|
||||
{% else %}
|
||||
{% set r = '' %}
|
||||
{% endif %}
|
||||
{% if checker_result or errors %}
|
||||
<td class="{{ label }} column-reliability">{{- "" -}}
|
||||
<a href="{{ url_for('stats', engine=engine_name|e) }}">{{- "" -}}
|
||||
<span aria-labelledby="{{engine_name}}_reliability">
|
||||
{{ icon_big('warning', 'The engine is not reliabled') }} {{ r -}}
|
||||
</span>{{- "" -}}
|
||||
</a>{{- "" -}}
|
||||
<div class="engine-tooltip" role="tooltip" id="{{engine_name}}_reliability">
|
||||
{%- if checker_result -%}
|
||||
<p>{{ _("Failed checker test(s): ") }} {{ ', '.join(checker_result) }}</p>
|
||||
{%- endif -%}
|
||||
{%- if errors %}<p>{{ _('Errors:') }}</p>{% endif -%}
|
||||
{%- for error in errors -%}
|
||||
<p>{{ error }} </p>{{- "" -}}
|
||||
{%- endfor -%}
|
||||
</div>{{- "" -}}
|
||||
</td>
|
||||
{%- else -%}
|
||||
<td class="{{ label }}">{% if r %}<span>{{ r }}</span>{% endif %}</td>
|
||||
{%- endif -%}
|
||||
{%- endmacro -%}
|
||||
|
||||
{% block head %} {% endblock %}
|
||||
{% block linkto_preferences %}{% endblock %}
|
||||
{% block content %}
|
||||
<h1>{{ _('Preferences') }}</h1>
|
||||
|
||||
<form id="search_form" method="post" action="{{ url_for('preferences') }}" autocomplete="off" class="reversed-checkbox">
|
||||
|
||||
{{ tabs_open() }}
|
||||
|
||||
{{ tab_header('maintab', 'general', _('General'), True) }}
|
||||
{% if 'categories' not in locked_preferences %}
|
||||
<fieldset>
|
||||
<legend>{{ _('Default categories') }}</legend>
|
||||
{% set display_tooltip = false %}
|
||||
{% include 'simple/categories.html' %}
|
||||
</fieldset>
|
||||
{% endif %}
|
||||
{% if 'language' not in locked_preferences %}
|
||||
<fieldset>
|
||||
<legend id="pref_language">{{ _('Search language') }}</legend>
|
||||
<p class="value">{{- '' -}}
|
||||
<select name='language' aria-labelledby="pref_language" aria-describedby="desc_language">{{- '' -}}
|
||||
<option value="all" {% if current_language == 'all' %}selected="selected"{% endif %}>{{ _('Default language') }}</option>
|
||||
<option value="auto" {% if current_language == 'auto' %}selected="selected"{% endif %}>{{ _('Auto-detect') }}</option>
|
||||
{%- for lang_id,lang_name,country_name,english_name,flag in language_codes | sort(attribute=1) -%}
|
||||
<option value="{{ lang_id }}" {% if lang_id == current_language %}selected="selected"{% endif %}>{% if flag %}{{ flag }} {% endif%} {{- lang_name }} {% if country_name %}({{ country_name }}) {% endif %}</option>
|
||||
{%- endfor -%}
|
||||
</select>{{- '' -}}
|
||||
</p>
|
||||
<div class="description" id="desc_language">
|
||||
{{- _('What language do you prefer for search?') }} {{ _('Choose Auto-detect to let SearXNG detect the language of your query.') -}}
|
||||
</div>
|
||||
</fieldset>
|
||||
{% endif %}
|
||||
{% if 'autocomplete' not in locked_preferences %}
|
||||
<fieldset>
|
||||
<legend id="pref_autocomplete">{{ _('Autocomplete') }}</legend>
|
||||
<p class="value">
|
||||
<select name="autocomplete" aria-labelledby="pref_autocomplete">
|
||||
<option value=""> - </option>
|
||||
{%- for backend in autocomplete_backends -%}
|
||||
<option value="{{ backend }}" {% if backend == autocomplete %}selected="selected"{% endif %}>{{ backend }}</option>
|
||||
{%- endfor -%}
|
||||
</select>
|
||||
</p>
|
||||
<div class="description">{{ _('Find stuff as you type') }}</div>
|
||||
</fieldset>
|
||||
{% endif %}
|
||||
{% if 'safesearch' not in locked_preferences %}
|
||||
<fieldset>
|
||||
<legend id="pref_safesearch">{{ _('SafeSearch') }}</legend>
|
||||
<p class="value">
|
||||
<select name='safesearch' aria-labelledby="pref_safesearch">
|
||||
<option value="2" {% if safesearch == '2' %}selected="selected"{% endif %}>{{ _('Strict') }}</option>
|
||||
<option value="1" {% if safesearch == '1' %}selected="selected"{% endif %}>{{ _('Moderate') }}</option>
|
||||
<option value="0" {% if safesearch == '0' %}selected="selected"{% endif %}>{{ _('None') }}</option>
|
||||
</select>
|
||||
</p>
|
||||
<p class="description">{{ _('Filter content') }}</p>
|
||||
</fieldset>
|
||||
{% endif %}
|
||||
{{ plugin_preferences('general') }}
|
||||
{% if 'doi_resolver' not in locked_preferences %}
|
||||
<fieldset>
|
||||
<legend id="pref_doi_resolver">{{ _('Open Access DOI resolver') }}</legend>
|
||||
<p class="value">
|
||||
<select id='doi_resolver' name='doi_resolver' aria-labelledby="pref_doi_resolver">
|
||||
{%- for doi_resolver_name,doi_resolver_url in doi_resolvers.items() -%}
|
||||
<option value="{{ doi_resolver_name }}" {% if doi_resolver_url == current_doi_resolver %}selected="selected"{% endif %}>
|
||||
{{- doi_resolver_name }} - {{ doi_resolver_url -}}
|
||||
</option>
|
||||
{%- endfor -%}
|
||||
</select>
|
||||
</p>
|
||||
<div class="description"><!-- {{ _('Redirect to open-access versions of publications when available (plugin required)') }} --></div>
|
||||
</fieldset>
|
||||
{% endif %}
|
||||
<fieldset>
|
||||
<legend id="pref_tokens">{{ _('Engine tokens') }}</legend>
|
||||
<p class="value">
|
||||
<input name="tokens" aria-labelledby="pref_tokens" type="text" autocomplete="off" spellcheck="false" autocorrect="off" value='{{ preferences.tokens.get_value() }}'/>
|
||||
</p>
|
||||
<p class="description">{{ _('Access tokens for private engines') }}</p>
|
||||
</fieldset>
|
||||
{{ tab_footer() }}
|
||||
|
||||
{{ tab_header('maintab', 'ui', _('User interface')) }}
|
||||
{% if 'locale' not in locked_preferences %}
|
||||
<fieldset>
|
||||
<legend id="pref_locale">{{ _('Interface language') }}</legend>
|
||||
<p class="value">
|
||||
<select name='locale' aria-labelledby="pref_locale">
|
||||
{%- for locale_id,locale_name in locales.items() | sort -%}
|
||||
<option value="{{ locale_id }}" {% if locale_id == current_locale %}selected="selected"{% endif %}>{{ locale_name }}</option>
|
||||
{%- endfor -%}
|
||||
</select>
|
||||
</p>
|
||||
<div class="description">{{ _('Change the language of the layout') }}</div>
|
||||
</fieldset>
|
||||
{% endif %}
|
||||
{% if 'theme' not in locked_preferences %}
|
||||
<fieldset>
|
||||
<legend id="pref_theme">{{ _('Theme') }}</legend>
|
||||
<p class="value">
|
||||
<select name="theme" aria-labelledby="pref_theme">
|
||||
{%- for name in themes -%}
|
||||
<option value="{{ name }}" {% if name == theme %}selected="selected"{% endif %}>{{ name }}</option>
|
||||
{%- endfor -%}
|
||||
</select>
|
||||
</p>
|
||||
<div class="description">{{ _('Change SearXNG layout') }}</div>
|
||||
</fieldset>
|
||||
<fieldset>
|
||||
<legend id="pref_simple_style">{{ _('Theme style') }}</legend>
|
||||
<p class="value">
|
||||
<select name="simple_style" aria-labelledby="pref_simple_style">
|
||||
{%- for name in ['auto', 'light', 'dark'] -%}
|
||||
<option value="{{ name }}" {% if name == preferences.get_value('simple_style') %}selected="selected"{% endif %}>{{ _(name) }}</option>
|
||||
{%- endfor -%}
|
||||
</select>
|
||||
</p>
|
||||
<div class="description">{{ _('Choose auto to follow your browser settings') }}</div>
|
||||
</fieldset>
|
||||
<fieldset>
|
||||
<legend id="pref_center_alignment">{{ _('Center Alignment') }}</legend>
|
||||
<p class="value">
|
||||
<select name="center_alignment" aria-labelledby="pref_center_alignment">
|
||||
<option value="1" {% if preferences.get_value('center_alignment') %}selected="selected"{% endif %}>{{ _('On') }}</option>
|
||||
<option value="0" {% if not preferences.get_value('center_alignment') %}selected="selected"{% endif %}>{{ _('Off')}}</option>
|
||||
</select>
|
||||
</p>
|
||||
<div class="description">{{ _('Displays results in the center of the page (Oscar layout).') }}</div>
|
||||
</fieldset>
|
||||
{% endif %}
|
||||
{% if 'results_on_new_tab' not in locked_preferences %}
|
||||
<fieldset>
|
||||
<legend id="pref_results_on_new_tab">{{ _('Results on new tabs') }}</legend>
|
||||
<p class="value">
|
||||
<select name='results_on_new_tab' aria-labelledby="pref_results_on_new_tab">
|
||||
<option value="1" {% if results_on_new_tab %}selected="selected"{% endif %}>{{ _('On') }}</option>
|
||||
<option value="0" {% if not results_on_new_tab %}selected="selected"{% endif %}>{{ _('Off')}}</option>
|
||||
</select>
|
||||
</p>
|
||||
<div class="description">{{_('Open result links on new browser tabs') }}</div>
|
||||
</fieldset>
|
||||
{% endif %}
|
||||
{% if 'infinite_scroll' not in locked_preferences %}
|
||||
<fieldset>
|
||||
<legend>{{ _('Infinite scroll') }}</legend>
|
||||
<p class="value">
|
||||
<select name='infinite_scroll'>
|
||||
<option value="1" {% if infinite_scroll %}selected="selected"{% endif %}>{{ _('On') }}</option>
|
||||
<option value="0" {% if not infinite_scroll %}selected="selected"{% endif %}>{{ _('Off')}}</option>
|
||||
</select>
|
||||
</p>
|
||||
<div class="description">{{ _('Automatically load next page when scrolling to bottom of current page') }}</div>
|
||||
</fieldset>
|
||||
{% endif %}
|
||||
{{ plugin_preferences('ui') }}
|
||||
{{ tab_footer() }}
|
||||
|
||||
{{ tab_header('maintab', 'privacy', _('Privacy')) }}
|
||||
{% if 'method' not in locked_preferences %}
|
||||
<fieldset>
|
||||
<legend id="pref_method">{{ _('HTTP Method') }}</legend>
|
||||
<p class="value">
|
||||
<select name='method' aria-labelledby="pref_method">
|
||||
<option value="POST" {% if method == 'POST' %}selected="selected"{% endif %}>POST</option>
|
||||
<option value="GET" {% if method == 'GET' %}selected="selected"{% endif %}>GET</option>
|
||||
</select>
|
||||
</p>
|
||||
<div class="description">{{ _('Change how forms are submitted, <a href="http://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol#Request_methods" rel="external">learn more about request methods</a>') }}</div>
|
||||
</fieldset>
|
||||
{% endif %}
|
||||
{% if 'image_proxy' not in locked_preferences %}
|
||||
<fieldset>
|
||||
<legend id="pref_image_proxy">{{ _('Image proxy') }}</legend>
|
||||
<p class="value">
|
||||
<select name='image_proxy' aria-labelledby="pref_image_proxy">
|
||||
<option value="1" {% if image_proxy %}selected="selected"{% endif %}>{{ _('Enabled') }}</option>
|
||||
<option value="0" {% if not image_proxy %}selected="selected"{% endif %}>{{ _('Disabled') }}</option>
|
||||
</select>
|
||||
</p>
|
||||
<div class="description">{{ _('Proxying image results through SearXNG') }}</div>
|
||||
</fieldset>
|
||||
{% endif %}
|
||||
{% if 'query_in_title' not in locked_preferences %}
|
||||
<fieldset>
|
||||
<legend id="pref_query_in_title">{{ _("Query in the page's title") }}</legend>
|
||||
<p class="value">
|
||||
<select name='query_in_title' aria-labelledby="pref_query_in_title">
|
||||
<option value="1" {% if query_in_title %}selected="selected"{% endif %}>{{ _('Enabled') }}</option>
|
||||
<option value="0" {% if not query_in_title %}selected="selected"{% endif %}>{{ _('Disabled') }}</option>
|
||||
</select>
|
||||
</p>
|
||||
<div class="description">{{ _("When enabled, the result page's title contains your query. Your browser can record this title") }}</div>
|
||||
</fieldset>
|
||||
{% endif %}
|
||||
{{ plugin_preferences('privacy') }}
|
||||
{{ tab_footer() }}
|
||||
|
||||
{{ tab_header('maintab', 'engines', _('Engines')) }}
|
||||
<p>{{ _('Currently used search engines') }}</p>
|
||||
{{ tabs_open() }}
|
||||
{% set ns = namespace(checked=true) %}
|
||||
{% for categ in categories_as_tabs + [OTHER_CATEGORY] %}
|
||||
{{ tab_header('enginetab', 'category' + categ, _(categ), ns.checked )}}
|
||||
{% set ns.checked = false %}
|
||||
{% if categ == OTHER_CATEGORY %}
|
||||
<p>{{_('This tab does not show up for search results, but you can search the engines listed here via bangs.')}}</p>
|
||||
{% endif %}
|
||||
<div class="scrollx">
|
||||
<table class="striped table_engines">
|
||||
<tr>{{- "" -}}
|
||||
<th class="engine_checkbox">{{ _("Allow") }}</th>{{- "" -}}
|
||||
<th class="name">{{ _("Engine name") }}</th>{{- "" -}}
|
||||
<th class="shortcut">{{ _("Shortcut") }}</th>{{- "" -}}
|
||||
<th>{{ _("Supports selected language") }}</th>{{- "" -}}
|
||||
<th>{{ _("SafeSearch") }}</th>{{- "" -}}
|
||||
<th>{{ _("Time range") }}</th>{{- "" -}}
|
||||
{%- if enable_metrics %}<th>{{ _("Response time") }}</th>{% endif -%}
|
||||
<th>{{ _("Max time") }}</th>{{- "" -}}
|
||||
{%- if enable_metrics %}<th>{{ _("Reliability") }}</th>{% endif -%}
|
||||
</tr>
|
||||
{% for group, engines in engines_by_category[categ] | group_engines_in_tab %}
|
||||
{% if loop.length > 1 %}
|
||||
<tr><th colspan="9" class="engine-group">{{_(group)}}</th></tr>
|
||||
{% endif %}
|
||||
{% for search_engine in engines %}
|
||||
{% if not search_engine.private %}
|
||||
{% set engine_id = 'engine_' + search_engine.name|replace(' ', '_') + '__' + categ|replace(' ', '_') %}
|
||||
<tr>{{- "" -}}
|
||||
<td>{{ checkbox_onoff(engine_id, (search_engine.name, categ) in disabled_engines) }}</td>{{- "" -}}
|
||||
<th class="name" data-engine-name="{{ search_engine.name }}">{% if search_engine.enable_http %}{{ icon_big('warning', 'No HTTPS') }}{% endif -%}
|
||||
<label for="{{ engine_id }}">
|
||||
{{- search_engine.name -}}
|
||||
{%- if search_engine.about and search_engine.about.language -%}
|
||||
({{search_engine.about.language | upper}})
|
||||
{%- endif -%}
|
||||
</label>
|
||||
{{- engine_about(search_engine) -}}
|
||||
</th>{{- "" -}}
|
||||
<td class="shortcut">{{ shortcuts[search_engine.name] }}</td>{{- "" -}}
|
||||
<td>{{ checkbox(None, supports[search_engine.name]['supports_selected_language'], true) }}</td>{{- "" -}}
|
||||
<td>{{ checkbox(None, supports[search_engine.name]['safesearch'], true) }}</td>{{- "" -}}
|
||||
<td>{{ checkbox(None, supports[search_engine.name]['time_range_support'], true) }}</td>{{- "" -}}
|
||||
{%- if enable_metrics %}{{- engine_time(search_engine.name) -}}{% endif -%}
|
||||
<td class="{{ 'danger' if stats[search_engine.name]['warn_timeout'] else '' }}">{{ search_engine.timeout }}</td>{{- "" -}}
|
||||
{%- if enable_metrics %}{{ engine_reliability(search_engine.name) -}}{% endif -%}
|
||||
</tr>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% endfor %}
|
||||
</table>
|
||||
</div>
|
||||
{{ tab_footer() }}
|
||||
{% endfor %}
|
||||
{{ tabs_close() }}
|
||||
{{ tab_footer() }}
|
||||
|
||||
{{ tab_header('maintab', 'query', _('Special Queries')) }}
|
||||
{% if answerers %}
|
||||
<div class="scrollx">
|
||||
<table class="striped">
|
||||
<tr>
|
||||
<th>{{ _('Allow') }}</th>
|
||||
<th>{{ _('Keywords') }}</th>
|
||||
<th>{{ _('Name') }}</th>
|
||||
<th>{{ _('Description') }}</th>
|
||||
<th>{{ _('Examples') }}</th>
|
||||
</tr>
|
||||
<td></td>
|
||||
<th scope="colgroup" colspan="4">{{ _("This is the list of SearXNG's instant answering modules.") }}</th>
|
||||
{% for answerer in answerers %}
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>{{ answerer.keywords|join(', ') }}</td>
|
||||
<td>{{ answerer.info.name }}</td>
|
||||
<td>{{ answerer.info.description }}</td>
|
||||
<td>{{ answerer.info.examples|join(', ') }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
<td></td>
|
||||
<th scope="colgroup" colspan="4">{{ _('This is the list of plugins.') }}</th>
|
||||
{%- for plugin in plugins -%}
|
||||
{%- if plugin.preference_section == 'query' -%}
|
||||
<tr>
|
||||
<td>{{- checkbox_onoff('plugin_' + plugin.id, plugin.id not in allowed_plugins) -}}</td>
|
||||
<td>{{ plugin.query_keywords|join(', ') }}</td>
|
||||
<td>{{ _(plugin.name) }}</td>
|
||||
<td>{{ _(plugin.description) }}</td>
|
||||
<td>{{ plugin.query_examples }}</td>
|
||||
</tr>
|
||||
{%- endif -%}
|
||||
{%- endfor -%}
|
||||
</table>
|
||||
</div>
|
||||
{% endif %}
|
||||
{{ tab_footer() }}
|
||||
|
||||
{{ tab_header('maintab', 'cookies', _('Cookies')) }}
|
||||
<p class="text-muted">{{- "" -}}
|
||||
{{- _('This is the list of cookies and their values SearXNG is storing on your computer.') }}<br />{{- "" -}}
|
||||
{{- _('With that list, you can assess SearXNG transparency.') }}<br />{{- "" -}}
|
||||
</p>
|
||||
{% if cookies %}
|
||||
<table class="cookies">
|
||||
<tr>{{- "" -}}
|
||||
<th>{{ _('Cookie name') }}</th>{{- "" -}}
|
||||
<th>{{ _('Value') }}</th>{{- "" -}}
|
||||
</tr>
|
||||
{% for cookie in cookies %}
|
||||
<tr>{{- "" -}}
|
||||
<td>{{ cookie }}</td>{{- "" -}}
|
||||
<td>{{ cookies[cookie] }}</td>{{- "" -}}
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
{% else %}
|
||||
{% include 'simple/messages/no_cookies.html' %}
|
||||
{% endif %}
|
||||
<h4>{{ _('Search URL of the currently saved preferences') }} :</h4>
|
||||
<div class="selectable_url">
|
||||
<pre>{{ url_for('index', _external=True) }}?preferences={{ preferences_url_params|e }}{% raw %}&q=%s{% endraw %}</pre>
|
||||
</div>
|
||||
<p class="small_font">{{ _('Note: specifying custom settings in the search URL can reduce privacy by leaking data to the clicked result sites.') }}</p>
|
||||
<h4>{{ _('URL to restore your preferences in another browser') }} :</h4>
|
||||
<div class="selectable_url">
|
||||
<pre>{{ url_for('preferences', _external=True) }}?preferences={{ preferences_url_params|e }}&save=1</pre>
|
||||
</div>
|
||||
<p class="small_font">{{ _('Specifying custom settings in the preferences URL can be used to sync preferences across devices.') }}</p>
|
||||
{{ tab_footer() }}
|
||||
|
||||
{{ tabs_close() }}
|
||||
|
||||
<p class="small_font">{{ _('These settings are stored in your cookies, this allows us not to store this data about you.') }}
|
||||
<br />
|
||||
{{ _("These cookies serve your sole convenience, we don't use these cookies to track you.") }}
|
||||
</p>
|
||||
|
||||
<input type="submit" value="{{ _('Save') }}" />
|
||||
<div class="{% if rtl %}left{% else %}right{% endif %} preferences_back"><a href="{{ url_for('clear_cookies') }}">{{ _('Reset defaults') }}</a></div>
|
||||
<div class="{% if rtl %}left{% else %}right{% endif %} preferences_back"><a href="{{ url_for('index') }}">{{ _('Back') }}</a></div>
|
||||
|
||||
</form>
|
||||
{% endblock %}
|
13
beetroot_template/result_templates/code.html
Normal file
|
@ -0,0 +1,13 @@
|
|||
{% from 'simple/macros.html' import result_header, result_sub_header, result_sub_footer, result_footer with context %}
|
||||
|
||||
{{ result_header(result, favicons, image_proxify) -}}
|
||||
{{- result_sub_header(result) -}}
|
||||
{%- if result.content %}{{ result.content|safe }}{% endif %}</p>
|
||||
{%- if result.repository -%}
|
||||
<p class="content"><a href="{{ result.repository|safe }}" {% if results_on_new_tab %}target="_blank" rel="noopener noreferrer"{% else %}rel="noreferrer"{% endif %}>{{ result.repository }}</a></p>
|
||||
{%- endif -%}
|
||||
<div dir="ltr" class="codelines">
|
||||
{{- result.codelines|code_highlighter(result.code_language)|safe -}}
|
||||
</div>{{- '' -}}
|
||||
{{- result_sub_footer(result, proxify) -}}
|
||||
{{ result_footer(result) }}
|
28
beetroot_template/result_templates/default.html
Normal file
|
@ -0,0 +1,28 @@
|
|||
{% from 'simple/macros.html' import result_header, result_sub_header, result_sub_footer, result_footer with context %}
|
||||
|
||||
{{ result_header(result, favicons, image_proxify) -}}
|
||||
{{- result_sub_header(result) -}}
|
||||
{% if result.iframe_src -%}
|
||||
<p class="altlink"><a class="btn-collapse collapsed media-loader disabled_if_nojs" data-target="#result-media-{{ index }}" data-btn-text-collapsed="{{ _('show media') }}" data-btn-text-not-collapsed="{{ _('hide media') }}">{{ icon('music-note') }} {{ _('show media') }}</a></p>
|
||||
{%- endif %}
|
||||
{%- if result.content %}
|
||||
<p class="content">
|
||||
{{ result.content|safe }}
|
||||
</p>
|
||||
{%- else %}
|
||||
<p class="content empty_element">
|
||||
{{ _('This site did not provide any description.')|safe }}
|
||||
</p>
|
||||
{% endif -%}
|
||||
{{- result_sub_footer(result, proxify) -}}
|
||||
{% if result.iframe_src -%}
|
||||
<div id="result-media-{{ index }}" class="embedded-content invisible">
|
||||
<iframe data-src="{{result.iframe_src}}" frameborder="0" allowfullscreen></iframe>
|
||||
</div>
|
||||
{%- endif %}
|
||||
{% if result.audio_src -%}
|
||||
<div id="result-media-{{ index }}" class="audio-control">
|
||||
<audio controls><source src="{{result.audio_src}}"></audio>
|
||||
</div>
|
||||
{%- endif %}
|
||||
{{- result_footer(result) }}
|
25
beetroot_template/result_templates/images.html
Normal file
|
@ -0,0 +1,25 @@
|
|||
<article class="result result-images {% if result['category'] %}category-{{ result['category'] }}{% endif %}">{{- "" -}}
|
||||
<a {% if results_on_new_tab %}target="_blank" rel="noopener noreferrer"{% else %}rel="noreferrer"{% endif %} href="{{ result.img_src }}">{{- "" -}}
|
||||
<img class="image_thumbnail" {% if results_on_new_tab %}target="_blank" rel="noopener noreferrer"{% else %}rel="noreferrer"{% endif %} src="{% if result.thumbnail_src %}{{ image_proxify(result.thumbnail_src) }}{% else %}{{ image_proxify(result.img_src) }}{% endif %}" alt="{{ result.title|striptags }}" loading="lazy" width="200" height="200">{{- "" -}}
|
||||
<span class="title">{{ result.title|striptags }}</span>{{- "" -}}
|
||||
<span class="source">{{ result.parsed_url.netloc }}</span>{{- "" -}}
|
||||
</a>{{- "" -}}
|
||||
<div class="detail">{{- "" -}}
|
||||
<a class="result-detail-close" href="#">{{ icon('close') }}</a>{{- "" -}}
|
||||
<a class="result-detail-previous" href="#">{{ icon('chevron-left') }}</a>{{- "" -}}
|
||||
<a class="result-detail-next" href="#">{{ icon('chevron-right') }}</a>{{- "" -}}
|
||||
<a class="result-images-source" {% if results_on_new_tab %}target="_blank" rel="noopener noreferrer"{% else %}rel="noreferrer"{% endif %} href="{{ result.img_src }}">
|
||||
<img src="" data-src="{{ image_proxify(result.img_src) }}" alt="{{ result.title|striptags }}">{{- "" -}}
|
||||
</a>{{- "" -}}
|
||||
<div class="result-images-labels">{{- "" -}}
|
||||
<h4>{{ result.title|striptags }}</h4>{{- "" -}}
|
||||
<p class="result-content">{%- if result.content %}{{ result.content|striptags }}{% else %} {% endif -%}</p>{{- "" -}}
|
||||
<hr>{{- "" -}}
|
||||
<p class="result-author">{%- if result.author %}<span>{{ _('Author') }}:</span>{{ result.author|striptags }}{% else %} {% endif -%}</p>{{- "" -}}
|
||||
<p class="result-format">{%- if result.img_format %}<span>{{ _('Format') }}:</span>{{ result.img_format }}{% else %} {% endif -%}</p>{{- "" -}}
|
||||
<p class="result-source">{%- if result.source %}<span>{{ _('Source') }}:</span>{{ result.source }}{% else %} {% endif -%}</p>{{- "" -}}
|
||||
<p class="result-engine"><span>{{ _('Engine') }}:</span>{{ result.engine }}</p>{{- "" -}}{{- "" -}}
|
||||
<p class="result-url"><span>{{ _('View source') }}:</span><a {% if results_on_new_tab %}target="_blank" rel="noopener noreferrer"{% else %}rel="noreferrer"{% endif %} href="{{ result.url }}">{{ result.url }}</a></p>{{- "" -}}
|
||||
</div>{{- "" -}}
|
||||
</div>{{- "" -}}
|
||||
</article>
|
11
beetroot_template/result_templates/key-value.html
Normal file
|
@ -0,0 +1,11 @@
|
|||
<table>
|
||||
{% for key, value in result.items() %}
|
||||
{% if key in ['engine', 'engines', 'template', 'score', 'category', 'positions', 'pretty_url', 'parsed_url'] %}
|
||||
{% continue %}
|
||||
{% endif %}
|
||||
<tr>
|
||||
<td><b>{{ key|upper }}</b>: {{ value }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
<div class="engines">{% for engine in result.engines %}<span>{{ engine }}</span>{% endfor %}</div>{{- '' -}}
|
52
beetroot_template/result_templates/map.html
Normal file
|
@ -0,0 +1,52 @@
|
|||
{% from 'simple/macros.html' import result_header, result_sub_header, result_sub_footer, result_footer with context %}
|
||||
{% from 'simple/icons.html' import icon_small %}
|
||||
|
||||
{{ result_header(result, favicons, image_proxify) -}}
|
||||
{{- result_sub_header(result) -}}
|
||||
|
||||
{%- if result.content %}<p class="content">{{ result.content|safe }}</p>{% endif -%}
|
||||
|
||||
<table>
|
||||
{%- if result.address -%}
|
||||
<tr>
|
||||
<th scope="row">{{ result.address_label or _('address') }}</th>
|
||||
<td itemscope itemtype="http://schema.org/PostalAddress">
|
||||
{%- if result.address.name -%}
|
||||
<strong itemprop="name" class="hidden">{{ result.address.name }}</strong>
|
||||
{%- endif -%}
|
||||
{% if result.address.road -%}
|
||||
<span itemprop="streetAddress">
|
||||
{%- if result.address.house_number -%}{{- result.address.house_number -}}, {% endif %}
|
||||
{{- result.address.road -}}
|
||||
</span><br/>
|
||||
{%- endif %}
|
||||
{%- if result.address.locality -%}
|
||||
<span itemprop="addressLocality">{{- result.address.locality -}}</span>
|
||||
{%- if result.address.postcode -%}, <span itemprop="postalCode">{{- result.address.postcode -}}</span>{% endif %}
|
||||
<br/>
|
||||
{%- endif -%}
|
||||
{%- if result.address.country -%}
|
||||
<span itemprop="addressCountry">{{- result.address.country -}}</span>
|
||||
{%- endif -%}
|
||||
</td>
|
||||
</tr>
|
||||
{%- endif %}
|
||||
{%- for info in result.data -%}
|
||||
<tr><th scope="row">{{ info.label }}</th><td>{{ info.value|safe }}</td></tr>
|
||||
{%- endfor -%}
|
||||
{%- for link in result.links -%}
|
||||
<tr><th scope="row">{{ link.label }}</th><td><a class="text-info cursor-pointer" href="{{ link.url }}">{{ link.url_label|safe }}</a></td></tr>
|
||||
{%- endfor -%}
|
||||
</table>
|
||||
|
||||
{%- if (result.latitude and result.longitude) or result.boundingbox -%}
|
||||
<small> <a class="btn-collapse collapsed searxng_init_map hide_if_nojs" data-target="#result-map-{{ index }}" data-btn-text-collapsed="{{ _('show map') }}" data-btn-text-not-collapsed="{{ _('hide map') }}" data-leaflet-target="osm-map-{{ index }}" data-map-lon="{{ result.longitude }}" data-map-lat="{{ result.latitude }}" {% if result.boundingbox %}data-map-boundingbox='{{ result.boundingbox|tojson|safe }}'{% endif %} {% if result.geojson %}data-map-geojson='{{ result.geojson|tojson|safe }}'{% endif %}>{{ icon_small( 'globe-outline') }} {{ _('show map') }}</a></small>
|
||||
{%- endif -%}
|
||||
|
||||
{{- result_sub_footer(result, proxify) -}}
|
||||
|
||||
{% if (result.latitude and result.longitude) or result.boundingbox -%}
|
||||
<div id="result-map-{{ index }}" class="invisible"><div id="osm-map-{{ index }}" class="osm-map-box"></div></div>
|
||||
{%- endif %}
|
||||
|
||||
{{- result_footer(result) }}
|
38
beetroot_template/result_templates/paper.html
Normal file
|
@ -0,0 +1,38 @@
|
|||
{% from 'simple/macros.html' import result_header, result_sub_header, result_sub_footer, result_footer, result_link with context %}
|
||||
|
||||
{{ result_header(result, favicons, image_proxify) -}}
|
||||
<div class="attributes">
|
||||
{%- if result.publishedDate %}<div class="result_publishedDate"><span>{{ _("Published date") }}:</span><span><time class="published_date" datetime="{{ result.pubdate }}" >{{ result.publishedDate }}</time></span></div>{% endif -%}
|
||||
{%- if result.authors %}<div class="result_authors"><span>{{ _("Author") }}:</span><span>{{ result.authors | join(", ") }}</span></div>{% endif -%}
|
||||
{%- if result.journal -%}
|
||||
<div class="result_journal">
|
||||
<span>{{- _("Journal") }}:</span><span>{{ result.journal -}}
|
||||
{%- if result.volume -%}
|
||||
{{- result.volume -}}
|
||||
{%- if result.number -%}
|
||||
.{{- result.number -}}
|
||||
{%- endif -%}
|
||||
{%- endif -%}
|
||||
{%- if result.pages -%}
|
||||
{{- result.pages -}}
|
||||
{%- endif -%}
|
||||
</span>
|
||||
</div>
|
||||
{%- endif %}
|
||||
{%- if result.editor %}<div class="result_editor"><span>{{ _("Editor") }}:</span><span>{{ result.editor }}</span></div>{% endif -%}
|
||||
{%- if result.publisher %}<div class="result_publisher"><span>{{ _("Publisher") }}:</span><span>{{ result.publisher }}</span></div>{% endif -%}
|
||||
{%- if result.type %}<div class="result_type"><span>{{ _("Type") }}:</span><span>{{ result.type }}</span></div>{% endif -%}
|
||||
{%- if result.tags %}<div class="result_tags"><span>{{ _("Tags") }}:</span><span>{{ result.tags | join(", ")}}</span></div>{%- endif -%}
|
||||
{%- if result.doi %}<div class="result_doi"><span>{{ _("DOI") }}:</span><span>{{ result_link(doi_resolver + result.doi, result.doi) }}</span></div>{% endif -%}
|
||||
{%- if result.issn %}<div class="result_issn"><span>{{ _("ISSN") }}:</span><span>{{ result.issn | join(", ") }}</span></div>{% endif -%}
|
||||
{%- if result.isbn %}<div class="result_isbn"><span>{{ _("ISBN") }}:</span><span>{{ result.isbn | join(", ") }}</span></div>{% endif -%}
|
||||
</div>
|
||||
{%- if result.content -%}<p class="content">{{- result.content | safe -}}</p>{%- endif -%}
|
||||
{%- if result.comments -%}<p class="comments">{{- result.comments -}}</p>{%- endif -%}
|
||||
<p class="altlink">
|
||||
{%- if result.pdf_url -%}{{ result_link(result.pdf_url, _('PDF')) }}{%- endif -%}
|
||||
{%- if result.html_url -%}{{ result_link(result.html_url, _('HTML')) }}{%- endif -%}
|
||||
{%- if result.doi %}{{ result_link('https://www.altmetric.com/details/doi/' + result.doi, 'Altmetric') }}{% endif -%}
|
||||
</p>
|
||||
{{- result_sub_footer(result, proxify) -}}
|
||||
{{- result_footer(result) }}
|
14
beetroot_template/result_templates/products.html
Normal file
|
@ -0,0 +1,14 @@
|
|||
{% from 'simple/macros.html' import result_header, result_sub_header, result_sub_footer, result_footer with context %}
|
||||
|
||||
{{ result_header(result, favicons, image_proxify) -}}
|
||||
{{- result_sub_header(result) -}}
|
||||
{% if result.price %}<div class="result_price">{{ result.price }}</div></br>{% endif %}
|
||||
{% if result.shipping %}<div class="result_shipping">{{ result.shipping }}</div></br>{% endif %}
|
||||
{% if result.source_country %}<div class="result_source_country">{{ result.source_country }}</div></br>{% endif %}
|
||||
{%- if result.content %}
|
||||
<p class="content">
|
||||
{{ result.content }}
|
||||
</p>
|
||||
{% endif -%}
|
||||
{{- result_sub_footer(result, proxify) -}}
|
||||
{{- result_footer(result) }}
|
24
beetroot_template/result_templates/torrent.html
Normal file
|
@ -0,0 +1,24 @@
|
|||
{% from 'simple/macros.html' import result_header, result_sub_header, result_sub_footer, result_footer, result_link with context %}
|
||||
|
||||
{{ result_header(result, favicons, image_proxify) -}}
|
||||
{{- result_sub_header(result) -}}
|
||||
|
||||
{% if result.magnetlink %}<p class="altlink"> • {{ result_link(result.magnetlink, icon_big('magnet-outline') + _('magnet link'), "magnetlink") }}</p>{% endif %}
|
||||
{% if result.torrentfile %}<p class="altlink"> • {{ result_link(result.torrentfile, icon_big('download-alt') + _('torrent file'), "torrentfile") }}</p>{% endif %}
|
||||
|
||||
{% if result.seed is defined %}<p class="stat"> • {{ icon_big('arrow-swap') }} {{ _('Seeder') }} <span class="badge">{{ result.seed }}</span> • {{ _('Leecher') }} <span class="badge">{{ result.leech }}</span></p>{% endif %}
|
||||
|
||||
{%- if result.filesize %}<p class="stat">{{ icon_big('floppy-disk') }} {{ _('Filesize') }}<span class="badge">
|
||||
{%- if result.filesize < 1024 %}{{ result.filesize }} {{ _('Bytes') }}
|
||||
{%- elif result.filesize < 1024*1024 %}{{ '{0:0.2f}'.format(result.filesize/1024) }} {{ _('kiB') }}
|
||||
{%- elif result.filesize < 1024*1024*1024 %}{{ '{0:0.2f}'.format(result.filesize/1024/1024) }} {{ _('MiB') }}
|
||||
{%- elif result.filesize < 1024*1024*1024*1024 %}{{ '{0:0.2f}'.format(result.filesize/1024/1024/1024) }} {{ _('GiB') }}
|
||||
{%- else %}{{ '{0:0.2f}'.format(result.filesize/1024/1024/1024/1024) }} {{ _('TiB') }}{% endif -%}
|
||||
</span></p>
|
||||
{%- endif -%}
|
||||
|
||||
{%- if result.files %}<p class="stat">{{ icon_big('file') }} {{ _('Number of Files') }} <span class="badge">{{ result.files }}</span></p>{% endif -%}
|
||||
|
||||
{%- if result.content %}<p class="content">{{ result.content|safe }}</p>{% endif -%}
|
||||
{{- result_sub_footer(result, proxify) -}}
|
||||
{{- result_footer(result) }}
|
24
beetroot_template/result_templates/videos.html
Normal file
|
@ -0,0 +1,24 @@
|
|||
{% from 'simple/macros.html' import result_header, result_sub_header, result_sub_footer, result_footer with context %}
|
||||
|
||||
{{ result_header(result, favicons, image_proxify) }}
|
||||
{{ result_sub_header(result) }}
|
||||
{% if result.iframe_src -%}
|
||||
<p class="altlink"> <a class="btn-collapse collapsed media-loader disabled_if_nojs" data-target="#result-video-{{ index }}" data-btn-text-collapsed="{{ _('show video') }}" data-btn-text-not-collapsed="{{ _('hide video') }}">{{ icon('film-outline') }} {{ _('show video') }}</a></p>
|
||||
{%- endif %}
|
||||
{%- if result.content %}
|
||||
<p class="content">
|
||||
{{ result.content|safe }}
|
||||
</p>
|
||||
{%- else %}
|
||||
<p class="content empty_element">
|
||||
{{ _('This site did not provide any description.')|safe }}
|
||||
</p>
|
||||
{% endif -%}
|
||||
</p>
|
||||
{{- result_sub_footer(result, proxify) -}}
|
||||
{% if result.iframe_src -%}
|
||||
<div id="result-video-{{ index }}" class="embedded-video invisible">
|
||||
<iframe data-src="{{result.iframe_src}}" frameborder="0" allowfullscreen></iframe>
|
||||
</div>
|
||||
{%- endif %}
|
||||
{{ result_footer(result) }}
|
222
beetroot_template/results.html
Normal file
|
@ -0,0 +1,222 @@
|
|||
{% extends "simple/base.html" %}
|
||||
{% from 'simple/icons.html' import icon, icon_big, icon_small %}
|
||||
{% macro engine_data_form(engine_data) -%}
|
||||
{% for engine_name, kv_data in engine_data.items() %}
|
||||
{% for k, v in kv_data.items() %}
|
||||
<input type="hidden" name="engine_data-{{ engine_name }}-{{ k|e }}" value="{{ v|e }}" />
|
||||
{% endfor %}
|
||||
{% endfor %}
|
||||
{%- endmacro %}
|
||||
{% block title %}{% if query_in_title %}{{- q|e }} - {% endif %}{% endblock %}
|
||||
{% block meta %}<link rel="alternate" type="application/rss+xml" title="Searx search: {{ q|e }}" href="{{ url_for('search', _external=True) }}?q={{ q|urlencode }}&categories={{ selected_categories|join(",") | replace(' ','+') }}&pageno={{ pageno }}&time_range={{ time_range }}&language={{ current_language }}&safesearch={{ safesearch }}&format=rss">{% endblock %}
|
||||
{% block content %}
|
||||
{% include 'simple/search.html' %}
|
||||
|
||||
{% if results and results|map(attribute='template')|unique|list|count == 1 %}
|
||||
{% set only_template = 'only_template_' + results[0]['template']|default('default')|replace('.html', '') %}
|
||||
{% else %}
|
||||
{% set only_template = '' %}
|
||||
{% endif %}
|
||||
|
||||
<div id="results" class="{{ only_template }}">
|
||||
{% if answers -%}
|
||||
<div id="answers" role="complementary" aria-labelledby="answers-title"><h4 class="title" id="answers-title">{{ _('Answers') }} : </h4>
|
||||
{%- for answer in answers.values() -%}
|
||||
<div class="answer">
|
||||
{% if answer.url %}
|
||||
<a href="{{ answer.url }}">{{ answer.answer }}</a>
|
||||
{% else %}
|
||||
<span>{{ answer.answer }}</span>
|
||||
{% endif %}
|
||||
</div>
|
||||
{%- endfor -%}
|
||||
</div>
|
||||
{%- endif %}
|
||||
|
||||
<div id="sidebar">
|
||||
|
||||
{% if number_of_results != '0' -%}
|
||||
<p id="result_count"><small>{{ _('Number of results') }}: {{ number_of_results }}</small></p>
|
||||
{%- endif %}
|
||||
|
||||
{% if unresponsive_engines and results|length >= 1 %}
|
||||
<div class="dialog-error" role="alert">
|
||||
{{ icon_big('warning') }}
|
||||
<div>
|
||||
<p><strong>{{ _('Error!') }}</strong> {{ _('Engines cannot retrieve results') }}:</p>
|
||||
{%- for engine_name, error_type in unresponsive_engines -%}
|
||||
<p>{{- engine_name }} (
|
||||
<a href="{{ url_for('stats', engine=engine_name|e) }}" title="{{ _('View error logs and submit a bug report') }}">
|
||||
{{- error_type -}}
|
||||
</a> ){{- '' -}}
|
||||
</p>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if infoboxes %}
|
||||
<div id="infoboxes">
|
||||
{% for infobox in infoboxes -%}
|
||||
{% include 'simple/infobox.html' %}
|
||||
{%- endfor %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if suggestions %}
|
||||
<div id="suggestions" role="complementary" aria-labelledby="suggestions-title">
|
||||
<h4 class="title" id="suggestions-title">{{ _('Suggestions') }}: </h4>
|
||||
<div class="wrapper">
|
||||
{% for suggestion in suggestions %}
|
||||
<form method="{{ method or 'POST' }}" action="{{ url_for('search') }}">
|
||||
<input type="hidden" name="q" value="{{ suggestion.url }}">
|
||||
{% for category in selected_categories %}
|
||||
<input type="hidden" name="category_{{ category }}" value="1">
|
||||
{% endfor %}
|
||||
<input type="hidden" name="language" value="{{ current_language }}">
|
||||
<input type="hidden" name="time_range" value="{{ time_range }}">
|
||||
<input type="hidden" name="safesearch" value="{{ safesearch }}">
|
||||
<input type="hidden" name="theme" value="{{ theme }}">
|
||||
{% if timeout_limit %}<input type="hidden" name="timeout_limit" value="{{ timeout_limit|e }}" >{% endif %}
|
||||
<input type="submit" class="suggestion" role="link" value="• {{ suggestion.title }}">
|
||||
</form>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if method == 'POST' %}
|
||||
<div id="search_url" role="complementary" aria-labelledby="search_url-title">
|
||||
<h4 class="title" id="search_url-title">{{ _('Search URL') }} :</h4>
|
||||
<div class="selectable_url"><pre>{{ url_for('search', _external=True) }}?q={{ q|urlencode }}&language={{ current_language }}&time_range={{ time_range }}&safesearch={{ safesearch }}{% if pageno > 1 %}&pageno={{ pageno }}{% endif %}{% if selected_categories %}&categories={{ selected_categories|join(",") | replace(' ','+') }}{% endif %}{% if timeout_limit %}&timeout_limit={{ timeout_limit|urlencode }}{% endif %}</pre></div>
|
||||
</div>
|
||||
{% endif %}
|
||||
<div id="apis" role="complementary" aria-labelledby="apis-title">
|
||||
{% if search_formats %}
|
||||
<h4 class="title" id="apis-title">{{ _('Download results') }}</h4>
|
||||
{% for output_type in search_formats %}
|
||||
<div class="left">
|
||||
<form method="{{ method or 'POST' }}" action="{{ url_for('search') }}">
|
||||
<input type="hidden" name="q" value="{{ q|e }}">
|
||||
{% for category in selected_categories %}
|
||||
<input type="hidden" name="category_{{ category }}" value="1">
|
||||
{% endfor %}
|
||||
<input type="hidden" name="pageno" value="{{ pageno }}">
|
||||
<input type="hidden" name="language" value="{{ current_language }}">
|
||||
<input type="hidden" name="time_range" value="{{ time_range }}">
|
||||
<input type="hidden" name="safesearch" value="{{ safesearch }}">
|
||||
<input type="hidden" name="format" value="{{ output_type }}">
|
||||
{% if timeout_limit %}<input type="hidden" name="timeout_limit" value="{{ timeout_limit|e }}" >{% endif %}
|
||||
<input type="submit" role="link" value="{{ output_type }}">
|
||||
</form>
|
||||
</div>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% if corrections %}
|
||||
<div id="corrections" role="complementary" aria-labelledby="corrections-title">
|
||||
<h4 id="corrections-title">{{ _('Try searching for:') }}</h4>
|
||||
{% for correction in corrections %}
|
||||
<div class="left">
|
||||
<form method="{{ method or 'POST' }}" action="{{ url_for('search') }}" role="navigation">
|
||||
{% for category in selected_categories %}
|
||||
<input type="hidden" name="category_{{ category }}" value="1">
|
||||
{% endfor %}
|
||||
<input type="hidden" name="q" value="{{ correction.url }}">
|
||||
<input type="hidden" name="language" value="{{ current_language }}">
|
||||
<input type="hidden" name="time_range" value="{{ time_range }}">
|
||||
<input type="hidden" name="safesearch" value="{{ safesearch }}">
|
||||
<input type="hidden" name="theme" value="{{ theme }}">
|
||||
{% if timeout_limit %}<input type="hidden" name="timeout_limit" value="{{ timeout_limit }}" >{% endif %}
|
||||
<input type="submit" role="link" value="{{ correction.title }}">
|
||||
</form>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<div id="urls" role="main">
|
||||
{% for result in results %}
|
||||
{% if result.open_group and not only_template %}<div class="template_group_{{ result['template']|replace('.html', '') }}">{% endif %}
|
||||
{% set index = loop.index %}
|
||||
{% include get_result_template('simple', result['template']) %}
|
||||
{% if result.close_group and not only_template %}</div>{% endif %}
|
||||
{% endfor %}
|
||||
{% if not results and not answers %}
|
||||
{% include 'simple/messages/no_results.html' %}
|
||||
{% endif %}
|
||||
</div>
|
||||
<div id="backToTop">
|
||||
<a href="#" aria-label="{{ _('Back to top') }}">{{ icon_small('chevron-up-outline') }}</a>
|
||||
</div>
|
||||
{% if paging %}
|
||||
<nav id="pagination" role="navigation">
|
||||
{% if pageno > 1 %}
|
||||
<form method="{{ method or 'POST' }}" action="{{ url_for('search') }}" class="previous_page">
|
||||
<div class="{% if rtl %}right{% else %}left{% endif %}">
|
||||
<input type="hidden" name="q" value="{{ q|e }}" >
|
||||
{% for category in selected_categories %}
|
||||
<input type="hidden" name="category_{{ category }}" value="1" >
|
||||
{% endfor %}
|
||||
<input type="hidden" name="pageno" value="{{ pageno-1 }}" >
|
||||
<input type="hidden" name="language" value="{{ current_language }}" >
|
||||
<input type="hidden" name="time_range" value="{{ time_range }}" >
|
||||
<input type="hidden" name="safesearch" value="{{ safesearch }}" >
|
||||
<input type="hidden" name="theme" value="{{ theme }}" >
|
||||
{% if timeout_limit %}<input type="hidden" name="timeout_limit" value="{{ timeout_limit|e }}" >{% endif %}
|
||||
{{- engine_data_form(engine_data) -}}
|
||||
<button role="link" type="submit">{{ icon_small('chevron-left') }} {{ _('Previous page') }}</button>
|
||||
</div>
|
||||
</form>
|
||||
{% endif %}
|
||||
<form method="{{ method or 'POST' }}" action="{{ url_for('search') }}" class="next_page">
|
||||
<div class="{% if rtl %}left{% else %}right{% endif %}">
|
||||
<input type="hidden" name="q" value="{{ q|e }}" >
|
||||
{% for category in selected_categories %}
|
||||
<input type="hidden" name="category_{{ category }}" value="1" >
|
||||
{% endfor %}
|
||||
<input type="hidden" name="pageno" value="{{ pageno+1 }}" >
|
||||
<input type="hidden" name="language" value="{{ current_language }}" >
|
||||
<input type="hidden" name="time_range" value="{{ time_range }}" >
|
||||
<input type="hidden" name="safesearch" value="{{ safesearch }}" >
|
||||
<input type="hidden" name="theme" value="{{ theme }}" >
|
||||
{% if timeout_limit %}<input type="hidden" name="timeout_limit" value="{{ timeout_limit|e }}" >{% endif %}
|
||||
{{- engine_data_form(engine_data) -}}
|
||||
<button role="link" type="submit">{{ _('Next page') }} {{ icon_small('chevron-right') }}</button>
|
||||
</div>
|
||||
</form>
|
||||
{% set pstart = 1 %}
|
||||
{% set pend = 11 %}
|
||||
{% if pageno > 5 %}
|
||||
{% set pstart = pageno - 4 %}
|
||||
{% set pend = pageno + 6 %}
|
||||
{% endif %}
|
||||
|
||||
<div class="numbered_pagination">
|
||||
{% for x in range(pstart, pend) %}
|
||||
<form method="{{ method or 'POST' }}" action="{{ url_for('search') }}" class="page_number">
|
||||
<input type="hidden" name="q" value="{{ q|e }}" >
|
||||
{% for category in selected_categories %}
|
||||
<input type="hidden" name="category_{{ category }}" value="1" >
|
||||
{% endfor %}
|
||||
<input type="hidden" name="pageno" value="{{ x }}" >
|
||||
<input type="hidden" name="language" value="{{ current_language }}" >
|
||||
<input type="hidden" name="time_range" value="{{ time_range }}" >
|
||||
<input type="hidden" name="safesearch" value="{{ safesearch }}" >
|
||||
<input type="hidden" name="theme" value="{{ theme }}" >
|
||||
{% if timeout_limit %}<input type="hidden" name="timeout_limit" value="{{ timeout_limit|e }}" >{% endif %}
|
||||
{{- engine_data_form(engine_data) -}}
|
||||
{% if pageno == x %}
|
||||
<input role="link" class="page_number_current" type="button" value="{{ x }}">
|
||||
{% else %}
|
||||
<input role="link" class="page_number" type="submit" value="{{ x }}">
|
||||
{% endif %}
|
||||
</form>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</nav>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endblock %}
|
24
beetroot_template/search.html
Normal file
|
@ -0,0 +1,24 @@
|
|||
<form id="search" method="{{ method or 'POST' }}" action="{{ url_for('search') }}" role="search">
|
||||
<div id="search_header">
|
||||
<a id="search_logo" href="{{ url_for('index') }}" tabindex="0" title="{{ _('Display the front page') }}">
|
||||
<span hidden>SearXNG</span>
|
||||
{% include 'simple/searxng-wordmark.min.svg' without context %}
|
||||
</a>
|
||||
<div id="search_view">
|
||||
<div class="search_box">
|
||||
<input id="q" name="q" type="text" placeholder="{{ _('Search for...') }}" tabindex="1" autocomplete="off" autocapitalize="none" spellcheck="false" autocorrect="off" dir="auto" value="{{ q or '' }}">
|
||||
<button id="clear_search" type="reset" aria-label="{{ _('clear') }}" class="hide_if_nojs"><span>{{ icon_big('close') }}</span><span class="show_if_nojs">{{ _('clear') }}</span></button>
|
||||
<button id="send_search" type="submit" aria-label="{{ _('search') }}"><span class="hide_if_nojs">{{ icon_big('search-outline') }}</span><span class="show_if_nojs">{{ _('search') }}</span></button>
|
||||
</div>
|
||||
</div>
|
||||
{% set display_tooltip = true %}
|
||||
{% include 'simple/categories.html' %}
|
||||
</div>
|
||||
<div class="search_filters">
|
||||
{% include 'simple/filters/languages.html' %}
|
||||
{% include 'simple/filters/time_range.html' %}
|
||||
{% include 'simple/filters/safesearch.html' %}
|
||||
</div>
|
||||
<input type="hidden" name="theme" value="{{ theme }}" >
|
||||
{% if timeout_limit %}<input type="hidden" name="timeout_limit" value="{{ timeout_limit|e }}" >{% endif %}
|
||||
</form>
|
86
beetroot_template/searxng-wordmark.min.svg
Normal file
|
@ -0,0 +1,86 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
width="92mm"
|
||||
height="92mm"
|
||||
viewBox="0 0 92 92"
|
||||
version="1.1"
|
||||
id="svg283"
|
||||
sodipodi:docname="favicon.svg"
|
||||
inkscape:version="1.2.2 (b0a8486541, 2022-12-01)"
|
||||
inkscape:export-filename="favicon.png"
|
||||
inkscape:export-xdpi="72.058701"
|
||||
inkscape:export-ydpi="72.058701"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs287" />
|
||||
<sodipodi:namedview
|
||||
id="namedview285"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#000000"
|
||||
borderopacity="0.25"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#d1d1d1"
|
||||
inkscape:document-units="mm"
|
||||
showgrid="false"
|
||||
inkscape:zoom="2.2805933"
|
||||
inkscape:cx="187.45122"
|
||||
inkscape:cy="180.87399"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="995"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg283" />
|
||||
<g
|
||||
id="g12851-2"
|
||||
transform="matrix(0.27333337,0,0,0.27333337,-18.69294,-5.0517884)"
|
||||
style="stroke:#50152c;stroke-opacity:0.992157"
|
||||
inkscape:export-filename="/home/fekete/Nextcloud-Antilopa/Disroot/Artwork/Icons/new_pngs/search.png"
|
||||
inkscape:export-xdpi="1080.73"
|
||||
inkscape:export-ydpi="1080.73">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path3814-0-7-1"
|
||||
d="m 80.033739,36.455764 c -7.11959,15.242893 -10.17798,31.779192 -8.22563,48.814566 5.01677,43.77413 41.675291,79.3245 91.536091,95.16289 -6.62576,-22.40752 -5.34093,-44.9362 2.6395,-65.84431 C 118.24672,100.40622 84.338699,71.780528 80.033739,36.455764 Z"
|
||||
style="fill:#50142b;fill-opacity:0.992157;fill-rule:nonzero;stroke:#50152c;stroke-opacity:0.992157" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path3814-0-8"
|
||||
d="m 313.2893,37.799153 c 7.11959,15.242893 10.17798,31.779192 8.22563,48.814566 -5.01677,43.774131 -41.67531,79.324501 -91.53611,95.162891 6.62576,-22.40752 5.34093,-44.9362 -2.6395,-65.84431 47.73698,-14.18269 81.64502,-42.808383 85.94998,-78.133147 z"
|
||||
style="fill:#50142b;fill-opacity:0.992157;fill-rule:nonzero;stroke:#50152c;stroke-opacity:0.992157" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="rect3804-7"
|
||||
d="m 201.77833,175.2842 12.07511,-13.9057 c 4.0785,-4.69679 19.95774,2.45971 35.60368,16.04598 l 130.50177,113.32219 c 15.64593,13.58626 24.95835,28.30512 20.87985,33.00192 l -12.07512,13.9057 c -4.07849,4.69679 -19.95774,-2.45971 -35.60367,-16.04598 L 222.65818,208.28612 C 207.01224,194.69986 197.69983,179.981 201.77833,175.2842 Z"
|
||||
style="fill:#50142b;fill-opacity:0.992157;fill-rule:nonzero;stroke:#50152c;stroke-opacity:0.992157" />
|
||||
<circle
|
||||
r="107.58125"
|
||||
cy="149.35568"
|
||||
cx="196.89389"
|
||||
id="path2987-9"
|
||||
style="fill:#50142b;fill-opacity:0.992157;fill-rule:nonzero;stroke:#50152c;stroke-opacity:0.992157" />
|
||||
<circle
|
||||
r="72.430138"
|
||||
cy="149.10315"
|
||||
cx="196.64131"
|
||||
id="path3757-9-0"
|
||||
style="fill:#ffffff;fill-opacity:0.992157;fill-rule:nonzero;stroke:#50152c;stroke-width:0.713454;stroke-opacity:0.992157" />
|
||||
<circle
|
||||
r="27.274118"
|
||||
cy="150.79912"
|
||||
cx="197.85327"
|
||||
id="path3800-2"
|
||||
style="fill:#50132a;fill-opacity:1;fill-rule:nonzero;stroke:#50152c;stroke-opacity:0.992157" />
|
||||
<circle
|
||||
r="5.5558391"
|
||||
cy="141.34952"
|
||||
cx="208.98526"
|
||||
id="path3802-3"
|
||||
style="fill:#ffffff;fill-opacity:0.992157;fill-rule:nonzero;stroke:#50152c;stroke-opacity:0.992157" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 3.7 KiB |
19
beetroot_template/simple_search.html
Normal file
|
@ -0,0 +1,19 @@
|
|||
<form id="search" method="{{ method or 'POST' }}" action="{{ url_for('search') }}" role="search">
|
||||
<div id="search_header">
|
||||
<div id="search_view">
|
||||
<div class="search_box">
|
||||
<input id="q" name="q" type="text" placeholder="{{ _('Search for...') }}" autocomplete="off" autocapitalize="none" spellcheck="false" autocorrect="off" dir="auto" value="{{ q or '' }}">
|
||||
<button id="clear_search" type="reset" aria-label="{{ _('clear') }}"><span class="hide_if_nojs">{{ icon_big('close') }}</span><span class="show_if_nojs">{{ _('clear') }}</span></button>
|
||||
<button id="send_search" type="submit" aria-label="{{ _('search') }}"><span class="hide_if_nojs">{{ icon_big('search-outline') }}</span><span class="show_if_nojs">{{ _('search') }}</span></button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% for category in selected_categories %}
|
||||
<input type="hidden" name="category_{{ category }}" value="1" >
|
||||
{% endfor %}
|
||||
<input type="hidden" name="language" value="{{ current_language }}" >
|
||||
<input type="hidden" name="time_range" value="{{ time_range }}" >
|
||||
<input type="hidden" name="safesearch" value="{{ safesearch }}" >
|
||||
<input type="hidden" name="theme" value="{{ theme }}" >
|
||||
{% if timeout_limit %}<input type="hidden" name="timeout_limit" value="{{ timeout_limit|e }}" >{% endif %}
|
||||
</form>
|
148
beetroot_template/stats.html
Normal file
|
@ -0,0 +1,148 @@
|
|||
{% from 'simple/icons.html' import icon_big %}
|
||||
{% from 'simple/new_issue.html' import new_issue with context %}
|
||||
|
||||
{% extends "simple/page_with_header.html" %}
|
||||
|
||||
{%- macro th_sort(column_order, column_name) -%}
|
||||
{% if selected_engine_name %}
|
||||
{{ column_name }}
|
||||
{% elif column_order==sort_order %}
|
||||
{{ column_name }} {{ icon_big('arrow-dropdown') }}
|
||||
{% else %}
|
||||
<a href="{{ url_for('stats', sort=column_order) }}">{{ column_name }}</a>
|
||||
{% endif %}
|
||||
{%- endmacro -%}
|
||||
|
||||
{% block head %} {% endblock %}
|
||||
{% block content %}
|
||||
<h1>{% if selected_engine_name %}<a href="{{ url_for('stats') }}">{% endif %}{{ _('Engine stats') }}{% if selected_engine_name %}</a> - {{ selected_engine_name }}{% endif %}</h1>
|
||||
|
||||
{% if not engine_stats.get('time') %}
|
||||
{{ _('There is currently no data available. ') }}
|
||||
{% else %}
|
||||
<table class="engine-stats">
|
||||
<tr>
|
||||
<th scope="col" class="engine-name">{{ th_sort('name', _("Engine name")) }}</th>
|
||||
<th scope="col" class="engine-score">{{ th_sort('score', _('Scores')) }}</th>
|
||||
<th scope="col" class="result-count">{{ th_sort('result_count', _('Result count')) }}</th>
|
||||
<th scope="col" class="response-time">{{ th_sort('time', _('Response time')) }}</th>
|
||||
<th scope="col" class="engine-reliability">{{ th_sort('reliability', _('Reliability')) }}</th>
|
||||
</tr>
|
||||
{% for engine_stat in engine_stats.get('time', []) %}
|
||||
<tr>
|
||||
<td class="engine-name"><a href="{{ url_for('stats', engine=engine_stat.name|e) }}">{{ engine_stat.name }}</a></td>
|
||||
<td class="engine-score">
|
||||
{% if engine_stat.score %}
|
||||
<span>{{ engine_stat.score_per_result|round(1) }}</span>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td class="engine-result-count">
|
||||
{%- if engine_stat.result_count -%}
|
||||
|
||||
<div class="bar-chart-value">{{- engine_stat.result_count | int -}}</div>{{- "" -}}
|
||||
<div class="bar-chart-graph" aria-hidden="true">
|
||||
<div class="bar-chart-bar bar{{ (100 * engine_stat.result_count / engine_stats.max_result_count)|round }}"></div>{{- "" -}}
|
||||
</div>
|
||||
{%- endif -%}
|
||||
</td>
|
||||
<td class="response-time">
|
||||
{%- if engine_stat.total is not none -%}
|
||||
<div class="bar-chart-value">{{- engine_stat.total | round(1) -}}</div>{{- "" -}}
|
||||
<div class="bar-chart-graph" aria-labelledby="{{engine_stat.name}}_time" aria-hidden="true">
|
||||
{% if engine_stat.http is not none and engine_stats.max_time %}<div class="bar-chart-serie1 bar{{ (100 * engine_stat.http / engine_stats.max_time)|round }}"></div>{%- endif -%}
|
||||
{% if engine_stat.processing is not none and engine_stats.max_time %}<div class="bar-chart-serie2 bar{{ (100 * engine_stat.processing / engine_stats.max_time)|round }}"></div>{%- endif -%}
|
||||
</div>
|
||||
<div class="engine-tooltip" role="tooltip" id="{{engine_stat.name}}_time">{{- "" -}}
|
||||
<table>
|
||||
<tr>
|
||||
<th scope="col"></th>
|
||||
<th scope="col">{{ _('Total') }}</th>
|
||||
<th scope="col">{{ _('HTTP') }}</th>
|
||||
<th scope="col">{{ _('Processing') }}</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="col">{{ _('Median') }}</th>
|
||||
<td>{{ engine_stat.total }}</td>
|
||||
<td>{{ engine_stat.http or ''}}</td>
|
||||
<td>{{ engine_stat.processing }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="col">{{ _('P80') }}</th>
|
||||
<td>{{ engine_stat.total_p80 }}</td>
|
||||
<td>{{ engine_stat.http_p80 or '' }}</td>
|
||||
<td>{{ engine_stat.processing_p80 }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="col">{{ _('P95') }}</th>
|
||||
<td>{{ engine_stat.total_p95 }}</td>
|
||||
<td>{{ engine_stat.http_p95 or '' }}</td>
|
||||
<td>{{ engine_stat.processing_p95 }}</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
{%- endif -%}
|
||||
</td>
|
||||
<td class="engine-reliability"> {{ engine_reliabilities.get(engine_stat.name, {}).get('reliablity') }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
{% endif %}
|
||||
|
||||
{% if selected_engine_name %}
|
||||
<div class="engine-errors">
|
||||
{% for secondary in [False, True] %}
|
||||
{% set ns = namespace(first=true) %}
|
||||
{% for error in engine_reliabilities[selected_engine_name].errors %}
|
||||
{% if secondary == error.secondary %}
|
||||
{% if ns.first %}
|
||||
{% set ns.first = false %}
|
||||
<h2>{% if secondary %}{{ _('Warnings') }}{% else %}{{ _('Errors and exceptions') }}{% endif %}</h2>
|
||||
{% endif %}
|
||||
<table class="engine-error">
|
||||
<tbody>
|
||||
<tr>
|
||||
{%- if error.exception_classname -%}
|
||||
<th scope="row" class="engine-error-type">{{ _('Exception') }}</th><td>{{ error.exception_classname }}</td>
|
||||
{%- elif error.log_message -%}
|
||||
<th scope="row" class="engine-error-type">{{ _('Message') }}</th><td>{{ error.log_message }}</td>
|
||||
{%- endif -%}
|
||||
<th scope="row" class="engine-error-type">{{ _('Percentage') }}</th><td class="engine-error-type">{{ error.percentage }}</td>
|
||||
</tr>
|
||||
{% if error.log_parameters and error.log_parameters != (None, None, None) %}<tr><th scope="row">{{ _('Parameter') }}</th>{{- '' -}}
|
||||
<td colspan="3">
|
||||
{%- for param in error.log_parameters -%}
|
||||
<span class="log_parameters">{{ param }}</span>
|
||||
{%- endfor -%}
|
||||
</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
<tr><th scope="row">{{ _('Filename') }}</th><td colspan="3">{{ error.filename }}:{{ error.line_no }}</td></tr>
|
||||
<tr><th scope="row">{{ _('Function') }}</th><td colspan="3">{{ error.function }}</td></tr>
|
||||
<tr><th scope="row">{{ _('Code') }}</th><td colspan="3">{{ error.code }}</td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% endfor %}
|
||||
{% if engine_reliabilities[selected_engine_name].checker %}
|
||||
<h3>{{ _('Checker') }}</h3>
|
||||
<table>
|
||||
<tr>
|
||||
<th scope="col" class="failed-test">{{ _('Failed test') }}</th>
|
||||
<th scope="col">{{ _('Comment(s)') }}</th>
|
||||
</tr>
|
||||
{% for test_name, results in engine_reliabilities[selected_engine_name].checker.items() %}
|
||||
<tr>
|
||||
<td>{{ test_name }}</td>
|
||||
<td>
|
||||
{% for r in results %}<p>{{ r }}</p>{% endfor %}
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
{% endif %}
|
||||
{{ new_issue(selected_engine_name, engine_reliabilities[selected_engine_name]) }}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% endblock %}
|
BIN
img/Dark01.png
Normal file
After Width: | Height: | Size: 93 KiB |
BIN
img/Dark02.png
Normal file
After Width: | Height: | Size: 248 KiB |
BIN
img/Dark03.png
Normal file
After Width: | Height: | Size: 228 KiB |
BIN
img/Light01.png
Normal file
After Width: | Height: | Size: 94 KiB |
BIN
img/Light02.png
Normal file
After Width: | Height: | Size: 225 KiB |
BIN
img/Light03.png
Normal file
After Width: | Height: | Size: 209 KiB |