From 7eedd44f5f9965cf2fbff14d276f96944b5c6a98 Mon Sep 17 00:00:00 2001 From: Markus Heiser Date: Wed, 10 Sep 2025 16:10:42 +0200 Subject: [mod] typification of SearXNG: add new result type Paper This patch adds a new result type: Paper - Python class: searx/result_types/paper.py - Jinja template: searx/templates/simple/result_templates/paper.html - CSS (less) client/simple/src/less/result_types/paper.less Signed-off-by: Markus Heiser --- searx/result_types/__init__.py | 3 + searx/result_types/_base.py | 6 +- searx/result_types/paper.py | 96 +++++++++++++++++++ searx/templates/simple/result_templates/paper.html | 102 ++++++++++++++++----- searx/utils.py | 36 +++++--- searx/weather.py | 30 +++++- 6 files changed, 236 insertions(+), 37 deletions(-) create mode 100644 searx/result_types/paper.py (limited to 'searx') diff --git a/searx/result_types/__init__.py b/searx/result_types/__init__.py index c8b8eb4f4..a1976c10f 100644 --- a/searx/result_types/__init__.py +++ b/searx/result_types/__init__.py @@ -22,6 +22,7 @@ __all__ = [ "Translations", "WeatherAnswer", "Code", + "Paper", ] import typing as t @@ -31,6 +32,7 @@ from ._base import Result, MainResult, LegacyResult from .answer import AnswerSet, Answer, Translations, WeatherAnswer from .keyvalue import KeyValue from .code import Code +from .paper import Paper class ResultList(list[Result | LegacyResult], abc.ABC): @@ -44,6 +46,7 @@ class ResultList(list[Result | LegacyResult], abc.ABC): Answer = Answer KeyValue = KeyValue Code = Code + Paper = Paper MainResult = MainResult Result = Result Translations = Translations diff --git a/searx/result_types/_base.py b/searx/result_types/_base.py index 1c614651b..b3f2afdeb 100644 --- a/searx/result_types/_base.py +++ b/searx/result_types/_base.py @@ -362,7 +362,11 @@ class MainResult(Result): # pylint: disable=missing-class-docstring """The date on which the object was published.""" pubdate: str = "" - """String representation of :py:obj:`MainResult.publishedDate`""" + """String representation of :py:obj:`MainResult.publishedDate` + + Deprecated: it is still partially used in the templates, but will one day be + completely eliminated. + """ length: time.struct_time | None = None """Playing duration in seconds.""" diff --git a/searx/result_types/paper.py b/searx/result_types/paper.py new file mode 100644 index 000000000..33bb5f99a --- /dev/null +++ b/searx/result_types/paper.py @@ -0,0 +1,96 @@ +# SPDX-License-Identifier: AGPL-3.0-or-later +"""Typification of the *paper* results. + +.. _BibTeX field types: https://en.wikipedia.org/wiki/BibTeX#Field_types +.. _BibTeX format: https://www.bibtex.com/g/bibtex-format/ + +Results of this type are rendered in the :origin:`paper.html +` template. + +Related topics: + +- `BibTeX field types`_ +- `BibTeX format`_ + +---- + +.. autoclass:: Paper + :members: + :show-inheritance: + +""" +# pylint: disable=too-few-public-methods, disable=invalid-name + +from __future__ import annotations + +__all__ = ["Paper"] + +import typing as t + +from searx.weather import DateTime +from ._base import MainResult + + +@t.final +class Paper(MainResult, kw_only=True): + """Result type suitable for displaying scientific papers and other + documents.""" + + template: str = "paper.html" + + date_of_publication: DateTime | None = None + """Date the document was published.""" + + content: str = "" + """An abstract or excerpt from the document.""" + + comments: str = "" + """Free text display in italic below the content.""" + + tags: list[str] = [] + """Free tag list.""" + + type: str = "" + """Short description of medium type, e.g. *book*, *pdf* or *html* ...""" + + authors: list[str] | set[str] = [] + """List of authors of the work (authors with a "s" suffix, the "author" is + in the :py:obj:`MainResult.author`).""" + + editor: str = "" + """Editor of the book/paper.""" + + publisher: str = "" + """Name of the publisher.""" + + journal: str = "" + """Name of the journal or magazine the article was published in.""" + + volume: str | int = "" + """Volume number.""" + + pages: str = "" + """Page range where the article is.""" + + number: str = "" + """Number of the report or the issue number for a journal article.""" + + doi: str = "" + """DOI number (like ``10.1038/d41586-018-07848-2``).""" + + issn: list[str] = [] + """List of ISSN numbers like ``1476-4687``""" + + isbn: list[str] = [] + """List of ISBN numbers like ``9780201896831``""" + + pdf_url: str = "" + """URL to the full article, the PDF version""" + + html_url: str = "" + """URL to full article, HTML version""" + + def __post_init__(self): + super().__post_init__() + if self.date_of_publication is None and self.publishedDate is not None: + self.date_of_publication = DateTime(self.publishedDate) diff --git a/searx/templates/simple/result_templates/paper.html b/searx/templates/simple/result_templates/paper.html index 7e94cf174..074ad9081 100644 --- a/searx/templates/simple/result_templates/paper.html +++ b/searx/templates/simple/result_templates/paper.html @@ -1,34 +1,92 @@ {% from 'simple/macros.html' import result_header, result_sub_header, result_sub_footer, result_footer, result_link with context %} -{{ result_header(result, favicons, image_proxify) -}} +{{ result_header(result, favicons, image_proxify) }} +
- {%- if result.publishedDate %}
{{ _("Published date") }}:
{% endif -%} - {%- if result.authors %}
{{ _("Author") }}:{{ result.authors | join(", ") }}
{% endif -%} + {%- if result.date_of_publication %} +
+ {{ _("Published date") }}: + {{ result.date_of_publication.l10n_date("long", "UI") }} +
+ {% endif -%} + {%- if result.authors %} +
+ {{ _("Author") }}: + {{ result.authors | join(", ") }} +
+ {% endif -%} {%- if result.journal -%} -
- {{- _("Journal") }}:{{ result.journal -}} - {%- if result.volume -%} -  {{- result.volume -}} - {%- if result.number -%} - .{{- result.number -}} +
+ {{- _("Journal") }}: + {{ result.journal -}} + {%- if result.volume -%} +  {{- result.volume -}} + {%- if result.number -%}.{{- result.number -}}{%- endif -%} {%- endif -%} - {%- endif -%} - {%- if result.pages -%} -  {{- result.pages -}} - {%- endif -%} + {%- if result.pages -%} {{- result.pages -}}{%- endif -%}
{%- endif %} - {%- if result.editor %}
{{ _("Editor") }}:{{ result.editor }}
{% endif -%} - {%- if result.publisher %}
{{ _("Publisher") }}:{{ result.publisher }}
{% endif -%} - {%- if result.type %}
{{ _("Type") }}:{{ result.type }}
{% endif -%} - {%- if result.tags %}
{{ _("Tags") }}:{{ result.tags | join(", ")}}
{%- endif -%} - {%- if result.doi %}
{{ _("DOI") }}:{{ result_link(doi_resolver + result.doi, result.doi) }}
{% endif -%} - {%- if result.issn %}
{{ _("ISSN") }}:{{ result.issn | join(", ") }}
{% endif -%} - {%- if result.isbn %}
{{ _("ISBN") }}:{{ result.isbn | join(", ") }}
{% endif -%} + {%- if result.editor %} +
+ {{ _("Editor") }}: + {{ result.editor }} +
+ {% endif -%} + {%- if result.publisher %} +
+ {{ _("Publisher") }}: + {{ result.publisher }} +
+ {% endif -%} + {%- if result.type %} +
+ {{ _("Type") }}: + {{ result.type }} +
+ {% endif -%} + {%- if result.tags %} +
+ {{ _("Tags") }}: + {{ result.tags | join(", ")}} +
+ {%- endif -%} + {%- if result.doi %} +
+ {{ _("DOI") }}: + {{ result_link(doi_resolver + result.doi, result.doi) }} +
+ {% endif -%} + {%- if result.issn %} +
+ {{ _("ISSN") }}: + {{ result.issn | join(", ") }} +
+ {% endif -%} + {%- if result.isbn %} +
+ {{ _("ISBN") }}: + {{ result.isbn | join(", ") }} +
+ {% endif -%} + {%- if result.views %} +
+ {{ _('Views') }}: + {{ result.views }} +
+ {% endif -%}
-{%- if result.content -%}

{{- result.content | safe -}}

{%- endif -%} -{%- if result.comments -%}

{{- result.comments -}}

{%- endif -%} +{%- if result.content -%} +

{{- result.content | safe -}}

+{%- endif -%} +{%- if result.comments -%} +

{{- result.comments -}}

+{%- endif -%} + +{%- if result.metadata %} +
{{ result.metadata|safe }}
+{% endif -%} +