diff options
-rw-r--r-- | searx/infopage/__init__.py | 92 | ||||
-rw-r--r-- | searx/infopage/en/about.md (renamed from searx/info/en/about.md) | 0 | ||||
-rw-r--r-- | searx/infopage/en/search-syntax.md (renamed from searx/info/en/search-syntax.md) | 0 | ||||
-rw-r--r-- | searx/templates/oscar/info.html | 6 | ||||
-rw-r--r-- | searx/templates/oscar/navbar.html | 2 | ||||
-rw-r--r-- | searx/templates/simple/base.html | 2 | ||||
-rw-r--r-- | searx/templates/simple/info.html | 4 | ||||
-rwxr-xr-x | searx/webapp.py | 22 | ||||
-rwxr-xr-x | searxng_extra/docs_prebuild | 39 |
9 files changed, 82 insertions, 85 deletions
diff --git a/searx/infopage/__init__.py b/searx/infopage/__init__.py index 5c58193c1..9b181ad60 100644 --- a/searx/infopage/__init__.py +++ b/searx/infopage/__init__.py @@ -19,8 +19,9 @@ Usage in a Flask app route: """ -__all__ = ['InfoPage', 'MistletoePage', 'InfoPageSet'] +__all__ = ['InfoPage', 'InfoPageSet'] +import os import os.path import logging import typing @@ -33,16 +34,18 @@ import mistletoe from .. import get_setting from ..compat import cached_property from ..version import GIT_URL +from ..locales import LOCALE_NAMES -logger = logging.getLogger('doc') + +logger = logging.getLogger('searx.infopage') +_INFO_FOLDER = os.path.abspath(os.path.dirname(__file__)) class InfoPage: """A page of the :py:obj:`online documentation <InfoPageSet>`.""" - def __init__(self, fname, base_url=None): + def __init__(self, fname): self.fname = fname - self.base_url = base_url @cached_property def raw_content(self): @@ -66,19 +69,25 @@ class InfoPage: t = l.strip('# ') return t + @cached_property + def html(self): + """Render Markdown (CommonMark_) to HTML by using mistletoe_. + + .. _CommonMark: https://commonmark.org/ + .. _mistletoe: https://github.com/miyuchina/mistletoe + + """ + return mistletoe.markdown(self.content) + def get_ctx(self): # pylint: disable=no-self-use """Jinja context to render :py:obj:`InfoPage.content`""" def _md_link(name, url): - url = url_for(url) - if self.base_url: - url = self.base_url + url + url = url_for(url, _external=True) return "[%s](%s)" % (name, url) def _md_search(query): - url = '%s?q=%s' % (url_for('search'), urllib.parse.quote(query)) - if self.base_url: - url = self.base_url + url + url = '%s?q=%s' % (url_for('search', _external=True), urllib.parse.quote(query)) return '[%s](%s)' % (query, url) ctx = {} @@ -89,33 +98,8 @@ class InfoPage: return ctx - def render(self): - """Render / return content""" - return self.content - - -class MistletoePage(InfoPage): - """A HTML page of the :py:obj:`online documentation <InfoPageSet>`.""" - - def __init__(self, *args, **kwargs): - super().__init__(*args, **kwargs) - - @cached_property - def html(self): - """HTML representation of this page""" - return self.render() - - def render(self): - """Render Markdown (CommonMark_) to HTML by using mistletoe_. - - .. _CommonMark: https://commonmark.org/ - .. _mistletoe: https://github.com/miyuchina/mistletoe - - """ - return mistletoe.markdown(self.content) - - -_INFO_FOLDER = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', 'info')) + def __repr__(self): + return f'<{self.__class__.__name__} fname={self.fname!r}>' class InfoPageSet: # pylint: disable=too-few-public-methods @@ -123,24 +107,26 @@ class InfoPageSet: # pylint: disable=too-few-public-methods :param page_class: render online documentation by :py:obj:`InfoPage` parser. :type page_class: :py:obj:`InfoPage` + + :param info_folder: information directory + :type info_folder: str """ - def __init__(self, page_class: typing.Type[InfoPage], base_url=None): - self.page_class = page_class - self.base_url = base_url - self.CACHE: typing.Dict[tuple, InfoPage] = {} + def __init__( + self, page_class: typing.Optional[typing.Type[InfoPage]] = None, info_folder: typing.Optional[str] = None + ): + self.page_class = page_class or InfoPage + self.CACHE: typing.Dict[tuple, typing.Optional[InfoPage]] = {} # future: could be set from settings.xml - self.folder: str = _INFO_FOLDER + self.folder: str = info_folder or _INFO_FOLDER """location of the Markdwon files""" - self.i18n_origin: str = 'en' + self.locale_default: str = 'en' """default language""" - self.l10n: typing.List = [ - 'en', - ] + self.locales: typing.List = [locale for locale in os.listdir(_INFO_FOLDER) if locale in LOCALE_NAMES] """list of supported languages (aka locales)""" self.toc: typing.List = [ @@ -160,12 +146,13 @@ class InfoPageSet: # pylint: disable=too-few-public-methods :type locale: str """ + locale = locale or self.locale_default + if pagename not in self.toc: return None - if locale is not None and locale not in self.l10n: + if locale not in self.locales: return None - locale = locale or self.i18n_origin cache_key = (pagename, locale) page = self.CACHE.get(cache_key) @@ -176,16 +163,17 @@ class InfoPageSet: # pylint: disable=too-few-public-methods fname = os.path.join(self.folder, locale, pagename) + '.md' if not os.path.exists(fname): - logger.error('file %s does not exists', fname) + logger.info('file %s does not exists', fname) + self.CACHE[cache_key] = None return None - page = self.page_class(fname, self.base_url) + page = self.page_class(fname) self.CACHE[cache_key] = page return page def all_pages(self, locale: typing.Optional[str] = None): - """Iterate over all pages""" - locale = locale or self.i18n_origin + """Iterate over all pages of the TOC""" + locale = locale or self.locale_default for pagename in self.toc: page = self.get_page(pagename, locale) yield pagename, page diff --git a/searx/info/en/about.md b/searx/infopage/en/about.md index 9f323870e..9f323870e 100644 --- a/searx/info/en/about.md +++ b/searx/infopage/en/about.md diff --git a/searx/info/en/search-syntax.md b/searx/infopage/en/search-syntax.md index ae820dfbc..ae820dfbc 100644 --- a/searx/info/en/search-syntax.md +++ b/searx/infopage/en/search-syntax.md diff --git a/searx/templates/oscar/info.html b/searx/templates/oscar/info.html index 3a696da50..0c2044adb 100644 --- a/searx/templates/oscar/info.html +++ b/searx/templates/oscar/info.html @@ -2,9 +2,9 @@ {% block title %}{{ active_page.title }} - {% endblock %} {% block content %} <ul class="nav nav-tabs"> -{% for pagename, page in all_pages('en') %} - <li {% if pagename == active_pagename %}class="active"{% endif %}> - <a href="{{pagename}}">{{page.title}}</a> + {% for pagename, page, locale 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> diff --git a/searx/templates/oscar/navbar.html b/searx/templates/oscar/navbar.html index 4c0ec0068..f5401c382 100644 --- a/searx/templates/oscar/navbar.html +++ b/searx/templates/oscar/navbar.html @@ -3,7 +3,7 @@ <a href="{{ url_for('index') }}">{{ instance_name }}</a>{{- "" -}} </span>{{- "" -}} <span class="{% if rtl %}pull-left{% else %}pull-right{% endif %}">{{- "" -}} - <a href="{{ url_for('info', pagename='about', locale=current_locale) }}">{{ _('about') }}</a>{{- "" -}} + <a href="{{ url_for('info', pagename='about') }}">{{ _('about') }}</a>{{- "" -}} <a href="{{ url_for('preferences') }}">{{ _('preferences') }}</a>{{- "" -}} </span>{{- "" -}} </div> diff --git a/searx/templates/simple/base.html b/searx/templates/simple/base.html index 135a95669..a82c26a61 100644 --- a/searx/templates/simple/base.html +++ b/searx/templates/simple/base.html @@ -58,7 +58,7 @@ </main> <footer> <p> - {{ _('Powered by') }} <a href="{{ url_for('info', pagename='about', locale=current_locale) }}">searxng</a> - {{ searx_version }} — {{ _('a privacy-respecting, hackable metasearch engine') }}<br/> + {{ _('Powered by') }} <a href="{{ url_for('info', pagename='about') }}">searxng</a> - {{ searx_version }} — {{ _('a privacy-respecting, hackable metasearch engine') }}<br/> <a href="{{ searx_git_url }}">{{ _('Source code') }}</a> | <a href="{{ get_setting('brand.issue_url') }}">{{ _('Issue tracker') }}</a> | <a href="{{ url_for('stats') }}">{{ _('Engine stats') }}</a> | diff --git a/searx/templates/simple/info.html b/searx/templates/simple/info.html index ef6b343ad..5030cd490 100644 --- a/searx/templates/simple/info.html +++ b/searx/templates/simple/info.html @@ -2,9 +2,9 @@ {% block title %}{{ active_page.title }} - {% endblock %} {% block content %} <ul class="tabs"> -{% for pagename, page in all_pages('en') %} +{% for pagename, page, locale in all_pages %} <li> - <a href="{{pagename}}" {% if pagename == active_pagename %}class="active"{% endif %}>{{page.title}}</a> + <a href="{{ url_for('info', pagename=pagename, locale=locale) }}" {% if pagename == active_pagename %}class="active"{% endif %}>{{page.title}}</a> </li> {% endfor %} </ul> diff --git a/searx/webapp.py b/searx/webapp.py index 5263aaf1b..5d3e7ebfd 100755 --- a/searx/webapp.py +++ b/searx/webapp.py @@ -383,6 +383,11 @@ def url_for_theme(endpoint: str, override_theme: Optional[str] = None, **values) if file_hash: values['filename'] = filename_with_theme suffix = "?" + file_hash + if endpoint == 'info' and 'locale' not in values: + locale = request.preferences.get_value('locale') + if _INFO_PAGES.get_page(values['pagename'], locale) is None: + locale = _INFO_PAGES.locale_default + values['locale'] = locale return url_for(endpoint, **values) + suffix @@ -905,23 +910,30 @@ def about(): return redirect(url_for('info', pagename='about', locale=locale)) -_INFO_PAGES = infopage.InfoPageSet(infopage.MistletoePage) +_INFO_PAGES = infopage.InfoPageSet() @app.route('/info/<locale>/<pagename>', methods=['GET']) def info(pagename, locale): """Render page of online user documentation""" - locale = locale or request.preferences.get_value('locale') page = _INFO_PAGES.get_page(pagename, locale) if page is None: - page = _INFO_PAGES.get_page(pagename) - if page is None: flask.abort(404) + def all_pages(): + user_locale = request.preferences.get_value('locale') + for for_pagename, for_page in _INFO_PAGES.all_pages(user_locale): + for_locale = locale + if for_page is None: + # we are sure that for_pagename != pagename + for_page = _INFO_PAGES.get_page(for_pagename, _INFO_PAGES.locale_default) + for_locale = _INFO_PAGES.locale_default + yield for_pagename, for_page, for_locale + return render( 'info.html', - all_pages=_INFO_PAGES.all_pages, + all_pages=all_pages(), active_page=page, active_pagename=pagename, ) diff --git a/searxng_extra/docs_prebuild b/searxng_extra/docs_prebuild index 73c9c99b1..879007f64 100755 --- a/searxng_extra/docs_prebuild +++ b/searxng_extra/docs_prebuild @@ -8,24 +8,26 @@ import sys import os.path import time +from contextlib import contextmanager from searx import settings, get_setting from searx.infopage import InfoPageSet, InfoPage + _doc_user = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', 'docs', 'user')) -def main(): - DOC = None +def main(): base_url = get_setting('server.base_url', None) - if base_url: - DOC = _render_all_with_flask_ctx(base_url) + infopageset_ctx = _instance_infosetset_ctx(base_url) else: - DOC = _render_all() - for pagename, page in DOC.all_pages('en'): - fname = os.path.join(_doc_user, os.path.basename(page.fname)) - with open(fname, 'w') as f: - f.write(page.content) + infopageset_ctx = _offline_infosetset_ctx() + + with infopageset_ctx as infopageset: + for _, page in infopageset.all_pages('en'): + fname = os.path.join(_doc_user, os.path.basename(page.fname)) + with open(fname, 'w') as f: + f.write(page.content) class OfflinePage(InfoPage): @@ -41,21 +43,17 @@ class OfflinePage(InfoPage): return ctx -def _render_all(): - DOC = InfoPageSet(OfflinePage) - for pagename, page in DOC.all_pages('en'): - page.render() - return DOC - - -def _render_all_with_flask_ctx(base_url): +@contextmanager +def _offline_infosetset_ctx(): + yield InfoPageSet(OfflinePage) - DOC = InfoPageSet(InfoPage, base_url) +@contextmanager +def _instance_infosetset_ctx(base_url): # The url_for functions in the jinja templates need all routes to be # registered in the Flask app. - settings['server']['secret_key'] = "x" + settings['server']['secret_key'] = '' from searx.webapp import app # Specify base_url so that url_for() works for base_urls. If base_url is @@ -63,8 +61,7 @@ def _render_all_with_flask_ctx(base_url): # generics (see flaskfix.py). with app.test_request_context(base_url=base_url): - for pagename, page in DOC.all_pages('en'): - page.render() + yield InfoPageSet() # The searx.webapp import from above fires some HTTP requests, thats # why we get a RuntimeError:: |