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

@ -173,4 +173,5 @@ features or generally made searx better:
- Austin Olacsi `<https://github.com/Austin-Olacsi>` - Austin Olacsi `<https://github.com/Austin-Olacsi>`
- @micsthepick - @micsthepick
- Daniel Kukula `<https://github.com/dkuku>` - Daniel Kukula `<https://github.com/dkuku>`
- Patrick Evans `https://github.com/holysoles` - Patrick Evans `https://github.com/holysoles`
- shreven `<https://shreven.org>`_ B8B56F6FC0EADCA5B6177BC5F599020F48EE6F97

View file

@ -11,6 +11,10 @@
docs_url: https://docs.searxng.org docs_url: https://docs.searxng.org
public_instances: https://searx.space public_instances: https://searx.space
wiki_url: https://github.com/searxng/searxng/wiki wiki_url: https://github.com/searxng/searxng/wiki
custom_files:
logo: /path/to/file.png
favicon_png: /path/to/file.png
favicon_svg: /path/to/file.svg
``issue_url`` : ``issue_url`` :
If you host your own issue tracker change this URL. If you host your own issue tracker change this URL.
@ -23,3 +27,12 @@
``wiki_url`` : ``wiki_url`` :
Link to your wiki (or ``false``) Link to your wiki (or ``false``)
``custom_files.logo`` :
Filepath to a custom logo. Be sure it has the right file extension, as that's used to determine the mimetype.
``custom_files.favicon_png`` :
Filepath to a custom PNG favicon.
``custom_files.favicon_svg`` :
Filepath to a custom SVG favicon. When using, be sure to also set ``custom_files.favicon_png``, as some browsers still don't support SVG favicons.

View file

@ -29,6 +29,12 @@ brand:
# links: # links:
# Uptime: https://uptime.searxng.org/history/darmarit-org # Uptime: https://uptime.searxng.org/history/darmarit-org
# About: "https://searxng.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: search:
# Filter results. 0: None, 1: Moderate, 2: Strict # Filter results. 0: None, 1: Moderate, 2: Strict

View file

@ -152,6 +152,7 @@ SCHEMA = {
'public_instances': SettingsValue((False, str), 'https://searx.space'), 'public_instances': SettingsValue((False, str), 'https://searx.space'),
'wiki_url': SettingsValue(str, 'https://github.com/searxng/searxng/wiki'), 'wiki_url': SettingsValue(str, 'https://github.com/searxng/searxng/wiki'),
'custom': SettingsValue(dict, {'links': {}}), 'custom': SettingsValue(dict, {'links': {}}),
'custom_files': SettingsValue(dict, {}),
}, },
'search': { 'search': {
'safe_search': SettingsValue((0, 1, 2), 0), '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'] svgo: ['--config', 'svg4web.svgo.js']
}, },
files: { files: {
'<%= _templates %>/simple/searxng-wordmark.min.svg': '<%= _brand %>/searxng-wordmark.svg',
'img/searxng.svg': '<%= _brand %>/searxng.svg', 'img/searxng.svg': '<%= _brand %>/searxng.svg',
'img/img_load_error.svg': '<%= _brand %>/img_load_error.svg' 'img/img_load_error.svg': '<%= _brand %>/img_load_error.svg'
} }

View file

@ -6,7 +6,11 @@
text-align: center; text-align: center;
.title { .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; min-height: 4rem;
margin: 4rem auto; margin: 4rem auto;
background-position: center; background-position: center;

View file

@ -27,9 +27,11 @@
{% block head %} {% block head %}
<link title="{{ instance_name }}" type="application/opensearchdescription+xml" rel="search" href="{{ opensearch_url }}"> <link title="{{ instance_name }}" type="application/opensearchdescription+xml" rel="search" href="{{ opensearch_url }}">
{% endblock %} {% endblock %}
<link rel="icon" href="{{ url_for('static', filename='img/favicon.png') }}" sizes="any"> <link rel="icon" href="{{ url_for('custom', custom_file='favicon_png', 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('custom', custom_file='favicon_png', filename='img/favicon.png') }}">
<link rel="apple-touch-icon" href="{{ url_for('static', 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> </head>
<body class="{{ endpoint }}_endpoint" > <body class="{{ endpoint }}_endpoint" >
<main id="main_{{ self._TemplateReference__context.name|replace("simple/", "")|replace(".html", "") }}" class="{{body_class}}"> <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 %} {% from 'simple/icons.html' import icon_big %}
{% block content %} {% block content %}
<div class="index"> <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' %} {% include 'simple/simple_search.html' %}
</div> </div>
{% endblock %} {% endblock %}

View file

@ -4,7 +4,7 @@
<LongName>SearXNG metasearch</LongName> <LongName>SearXNG metasearch</LongName>
<Description>SearXNG is a metasearch engine that respects your privacy.</Description> <Description>SearXNG is a metasearch engine that respects your privacy.</Description>
<InputEncoding>UTF-8</InputEncoding> <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' %} {% if opensearch_method == 'GET' %}
<Url rel="results" type="text/html" method="{{ opensearch_method }}" template="{{ url_for('search', _external=True) }}?q={searchTerms}"/> <Url rel="results" type="text/html" method="{{ opensearch_method }}" template="{{ url_for('search', _external=True) }}?q={searchTerms}"/>
{% else %} {% else %}

View file

@ -2,6 +2,6 @@
{%- extends "simple/base.html" -%} {%- extends "simple/base.html" -%}
{%- block header -%} {%- block header -%}
<a href="{{ url_for('index') }}">{{- '' -}} <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>{{- '' -}} </a>{{- '' -}}
{%- endblock -%} {%- endblock -%}

View file

@ -2,7 +2,12 @@
<div id="search_header"> <div id="search_header">
<a id="search_logo" href="{{ url_for('index') }}" tabindex="0" title="{{ _('Display the front page') }}"> <a id="search_logo" href="{{ url_for('index') }}" tabindex="0" title="{{ _('Display the front page') }}">
<span hidden>SearXNG</span> <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> </a>
<div id="search_view"> <div id="search_view">
<div class="search_box"> <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, make_response,
redirect, redirect,
send_from_directory, send_from_directory,
send_file,
) )
from flask.wrappers import Response from flask.wrappers import Response
from flask.json import jsonify from flask.json import jsonify
@ -74,6 +75,7 @@ from searx import webutils
from searx.webutils import ( from searx.webutils import (
highlight_content, highlight_content,
get_static_files, get_static_files,
get_custom_files,
get_result_templates, get_result_templates,
get_themes, get_themes,
exception_classname_to_text, exception_classname_to_text,
@ -132,6 +134,7 @@ if not searx_debug and settings['server']['secret_key'] == 'ultrasecretkey':
# about static # about static
logger.debug('static directory is %s', settings['ui']['static_path']) logger.debug('static directory is %s', settings['ui']['static_path'])
static_files = get_static_files(settings['ui']['static_path']) static_files = get_static_files(settings['ui']['static_path'])
custom_files = get_custom_files()
# about templates # about templates
logger.debug('templates directory is %s', settings['ui']['templates_path']) 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): def custom_url_for(endpoint: str, **values):
suffix = "" 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'): if endpoint == 'static' and values.get('filename'):
file_hash = static_files.get(values['filename']) file_hash = static_files.get(values['filename'])
if not file_hash: if not file_hash:
@ -1275,8 +1287,25 @@ def opensearch():
return resp 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') @app.route('/favicon.ico')
def favicon(): 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") theme = request.preferences.get_value("theme")
return send_from_directory( return send_from_directory(
os.path.join(app.root_path, settings['ui']['static_path'], 'themes', theme, 'img'), # pyright: ignore 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 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): def get_result_templates(templates_path):
result_templates = set() result_templates = set()
templates_path_length = len(templates_path) + 1 templates_path_length = len(templates_path) + 1

View file

@ -8,7 +8,6 @@ STATIC_BUILT_PATHS=(
'searx/static/themes/simple/js' 'searx/static/themes/simple/js'
'searx/static/themes/simple/src/generated/pygments.less' 'searx/static/themes/simple/src/generated/pygments.less'
'searx/static/themes/simple/img' 'searx/static/themes/simple/img'
'searx/templates/simple/searxng-wordmark.min.svg'
'searx/templates/simple/icons.html' 'searx/templates/simple/icons.html'
) )