Gestalterische Anpassungen

Für die Grundwissen-Webseite nutze ich das Sphinx-Standard-Theme mit einigen Anpassungen. Diese habe ich als Super-User direkt am zentralen Installationspfad (in meinem Fall /usr/local/lib/python3.5/dist-packages/Sphinx-1.4.5-py3.5.egg/sphinx) vorgenommen, so dass sie global für alle Dokumentations-Projekte gleichermaßen gelten. Als (empfehlenswertere) Alternative hierzu kann Sphinx mittels einer virtuellen Umgebung lokal im Ordner des Benutzers installiert und dort auch ohne Super-User-Rechte angepasst werden. Die im folgenden Abschnitt aufgelisteten Datei-Änderungen beziehen sich dabei stets auf den jeweiligen Installationspfad.

In der Fußnotenzeile der Webseite wollte ich ein Link auf Kontakt/Impressum eingefügen. Dies kann in in der Datei themes/basic/layout.html festgelegt werden:

VORHER:

{%- if last_updated %}
  {% trans last_updated=last_updated|e %}Last updated on {{ last_updated }}.
  {% endtrans %}
{%- endif %}

NACHHER:

{%- if last_updated %}
  {% trans last_updated=last_updated|e %}
  Zuletzt aktualisiert am {{ last_updated }}.
  <a href='http://grund-wissen.de/impressum.html'>Kontakt/Impressum</a>
  {% endtrans %}
{%- endif %}

Zeilenumbruch bei langen HTML-Navigationszeilen ermöglichen

In der obersten Zeile einer jeden mit Sphinx erstellten HTML-Seite wird eine Navigations-Leiste angezeigt. Bei einer umfangreichen Dokumentation mit vielen Unterabschnitten kann es vorkommen, dass auf kleinen Bildschirmen hierbei ein Zeilenumbruch nötig ist – der letzte Listeneintrag wird also in eine neue Zeile geschrieben. In der Grundversion wird hierbei die Seitenüberschrift verschoben. Um dies zu vermeiden, muss folgender Eintrag in der Datei themes/basic/static/basic.css_t ergänzt werden:

VORHER:

div.related ul {
    margin: 0;
    padding: 0 0 0 10px;
    list-style: none;
    }


NACHHER:

div.related ul {
    margin: 0;
    padding: 0 0 0 10px;
    list-style: none;
    min-height: 2em;
    height: auto;
    overflow: hidden;
    }

Durch den Eintrag height: auto wird die Höhe der Navigations-Leiste automatisch angepasst. Der Eintrag overflow: hidden; fügt anschließend bei Bedarf automatisch eine (wieder ganz von links beginnende) neue Zeile ein.

Maximalbreite der HTML-Dokumentation festlegen

In den letzten Jahren sind Computer-Monitore immer breiter geworden. Im Vergleich zu einer DinA4-Seite sind somit, sofern keine Beschränkungen festgelegt werden, auch wesentlich längere Textzeilen möglich.

Mittels einer entsprechenden CSS-Option kann erreicht werden, dass auch bei sehr breiten Monitoren ein als kleiner Absatz geschriebener Text als eine einzige Zeile erscheint – das Layout der HTML-Seite bleibt somit der Druckversion ähnlich. Dies gilt nicht nur für Text, sondern auch für Graphiken, die mit einer prozentualen Breitenangabe eingebunden werden: In LaTeX ist die Zeilenbreite des Texts als Referenzwert üblich, in HTML standardmäßig die Breite des Browserfensters; auf breiten Monitoren werden Graphiken in einem Vollbild-Browser entsprechend groß dargestellt.

Bei der Grund-Wissen-Seite wird das Theme sphinxdoc verwendet; die entsprechende CSS-Datei ist themes/sphinxdoc/static/sphinxdoc.css_t. Hier muss zur Begrenzung der HTMl-Seitenbreite folgende Änderung vorgenommen werden:

NACHHER:

body {
    font-family: 'Lucida Grande', 'Lucida Sans Unicode', 'Geneva',
                 'Verdana', sans-serif;
    font-size: 14px;
    letter-spacing: -0.01em;
    line-height: 150%;
    text-align: center;
    background-color: #BFD1D4;
    color: black;
    padding: 0;
    border: 1px solid #aaa;

    margin: auto;
    min-width: 740px;
    max-width: 1200px;
}

Mit den obigen Einstellungen wird die Webseite mit der angegebenen Breite zentriert dargestellt; der Rest des Browserfensters durch einen neutralen Hintergrund ausgefüllt.

Tabellen zentrieren

Normalerweise stellt Sphinx Tabellen im LaTeX-Output linksbündig dar. Persönlich sind mir zentrierte Tabellen lieber. Daher habe ich die (umfangreiche) Datei writers/latex.py, speziell die Funktion depart_table(self, node), etwas abgeändert:

VORHER:

if not self.table.longtable and self.table.caption is not None:
    self.body.append(u'\n\\begin{threeparttable}\n'
                     u'\\capstart\\caption{%s}\n' % self.table.caption)
elif self.table.has_verbatim:
    self.body.append('\n\\begin{tabular}')
    endmacro = '\\end{tabular}\n'
elif self.table.has_problematic and not self.table.colspec:
    # if the user has given us tabularcolumns, accept them and use
    # tabulary nevertheless
    self.body.append('\n\\begin{tabular}')
    endmacro = '\\end{tabular}\n'
else:
    self.body.append('\n\\begin{tabulary}{\\linewidth}')
    endmacro = '\\end{tabulary}\n'

[...]

if not self.table.longtable and self.table.caption is not None:
    self.body.append('\\end{threeparttable}\n')


NACHHER:

if not self.table.longtable and self.table.caption is not None:
    self.body.append(u'\n\n\\begin{table}\\centering\n'
                     u'\\capstart\\caption{%s}\n' % self.table.caption)
if self.table.longtable:
    self.body.append('\n\\begin{longtable}')
    endmacro = '\\end{longtable}\n\n'
elif self.table.has_verbatim:
    self.body.append('\n\\begin{center}\\begin{tabular}')
    endmacro = '\\end{tabular}\\end{center}\n\n'
elif self.table.has_problematic and not self.table.colspec:
    self.body.append('\n\\begin{center}\\begin{tabular}')
    endmacro = '\\end{tabular}\\end{center}\n\n'
else:
    self.body.append('\n\\begin{center}\\begin{tabulary}{\\linewidth}')
    endmacro = '\\end{tabulary}\\end{center}\n\n'

[...]

if not self.table.longtable and self.table.caption is not None:
    self.body.append('\\end{table}\n\n')

Auch in der HTML-Ausgabe möchte ich Tabellen gerne zentriert haben; gleichzeitig sollen die Fußnoten, die von Sphinx ebenfalls in Tabellen-Form dargestellt werden, linksbündig bleiben. Um dies zu erreichen, habe ich in der Datei themes/basic/static/basic.css_t den Eintrag table.docutils folgendermaßen ergänzt:

table.docutils {
    border: 1px solid gray;
    border-collapse: collapse;
    margin-left: auto;
    margin-right: auto;
}

table.docutils.footnote, table.docutils.citation {
    border: 0px;
    border-collapse: collapse;
    margin-left: 0;
}

table.docutils.footnote td, table.docutils.citation td {
    border: 0px;
}

Kopfzeile in der Druckversion entfernen

Normalerweise erscheint in der mittels LaTeX erzeugten PDF-Datei in der Kopfzeile jeder Seite ein Versionshinweis. Um dies zu deaktivieren, muss die Datei texinputs/sphinx.sty an zwei Stellen abgeändert werden. Zum einen muss die \fancyhead-Zeile, die den Versions-Eintrag erzeugt, mit einem %-Zeichen auskommentiert werden. Zum anderen kann der Strich zwischen Kopfzeile und erster Textzeile entfernt werden, indem ihr Wert auf 0.0 gesetzt wird:

VORHER:

\fancypagestyle{normal}{
  \fancyhf{}
  \fancyfoot[LE,RO]{{\py@HeaderFamily\thepage}}
  \fancyfoot[LO]{{\py@HeaderFamily\nouppercase{\rightmark}}}
  \fancyfoot[RE]{{\py@HeaderFamily\nouppercase{\leftmark}}}
  \fancyhead[LE,RO]{{\py@HeaderFamily \@title, \py@release}}
  \renewcommand{\headrulewidth}{0.4pt}
  \renewcommand{\footrulewidth}{0.4pt}


NACHHER:

\fancypagestyle{normal}{
  \fancyhf{}
  \fancyfoot[CE,CO]{{\py@HeaderFamily\thepage}}
% \fancyfoot[LO]{{\py@HeaderFamily\nouppercase{\rightmark}}}
% \fancyfoot[RE]{{\py@HeaderFamily\nouppercase{\leftmark}}}
% \fancyhead[LE,RO]{{\py@HeaderFamily \@title, \py@release}}
  \renewcommand{\headrulewidth}{0.0pt}
  \renewcommand{\footrulewidth}{0.4pt}

Mehrspaltige Aufzählungen (hlist) in LaTeX

Mit der hlist-Umgebung kann man mit Sphinx mehrspaltige Tabellen erstellen. Der Code dafür sieht etwa so aus:

.. hlist::
    :columns: 2

    * Item 1
    * Item 2
    * ...

Während die HTML-Ausgabe ausgezeichnet funktioniert, werden hlist-Umgebungen vom LaTeX-Übersetzer wie “normale” Listen behandelt. Persönlich verwende ich in den allermeisten Fällen zweispaltige hlists, so dass ich mir in der Datei writers/latex.py mit folgendem Trick Abhilfe für den erstellten LaTeX-Code geschaffen habe:

VORHER:

\usepackage{sphinx}

[...]

def visit_hlist(self, node):
    self.compact_list += 1
    self.body.append('\\begin{itemize}\\setlength{\\itemsep}{0pt}'
                     '\\setlength{\\parskip}{0pt}\n')

[...]

def depart_hlist(self, node):
    self.compact_list -= 1
    self.body.append('\\end{itemize}\n')


NACHHER:

\usepackage{sphinx}
\usepackage{multicol}

[...]

def visit_hlist(self, node):
    self.compact_list += 1
    self.body.append('\\begin{multicols}{2}')
    self.body.append('\\begin{itemize}\\setlength{\\itemsep}{0pt}'
                     '\\setlength{\\parskip}{0pt}\n')

[...]

def depart_hlist(self, node):
    self.compact_list -= 1
    self.body.append('\\end{itemize}\n')
    self.body.append('\\end{multicols}')

Damit werden alle hlists in der Druckversion als zweispaltige Aufzählungen dargestellt.[1]

Darstellung von Verbatim-Boxen anpassen

Um Code-Beispiele in LaTeX besser hervorzuheben, habe ich in der Datei texinputs/sphinx.sty die Farben für die Verbatim-Umgebung und ihre Umrandung etwas angepasst:

VORHER:

\definecolor{VerbatimColor}{rgb}{1,1,1}
\definecolor{VerbatimBorderColor}{rgb}{1,1,1}

NACHHER:

\definecolor{VerbatimColor}{rgb}{0.97,0.97,1}
\definecolor{VerbatimBorderColor}{rgb}{0.75,0.75,1}

Die Boxen werden so in einem schwachen Blau mit einem ebenfalls leicht blauen Rahmen gedruckt.

Titelseite gestalten

Nach persönlichem Geschmack habe ich die Titelseite etwas abgewandelt – insbesondere wollte ich dort einen Link auf die URL der Homepage einfügen. Hierbei habe ich die Datei texinputs/sphinxmanual.cls etwas angepasst:

VORHER:

\begin{flushright}
    \sphinxlogo
    \py@HeaderFamily
    {\Huge \@title \par}
    {\em\LARGE\py@HeaderFamily \py@release\releaseinfo \par}
    \vfill
    {\LARGE
        \begin{tabular}[t]{c}
            \@author
        \end{tabular}
        \par}
    }
    \vfill\vfill
    {\large
        \@date \par
        \vfill
        \py@authoraddress
        \par
    }
\end{flushright}

NACHHER:

\begin{flushright}%
    \sphinxlogo
    \py@HeaderFamily
    {\Huge \@title \par}
    {\em\large\py@HeaderFamily \py@release\releaseinfo \par}
    {\em\py@HeaderFamily Aktualisiert am \@date \par}
    \vfill
    {\LARGE
        \begin{tabular}[t]{c}
            \@author
        \end{tabular}
        \par}
    }
    \vfill\vfill
    {\Large
        \url{http://www.grund-wissen.de}
    }
\end{flushright}

An der unmittelbar folgenden Stelle in der Datei texinputs/sphinxmanual.cls habe ich folgenden Text hinzugefügt, der bei jeder meiner Dokumentationen auf der zweiten Seite des Dokuments, also unmittelbar vor dem Inhaltsverzeichnis, erscheinen soll:[2]

VORHER:

[...]

      \@thanks
\end{titlepage}%
\cleardoublepage%

\setcounter{footnote}{0}%
  \let\thanks\relax\let\maketitle\relax
  %\gdef\@thanks{}\gdef\@author{}\gdef\@title{}
}


NACHHER:

[...]

      \@thanks
\end{titlepage}%
Dieses Buch wird unter der
\href{http://de.wikipedia.org/wiki/Creative_Commons}{Creative Commons
License (Version 3.0, by-nc-sa)} ver\"{o}ffentlicht. Alle Inhalte d\"{u}rfen
daher in jedem beliebigen Format vervielf\"{a}ltigt und/oder
weiterverarbeitet werden, sofern die Weitergabe nicht kommerziell ist, unter
einer gleichen Lizenz erfolgt, und das Original als Quelle genannt wird.
Siehe auch:

\href{https://creativecommons.org/licenses/by-nc-sa/3.0/deed.de}{Erl\"{a}uterung
der Einschr\"{a}nkung by-nc-sa} \\
\href{https://irights.info/wp-content/uploads/userfiles/CC-NC_Leitfaden_web.pdf}{Leitfaden
zu Creative-Commons-Lizenzen}

Unabh\"{a}ngig von dieser Lizenz ist die Nutzung dieses Buchs f\"{u}r
Unterricht und Forschung \href{http://dejure.org/gesetze/UrhG/52a.html}{(\S
52a UrhG)} sowie zum privaten Gebrauch
\href{http://dejure.org/gesetze/UrhG/53.html}{(\S 53 UrhG)} ausdr\"{u}cklich
erlaubt.

Der Autor erhebt mit dem Buch weder den Anspruch auf Vollst\"{a}ndigkeit
noch auf Fehlerfreiheit; insbesondere kann f\"{u}r inhaltliche Fehler keine
Haftung \"{u}bernommen werden.

Die Quelldateien dieses Buchs wurden unter
\href{http://grund-wissen.de/linux/index.html}{Linux} mittels
\href{http://grund-wissen.de/linux/tools/vim/index.html}{Vim} und
\href{http://grund-wissen.de/linux/tools/sphinx/index.html}{Sphinx}, die
enthaltenen Graphiken mittels
\href{http://grund-wissen.de/linux/tools/inkscape.html}{Inkscape} erstellt.
Der Quellcode sowie die Original-Graphiken  k\"{o}nnen \"{u}ber die
Projektseite heruntergeladen werden:

\textbf{http://www.grund-wissen.de}
\\[3pt]

Bei Fragen, Anmerkungen und Verbesserungsvorschl\"{a}gen bittet der Autor um
eine kurze Email an folgende Adresse:

\textbf{info@grund-wissen.de}
\\[5pt]

Augsburg, den \today. \\[6pt]
\@author

\cleardoublepage%

\setcounter{footnote}{0}%
  \let\thanks\relax\let\maketitle\relax
  %\gdef\@thanks{}\gdef\@author{}\gdef\@title{}
}

Zusätzlich habe ich in der Datei writers/latex.py beide Vorkommnisse der Bezeichnung “Release” durch “Version” ersetzt.

Linkcheck bei URLs mit Umlauten

Sphinx ist für englisch-sprachige Dokumentationen entworfen worden. Inzwischen kann beispielsweise eine deutsch-sprachige Sprache in der Konfigurationsdatei des jeweiligen Projekts mittels der Option language=de eingestellt werden; auch vielerlei weitere Sprachen werden inzwischen unterstützt.

Schwierigkeiten bereiten auch in der Sphinx-Version 1.4.5 immer noch Links auf Webseiten, die Umlaute in ihren URLs beinhalten; dies ist beispielsweise des öfteren bei Wikipedia-Seiten der Fall. Ruft man im Projektverzeichnis make linkcheck auf, so bricht der Test bei einer solchen URL mit einer Fehlermeldung ab.

Als kleinen Workaround habe ich in der Datei builders/linkcheck.py folgende Änderung an der Funktion check_uri() vorgenommen:

VORHER:

# handle non-ASCII URIs
try:
    req_url.encode('ascii')
except UnicodeError:

    (...)

NACHHER:

# handle non-ASCII URIs
try:
    req_url.encode('utf-8')
except UnicodeError:

    (...)

Trotz der obigen Änderung werden URLs mit Umlauten beim Linkcheck zwar als fehlerhaft angezeigt, der Test läuft jedoch durch. Dadurch kann der Linkcheck wie gewohnt genutzt werden, man muss lediglich bei URLs mit Umlauten die Fehler ignorieren oder diese manuell prüfen.


Anmerkungen:

[1]Hierbei muss das LaTeX-Paket multicol installiert sein. Sollte dies nicht der Fall sein, kann es von der CTAN-Projektseite herunter geladen werden und gemäß dem üblichen Installations-Schema nachinstalliert werden.
[2]Diese Lösung ist nicht elegant, erfüllt aber ihren Zweck. Für Verbesserungshinweise bin ich dankbar. ;-)