HTML-Theme-Entwicklung¶
Hinzugefügt in Version 0.6.
Hinweis
Dieses Dokument enthält Informationen zur Erstellung eigener Themes. Wenn Sie lediglich ein bereits vorhandenes HTML-Theme verwenden möchten, lesen Sie bitte HTML-Theming.
Sphinx unterstützt die Änderung des Erscheinungsbildes seiner HTML-Ausgabe durch Themes. Ein Theme ist eine Sammlung von HTML-Templates, Stylesheets und anderen statischen Dateien. Zusätzlich gibt es eine Konfigurationsdatei, die festlegt, von welchem Theme geerbt werden soll, welcher Hervorhebungsstil verwendet werden soll und welche Optionen zur Anpassung des Erscheinungsbildes des Themes verfügbar sind.
Themes sind so konzipiert, dass sie projektunabhängig sind, sodass sie ohne Änderungen für verschiedene Projekte verwendet werden können.
Hinweis
Weitere nützliche Informationen zur Theme-Entwicklung finden Sie in Sphinx API.
Themes erstellen¶
Themes liegen entweder als Verzeichnis oder als Zip-Datei vor (deren Name der Theme-Name ist) und enthalten Folgendes:
Entweder eine Datei
theme.toml(bevorzugt) oder eine Dateitheme.conf.HTML-Templates, falls benötigt.
Ein Verzeichnis
static/, das alle statischen Dateien enthält, die in das Ausgabeverzeichnis für statische Dateien kopiert werden. Dies können Bilder, Stile und Skriptdateien sein.
Theme-Konfiguration (theme.toml)¶
Die Datei theme.toml ist ein TOML-Dokument und enthält zwei Tabellen: [theme] und [options].
Die Tabelle [theme] definiert die Einstellungen des Themes.
inherit (string): Der Name des Basisthemes, von dem Einstellungen, Optionen, Templates und statische Dateien geerbt werden. Alle statischen Dateien von „Vorfahren“-Themes werden verwendet. Das Theme übernimmt alle in geerbten Themes definierten Optionen. Schließlich werden geerbte Themes verwendet, um fehlende Templates zu finden (z. B. wenn
"basic"als Basistheme verwendet wird, sind die meisten Templates bereits definiert).Wenn auf
"none"gesetzt, erbt das Theme kein anderes Theme. Die Vererbung ist rekursiv und bildet eine Kette von geerbten Themes (z. B.default->classic->basic->none).stylesheets (liste von strings): Eine Liste von CSS-Dateinamen, die in die generierte HTML-Kopfzeile aufgenommen werden. Das Setzen des Konfigurationswertes
html_styleüberschreibt diese Einstellung.Andere Mechanismen zum Einbinden mehrerer Stylesheets sind
@importin CSS oder die Verwendung eines benutzerdefinierten HTML-Templates mit entsprechenden<link rel="stylesheet">-Tags.sidebars (liste von strings): Eine Liste von Sidebar-Templates. Dies kann vom Benutzer über den Konfigurationswert
html_sidebarsüberschrieben werden.pygments_style (tabelle): Eine TOML-Tabelle, die die Namen der Pygments-Stile für die Syntaxhervorhebung definiert. Die Tabelle hat zwei erkannte Schlüssel:
defaultunddark. Der indarkdefinierte Stil wird verwendet, wenn die CSS-Media-Abfrage(prefers-color-scheme: dark)wahr ist.[theme.pygments_style.default]kann vom Benutzer über den Konfigurationswertpygments_styleüberschrieben werden.
Die Tabelle [options] definiert die Optionen für das Theme. Sie ist so strukturiert, dass jedes Schlüssel-Wert-Paar einem Variablennamen und dem entsprechenden Standardwert entspricht. Diese Optionen können vom Benutzer in html_theme_options überschrieben werden und sind aus allen Templates als theme_<name> zugänglich.
Hinzugefügt in Version 7.3: theme.toml Unterstützung.
Beispiel für eine theme.toml-Datei
[theme]
inherit = "basic"
stylesheets = [
"main-CSS-stylesheet.css",
]
sidebars = [
"localtoc.html",
"relations.html",
"sourcelink.html",
"searchbox.html",
]
# Style names from https://pygments.org/styles/
pygments_style = { default = "style_name", dark = "dark_style" }
[options]
variable = "default value"
Theme-Konfiguration (theme.conf)¶
Die Datei theme.conf hat das INI-Format [1] (lesbar durch das Standard-Python-Modul configparser) und hat die folgende Struktur:
[theme]
inherit = base theme
stylesheet = main CSS name
pygments_style = stylename
sidebars = localtoc.html, relations.html, sourcelink.html, searchbox.html
[options]
variable = default value
Die Einstellung inherit gibt den Namen eines „Basisthemes“ oder
nonean. Das Basistheme wird verwendet, um fehlende Templates zu finden (die meisten Themes müssen nicht die meisten Templates bereitstellen, wenn siebasicals Basistheme verwenden), seine Optionen werden geerbt und alle seine statischen Dateien werden ebenfalls verwendet. Wenn Sie auch das Stylesheet erben möchten, fügen Sie es über@importvon CSS in Ihr eigenes ein.Die Einstellung stylesheet gibt eine durch Kommas getrennte Liste von CSS-Dateinamen an, die in der HTML-Kopfzeile referenziert werden. Sie können auch die
@import-Technik von CSS verwenden, um eine aus der anderen einzubinden, oder ein benutzerdefiniertes HTML-Template verwenden, das die notwendigen<link rel="stylesheet">-Tags hinzufügt. Das Setzen des Konfigurationswerteshtml_styleüberschreibt diese Einstellung.Die Einstellung pygments_style gibt den Namen eines Pygments-Stils für die Hervorhebung an. Dies kann vom Benutzer im Konfigurationswert
pygments_styleüberschrieben werden.Die Einstellung pygments_dark_style gibt den Namen eines Pygments-Stils für die Hervorhebung an, wenn die CSS-Media-Abfrage
(prefers-color-scheme: dark)wahr ist. Sie wird überadd_css_file()in die Seite eingefügt.Die Einstellung sidebars gibt die durch Kommas getrennte Liste von Sidebar-Templates für die Konstruktion von Sidebars an. Dies kann vom Benutzer im Konfigurationswert
html_sidebarsüberschrieben werden.Der Abschnitt options enthält Paare von Variablennamen und Standardwerten. Diese Optionen können vom Benutzer in
html_theme_optionsüberschrieben werden und sind aus allen Templates alstheme_<name>zugänglich.
Hinzugefügt in Version 1.7: Sidebar-Einstellungen
Geändert in Version 5.1: Die Einstellung stylesheet akzeptiert mehrere CSS-Dateinamen
theme.conf nach theme.toml konvertieren¶
INI-basierte Theme-Konfigurationsdateien (theme.conf) können mit einem mit Sphinx ausgelieferten Hilfsprogramm in TOML konvertiert werden. Dies ist für den einmaligen Gebrauch gedacht und kann ohne Vorankündigung in einer zukünftigen Version von Sphinx entfernt werden.
$ python -m sphinx.theming conf_to_toml [THEME DIRECTORY PATH]
Das erforderliche Argument ist ein Pfad zu einem Verzeichnis, das eine theme.conf-Datei enthält. Das Programm schreibt eine theme.toml-Datei im selben Verzeichnis und ändert die ursprüngliche theme.conf-Datei nicht.
Hinzugefügt in Version 7.3.
Verteilen Sie Ihr Theme als Python-Paket¶
Als Möglichkeit, Ihr Theme zu verteilen, können Sie ein Python-Paket verwenden. Dies erleichtert den Benutzern die Einrichtung Ihres Themes.
Um Ihr Theme als Python-Paket zu verteilen, definieren Sie einen Entry Point namens sphinx.html_themes in Ihrer pyproject.toml-Datei und schreiben Sie eine setup()-Funktion, um Ihr Theme mit der add_html_theme() API zu registrieren.
# pyproject.toml
[project.entry-points."sphinx.html_themes"]
name_of_theme = "your_theme_package"
# your_theme_package.py
from pathlib import Path
def setup(app):
app.add_html_theme('name_of_theme', Path(__file__).resolve().parent)
Wenn Ihr Theme-Paket zwei oder mehr Themes enthält, rufen Sie add_html_theme() zweimal oder öfter auf.
Hinzugefügt in Version 1.2: „sphinx_themes“-Entry-Points-Feature.
Veraltet seit Version 1.6: sphinx_themes Entry-Points wurde als veraltet markiert.
Hinzugefügt in Version 1.6: sphinx.html_themes Entry-Points-Feature.
Styling mit CSS¶
Die Einstellung stylesheets kann verwendet werden, um benutzerdefinierte CSS-Dateien zu einem Theme hinzuzufügen.
Vorsicht
Die Struktur der HTML-Elemente und ihre Klassen sind derzeit keine klar definierte öffentliche API. Bitte leiten Sie sie aus der Inspektion der gebauten HTML-Seiten ab. Obwohl wir keine vollständige Stabilität garantieren können, sind sie tendenziell ziemlich stabil.
Suche Ergebnisseinträge nach Kategorie gestalten¶
Hinzugefügt in Version 8.0.
Hinweis
Die unten genannten CSS-Klassen werden vom Standalone-Suchcode von Sphinx generiert. Wenn Sie einen Drittanbieter-Suchdienst wie ReadTheDocs zur Bereitstellung von Suchergebnissen verwenden, können die verfügbaren Theming-Optionen variieren.
Die Suche-Ergebnis-Elemente haben Klassen, die den Kontext angeben, in dem der Suchbegriff gefunden wurde. Sie können die CSS-Selektoren verwenden:
ul.search li.kind-index: Für Ergebnisse in einem Index, z. B. im Glossar.ul.search li.kind-object: Für Ergebnisse im Quellcode, wie z. B. Python-Funktionsdefinitionen.ul.search li.kind-title: Für Ergebnisse, die in Abschnittsüberschriften gefunden wurden.ul.search li.kind-text: Für Ergebnisse, die an anderer Stelle im Dokumentationstext gefunden wurden.
Als Basis für die Vererbung durch andere Themes ist das basic-Theme absichtlich minimal und definiert keine CSS-Regeln mit diesen Selektoren. Abgeleitete Themes werden ermutigt, diese Selektoren nach Belieben zu verwenden. Zum Beispiel fügt das folgende Stylesheet kontextbezogene Icons zur Ergebnisliste der Suche hinzu:
ul.search {
padding-left: 30px;
}
ul.search li {
padding: 5px 0 5px 10px;
list-style-type: "\25A1"; /* Unicode: White Square */
}
ul.search li.kind-index {
list-style-type: "\1F4D1"; /* Unicode: Bookmark Tabs */
}
ul.search li.kind-object {
list-style-type: "\1F4E6"; /* Unicode: Package */
}
ul.search li.kind-title {
list-style-type: "\1F4C4"; /* Unicode: Page Facing Up */
}
ul.search li.kind-text {
list-style-type: "\1F4C4"; /* Unicode: Page Facing Up */
}
Templating¶
Der Leitfaden zum Templating ist hilfreich, wenn Sie Ihre eigenen Templates schreiben möchten. Wichtig ist, die Reihenfolge zu beachten, in der Sphinx nach Templates sucht:
Zuerst in den
templates_path-Verzeichnissen des Benutzers.Dann im ausgewählten Theme.
Dann im Basistheme, im Basistheme des Basisthemes usw.
Beim Erweitern eines Templates im Basistheme mit demselben Namen verwenden Sie den Theme-Namen als Verzeichnis: {% extends "basic/layout.html" %}. Aus einem Template im templates_path eines Benutzers können Sie weiterhin die „Ausrufezeichen“-Syntax verwenden, wie im Templating-Dokument beschrieben.
Statische Templates¶
Da Theme-Optionen für den Benutzer dazu gedacht sind, ein Theme einfacher zu konfigurieren, ohne ein benutzerdefiniertes Stylesheet schreiben zu müssen, ist es notwendig, sowohl statische Dateien als auch HTML-Dateien per Template verarbeiten zu können. Daher unterstützt Sphinx sogenannte „statische Templates“, wie diese:
Wenn der Name einer Datei im Verzeichnis static/ eines Themes (oder im statischen Pfad des Benutzers) mit .jinja oder _t endet, wird sie von der Template-Engine verarbeitet. Die Endung wird aus dem endgültigen Dateinamen entfernt.
Zum Beispiel könnte ein Theme mit einer Datei static/theme_styles.css.jinja Templating verwenden, um Optionen in das Stylesheet einzufügen. Wenn ein Dokumentationsprojekt mit diesem Theme erstellt wird, enthält das Ausgabeverzeichnis eine Datei _static/theme_styles.css, in der alle Template-Tags verarbeitet wurden.
Geändert in Version 7.4
Die bevorzugte Endung für statische Templates ist nun
.jinja, im Einklang mit der empfohlenen Dateiendung von Jinja vom Jinja-Projekt.Die Dateiendung
_tfür statische Templates gilt nun als „Legacy“ und die Unterstützung kann schließlich entfernt werden.Wenn ein statisches Template mit der Endung
_toder.jinjaerkannt wird, wird es von der Template-Engine verarbeitet, wobei die Endung aus dem endgültigen Dateinamen entfernt wird.
Benutzerdefinierte Seitenmetadaten in HTML-Templates verwenden¶
Alle Schlüssel/Wert-Paare in Feldlisten, die vor dem Seitentitel platziert werden, sind für das Jinja-Template verfügbar, wenn die Seite innerhalb des Attributs meta erstellt wird. Wenn beispielsweise eine Seite den folgenden Text vor ihrem ersten Titel hatte:
:mykey: My value
My first title
--------------
Dann könnte sie in einem Jinja-Template wie folgt aufgerufen werden:
{%- if meta is mapping %}
{{ meta.get("mykey") }}
{%- endif %}
Beachten Sie die Prüfung, ob meta ein Dictionary ist („mapping“ im Jinja-Jargon), um sicherzustellen, dass die Verwendung auf diese Weise gültig ist.
Benutzerdefinierte Template-Funktionen definieren¶
Manchmal ist es nützlich, eine eigene Funktion in Python zu definieren, die Sie dann in einem Template verwenden möchten. Zum Beispiel, wenn Sie einen Template-Wert mit Logik einfügen möchten, die von der Konfiguration des Benutzers im Projekt abhängt, oder wenn Sie nicht triviale Prüfungen einschließen und freundliche Fehlermeldungen für falsche Konfigurationen im Template bereitstellen möchten.
Um Ihre eigene Template-Funktion zu definieren, müssen Sie zwei Funktionen in Ihrem Modul definieren:
Eine Seitenkontext-Ereignishandler (oder Registrierungsfunktion). Diese wird über einen Event-Callback mit der
Sphinx-Anwendung verbunden.Eine Template-Funktion, die Sie in Ihrem Jinja-Template verwenden werden.
Definieren Sie zunächst die Registrierungsfunktion, die die Argumente für html-page-context akzeptiert.
Innerhalb der Registrierungsfunktion definieren Sie die Template-Funktion, die Sie in Jinja verwenden möchten. Die Template-Funktion sollte einen String oder Python-Objekte (Listen, Dictionaries) mit Strings darin zurückgeben, die Jinja im Templating-Prozess verwendet.
Hinweis
Die Template-Funktion hat Zugriff auf alle Variablen, die an die Registrierungsfunktion übergeben werden.
Am Ende der Registrierungsfunktion fügen Sie die Template-Funktion dem Kontext der Sphinx-Anwendung mit context['template_func'] = template_func hinzu.
Schließlich fügen Sie in der setup()-Funktion Ihrer Erweiterung Ihre Registrierungsfunktion als Callback für html-page-context hinzu.
# The registration function
def setup_my_func(app, pagename, templatename, context, doctree):
# The template function
def my_func(mystring):
return "Your string is %s" % mystring
# Add it to the page's context
context['my_func'] = my_func
# Your extension's setup function
def setup(app):
app.connect("html-page-context", setup_my_func)
Nun haben Sie Zugriff auf diese Funktion in Jinja wie folgt:
<div>
{{ my_func("some string") }}
</div>
Eigene statische Dateien zu den Build-Assets hinzufügen¶
Standardmäßig kopiert Sphinx statische Dateien aus dem Verzeichnis static/ des Template-Verzeichnisses. Wenn Ihr Paket jedoch aus bestimmten Gründen statische Dateien außerhalb des Verzeichnisses static/ platzieren muss, müssen Sie sie beim Build über einen Event-Hook manuell in das Verzeichnis _static/ der HTML-Ausgaben kopieren. Hier ist ein Beispielcode, um dies zu erreichen:
import shutil
def copy_custom_files(app, exc):
if app.builder.format == 'html' and not exc:
static_dir = app.outdir / '_static'
shutil.copyfile('path/to/myextension/_static/myjsfile.js', static_dir)
def setup(app):
app.connect('build-finished', copy_custom_files)
JavaScript basierend auf Benutzerkonfiguration einfügen¶
Wenn Ihre Erweiterung JavaScript verwendet, kann es nützlich sein, Benutzern die Steuerung seines Verhaltens über ihre Sphinx-Konfiguration zu ermöglichen. Dies kann jedoch schwierig sein, wenn Ihr JavaScript in Form einer statischen Bibliothek vorliegt (die nicht mit Jinja kompiliert wird).
Es gibt zwei Möglichkeiten, Variablen basierend auf der Benutzerkonfiguration in den JavaScript-Bereich einzufügen.
Erstens können Sie _t an das Ende jeder mit Ihrer Erweiterung gelieferten statischen Datei anhängen. Dadurch wird Sphinx diese Dateien mit der Template-Engine verarbeiten, sodass Sie Variablen einbetten und das Verhalten steuern können.
Zum Beispiel die folgende JavaScript-Struktur:
mymodule/
├── _static
│ └── myjsfile.js_t
└── mymodule.py
Führt zu der folgenden statischen Datei, die in die Build-Ausgabe Ihres HTML eingefügt wird:
_build/
└── html
└── _static
└── myjsfile.js
Weitere Informationen finden Sie unter Statische Templates.
Zweitens können Sie die Methode Sphinx.add_js_file() verwenden, ohne auf eine Datei zu verweisen. Normalerweise wird diese Methode verwendet, um eine neue JavaScript-Datei in Ihre Website einzufügen. Wenn Sie jedoch keinen Dateipfad übergeben, sondern einen String an das Argument „body“ übergeben, wird dieser Text als JavaScript in den Kopfbereich Ihrer Website eingefügt. Dies ermöglicht es Ihnen, Variablen aus Python in den JavaScript-Code Ihres Projekts einzufügen.
Zum Beispiel liest der folgende Code einen benutzerkonfigurierten Wert aus und fügt diesen Wert als JavaScript-Variable ein, die der JavaScript-Code Ihrer Erweiterung verwenden kann:
# This function reads in a variable and inserts it into JavaScript
def add_js_variable(app):
# This is a configuration that you've specified for users in `conf.py`
js_variable = app.config['my_javascript_variable']
js_text = "var my_variable = '%s';" % js_variable
app.add_js_file(None, body=js_text)
# We connect this function to the step after the builder is initialized
def setup(app):
# Tell Sphinx about this configuration variable
app.add_config_value('my_javascript_variable', 0, 'html')
# Run the function after the builder is initialized
app.connect('builder-inited', add_js_variable)
Infolgedessen können Sie in Ihrem Theme Code verwenden, der von der Anwesenheit dieser Variablen abhängt. Benutzer können den Wert der Variablen steuern, indem sie ihn in ihrer conf.py-Datei definieren.