Motivation

Übers Jahr verteilt veröffentlichen innoQ-Mitarbeiter zahlreiche Fachartikel zu unterschiedlichsten Themen in namhaften Fachmagazinen wie iX, JavaMagazin oder JavaSPEKTRUM. Seit zwei Jahren stellen wir eine Sammlung aller Artikel des Jahres in Form eines Buches zusammen – unser “Published”. In diesem Jahr haben wir uns vorgenommen, den Satz und die Erstellung des PDFs nicht wie in den Vorjahren einer Agentur zu überlassen, sondern uns selbst darum zu kümmern: Das Projekt “Printingpipeline” war geboren.

Technologieentscheidung

Als wir vor einiger Zeit unsere Webseite neugestaltet haben, hatte das damit betraute Projektteam die Entscheidung getroffen, sämtlichen Inhalt zukünftig in (Multi)-Markdown zu pflegen. Die Artikel die auf unserer Homepage [1] veröffentlicht werden und am Ende des Jahres den Weg ins Buch finden, liegen somit bereits im Markdown-Format vor. Die Druckerei, die das Buch drucken soll, erwartet für den Druck des Sammelbandes jedoch ein fertiges PDF-Datei. Wie kommen wir also effizient von Markdown zum druckfertigen PDF?

Dazu gab es zunächst eine gute Handvoll von Vorschlägen. Im Gespräch waren unter anderem:

Nach Recherchen, Experimenten und Diskussionen einigten wir uns, aus Markdown zunächst LaTeX zu erzeugen und aus diesem dann das PDF. LaTeX ist eine seit langem erprobte, funktionierende Technologie und bietet einen guten Mix aus eingebauter Funktionalität auf hohem Niveau bei gleichzeitiger Detailkontrolle, wo man sie braucht.

Weitere Informationen zum Thema: Multimarkdown

Markdown?, Multimarkdown?

Wie bereits erwähnt pflegen wir sämtlichen Content für die innoQ-Webseite im (Multi)-Markdown-Format. Doch worum handelt es sich bei Markdown überhaupt? Wo liegen die Vorteile? Wo liegen die Unterschiede zwischen Markdown und Mutlimarkdown?

Markdown ist eine vereinfachte Auszeichnungssprache, welche mithilfe von Konvertern in valides, W3C-konformes XHTML umgewandelt wird. Ein mit Markdown formatiertes Dokument ist in seiner Grundform schon lesbar und stört den Leser nicht durch Tags und andere Formatierungsbefehle. Markdown ist deswegen auch sehr einfach zu erlernen und besonders bei Autoren und Bloggern beliebt.

Hierzu ein Beispiel:

# Ich bin eine Überschrift auf der ersten Ebene

Dies in ein Absatz in Markdown. Mit Hilfe des Unterstrichs kann man
Wörter __fett__ oder _kursiv_ hervorheben. [Links][example] können
ebenfalls einfach eingebunden werden. Außerdem gibt es:

* Listen
* Grafiken
* Zitate
* u.v.m

[example]: http://www.example.org

Mit einem Markdown-Konverter kann der abgebildete Markdown-Quellcode in valides XHTML umgeformt werden. Der Konverter wandelt die Zeilen automatisch in HTML-konforme Überschriften (<h1>), Absätze (<p>), Listen (<ul>) usw. um.

Viele Content-Management-Systeme bieten die Möglichkeit, Inhalte in Markdown zu verfassen, oder können durch Plugins erweitert werden. Plattformen wie Github [2] und Stack Overflow [3] setzen ebenfalls auf Markdown.

Multimarkdown [4] ist eine Erweiterung der Markdown-Syntax und fügt Unterstützung für Tabellen, Fußnoten, Zitationen sowie Metadaten hinzu. Jedes korrekte Markdown-Dokument enthält dabei auch gleichzeitig valides Multimarkdown.

Im Vergleich zu Markdown besitzt Multimarkdown aber einen weiteren Vorteil: der Multimarkdown-Konverter kann nicht nur nach HTML konvertieren. Er unterstützt die Ausgabe ins OpenDocument-Format und nach LaTeX sowie indirekt über LaTeX die Ausgabe als PDF-Dokument. An dieser Stelle setzt die Printingpipeline zur Erstellung von Published 03 an.

Zum Ziel in kleinen Schritten

Die Konvertierung von Markdown nach PDF wurde als Abfolge von kleinen Verarbeitungsschritten geplant, nach denen immer wieder nachvollziehbare Zwischenergebnisse als Dateien auf der Festplatte liegen.

Abb. 1: Übersicht über die einzelnen Schritte der Pipeline

Die Verarbeitungsschritte sind im Einzelnen:

  1. MMD-Präprozessor: Bereitet Markdown für die Transformation zu LaTeX auf
  2. MMD-2-LaTeX-Konverter: Transformiert Markdown zu LaTeX
  3. LaTeX-Präprozessor: Bereitet den LaTeX-Code für die PDF-Konvertierung auf
  4. LaTeX-2-PDF-Konverter: Konvertiert den aufbereiteten LaTeX-Code in ein PDF

Angelehnt haben wir uns hier an das Architekturmuster “Pipes & Filters”. Die Pipes treten allerdings nicht als eigene Komponenten auf, sondern werden durch Zwischendateien ersetzt. Der MMD-2-LaTeX-Filter erwartet beispielsweise als Eingabe einen Artikel im Markdown-Format (.md) und liefert als Ergebnis den konvertierten Artikel in LaTeX (.tex).

Technologieentscheidung II

Nachdem über den grundsätzlichen Aufbau entschieden war, blieb die Frage, mit welcher Programmiersprache dieser Aufbau realisiert werden sollte. Wir waren uns einig, dass wir das Rad des Buildwerkzeugs nicht neu erfinden wollten. So standen in der engeren Auswahl zunächst Make, das Ruby-basierte Rake sowie die NodeJS-basierten Gattungsvertreter Grunt und Gulp.

Wir einigten uns schließlich auf einen auf Ruby und Rake [5] basierenden Ansatz, da wir hier auf die breite Erfahrung im Team zurückgreifen konnten. Außerdem existierte bereits ein Ruby-Wrapper für die offizielle Multimarkdown-Implementierung von einem unserer Kollegen. Die bereits erwähnten Verarbeitungsschritte wurden somit als Rake-Tasks in Ruby auskodiert: Rake koordiniert den Gesamtablauf.

Projekt-Setup

Die Printingpipeline wurde in einem verteilten Team entwickelt. Zentrum der Entwicklungsaktivität war ein privates GitHub-Repository. Dort entstand der Sourcecode; auch Fonts, Logos und anderes Artwork wurde dort abgelegt. Für spontane Diskussionen und Absprachen diente ein eigener Jabber-Chatraum. Das Projektmanagement (“Was muss getan werden und wer tut es?”) organisierten wir mit Hilfe von GitHub-Issues. In der Anfangsphase wurden Änderungen über Pull- Requests einem Review unterworfen, später wurde das Team zu klein dafür.

Der eigentliche Content (d.h. die Artikel) wird in einem eigenen Git-Repository verwaltet. Dieses Repository wurde als Git-Submodule in das Code-Repository der Printingpipeline eingebunden. So entfiel lästiges, händisches Aktualisieren des Content-Repositories und die Pipeline hat direkten Zugriff auf die Artikeldaten.

Markdown als Quellformat

Das Ausgangsformat war, wie bereits erwähnt, Markdown bzw. Multimarkdown, welches gleichermaßen im Content-Repository für die Webseite verwendet wird. Die Dateistruktur eines Artikels ist dabei folgendermaßen aufgeteilt:

Abb. 2: Dateistruktur eines Artikel

Eigene Erweiterungen

Zusätzlich zur Multimarkdown-Syntax existieren ein paar wenige innoQ-spezifische Besonderheiten.

Quellenangaben

Für Referenzen auf Quellen, die im Text erwähnt werden, verwenden wir auf der Webseite (HTML-)Fußnoten, welche in Markdown mit [^platzhalter-a] gesetzt und an anderer Stelle – meist am Ende der Datei – im Detail definiert werden. Dort werden dann Bücher oder Webseiten beschrieben und so auf der Webseite referenziert. Im Buch bauen wir daraus dann Bibitems, worauf in einem späteren Abschnitt noch näher eingegangen wird.

Sollen weitere Bücher oder Links über die aus dem Text referenzierten Quellen hinaus zur Verfügung gestellt werden, so werden diese als einfache Liste vor die Referenzen gesetzt.

Code-Blöcke

Für das Syntax-Highlighting der Listings wird Pygments [6] verwendet, wobei hinter den drei einleitenden Backticks des fenced codeblock die (Programmier-)Sprache definiert und nach einem Leerzeichen eine Captions als Beschreibung angegeben werden kann (siehe Listing 1).

Listing 1: Beispiel für die Auszeichnung eines Listings
# Eine Überschrift
Dieses Markdown innerhalb des Codeblocks wird nicht ausgewertet, sondern als Listing gesetzt.
Grafiken

Grafiken eines Artikels liegen i.d.R. im PNG-Format vor. Schematische Zeichungen und Diagramme sind außerdem oft im Vektorformat SVG vorhanden. Die Einbindung der Grafiken erfolgt jeweils identisch mit Platzhalter über ![][image_01], wobei die Bildressource ebenfalls meist am Ende der Datei im Detail definiert wird.

Kästen

Viele unserer Artikel enthalten “Kästen”. Ein Kasten stellt weiterführende Informationen zu einem bestimmten Thema bereit, steht jedoch in keinen chronologischen Zusammenhang zum Artikeltext. Die Zusatzinformationen zu (Multi)-Markdown im grauen Kasten dieses Artikels bilden hierfür ein Beispiel.

Die Kästen liegen als eigenständige Markdown-Dateien vor und werden ähnlich wie Bilder im Hauptartikel eingebunden. Die Einbindung erfolgt zusätzlich unter Verwendung des class-Attributs. So wird bei der Angabe des Dateinames des Kastens ein class="box" ergänzt und damit die Möglichkeit geschaffen, diese Kästen zu identifizieren:

[box_01]: ./box_markdown.html "weitere Informationen zum Thema: Multimarkdown" class="box"

Kästen können wiederum Bilder und Tabellen einbinden und verfügen ggf. über eigene Quellenverweise.

Druck-spezifische Inhalte

Neben den eigentlichen Artikeln beinhaltet ein Buch weitere Inhalte und Abschnitte. Hierzu zählen das Vorwort und im Fall von Published außerdem eine Autorenübersicht, Nachwort sowie eine Liste der Verlage und Zeitschriften. Diese Inhalte liegen ebenfalls als Markdown-Dateien vor und werden gleichermaßen in LaTeX konvertiert.

Software-Setup

Die Printingpipeline benutzt einen beachtlichen Fundus an Software:

Bei so einer Softwarefülle wird das Aufsetzen einer Entwicklungsumgebung schnell zu einem Puzzlespiel, auch weil wir auf unterschiedlichen Plattformen entwickelt haben. Deshalb entschieden wir uns, die Entwicklungsumgebung mithilfe von Docker zu virtualisieren. Wir erstellten ein Dockerimage auf Ubuntu-Basis, welches eine verschlankte Installation von TeXLive, Inkscape, Pygments und Ruby mit allen initial benötigten Bibliotheken enthält. Beim Aufruf der Pipeline im Dockercontainer wird die lokale Working-Copy des Repositories per Volume in den Container gemounted. Dadurch liest und schreibt der Container die Daten direkt in das lokale Verzeichnis, läuft aber in einer reproduzierbaren und gesicherten Umgebung.

Die Pipeline

Die Voraussetzungen waren nun gesammelt und das grobe Konzept stand fest. Die eigentliche Arbeit konnte beginnen.

Die Ablaufsteuerung der Printingpipeline bedient sich aus dem Fundus der Markdown-Dateien, die der innoQ-Webseite zugrunde liegen und auch ältere Artikel enthalten. Die Auswahl der jährlich aktuellen Artikel erfolgt über eine Liste, die als Datei in einer DSL erfasst wird, und die es erlaubt, zu jedem Artikel zusätzlich Metadaten zu definieren.

Ablaufsteuerung mit Rake

Rake bietet mit den FileTasks [7] ein Konstrukt, welches sich sehr gut für den “Build-Prozess” von Published eignet. FileTasks sind herkömmlichen Rake-Tasks sehr ähnlich, können jedoch zeitbasierte Abhängigkeiten enthalten. Hierzu ein Beispiel:

file 'article.tex' => 'article.md' do
  # Code für die LaTeX-Konvertierung
end

Rake:FileTasks werden mit dem Schlüsselwort file sowie mit einer Zieldatei als Namen (hier: article.tex) definiert. Zusätzlich wird in diesem Fall die Quelldatei article.md als zeitliche Abhängigkeit spezifiziert. Das Build-System kümmert sich von nun an um die Ausführung des Tasks. Der Task wird nur ausgeführt, wenn die Zieldatei nicht existiert oder älter als die Quelldatei ist, sprich: sich der Artikel verändert hat. Durch dieses Vorgehen werden die entsprechenden Verarbeitungsschritte nur ausgeführt, wenn es wirklich notwendig ist.

Die Ablaufsteuerung verwendet außerdem Rake:RuleTasks. RuleTasks [8] führen das Konzept der FileTasks fort und beziehen sich nicht auf eine konkrete Datei, sondern erlauben die Definition eines Regelwerks (z.B. über reguläre Ausdrücke).

Naming things

In diesem Absatz soll auf die Architekturentscheidung der Dateinamen durch die Printingpipeline eingegangen werden. Das Namensmuster spielt eine wichtige Rolle, da die Dateinamen die Abhängigkeitsbeziehungen der einzelnen Pipeline-Filter widerspiegeln.

Der MMD-Präprozessor nimmt einige Korrekturen am Markdown vor und speichert den abgeänderten Text in einer Datei mit dem Suffix _final.md. Aus dem Artikel (content.md) wird nach Ausführung des Präprozessors die Datei content_final.md erzeugt. Die Ausgabe des Präprozessors fungiert im nächsten Schritt als Eingabe des MMD-2-LaTeX-Konverters. Der MMD-2-LaTeX-Konverter speichert seine Ausgabe in die Datei article_pre.tex.

Mithilfe dieses Namensmusters und den Abhängigkeitsmechanismus von Rake haben wir die gesamte Ablaufsteuerung der Printingpipeline implementiert. Es wurden voneinander abhängige Rake-Task programmiert, welche jeweils eine klar definierte Ein- und Ausgabe besitzen und über das Build-System ausgeführt werden. Die Änderungen eines Filters können außerdem bequem über ein Diff-Tool nachvollzogen werden.

Die Filter der Pipeline

Im Folgenden werden die einzelnen Pipelineschritte beschrieben. Im ersten initialen Schritt werden die für das Buch spezifizierten Artikel samt aller Dateien in ein separates Arbeitsverzeichnis kopiert. Eventuell vorhandene Vektordateien (*.svg) werden zusätzlich für die leichtere Verwendung mit LaTeX ins PDF-Format konvertiert. Anschließend durchläuft jeder Artikel die Pipeline. Der erste Filter ist der Markdown-Präprozessor.

Der Markdown-Präprozessor

Der Markdown-Präprozessor nimmt Korrekturen an den Artikeln vor, bevor diese nach LaTeX konvertiert werden. So werden beispielsweise Tabellenköpfe und Codeblöcke in ein einheitliches Format umgeformt und Bildunterschriften korrigiert. Diese Korrekturen werden auf alle Markdown-Dateien (.md) angewandt.

Des Weiteren erfolgt eine Trennung der Artikelmetadaten und des Artikelinhalts. Die Ausgabe dieses Filters sind somit die Artikelmetadaten (metadata.md) und der durch den Präprozessor verarbeitete Abstract (abstract_final.md) sowie der Artikelinhalt (content_final.md).

Eine besondere Herausforderung war die Handhabung von Kästen sowie von Quellen/Verweisen eines Artikels. Quellen werden in LaTeX i.d.R. über Bibtex bzw. BibLaTeX gesetzt. Hierbei werden die Metadaten einer Quelle (z.B. Autoren, Erscheinungsdatum etc.) strukturiert in einer Datei gesammelt und im Text referenziert. Multimarkdown hingegeben liefert lediglich die Möglichkeit, einen Schlüssel mit einem unstrukturierten Metadatum zu verbinden. Wir mussten uns somit selbst um den Aufbau und die Gestaltung einer Referenzenliste bemühen. Im ersten Schritt suchen wir in allen Artikeldateien nach Referenzen und sammeln diese im Hauptdokument des Artikels. Im Anschluss erfolgt die Sortierung gemäß Artikelvorkommen bevor die Liste mit der Ruby Standard Template-Bibliothek ERB erstellt und als LaTeX-Fragment in das Hauptdokument eingebaut wird. Die Markdown-Datei content_final.md enthält somit bereits vor der LaTeX-Konvertierung gewisse Anteile von LaTeX-Code. Die Handhabung der Kästen erfolgt analog und wird ebenfalls in diesem Schritt als LaTeX-Fragment eingebunden.

Der MMD-2-LaTeX-Konverter

In diesem Filter wird aus den zuvor verarbeiteten Markdown-Dateien ein Artikel in LaTeX erstellt. Hierzu werden die Dateien abstract_final.md, content_final.md und metadata.md gemäß des eigens erstellten Makros (siehe Anschnitt Textsatz mit (Xe)LaTeX) in einen Artikel umgeformt und in der Datei article_pre.tex ausgegeben. Die LaTeX-Konvertierung wurde uns durch die Ruby-Bibliothek rmultimarkdown abgenommen. Die Zusammensetzung zu einem Artikel haben wir ebenfalls mit ERB durchgeführt. Die zuvor generierten LaTeX-Fragemente wurden unverändert in das Dokument übernommen.

Den LaTeX-Code gerade rücken

Analog zum Markdown-Präprozessor beinhaltet die Pipeline ebenfalls einen LaTeX- Präprozessor, welcher bereinigende Aufgaben am LaTeX-Code durchführt. Hierzu gehört beispielsweise die Substitution der SVG-Suffixe durch die PDF- Erweiterung (.pdf). Mit diesem Schritt tauschen wir die Vektorgrafiken durch die zuvor erstellten PDF-Versionen aus.

Da die Artikel ebenfalls auf unserer Webseite publiziert werden, können diese auch Hyperlinks auf Web-Ressourcen enthalten. Links müssen gesondert behandelt werden, um das Link-Ziel im Buch sichtbar zu machen. Wir haben uns zur Auszeichnung von Link-Zielen als Fußnoten geeinigt.

Die letzte Korrekturmaßnahme betrifft die Eindeutigkeit von Überschrift-Verweisen. Der MMD-2-LaTeX-Konverter erstellt für jede Überschrift ein Label, mit dem diese referenziert werden kann. Im Kontext des Buches könnten sonst Kollisionen mit Referenzen aus anderen Artikeln auftreten – die Überschrift Referenzen kommt z.B. in vielen Artikeln vor. Kollisionen werden durch Voranstellung eines eindeutigen Artikelpräfixes aufgelöst.

Vorwort, Autorenliste und Verlage

Statische Seiten, wie das Vorwort, werden in einem gesonderten Konvertierungsschritt verarbeitet und in das Hauptdokument des Buches eingebunden.

Die Erstellung der Autorenliste erfolgt dynamisch auf Grundlage der Artikel. Jeder Artikel enthält in den Metadaten die Kürzel der jeweiligen Autoren. Diese Kürzel werden global über alle Artikel hinweg gesammelt und für die Erstellung der Autorenliste genutzt. Detailinformationen wie Klarnamen, Kurzbiographie und Twitter-Nutzername sind über eine firmeninterne JSON-Ressource einsehbar. Die Autorenliste wird ebenfalls mithilfe der Template-Engine ERB erstellt und in das Hauptdokument des Buches eingebunden.

Auch die Verlagsliste wird dynamisch, aber ohne Zuhilfenahme der Artikelmetadaten erstellt. Die Informationen liegen in einer strukturierten JSON-Datei vor und werden während des Konvertierungsprozesses erstellt und eingebunden. Die Verwendung der Artikel-Metadaten ist als Optimierung für Zukunft geplant.

Textsatz mit (Xe)LaTeX

Das Ziel der Pipeline war es, den Textsatz möglichst maschinell und ohne manuelle und wiederkehrende Arbeit umzusetzen und dabei trotzdem nicht auf ein ansprechendes Design verzichten zu müssen. LaTeX ist bekannt für einen hervoragenden Textsatz, der auch mikrotypographische Feinheiten berücksichtigt, allerdings fristet es auch ein Nischen-Dasein in der akademischen Welt zum Satz von wissenschaftlichen Publikationen, an die in der Regel keine hohen gestalterischen Ansprüche gestellt werden. Die Herausforderung an den Textsatz mit LaTeX war also, das Ergebnis den gestalterischen Vorstellungen unserer Designerin entsprechen zu lassen.

Glücklicherweise hat sich in den vergangenen Jahren auch in der LaTeX-Welt einiges getan. So sind mit XeTeX und LuaTeX zwei TeX-Engines in der Lage, beliebige TrueType- und OpenType-Schriftarten zu setzen und können zudem problemlos mit Unicode arbeiten. Mit TikZ (“TeX ist kein Zeichenprogramm”) kann man auch komplexe Vektorgrafiken direkt in LaTeX “programmieren”.

Für die Pipeline haben wir zunächst eine eigene Dokumentenklasse angelegt. In ihr werden alle typografischen Konventionen für das Buch definiert. Unser Ziel war es, möglichst wenig Änderungen an dem von MultiMarkdown generierten LaTeX- Code vornehmen zu müssen. Der generierte Code ist leider nicht semantisch ausgezeichnet, sondern mutet eher pragmatisch an. Deshalb gehen einerseits oft Informationen wie “Diese Zelle ist ein Tabellenkopf” verloren, andererseits finden sich im generierten LaTeX-Code auch gestalterische Entscheidungen des MultiMarkdown-Autors wie Linien in den Tabellen wieder.

Glücklicherweise lassen sich alle Macros in LaTeX umdefinieren, so dass ein Monkey-Patching in solchen Fällen problemlos möglich war und einige der von MultiMarkdown generierten Befehle umdefiniert oder ignoriert werden konnten.

Als Basis haben wir die Buchklasse aus KOMA-Script gewählt, die für den exzellenten Textsatz nach deutschen Konventionen bekannt ist. Im Verlauf des Projekts mussten wir jedoch sehr viele Anpassungen vornehmen, so dass für die nächste Ausgabe des Buches zu überlegen ist, ob nicht eine weniger komplexe Basisklasse die bessere Wahl wäre.

Von unserer Designerin bekamen wir präzise Vorgaben. Neben der Seitengeometrie und des Seitenlayouts (Kolumnentitel, Schriftarten, Farben und Abstände) entwarf sie die Kapitelseiten der Artikel, den Schmutztitel, ein individuell gestaltetes Inhaltsverzeichnis sowie die Vorgaben für die Autoren- und Verlagslisten.

Die spannendste Aufgabe war die Umsetzung der Kapitelseiten, die sich tatsächlich punktgenau an der Designvorlage orientieren ließen. Die Seiten werden komplett mithilfe von TikZ gerendert. Die “Linienkunst” unter dem Abstract wurde in InDesign erstellt, als SVG exportiert und dann in TikZ-Pfade konvertiert. So bleiben die Linien als Vektorgrafiken erhalten und lassen sich für den Druck beliebig skalieren. Die zusätzlichen Parameter wie Autor, Magazin, Untertitel und Abstract wurden in spezielle Makros gekapselt, so dass ein Kapitelkopf semantisch ausgezeichnet wird, wie Listing 2 zeigt.

\chaptercolor{iqgreen}
\chapterauthor{John Doe}
\chaptersource{Magazin XY 01/2014}
\chaptersubtitle{Untertitel}
\chapterabstract{%
  ...
}
\chapter{Titel}
Listing 2: Beispiel für einen Kapitelkopf in LaTeX

Dieser Kopf wird von der Pipeline generiert, der Rest des Dokuments ist nahezu Standard-LaTeX. Jedes Kapitel ist in einem eigenen Verzeichnis mit all seinen Quellen und Bildern organisiert und wird in einer zentralen ‘document.tex’-Datei zusammengefahren. Eine Besonderheit sind die grau-unterlegten Kästen, die sich jedoch mithilfe des tcolorbox-Pakets leicht implementieren ließen.

Zunächst herausfordernd war der Satz des neuen Inhaltsverzeichnisses. LaTeX generiert die Inhaltsverzeichnisse vollautomatisch und geht davon aus, dass Verzeichniseinträge nur Titel und Seitenzahl enthalten. Um unserer Vorlage entsprechend auch die Autoren des Eintrags zu nennen, mussten einige Verrenkungen vorgenommen werden. Dank des etoc-Pakets blieben diese jedoch überschaubar.

Für die Autoren- und Verlagslisten wurden eigene Macros definiert, so dass die Pipeline aus den verfügbaren JSON-Daten nur diese Schnittstelle bedienen muss.

Neben diesen größeren Aufgaben mussten natürlich unzählige kleine Anpassungen an der LaTeX-Klasse vorgenommen werden, bis das Ergebnis unseren Anforderungen entsprach. Dank der Flexibilität von LaTeX gab es für (fast) alle Probleme eine Lösung, der Weg dorthin war mitunter jedoch mit einigem Aufwand verbunden.

Manuelle Nachbearbeitung

Ganz ohne eine manuelle Nachbearbeitung kamen wir schlußendlich leider doch nicht aus, da wir ein optisch ansprechendes Ergebnis vorweisen wollten. LaTeX macht bereits einen guten Job beim Textsatz, und versucht Bilder und Tabellen so sinnvoll wie möglich anzuordnen. Dennoch passieren dabei Fehler, die eine händische Nachkontrolle erfordern. Unser Ziel bei der Entwicklung der LaTeX- Klasse war, die manuellen Korrekturen so gering wie möglich zu halten.

Übrig geblieben ist hauptsächlich die Korrektur von ungeschickten Zeilen- oder Seitenumbrüchen, die bei einem 300+ Seiten Dokument doch einiges an Zeit beansprucht. Dabei erweist sich der Compiler-Ansatz von LaTeX als nachteilig, denn bei dieser Arbeit würde man sich ein visuelles Werkzeug wünschen.

Damit wir die manuellen Änderungen unabhängig von der Pipeline-Entwicklung durchführen konnten, haben wir das Generat in ein separates Git-Repository kopiert. Das Repository haben wir in zwei Branches unterteilt, einer für weitere Generate, ein anderer für die manuellen Änderungen. Somit konnten wir Änderungen, die durch nachfolgende Generator-Durchläufe entstanden sind, problemlos mit den manuellen Anpassungen mergen.

Fazit

Abb. 3: Published 03: Die Arbeit hat sich gelohnt

Das Projekt Printing-Pipeline war eine spannende Herausforderung für uns. Bei der Auswahl der Technologien waren wir zwar zuversichtlich, damit ein akzeptables Ergebnis zu erhalten. Dennoch konnten wir nicht so recht einschätzen, ob wir mit LaTeX auch den gestalterischen Aspekten gerecht werden können und wie viel Aufwand das Projekt insgesamt benötigen würde.

Rückblickend können wir sagen, dass wir die Entscheidungen genau so wieder treffen würden. Rake hat sich als effiziente und einfach zu benutzende Ablaufsteuerung verdient gemacht und mit (Xe)LaTeX konnten wir auch anspruchsvolle Designvorgaben erfolgreich umsetzen. Nichtsdestotrotz bleibt natürlich auch Raum für Verbesserungen. Auf der Eingabe-Seite wurde schnell offensichtlich, dass (Multi)Markdown nicht die geeignetste Auszeichnungssprache für gedruckte Bücher ist, da die Kreuzreferenzierung von Bildern, Listings, Tabellen und Referenzen nur sehr eingeschränkt möglich ist. Auf der LaTeX-Seite gibt es noch einige Punkte, die wir in der Nachbearbeitung adressiert haben, die wir in Zukunft aber schon bei der ersten Generierung bzw. global in der Dokumentenklasse lösen möchten, wie z.B. bestimmte Abstände oder das Umbruchverhalten zwischen Listings und Unterschriften.

Mit dem vorliegenden Ergebnis (siehe Bild) sind wir sehr zufrieden. Die Frage, ob man auch automatisiert anspruchsvoll anmutende Dokumente erstellen kann, ist aus unserer Sicht geklärt und lässt sich mit Sicherheit auch auf andere Domänen übertragen.

Referenzen

  1. Artikelübersicht auf der innoQ–Webseite, https://www.innoq.com/de/timeline/?type=articles  ↩

  2. http://www.github.com  ↩

  3. http://stackoverflow.com/  ↩

  4. http://fletcherpenney.net/multimarkdown  ↩

  5. Rake – Ruby Make, https://github.com/ruby/rake  ↩

  6. Ein Syntax Highlighter in Python, http://pygments.org/  ↩

  7. Blogeintrag über Rake: File Tasks, http://blog.envylabs.com/post/68063567445/rake-file-tasks  ↩

  8. Blogeintrag über Rake: Rule Tasks, http://blog.envylabs.com/post/79858773935/rake-rule-tasks  ↩