mkdocs – PDF-Namen generieren

Stand: 2022-05-04
Autor: Wolfgang R. Schulz

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:

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:

Die Nachteile dagegen:

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:

Es gibt aber auch Nachteile:

[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:

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.

[Zurück zum Inhaltsverzeichnis]