Befreiung vom digitalen Überfluss

E-Books mit HUGO

Ein epub-Theme für den Static Site Generator HUGO

Der Static Site Generator HUGO ist sehr vielseitig und kann nicht nur HTML-Seiten erzeugen, sondern auch andere Dateiformate wie z.B. JSON oder XML. Das weit verbreitete E-Book-Dateiformat epub ist eigentlich nur ein Zip-Ordner, der aus einer festgelegten Struktur von XHTML-Dateien, Bildern und ein paar Metadaten besteht. Deshalb bin ich auf die Idee gekommen, ein HUGO-Theme zu entwickeln, das ohne weitere manuelle Eingriffe aus dem HUGO-Content-Ordner direkt ein E-Book erzeugt. So wird es z.B. möglich, ganz einfach ein vorhandenes HUGO-Blog auch zum Download als E-Book anzubieten bzw. mit Markdown formatierte Texte direkt in sauber formatierte, valide E-Books umzuwandeln.

» Download epub-theme.zip «


Das epub-Format

Ich habe mich entschieden, das neuere epub3-Format zu verwenden. Die Dateistruktur sieht wie folgt aus:

├── mimetype
├── META-INF
│   └── container.xml
└── OEBPS
    ├── chapter
    │   ├── chapter-1.xhtml
    │   ├── chapter-1
    │   │   ├── image-1-1.jpg
    │   │   └── image-1-2.jpg
    │   ├── chapter-2.xhtml
    │   ├── chapter-3.xhtml
    │   ├── chapter-3
    │   │   └── image-3.jpg
    │   ...
    │
    ├── content.opf
    ├── cover.jpg
    ├── css
    │   └── stylesheet.css
    ├── inhaltsverzeichnis.xhtml
    ├── titelseite.xhtml
    └── toc.ncx

Das HUGO-epub-Theme

So erzeugt dieses Theme die Dateien:

  • mimetype, container.xml und stylesheet.css sind statische Dateien die im theme-Ordner static/ liegen
  • cover.jpg liegt im Ordner static/OEBPS

Der Rest der Dateien wird dynamisch aus dem Content des HUGO-Projects erzeugt:

content
├── _index.md
├── inhaltsverzeichnis.md
├── posts
│   ├── chapter-1
│   │   ├── image-1-1.jpg
│   │   ├── image-1-2.jpg
│   │   └── index.md
│   ├── chapter-2.md
│   └── chapter-3
│       ├── image-3.jpg
│       └── index.md
└── titelseite.md


_index.md erzeugt über die Konfiguration in config.toml und dem Theme-Layout die zentralen Dateien content.opf und toc.ncx. Die Einstellung

cascade:
  _build:
    publishResources: false

im Front Matter sorgt dafür, dass nur die skalierten Bilder im E-Book-Ordner landen und die Originaldateien nicht mit kopiert werden – was HUGO sonst standardmäßig machen würde.

inhaltsverzeichnis.md und titelseite.md erzeugen diese notwendigen Seiten im E-Book. Diese Dateien dürfen nicht gelöscht oder umbenannt werden. Der Inhalt kommt aus config.toml. Im Front Matter sorgt der Parameter

ebook: toc

bzw.

ebook: cover

dafür, dass das Template single.xhtml diese Sonderfälle abweichend vom Standard behandelt.

Das eigentliche Theme-Layout unter themes/epub/layouts besteht aus nur drei Dateien:

├── _default
│   └── single.xhtml
├── index.ncx
├── index.opf


single.xhtml erzeugt alle xhtml-Seiten, index.ncx ist die Vorlage für toc.ncx und index.opf erzeugt content.opf. Das alles wird von config.toml gesteuert. Diese drei Dateien brauchen im Normalfall nicht verändert werden. Wenn die Sortierreihenfolge der Seiten geändert werden soll (vorgegeben ist: nach Datum aufsteigend), müsste in allen drei Dateien das {{ range ( where .Site.RegularPages "Section" "ne" "" ).ByPublishDate }} an insgesamt vier Stellen modifiziert werden.
Außerdem müssen alle im E-Book verwendeten Dateien im Manifest von content.opf angemeldet werden. Das passiert bei allen Dateien aus dem Content-Ordner automatisch. Sollten aber z.B. statische Bilder in den Seiten referenziert sein, müssten diese manuell im Manifest ergänzt werden. Das passiert in index.opf.

config.toml enthält alle Meta-Daten zum Buch und sorgt dafür, dass die korrekte Dateistruktur erzeugt wird:

  • Mit disableKinds wird fast alles abgestellt, was HUGO standardmäßig macht. Wir erzeugen nur noch Output für Pages und für die Root-Datei _index.md.
  • permalinks spielt eine wichtige Rolle. Hier muss der Pfad für jede Section, die in content/ enthalten ist, definiert werden. Vorgegeben habe ich einen Eintrag für “posts”. Sollte es andere bzw. weitere Sections (das sind die Ordner direkt unterhalb von content/) geben, muss jeweils eine Zeile ergänzt werden.
  • mediaTypes, outputFormats und outputs definieren die drei Dateiformate, die von HUGO dynamisch erzeugt werden sollen: xhtml, opf und ncx. Entsprechende Templates befinden sich im layouts/-Verzeichnis des Themes.
  • markup steuert die Interpretation der Markdown-Dateien und kann nach eigenem Belieben angepasst werden. Nicht geändert werden darf die Einstellung xHTML = true.
  • params enthält die Metadaten zum Buch (Buchtitel, Autor usw.). Außerdem wird vorgegeben, wie die Bilder skaliert werden sollen. Alte E-Book-Reader scheinen Probleme mit jpg-Dateien zu haben (zumindest mein uralter Kindle). Daher verwende ich für meine E-Books das png-Format.

Schritt-für-Schritt-Anleitung

  • epub-Theme runterladen und auspacken.
  • Das Theme ist sofort lauffähig. Der Aufruf von “hugo” im HUGO-Rootverzeichnis des Projekts erzeugt im public-Ordner das Demo-E-Book – allerdings noch ungepackt.
  • um das gewünschte epub-Format zu erhalten, muss der Inhalt des public-Verzeichnisses gezipt werden. Das Zip-Archiv muss die Endung .epub erhalten. Fertig! Wichtig: die Datei mimetype muss die erste Datei im Zip-Archiv sein. Der Aufruf von Zip sollte also (z.B.) so lauten
    # cd public
    # zip -rX ../ebook.epub mimetype OEBPS META-INF
    um ein E-Book mit dem Namen ebook.epub zu erzeugen, das im HUGO-Rootverzeichnis liegt.
  • Um keinen Dateimüll im fertigen E-Book zu haben, sollten das public/-Verzeichnis und die zip/epub-Datei vor der Neu-Erzeugung des E-Books gelöscht werden. Für Linux ist ein deploy-Bash-Skript im Theme enthalten, das alle Schritte automatisch macht.
  • Um nun ein eigenes E-Book zu erzeugen, müssen nur die Metadaten in config.toml angepasst und im Ordner content/posts/ die Page-Resources gegen den eigenen Content im Markdown-Format ausgetauscht werden.
  • Außerdem sollte die Datei static/OEBPS/cover.jpg gegen ein eigenes Cover (idealerweise im Hochformat) ausgetauscht werden (Dateiname und -Format nicht ändern).

Was man sonst noch wissen sollte

Ich verwende HUGO Page Bundles um die Bilder automatisch verwalten zu können. Wer Bilder in seine Ressourcen integrieren möchte, kann dies mit dem Shortcode
{{< image src="Bildname" caption="Bildbeschriftung" >}}
machen. Es reicht, einen Teilstring des Bildnamens anzugeben, so lange er eindeutig ist. Mein Theme unterstützt derzeit nur jpg- und png-Bilder. Die automatische Ermittlung des Mimetypes im Manifest von content.opf ist vielleicht noch verbesserungswürdig und kann bei Bedarf in index.opf angepasst werden. Generell sollten alle Datei- und Ordnernamen ohne Sonderzeichen auskommen, da das zu Validierungsfehler führen kann.

Wer statische Bilder aus dem static/-Ordner einbinden will, muss drei Sachen beachten:
1. Die Bilder müssen im Verzeichnis static/OEBPS/ liegen.
2. Jede Bilddatei muss im Manifest (im Template index.opf) aufgeführt werden. Der bereits vorhandene Eintrag für cover.jpg kann als Beispiel dienen.
3. Die Dateien müssen im Content relativ adressiert werden, also im Regelfall z.B.
![Alt-Text](../mein-bild.jpg)

Epub-Dateien mit Validierungsfehlern werden im Regelfall trotzdem von den Readern angezeigt. Es ist aber natürlich besser, wenn das E-Book formal fehlerfrei ist. Die sehr empfehlenswerte E-Book-Managementsoftware Calibre bietet die Möglichkeit, Bücher zu bearbeiten und in dem Zusammenhang auch auf Fehler zu prüfen und zu debuggen. Weitere Validatoren: Epub online Validator und pagina EPUB-Checker (Freeware)

Es gibt bei der automatischen Erzeugung vom Manifest in content.opf und dem Inhaltsverzeichnis (single.xhtml) einen Hack, für die mir keine bessere Lösung eingefallen ist. HUGO würde bei relativen URLs Pfade erzeugen, die z.B. so aussehen: ../OEBPS/chapter/chapter-1.xhtml. Das ist zwar theoretisch korrekt, aber manche E-Book-Reader (und auch Calibre) kommen damit nicht gut zurecht und zerstören die Kapitelreihenfolge. Ich korrigiere den Pfad deshalb durch ein nachträgliches Replace. Ich schneide ../OEBPS/ vom Pfad ab, so dass er dann z.B. so aussieht: chapter/chapter-1.xhtml.

Bei manuellen internen Links zwischen Artikeln sind die automatischen relativen HUGO-Pfade übrigens kein Problem. Hierfür sollte der interne ref-Shortcode verwendet werden.

Es gibt außerdem zwei Shortcodes, die die Titelseite erzeugen und bei Bedarf angepasst werden können: cover.html und covertext.html

Der Placeholder NoIntrotext: true im Front Matter sorgt dafür, dass in der betreffenden Seite kein Introtext unter dem Titel ausgegeben wird.


© Titelbild: Br. Felix Weckenmann OSB, Erzabtei Beuron


« Home | Matomo cookiefrei »