1. Einleitung
In diesem Artikel geht es darum, wie man bei mkdocs mehr oder weniger automatisch vom Namen eines Markdown-Dokuments auf den Namen einer zugehörigen PDF-Datei kommen kann. Hintergrund ist das Szenario, dass man innerhalb einer mit mkdocs erstellten Dokumentation den Lesern die Möglichkeit bieten möchte, die einzelnen Artikel auch als PDF-Datei herunterzuladen. Die PDF-Dateien werden dabei nach dem mkdocs build-Lauf mittels pandoc aus den Markdown-Dateien erstellt, sodass zu jeder Markdown-Datei je eine PDF-Datei existiert, die denselben Basisnamen wie die Markdown-Datei, aber die Endung .pdf hat und an der entsprechenden Stelle im site-Verzeichnis liegt.
Folgende Randbedingungen sollen dabei beachtet werden:
- Die PDF-Datei soll auf den Artikel-Seiten mittels eines Links "Diese Seite als PDF herunterladen" zum Download angeboten werden.
- Dieser Link soll möglichst automatisiert erstellt werden.
- Nach Möglichkeit sollen die reinen Übersichtsseiten - also Seiten, die nur Links auf die eigentlichen Artikel-Seiten enthalten - diesen Link nicht anbieten.
Hinweis: Es dreht sich in diesem Artikel also auch darum, wie man innerhalb einer Template, die gerade gerendert wird, an den Namen der zugrundeliegenden Markdown-Datei kommen kann.
[Zurück zum Inhaltsverzeichnis]
2. Mögliche Lösungsansätze
Neben diversen Plugins, die aber alle den Nachteil haben, dass sie zusätzlich installiert werden müssen und teils unschöne Seiteneffekte mit sich bringen, kann die Aufgabe grundsätzlich auch mit den "Bordmitteln" von mkdocs gelöst werden. Bei der Untersuchung dieser "Bordmittel" haben sich zwei Wege als besonders geeignet herausgestellt, die jedoch beide auch ihre Vor- und Nachteile haben. In diesem Abschnitt sollen die beiden Wege kurz skizziert und die Vor- und Nachteile aufgezählt werden. Die technischen Details dazu finden sich im Abschnitt "Die Lösungsansätze im Detail".
Der erste Weg besteht darin, Markdown-Meta-Informationen einzusetzen. Dabei wird jeder Markdown-Datei ihr zugehöriger PDF-Name als Meta-Information mitgegeben.
Die Vorteile sind:
- Bei Markdown-Dateien, für die kein PDF-Link erstellt werden soll, lässt man die entsprechende Meta-Info einfach weg.
- Der Basisname der PDF-Datei kann bei Bedarf abweichend von dem der Markdown-Datei angegeben werden.
- Bei Bedarf ist es möglich, Pfade zur PDF-Datei mit anzugeben.
Die Nachteile dagegen:
- Jede bestehende Markdown-Datei, die einen PDF-Link erhalten soll, muss noch einmal explizit angefasst werden, um die Meta-Info einzupflegen.
- Wird der Basisname der Markdown-Datei geändert und ändert sich dadurch aufgrund des PDF-Erstellungsprozesses auch der Basisname der erzeugten PDF-Datei, darf nicht vergessen werden, die Meta-Info entsprechend anzupassen, sonst zeigt der PDF-Link ins Leere.
Der zweite Weg besteht darin, das Page-Objekt der jinja-Umgebung auszuwerten. Dieses wird von mkdocs automatisch mit diversen Informationen gefüllt und enthält – zumindest theoretisch – alles, was wir zur PDF-Link-Erstellung brauchen.
Die Vorteile sind:
- Die bestehenden Markdown-Dateien müssen nicht noch einmal angefasst werden.
- Änderungen des Basisnamens einer Markdown-Datei werden "automagisch" nachgezogen. Das ist gut, sofern der PDF-Erstellungsprozess diese Änderung auch "automagisch" mitzieht.
Es gibt aber auch Nachteile:
- Sollen für bestimmte Markdown-Dateien keine PDF-Links erstellt werden, ist dies nur in ganz engem Rahmen möglich. Mehr dazu im "Detail"-Abschnitt.
- Die Basisnamen von Markdown- und PDF-Datei sind immer miteinander "verheiratet", sprich: identisch. Abweichungen sind nicht möglich.
- Evtl. benötigte Pfade müssen einheitlich sein, also für alle PDF-Dateien immer gleich (i. d. R. relativ zur erstellten HTML-Datei).
[Zurück zum Inhaltsverzeichnis]
3. Die Lösungsansätze im Detail
Schlussendlich kocht alles darauf herunter, dass eine der Template-Dateien so angepasst wird, dass sie mithilfe der Möglichkeiten, die jinja bietet, den gewünschten PDF-Link erstellt. Für eine Beschreibung, wie man Templates anpasst, sei auf die entsprechenden Kapitel in der offiziellen mkdocs-Dokumentation verwiesen:
- Customizing Your Theme – für eine Beschreibung, wie man gezielt einzelne Elemente anpassen kann, ohne gleich ein komplettes Custom-Theme erstellen zu müssen.
- Developing Themes – für die Beschreibung, wie man das Aussehen der von mkdocs erstellten Seiten komplett selbst in die Hand nimmt.
Die in den folgenden Abschnitten gezeigten Code-Snipptes sind so ausgelegt, dass sie auf jeder Seite – Einbindung in die richtige Template vorausgesetzt –, die aufgrund eines der gewählten Verfahren einen PDF-Link erstellen würde, eine entsprechende Info in einer rot umrandeten Box anzeigen. Wie der zugrundeliegende jinja-Code arbeitet, wird in den folgenden Unterabschnitten ebenfalls erläutert.
[Zurück zum Inhaltsverzeichnis]
3.1. Meta-Informationen
Über die Markdown-Meta-Informationen können eine Reihe von Dingen gesteuert werden, z. B. kann man für einzelne Seiten gezielt den Titel (title-Tag und erzeugte Navigation) setzen. Siehe hierzu auch den Abschnitt Meta-Data in der mkdocs-Dokumentation.
Allerdings geht die offizielle Doku an der Stelle nicht weit genug ins Detail. Da ist folgende Seite m. E. hilfreicher: https://squidfunk.github.io/mkdocs-material/reference/
Hier erfährt man, dass man Meta-Infos mit beliebigen Namen platzieren und in der Template dann via page.meta.infoName abrufen kann, wobei infoName für den gewählten Namen steht.
Zum Beispiel kann man eine Quelldatei namens wrs.md mit folgendem "Vorspann" (die ersten drei Zeilen) beginnen lassen:
--- pdfName: wrs.pdf --- # Demo-Seite mit Meta-Info Sita usvilate inis taberce ines ...
Die Leerzeile nach dem zweiten --- ist dabei wichtig!
Dieser Vorspann setzt für die Markdown-Datei eine Meta-Info namens pdfName, die den Inhalt wrs.pdf hat. Das wiederum kann in der Template wie folgt ausgewertet werden:
{%- if page and page.meta and page.meta.pdfName %} <div style="border:1px solid red; border-radius:1em; padding:0.5em;"> <p style="margin:0; padding:0;">Für diese Seite ist der PDF-Name als Meta-Information gesetzt: <code>{{ page.meta.pdfName }}</code></p> </div> {%- endif %}
Die umschließende if-Anweisung stellt sicher, dass die Info-Box nur dann ausgegeben wird, wenn ein PDF-Name via Meta-Informationen gesetzt ist. Der Zugriff auf diese Information geschieht ganz einfach mittels {{ page.meta.pdfName }}. Wie daraus ein Link gebastelt wird, sollte klar sein.
[Zurück zum Inhaltsverzeichnis]
3.2. Page-Objekt
Bei der Verwendung des Page-Objekts müssen keine Vorbereitungen getroffen werden. Das Objekt kann direkt in der Template verwendet werden, z. B. so:
{%- if page %} <!-- {{ page }} --> <!-- {{ page.file }} --> {%- if page.file.name != 'index' %} <div style="border:1px solid red; border-radius:1em; padding:0.5em;"> <p style="margin:0; padding:0;">Für diese Seite wurde PDF-Name aus dem <code>page</code>-Objekt wie folgt ermittelt: <code>{{ page.file.name + '.pdf' }}</code></p> </div> {%- endif %} {%- endif %}
Die erste if-Anweisung stellt sicher, dass das Page-Objekt überhaupt verfügbar ist. Ist es das, werden zwei HTML-Kommentare erzeugt, die eine kurze Info über das Page-Objekt sowie das darin befindliche File-Objekt enthalten. Diese HTML-Kommentare sind nur zur Veranschaulichung gedacht und sollten im Live-Projekt nicht enthalten sein.
Die Zeile {%- if page.file.name != 'index' %} prüft, ob es sich bei der aktuellen Seite um eine Seite mit einem Artikel oder um eine reine Übersichtsseite handelt. PDF-Links sollen ja nur für Artikel-Seiten erzeugt werden. Vorsicht: Diese Vorgehensweise verlässt sich darauf, dass alle Übersichtsseiten – und nur diese – den Basisnamen index haben!
Ist es eine Artikel-Seite, wird eine entsprechende Info-Box ausgegeben. Den Namen der PDF-Datei erhält man mittels {{ page.file.name + '.pdf' }}. Wie daraus ein Link gebastelt wird, sollte klar sein. Interessant ist dabei der Umstand, dass page.file.name nur den Basisnamen der aktuellen Seite (also ohne die File-Extension) liefert; das war bei file.name – zumindest für mich – ein wenig unerwartet. Schaut man sich den erzeugten HTML-Code der Beispielseite wrs.md an, findet man in der vom eben beschriebenen jinja-Codeblock erstellten Ausgabe folgende HTML-Kommentare:
<!-- Page(title='Demo-Seite mit Meta-Info', url='/wrs/') --> <!-- File(src_path='wrs.md', dest_path='wrs/index.html', name='wrs', url='wrs/') -->
Hier sieht man, dass auch die anderen Infos wie z. B. die URL, der komplette Name der Markdown-Datei etc. zur Verfügung stehen.