This commit is contained in:
shreven0 2025-01-10 09:39:17 +00:00 committed by GitHub
commit db23c96a69
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
19 changed files with 96 additions and 16 deletions

View file

@ -29,6 +29,12 @@ brand:
# links:
# Uptime: https://uptime.searxng.org/history/darmarit-org
# About: "https://searxng.org"
# custom_files:
# # If using custom logo, be sure to set the right file extension as it's used to determine the mimetype.
# logo: /path/to/file.png
# # For custom favicons, you must include a PNG version, as some browsers still don't support SVG favicons.
# favicon_png: /path/to/file.png
# favicon_svg: /path/to/file.svg
search:
# Filter results. 0: None, 1: Moderate, 2: Strict

View file

@ -152,6 +152,7 @@ SCHEMA = {
'public_instances': SettingsValue((False, str), 'https://searx.space'),
'wiki_url': SettingsValue(str, 'https://github.com/searxng/searxng/wiki'),
'custom': SettingsValue(dict, {'links': {}}),
'custom_files': SettingsValue(dict, {}),
},
'search': {
'safe_search': SettingsValue((0, 1, 2), 0),

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -151,7 +151,6 @@ module.exports = function (grunt) {
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'
}

View file

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

View file

@ -27,9 +27,11 @@
{% 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">
<link rel="apple-touch-icon" href="{{ url_for('static', filename='img/favicon.png') }}">
<link rel="icon" href="{{ url_for('custom', custom_file='favicon_png', filename='img/favicon.png') }}" sizes="any">
<link rel="apple-touch-icon" href="{{ url_for('custom', custom_file='favicon_png', filename='img/favicon.png') }}">
{% if not get_setting('brand.custom_files.favicon_png', false) or get_setting('brand.custom_files.favicon_svg', false) %}
<link rel="icon" href="{{ url_for('custom', custom_file='favicon_svg', filename='img/favicon.svg') }}" type="image/svg+xml">
{% endif %}
</head>
<body class="{{ endpoint }}_endpoint" >
<main id="main_{{ self._TemplateReference__context.name|replace("simple/", "")|replace(".html", "") }}" class="{{body_class}}">

View file

@ -2,7 +2,7 @@
{% from 'simple/icons.html' import icon_big %}
{% block content %}
<div class="index">
<div class="title"><h1>SearXNG</h1></div>
<div class="title{% if get_setting('brand.custom_files.logo', false) %} custom_logo{% endif %}"><h1>SearXNG</h1></div>
{% include 'simple/simple_search.html' %}
</div>
{% endblock %}

View file

@ -4,7 +4,7 @@
<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>
<Image type="image/png">{{ url_for('custom', custom_file='favicon_png', 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 %}

View file

@ -2,6 +2,6 @@
{%- extends "simple/base.html" -%}
{%- block header -%}
<a href="{{ url_for('index') }}">{{- '' -}}
<img class="logo" src="{{ url_for('static', filename='img/searxng.png') }}" alt="SearXNG">{{- '' -}}
<img class="logo" src="{{ url_for('custom', custom_file='logo', filename='img/searxng.png') }}" alt="SearXNG">{{- '' -}}
</a>{{- '' -}}
{%- endblock -%}

View file

@ -2,7 +2,12 @@
<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 %}
<img width="23px" height="23px" src="
{%- if not get_setting('brand.custom_files.favicon_svg', false) -%}
{{ url_for('custom', custom_file='favicon_png', filename='img/favicon.svg') }}
{%- else -%} {{ url_for('custom', custom_file='favicon_svg', filename='img/favicon.svg') }}
{%- endif -%}
"></img>
</a>
<div id="search_view">
<div class="search_box">

View file

@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="92mm" height="92mm" viewBox="0 0 92 92"><g transform="translate(-40.921 -17.417)"><circle cx="75.921" cy="53.903" r="30" fill="none" fill-opacity="1" stroke="#3050ff" stroke-width="10" stroke-miterlimit="4" stroke-dasharray="none" stroke-opacity="1"/><path d="M67.515 37.915a18 18 0 0 1 21.051 3.313 18 18 0 0 1 3.138 21.078" fill="none" fill-opacity="1" stroke="#3050ff" stroke-width="5" stroke-miterlimit="4" stroke-dasharray="none" stroke-opacity="1"/><rect width="18.846" height="39.963" x="3.706" y="122.09" ry="0" transform="rotate(-46.235)" opacity="1" fill="#3050ff" fill-opacity="1" stroke="none" stroke-width="8" stroke-miterlimit="4" stroke-dasharray="none" stroke-opacity="1"/></g></svg>

Before

Width:  |  Height:  |  Size: 746 B

View file

@ -37,6 +37,7 @@ from flask import (
make_response,
redirect,
send_from_directory,
send_file,
)
from flask.wrappers import Response
from flask.json import jsonify
@ -74,6 +75,7 @@ from searx import webutils
from searx.webutils import (
highlight_content,
get_static_files,
get_custom_files,
get_result_templates,
get_themes,
exception_classname_to_text,
@ -132,6 +134,7 @@ if not searx_debug and settings['server']['secret_key'] == 'ultrasecretkey':
# about static
logger.debug('static directory is %s', settings['ui']['static_path'])
static_files = get_static_files(settings['ui']['static_path'])
custom_files = get_custom_files()
# about templates
logger.debug('templates directory is %s', settings['ui']['templates_path'])
@ -256,6 +259,15 @@ def get_result_template(theme_name: str, template_name: str):
def custom_url_for(endpoint: str, **values):
suffix = ""
if endpoint == 'custom' and values.get('custom_file'):
if values['custom_file'] in custom_files:
values.pop('filename')
if get_setting('ui.static_use_hash'):
suffix = "?" + custom_files[values['custom_file']]['hash']
else:
# if there's no custom file defined in settings.yml, then use the default file
values.pop('custom_file')
endpoint = 'static'
if endpoint == 'static' and values.get('filename'):
file_hash = static_files.get(values['filename'])
if not file_hash:
@ -1275,8 +1287,25 @@ def opensearch():
return resp
@app.route('/custom/<path:custom_file>')
def custom(custom_file):
if custom_file in custom_files:
filepath = custom_files[custom_file]['path']
if os.path.isfile(filepath):
if 'mimetype' in custom_files[custom_file]:
return send_file(filepath, mimetype=custom_files[custom_file]['mimetype'])
return send_file(filepath)
logger.warning('%s does not exist or is not a file', filepath)
return flask.abort(404)
@app.route('/favicon.ico')
def favicon():
if 'favicon_png' in custom_files:
filepath = custom_files['favicon_png']['path']
if os.path.isfile(filepath):
return send_file(filepath, mimetype='image/png')
logger.warning('%s does not exist or is not a file', filepath)
theme = request.preferences.get_value("theme")
return send_from_directory(
os.path.join(app.root_path, settings['ui']['static_path'], 'themes', theme, 'img'), # pyright: ignore

View file

@ -204,6 +204,28 @@ def get_static_files(static_path: str) -> Dict[str, str]:
return static_files
def get_custom_files() -> Dict[str, dict]:
custom_files: Dict[str, dict] = {}
for option in settings['brand']['custom_files']:
filepath = settings['brand']['custom_files'][option]
if os.path.isfile(filepath):
custom_files.setdefault(option, {})
custom_files[option]['path'] = filepath
custom_files[option]['hash'] = get_hash_for_file(pathlib.Path(filepath))
if option == 'favicon_png':
custom_files[option]['mimetype'] = 'image/png'
if option == 'favicon_svg':
custom_files[option]['mimetype'] = 'image/svg+xml'
else:
logger.warning('%s does not exist or is not a file', filepath)
if 'favicon_svg' in custom_files and 'favicon_png' not in custom_files:
logger.warning('Some browsers only support PNG favicons, but you have only set an SVG favicon')
return custom_files
def get_result_templates(templates_path):
result_templates = set()
templates_path_length = len(templates_path) + 1