Merge pull request #848 from not-my-profile/help-route

Introduce `/help` route
This commit is contained in:
Alexandre Flament 2022-02-05 08:52:19 +01:00 committed by GitHub
commit bf987bb608
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 90 additions and 32 deletions

View File

@ -1,4 +1,4 @@
# About [searxng][url_for:index] # About SearXNG
SearXNG is a fork from the well-known [searx] [metasearch engine], aggregating SearXNG is a fork from the well-known [searx] [metasearch engine], aggregating
the results of other [search engines][url_for:preferences] while not storing the results of other [search engines][url_for:preferences] while not storing

Binary file not shown.

View File

@ -221,6 +221,16 @@ div.selectable_url {
font-size: 90%; 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 { .tabs {
display: flex; display: flex;
flex-wrap: wrap; flex-wrap: wrap;
@ -235,7 +245,8 @@ div.selectable_url {
display: none; display: none;
} }
& > label { & > label,
& > li > a {
order: 1; order: 1;
padding: 0.7em; padding: 0.7em;
margin: 0 0.7em; margin: 0 0.7em;
@ -243,13 +254,21 @@ div.selectable_url {
text-transform: uppercase; text-transform: uppercase;
border: solid var(--color-toolkit-tabs-label-border); border: solid var(--color-toolkit-tabs-label-border);
border-width: 0 0 2px 0; border-width: 0 0 2px 0;
color: unset;
.disable-user-select(); .disable-user-select();
cursor: pointer; 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 { & > label:hover,
& > li > a:hover {
border-bottom: 2px solid var(--color-categories-item-border-selected); border-bottom: 2px solid var(--color-categories-item-border-selected);
} }

View File

@ -1,6 +0,0 @@
{% extends "oscar/base.html" %}
{% block title %}{{ _('about') }} - {% endblock %}
{% block content %}
{{ help.about | safe }}
{% include "__common__/aboutextend.html" ignore missing %}
{% endblock %}

View File

@ -0,0 +1,12 @@
{% extends "oscar/base.html" %}
{% block title %}{{ page.title }} - {% endblock %}
{% block content %}
<ul class="nav nav-tabs">
{% for name, page in all_pages %}
<li {% if name == page_filename %}class="active"{% endif %}>
<a href="{{name}}">{{page.title}}</a>
</li>
{% endfor %}
</ul>
{{ page.content | safe }}
{% endblock %}

View File

@ -3,7 +3,7 @@
<a href="{{ url_for('index') }}">{{ instance_name }}</a>{{- "" -}} <a href="{{ url_for('index') }}">{{ instance_name }}</a>{{- "" -}}
</span>{{- "" -}} </span>{{- "" -}}
<span class="{% if rtl %}pull-left{% else %}pull-right{% endif %}">{{- "" -}} <span class="{% if rtl %}pull-left{% else %}pull-right{% endif %}">{{- "" -}}
<a href="{{ url_for('about') }}">{{ _('about') }}</a>{{- "" -}} <a href="{{ url_for('help_page', pagename='about') }}">{{ _('about') }}</a>{{- "" -}}
<a href="{{ url_for('preferences') }}">{{ _('preferences') }}</a>{{- "" -}} <a href="{{ url_for('preferences') }}">{{ _('preferences') }}</a>{{- "" -}}
</span>{{- "" -}} </span>{{- "" -}}
</div> </div>

View File

@ -1,5 +0,0 @@
{% extends 'simple/page_with_header.html' %}
{% block content %}
{{ help.about | safe }}
{% include "__common__/aboutextend.html" ignore missing %}
{% endblock %}

View File

@ -58,7 +58,7 @@
</main> </main>
<footer> <footer>
<p> <p>
{{ _('Powered by') }} <a href="{{ url_for('about') }}">searxng</a> - {{ searx_version }} — {{ _('a privacy-respecting, hackable metasearch engine') }}<br/> {{ _('Powered by') }} <a href="{{ url_for('help_page', pagename='about') }}">searxng</a> - {{ searx_version }} — {{ _('a privacy-respecting, hackable metasearch engine') }}<br/>
<a href="{{ searx_git_url }}">{{ _('Source code') }}</a> | <a href="{{ searx_git_url }}">{{ _('Source code') }}</a> |
<a href="{{ get_setting('brand.issue_url') }}">{{ _('Issue tracker') }}</a> | <a href="{{ get_setting('brand.issue_url') }}">{{ _('Issue tracker') }}</a> |
<a href="{{ url_for('stats') }}">{{ _('Engine stats') }}</a> | <a href="{{ url_for('stats') }}">{{ _('Engine stats') }}</a> |

View File

@ -0,0 +1,12 @@
{% extends 'simple/page_with_header.html' %}
{% block title %}{{ page.title }} - {% endblock %}
{% block content %}
<ul class="tabs">
{% for name, page in all_pages %}
<li>
<a href="{{name}}" {% if name == page_filename %}class="active"{% endif %}>{{page.title}}</a>
</li>
{% endfor %}
</ul>
{{ page.content | safe }}
{% endblock %}

View File

@ -1,5 +1,5 @@
from typing import Dict # pyright: basic
import os.path from typing import Dict, NamedTuple
import pkg_resources import pkg_resources
import flask import flask
@ -9,8 +9,17 @@ import mistletoe
from . import get_setting from . import get_setting
from .version import GIT_URL from .version import GIT_URL
HELP: Dict[str, str] = {}
""" Maps a filename under help/ without the file extension to the rendered HTML. """ class HelpPage(NamedTuple):
title: str
content: str
# Whenever a new .md file is added to help/ it needs to be added here
_TOC = ('about',)
PAGES: Dict[str, HelpPage] = {}
""" Maps a filename under help/ without the file extension to the rendered page. """
def render(app: flask.Flask): def render(app: flask.Flask):
@ -37,12 +46,16 @@ def render(app: flask.Flask):
define_link_targets = ''.join(f'[{name}]: {url}\n' for name, url in link_targets.items()) define_link_targets = ''.join(f'[{name}]: {url}\n' for name, url in link_targets.items())
for filename in pkg_resources.resource_listdir(__name__, 'help'): for pagename in _TOC:
rootname, ext = os.path.splitext(filename) file_content = pkg_resources.resource_string(__name__, 'help/' + pagename + '.md').decode()
markdown = define_link_targets + file_content
assert file_content.startswith('# ')
title = file_content.split('\n', maxsplit=1)[0].strip('# ')
content: str = mistletoe.markdown(markdown)
if ext != '.md': if pagename == 'about':
continue try:
content += pkg_resources.resource_string(__name__, 'templates/__common__/aboutextend.html').decode()
markdown = pkg_resources.resource_string(__name__, 'help/' + filename).decode() except FileNotFoundError:
markdown = define_link_targets + markdown pass
HELP[rootname] = mistletoe.markdown(markdown) PAGES[pagename] = HelpPage(title=title, content=content)

View File

@ -877,8 +877,21 @@ def __get_translated_errors(unresponsive_engines: Iterable[UnresponsiveEngine]):
@app.route('/about', methods=['GET']) @app.route('/about', methods=['GET'])
def about(): def about():
"""Render about page""" """Redirect to about page"""
return render('about.html', help=user_help.HELP) return redirect(url_for('help_page', pagename='about'))
@app.route('/help/en/<pagename>', methods=['GET'])
def help_page(pagename):
"""Render help page"""
page = user_help.PAGES.get(pagename)
if page is None:
flask.abort(404)
return render(
'help.html', page=user_help.PAGES[pagename], all_pages=user_help.PAGES.items(), page_filename=pagename
)
@app.route('/autocompleter', methods=['GET', 'POST']) @app.route('/autocompleter', methods=['GET', 'POST'])

View File

@ -174,9 +174,9 @@ class ViewsTestCase(SearxTestCase):
self.assertIn(b'<description>first test content</description>', result.data) self.assertIn(b'<description>first test content</description>', result.data)
def test_about(self): def test_about(self):
result = self.app.get('/about') result = self.app.get('/help/en/about')
self.assertEqual(result.status_code, 200) self.assertEqual(result.status_code, 200)
self.assertIn(b'<h1>About <a href="/">searxng</a></h1>', result.data) self.assertIn(b'<h1>About SearXNG</h1>', result.data)
def test_health(self): def test_health(self):
result = self.app.get('/healthz') result = self.app.get('/healthz')