Merge cc0ff4650b60f37766666373019d7b100b46bfa9 into 6afe0e29a7818313e8a3295a13bb8ed92d3d354c
@ -16,8 +16,8 @@
|
|||||||
var map_boundingbox = JSON.parse(this.dataset.mapBoundingbox);
|
var map_boundingbox = JSON.parse(this.dataset.mapBoundingbox);
|
||||||
var map_geojson = JSON.parse(this.dataset.mapGeojson);
|
var map_geojson = JSON.parse(this.dataset.mapGeojson);
|
||||||
|
|
||||||
searxng.loadStyle('css/leaflet.css');
|
searxng.loadStyle('css/leaflet.SEARXNG_HASH.css');
|
||||||
searxng.loadScript('js/leaflet.js', function () {
|
searxng.loadScript('js/leaflet.SEARXNG_HASH.js', function () {
|
||||||
var map_bounds = null;
|
var map_bounds = null;
|
||||||
if (map_boundingbox) {
|
if (map_boundingbox) {
|
||||||
var southWest = L.latLng(map_boundingbox[0], map_boundingbox[2]);
|
var southWest = L.latLng(map_boundingbox[0], map_boundingbox[2]);
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
text-align: center;
|
text-align: center;
|
||||||
|
|
||||||
.title {
|
.title {
|
||||||
background: url("../img/searxng.png") no-repeat;
|
background: url("../img/searxng.SEARXNG_HASH.png") no-repeat;
|
||||||
min-height: 4rem;
|
min-height: 4rem;
|
||||||
margin: 4rem auto;
|
margin: 4rem auto;
|
||||||
background-position: center;
|
background-position: center;
|
||||||
|
@ -2,12 +2,16 @@
|
|||||||
* CONFIG: https://vite.dev/config/
|
* CONFIG: https://vite.dev/config/
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { resolve } from "node:path";
|
import { resolve, relative } from "node:path";
|
||||||
|
import { Buffer } from 'buffer';
|
||||||
|
import path from 'path';
|
||||||
import { defineConfig } from "vite";
|
import { defineConfig } from "vite";
|
||||||
import stylelint from "vite-plugin-stylelint";
|
import stylelint from "vite-plugin-stylelint";
|
||||||
import { viteStaticCopy } from "vite-plugin-static-copy";
|
import { viteStaticCopy } from "vite-plugin-static-copy";
|
||||||
import { plg_svg2png } from "./tools/plg.js";
|
import { plg_svg2png } from "./tools/plg.js";
|
||||||
import { plg_svg2svg } from "./tools/plg.js";
|
import { plg_svg2svg } from "./tools/plg.js";
|
||||||
|
import fs from 'node:fs/promises';
|
||||||
|
import crypto from 'node:crypto';
|
||||||
|
|
||||||
|
|
||||||
const ROOT = "../.."; // root of the git reposetory
|
const ROOT = "../.."; // root of the git reposetory
|
||||||
@ -40,6 +44,155 @@ const svg2svg_favicon_opts = {
|
|||||||
]
|
]
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function AddSearxNGHashes(options = {}) {
|
||||||
|
const {
|
||||||
|
fileName = "hashes.json",
|
||||||
|
exclude = [],
|
||||||
|
include_without_hashes = []
|
||||||
|
} = options;
|
||||||
|
let outDir = null;
|
||||||
|
|
||||||
|
// Helper: recursively get all files (not directories) within `dir`.
|
||||||
|
async function getAllFiles(dir) {
|
||||||
|
let entries = await fs.readdir(dir, { withFileTypes: true });
|
||||||
|
let files = [];
|
||||||
|
for (const entry of entries) {
|
||||||
|
const fullPath = resolve(dir, entry.name);
|
||||||
|
if (entry.isDirectory()) {
|
||||||
|
files = files.concat(await getAllFiles(fullPath));
|
||||||
|
} else {
|
||||||
|
files.push(fullPath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Separate out `.map` files so they end up last
|
||||||
|
const mapFiles = files.filter((file) => file.endsWith(".map"));
|
||||||
|
const otherFiles = files.filter((file) => !file.endsWith(".map"));
|
||||||
|
|
||||||
|
return [...otherFiles, ...mapFiles];
|
||||||
|
}
|
||||||
|
|
||||||
|
function replacePathsInBuffer(body, mapping) {
|
||||||
|
// Convert the Buffer to a string (assuming UTF-8)
|
||||||
|
let content = body.toString("utf-8");
|
||||||
|
|
||||||
|
// Perform replacements
|
||||||
|
for (const logicalPath of Object.keys(mapping)) {
|
||||||
|
const hashedPath = mapping[logicalPath];
|
||||||
|
content = content.replaceAll(logicalPath, hashedPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert the modified string back to a Buffer
|
||||||
|
return Buffer.from(content, "utf-8");
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
name: "recursive-hash-manifest-plugin",
|
||||||
|
apply: "build",
|
||||||
|
|
||||||
|
// Capture the final "outDir" from the resolved Vite config
|
||||||
|
configResolved(config) {
|
||||||
|
outDir = config.build.outDir;
|
||||||
|
},
|
||||||
|
|
||||||
|
// "closeBundle" is called after everything (including other async tasks) is done writing
|
||||||
|
async closeBundle() {
|
||||||
|
// Check if the outDir is set (from configResolved)
|
||||||
|
if (outDir === null) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get a list of every file in the output directory
|
||||||
|
let allFiles = await getAllFiles(outDir);
|
||||||
|
|
||||||
|
// Optionally exclude certain files
|
||||||
|
const exclusionSet = new Set([...exclude, fileName]);
|
||||||
|
allFiles = allFiles.filter((filePath) => {
|
||||||
|
const relPath = relative(outDir, filePath);
|
||||||
|
return !exclusionSet.has(relPath);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Compute a hash for each file
|
||||||
|
const assets = {};
|
||||||
|
const var_mapping = {}
|
||||||
|
const hash_override = {}
|
||||||
|
for (const filePath of allFiles) {
|
||||||
|
const relPath = relative(outDir, filePath);
|
||||||
|
|
||||||
|
// Get the shortHash
|
||||||
|
let shortHash;
|
||||||
|
|
||||||
|
if (include_without_hashes.includes(relative(outDir, filePath))) {
|
||||||
|
shortHash = "";
|
||||||
|
} else if (Object.prototype.hasOwnProperty.call(hash_override, filePath)) {
|
||||||
|
shortHash = hash_override[filePath];
|
||||||
|
} else {
|
||||||
|
const fileBuf = await fs.readFile(filePath);
|
||||||
|
const hashSum = crypto.createHash("sha256").update(fileBuf).digest("hex");
|
||||||
|
shortHash = "." + hashSum.slice(0, 8);
|
||||||
|
hash_override[filePath + ".map"] = shortHash;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prepare to build a new file path
|
||||||
|
const dirName = path.dirname(filePath);
|
||||||
|
let newFilePath;
|
||||||
|
let varPath = null;
|
||||||
|
|
||||||
|
// Special handling for *.js.map
|
||||||
|
if (filePath.endsWith(".js.map")) {
|
||||||
|
const baseName = path.basename(filePath, ".js.map");
|
||||||
|
newFilePath = path.join(dirName, `${baseName}${shortHash}.js.map`);
|
||||||
|
}
|
||||||
|
// Special handling for *.css.map
|
||||||
|
else if (filePath.endsWith(".css.map")) {
|
||||||
|
const baseName = path.basename(filePath, ".css.map");
|
||||||
|
newFilePath = path.join(dirName, `${baseName}${shortHash}.css.map`);
|
||||||
|
}
|
||||||
|
// Otherwise, rename as usual
|
||||||
|
else {
|
||||||
|
const extName = path.extname(filePath);
|
||||||
|
const baseName = path.basename(filePath, extName);
|
||||||
|
newFilePath = path.join(dirName, `${baseName}${shortHash}${extName}`);
|
||||||
|
|
||||||
|
//
|
||||||
|
varPath = `${baseName}.SEARXNG_HASH${extName}`;
|
||||||
|
var_mapping[varPath] = `${baseName}${shortHash}${extName}`;
|
||||||
|
if (filePath.endsWith(".js")) {
|
||||||
|
var_mapping[`//# sourceMappingURL=${baseName}${extName}.map`] = `//# sourceMappingURL=${baseName}${shortHash}${extName}.map`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// New relative path
|
||||||
|
const newRelPath = relative(outDir, newFilePath);
|
||||||
|
assets[relPath] = newRelPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Step 2: Once the manifest is all set, read back files that might reference others
|
||||||
|
// and replace placeholders with hashed paths.
|
||||||
|
for (const filePath of allFiles) {
|
||||||
|
const extName = path.extname(filePath);
|
||||||
|
if (![".css", ".js", ".html"].includes(extName)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const originalBuf = await fs.readFile(filePath);
|
||||||
|
const replacedBuf = replacePathsInBuffer(originalBuf, var_mapping);
|
||||||
|
await fs.writeFile(filePath, replacedBuf);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Step 3: rename the original files to their hashed filenames
|
||||||
|
for (const filePath of allFiles) {
|
||||||
|
const relPath = path.relative(outDir, filePath);
|
||||||
|
const newRelPath = assets[relPath];
|
||||||
|
const newFilePath = path.join(outDir, newRelPath);
|
||||||
|
await fs.rename(filePath, newFilePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write out `assets.json`
|
||||||
|
const assetsPath = resolve(outDir, fileName);
|
||||||
|
await fs.writeFile(assetsPath, JSON.stringify(assets, null, 2), "utf-8");
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
|
|
||||||
@ -180,6 +333,22 @@ export default defineConfig({
|
|||||||
svg2svg_opts
|
svg2svg_opts
|
||||||
),
|
),
|
||||||
|
|
||||||
|
// -- create assets.json and add hashes to files
|
||||||
|
AddSearxNGHashes({
|
||||||
|
fileName: "assets.json",
|
||||||
|
exclude: [
|
||||||
|
".gitattributes",
|
||||||
|
"manifest.json"
|
||||||
|
],
|
||||||
|
include_without_hashes: [
|
||||||
|
"css/images/layers-2x.png",
|
||||||
|
"css/images/layers.png",
|
||||||
|
"css/images/marker-icon-2x.png",
|
||||||
|
"css/images/marker-icon.png",
|
||||||
|
"css/images/marker-shadow.png",
|
||||||
|
]
|
||||||
|
}),
|
||||||
|
|
||||||
] // end: plugins
|
] // end: plugins
|
||||||
|
|
||||||
});
|
});
|
||||||
|
@ -117,8 +117,6 @@ redis:
|
|||||||
ui:
|
ui:
|
||||||
# Custom static path - leave it blank if you didn't change
|
# Custom static path - leave it blank if you didn't change
|
||||||
static_path: ""
|
static_path: ""
|
||||||
# Is overwritten by ${SEARXNG_STATIC_USE_HASH}.
|
|
||||||
static_use_hash: false
|
|
||||||
# Custom templates path - leave it blank if you didn't change
|
# Custom templates path - leave it blank if you didn't change
|
||||||
templates_path: ""
|
templates_path: ""
|
||||||
# query_in_title: When true, the result page's titles contains the query
|
# query_in_title: When true, the result page's titles contains the query
|
||||||
|
@ -190,7 +190,6 @@ SCHEMA = {
|
|||||||
},
|
},
|
||||||
'ui': {
|
'ui': {
|
||||||
'static_path': SettingsDirectoryValue(str, os.path.join(searx_dir, 'static')),
|
'static_path': SettingsDirectoryValue(str, os.path.join(searx_dir, 'static')),
|
||||||
'static_use_hash': SettingsValue(bool, False, 'SEARXNG_STATIC_USE_HASH'),
|
|
||||||
'templates_path': SettingsDirectoryValue(str, os.path.join(searx_dir, 'templates')),
|
'templates_path': SettingsDirectoryValue(str, os.path.join(searx_dir, 'templates')),
|
||||||
'default_theme': SettingsValue(str, 'simple'),
|
'default_theme': SettingsValue(str, 'simple'),
|
||||||
'default_locale': SettingsValue(str, ''),
|
'default_locale': SettingsValue(str, ''),
|
||||||
|
25
searx/static/themes/simple/assets.json
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
{
|
||||||
|
"css/images/layers-2x.png": "css/images/layers-2x.png",
|
||||||
|
"css/images/layers.png": "css/images/layers.png",
|
||||||
|
"css/images/marker-icon-2x.png": "css/images/marker-icon-2x.png",
|
||||||
|
"css/images/marker-icon.png": "css/images/marker-icon.png",
|
||||||
|
"css/images/marker-shadow.png": "css/images/marker-shadow.png",
|
||||||
|
"css/leaflet.css": "css/leaflet.a7837102.css",
|
||||||
|
"css/rss.min.css": "css/rss.min.fe304faa.css",
|
||||||
|
"css/searxng-rtl.min.css": "css/searxng-rtl.min.726accde.css",
|
||||||
|
"css/searxng.min.css": "css/searxng.min.21f0e928.css",
|
||||||
|
"img/empty_favicon.svg": "img/empty_favicon.73e4f03b.svg",
|
||||||
|
"img/favicon.png": "img/favicon.1bf18897.png",
|
||||||
|
"img/favicon.svg": "img/favicon.c852f912.svg",
|
||||||
|
"img/img_load_error.svg": "img/img_load_error.d0fe32fb.svg",
|
||||||
|
"img/searxng.png": "img/searxng.d79d0c2c.png",
|
||||||
|
"img/searxng.svg": "img/searxng.25892637.svg",
|
||||||
|
"img/select-dark.svg": "img/select-dark.b971594e.svg",
|
||||||
|
"img/select-light.svg": "img/select-light.5f366b16.svg",
|
||||||
|
"js/leaflet.js": "js/leaflet.db49d009.js",
|
||||||
|
"js/searxng.head.min.js": "js/searxng.head.min.27558b92.js",
|
||||||
|
"js/searxng.min.js": "js/searxng.min.c2c12312.js",
|
||||||
|
"js/leaflet.js.map": "js/leaflet.db49d009.js.map",
|
||||||
|
"js/searxng.head.min.js.map": "js/searxng.head.min.27558b92.js.map",
|
||||||
|
"js/searxng.min.js.map": "js/searxng.min.c2c12312.js.map"
|
||||||
|
}
|
Before Width: | Height: | Size: 966 B After Width: | Height: | Size: 966 B |
Before Width: | Height: | Size: 4.9 KiB After Width: | Height: | Size: 4.9 KiB |
Before Width: | Height: | Size: 726 B After Width: | Height: | Size: 726 B |
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 4.8 KiB After Width: | Height: | Size: 4.8 KiB |
Before Width: | Height: | Size: 8.5 KiB After Width: | Height: | Size: 8.5 KiB |
Before Width: | Height: | Size: 120 B After Width: | Height: | Size: 120 B |
Before Width: | Height: | Size: 108 B After Width: | Height: | Size: 108 B |
@ -1,2 +1,2 @@
|
|||||||
(function(n,t){var r=t.currentScript||function(){var s=t.getElementsByTagName("script");return s[s.length-1]}();n.searxng={settings:JSON.parse(atob(r.getAttribute("client_settings")))};var e=t.getElementsByTagName("html")[0];e.classList.remove("no-js"),e.classList.add("js")})(window,document);
|
(function(n,t){var r=t.currentScript||function(){var s=t.getElementsByTagName("script");return s[s.length-1]}();n.searxng={settings:JSON.parse(atob(r.getAttribute("client_settings")))};var e=t.getElementsByTagName("html")[0];e.classList.remove("no-js"),e.classList.add("js")})(window,document);
|
||||||
//# sourceMappingURL=searxng.head.min.js.map
|
//# sourceMappingURL=searxng.head.min.27558b92.js.map
|
7
searx/static/themes/simple/js/searxng.min.c2c12312.js
Normal file
7
searx/static/themes/simple/js/searxng.min.js
vendored
@ -16,6 +16,7 @@ import base64
|
|||||||
from timeit import default_timer
|
from timeit import default_timer
|
||||||
from html import escape
|
from html import escape
|
||||||
from io import StringIO
|
from io import StringIO
|
||||||
|
from pathlib import Path
|
||||||
import typing
|
import typing
|
||||||
|
|
||||||
import urllib
|
import urllib
|
||||||
@ -63,7 +64,7 @@ from searx.botdetection import link_token
|
|||||||
from searx.data import ENGINE_DESCRIPTIONS
|
from searx.data import ENGINE_DESCRIPTIONS
|
||||||
from searx.result_types import Answer
|
from searx.result_types import Answer
|
||||||
from searx.settings_defaults import OUTPUT_FORMATS
|
from searx.settings_defaults import OUTPUT_FORMATS
|
||||||
from searx.settings_loader import DEFAULT_SETTINGS_FILE
|
from searx.settings_loader import DEFAULT_SETTINGS_FILE, searx_dir
|
||||||
from searx.exceptions import SearxParameterException
|
from searx.exceptions import SearxParameterException
|
||||||
from searx.engines import (
|
from searx.engines import (
|
||||||
DEFAULT_CATEGORY,
|
DEFAULT_CATEGORY,
|
||||||
@ -244,24 +245,21 @@ def get_result_template(theme_name: str, template_name: str):
|
|||||||
|
|
||||||
|
|
||||||
def custom_url_for(endpoint: str, **values):
|
def custom_url_for(endpoint: str, **values):
|
||||||
suffix = ""
|
|
||||||
if endpoint == 'static' and values.get('filename'):
|
if endpoint == 'static' and values.get('filename'):
|
||||||
file_hash = static_files.get(values['filename'])
|
actual_filename = static_files.get(values['filename'])
|
||||||
if not file_hash:
|
if not actual_filename:
|
||||||
# try file in the current theme
|
# try file in the current theme
|
||||||
theme_name = sxng_request.preferences.get_value('theme')
|
theme_name = sxng_request.preferences.get_value('theme')
|
||||||
filename_with_theme = "themes/{}/{}".format(theme_name, values['filename'])
|
logical_filename = "themes/{}/{}".format(theme_name, values['filename'])
|
||||||
file_hash = static_files.get(filename_with_theme)
|
actual_filename = static_files.get(logical_filename)
|
||||||
if file_hash:
|
if actual_filename:
|
||||||
values['filename'] = filename_with_theme
|
values['filename'] = actual_filename
|
||||||
if get_setting('ui.static_use_hash') and file_hash:
|
|
||||||
suffix = "?" + file_hash
|
|
||||||
if endpoint == 'info' and 'locale' not in values:
|
if endpoint == 'info' and 'locale' not in values:
|
||||||
locale = sxng_request.preferences.get_value('locale')
|
locale = sxng_request.preferences.get_value('locale')
|
||||||
if infopage.INFO_PAGES.get_page(values['pagename'], locale) is None:
|
if infopage.INFO_PAGES.get_page(values['pagename'], locale) is None:
|
||||||
locale = infopage.INFO_PAGES.locale_default
|
locale = infopage.INFO_PAGES.locale_default
|
||||||
values['locale'] = locale
|
values['locale'] = locale
|
||||||
return url_for(endpoint, **values) + suffix
|
return url_for(endpoint, **values)
|
||||||
|
|
||||||
|
|
||||||
def morty_proxify(url: str):
|
def morty_proxify(url: str):
|
||||||
@ -1250,9 +1248,11 @@ def opensearch():
|
|||||||
@app.route('/favicon.ico')
|
@app.route('/favicon.ico')
|
||||||
def favicon():
|
def favicon():
|
||||||
theme = sxng_request.preferences.get_value("theme")
|
theme = sxng_request.preferences.get_value("theme")
|
||||||
|
logical_file_name = 'themes/' + theme + '/img/favicon.png'
|
||||||
|
actual_file_name = static_files.get(logical_file_name, logical_file_name)
|
||||||
return send_from_directory(
|
return send_from_directory(
|
||||||
os.path.join(app.root_path, settings['ui']['static_path'], 'themes', theme, 'img'), # type: ignore
|
os.path.join(app.root_path, settings['ui']['static_path']), # type: ignore
|
||||||
'favicon.png',
|
actual_file_name,
|
||||||
mimetype='image/vnd.microsoft.icon',
|
mimetype='image/vnd.microsoft.icon',
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -1365,7 +1365,10 @@ def run():
|
|||||||
port=settings['server']['port'],
|
port=settings['server']['port'],
|
||||||
host=settings['server']['bind_address'],
|
host=settings['server']['bind_address'],
|
||||||
threaded=True,
|
threaded=True,
|
||||||
extra_files=[DEFAULT_SETTINGS_FILE],
|
extra_files=[
|
||||||
|
DEFAULT_SETTINGS_FILE,
|
||||||
|
Path(searx_dir) / "static/themes/simple/assets.json",
|
||||||
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@ -178,30 +178,45 @@ def get_themes(templates_path):
|
|||||||
return os.listdir(templates_path)
|
return os.listdir(templates_path)
|
||||||
|
|
||||||
|
|
||||||
def get_hash_for_file(file: pathlib.Path) -> str:
|
def get_static_files_legacy(static_path: str, path: pathlib.Path):
|
||||||
m = hashlib.sha1()
|
result: list[str] = []
|
||||||
with file.open('rb') as f:
|
for file in path.iterdir():
|
||||||
m.update(f.read())
|
if file.name.startswith('.'):
|
||||||
return m.hexdigest()
|
# ignore hidden file
|
||||||
|
continue
|
||||||
|
if file.is_file():
|
||||||
|
result.append(str(file.relative_to(static_path)))
|
||||||
|
if file.is_dir() and file.name not in ('node_modules', 'src'):
|
||||||
|
# ignore "src" and "node_modules" directories
|
||||||
|
result.extend(get_static_files_legacy(static_path, file))
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
def get_static_files(static_path: str) -> Dict[str, str]:
|
def get_static_files(static_path: str) -> Dict[str, str]:
|
||||||
static_files: Dict[str, str] = {}
|
results = {}
|
||||||
static_path_path = pathlib.Path(static_path)
|
themes_dir = pathlib.Path(static_path) / "themes"
|
||||||
|
for theme_dir in themes_dir.iterdir():
|
||||||
|
if not theme_dir.is_dir():
|
||||||
|
continue
|
||||||
|
assets_file = theme_dir / "assets.json"
|
||||||
|
if assets_file.is_file():
|
||||||
|
# assets.json exist
|
||||||
|
with assets_file.open("r", encoding="utf-8") as f:
|
||||||
|
assets = json.load(f)
|
||||||
|
for rel_logical_filename, rel_actual_filename in assets.items():
|
||||||
|
logical_filename = f"themes/{theme_dir.name}/{rel_logical_filename}"
|
||||||
|
actual_filename = f"themes/{theme_dir.name}/{rel_actual_filename}"
|
||||||
|
results[logical_filename] = actual_filename
|
||||||
|
else:
|
||||||
|
# assets.json does not exist
|
||||||
|
results.update(
|
||||||
|
{
|
||||||
|
logical_filename: logical_filename
|
||||||
|
for logical_filename in get_static_files_legacy(static_path, theme_dir)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
def walk(path: pathlib.Path):
|
return results
|
||||||
for file in path.iterdir():
|
|
||||||
if file.name.startswith('.'):
|
|
||||||
# ignore hidden file
|
|
||||||
continue
|
|
||||||
if file.is_file():
|
|
||||||
static_files[str(file.relative_to(static_path_path))] = get_hash_for_file(file)
|
|
||||||
if file.is_dir() and file.name not in ('node_modules', 'src'):
|
|
||||||
# ignore "src" and "node_modules" directories
|
|
||||||
walk(file)
|
|
||||||
|
|
||||||
walk(static_path_path)
|
|
||||||
return static_files
|
|
||||||
|
|
||||||
|
|
||||||
def get_result_templates(templates_path):
|
def get_result_templates(templates_path):
|
||||||
|
@ -25,9 +25,6 @@ class ViewsTestCase(SearxTestCase): # pylint: disable=too-many-public-methods
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
self.setattr4test(searx.search.processors, 'initialize_processor', dummy)
|
self.setattr4test(searx.search.processors, 'initialize_processor', dummy)
|
||||||
# remove sha for the static file so the tests don't have to care about
|
|
||||||
# the changing URLs
|
|
||||||
self.setattr4test(searx.webapp, 'static_files', {})
|
|
||||||
|
|
||||||
# set some defaults
|
# set some defaults
|
||||||
test_results = [
|
test_results = [
|
||||||
|
@ -122,4 +122,5 @@ static.build.restore() {
|
|||||||
build_msg STATIC "git-restore of the built files (/static)"
|
build_msg STATIC "git-restore of the built files (/static)"
|
||||||
git restore --staged "${STATIC_BUILT_PATHS[@]}"
|
git restore --staged "${STATIC_BUILT_PATHS[@]}"
|
||||||
git restore --worktree "${STATIC_BUILT_PATHS[@]}"
|
git restore --worktree "${STATIC_BUILT_PATHS[@]}"
|
||||||
|
git clean --force -d "${STATIC_BUILT_PATHS[@]}"
|
||||||
}
|
}
|
||||||
|