Vorlesungsfolien mit Markdown und HTML

Für eine Vorlesung zu Webtechnologien wäre es mehr als angebracht, die Präsentationsfolien ebenfalls mit Mitteln des Webs zu erstellen, also mit HTML. Hierfür habe ich mir einen Workflow mit Markdown zusammengestellt und ein paar Werkzeuge programmiert.

Vorlesungen verwenden heute sehr häufig Präsentationen. Üblicherweise erstelle ich meine Vorlesungsfolien mit Keynote, manchmal in schwachen Momenten auch mit PowerPoint. Für eine Vorlesung zu Webtechnologien erschienen mir diese Tools aber doch etwas unpassend. Schnell war also die Idee geboren, die Folien mit HTML zu erstellen und im Browser zu präsentieren. Hierdurch bestünde sogar die Möglichkeit, Folien zu gestalten in denen man Interaktiv HTML, CSS oder JavaScript-Konstrukte ausprobieren kann. Als Nebeneffekt kann man die Folien dann auch viel einfacher versionieren, als dies bei den binären Formaten der klassischen Präsentationsprogramme möglich wäre.

Frameworks für HTML-Präsentationen

Für HTMLbasierte Präsentationen gibt es einige Frameworks, z.B. impress.js, HTML5Slides, reveal.js oder deck.js, sie sich alle mehr oder weniger ähnlich sind: die Folien werden durch section- oder div-Elemente umschlossen, mit normalem HTML gefüllt und die Frameworks kümmern sich um das Blättern, die Navigation und eine ansprechende Darstellung.

Ein großes Problem der HTML-Slides ist allerdings die große Menge an HTML-Code, die man schreiben muss, um Tabellen, Listen etc. zu erhalten. Hierdurch werden die Folien schnell unübersichtlich und der eigentliche Inhalt ist nicht mehr so gut zu sehen.

Das folgende Beispiel zeigt eine solche Folie, die stark unter dem HTML leidet. Besonders das unweigerliche Escapen der HTML-Sonderzeichen macht den Text unübersichtlich. Und gerade in einer Präsentation zu Web-Technologien kommen sehr viele HTML-Tags vor.

<section>
  <h1>SGML-Wurzeln von HTML</h1>

  <ul>
    <li>SGML ist ein sehr komplexer Standard</li>
    <li>Theoretisch geht in HTML alles, was auch in SGML geht</li>
    <li>Browser benutzen keine SGML-Parser (tag soup parser)</li>
  </ul>

  <pre><code>&lt;!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"
          "http://www.w3.org/TR/html4/strict.dtd"&gt;
&lt;&gt;
&lt;title//
&lt;p&gt;&lt;b&gt;Hello SGML!&lt;/b&lt;/p&gt;
&lt;/&gt;</code></pre>
</section>

Markdown als Alternative zu HTML

Zum Schreiben von Dokumenten für das Web hat sich schon seit einiger Zeit Markdown etabliert, das es erlaubt sehr einfach Texte zu schreiben, die sich sowohl im Quelltext gut lesen lassen als auch hervorragend zu HTML transformieren. Bekannt geworden ist Markdown auch durch Github, bei dem Markdown das Standardformat für Readme-Dateien und Dokumentationen ist. Zusammen mit der Erweiterung Markdown-Extra hat man eigentlich alle Syntax-Elemente, um Folien zu erstellen. Es gibt leistungsfähige Editoren für Markdown, wobei ich persönlich MarkdownPad 2 und Mou verwende.

Über entsprechende JavaScript-Bibliotheken, z.B. showdown.js kann man Markdown auch in den HTML-basierten Folien verwenden, wodurch der Text deutlich besser zu lesen wird, wie folgendes Beispiel zeigt:

<section data-markdown>
# SGML-Wurzeln von HTML

  * SGML ist ein sehr komplexer Standard
  * Theoretisch geht in HTML alles, was auch in SGML geht
  * Browser benutzen keine SGML-Parser (tag soup parser)

<pre><code>&lt;!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"
		  "http://www.w3.org/TR/html4/strict.dtd"&gt;
&lt;&gt;
&lt;title//
&lt;p&gt;&lt;b&gt;Hello SGML!&lt;/b&lt;/p&gt;
&lt;/&gt;</code></pre>
</section>

Grundsätzlich bleiben aber zwei Probleme bei diesem Ansatz:

  • Alle Folien befinden sich in einem großen HTML-Dokument, das sich nur schwer modularisieren lässt
  • Trotz Markdown innerhalb der Folien muss man noch eine Menge HTML-Boilerplate mit sich herumschleppen.

Der Boilderplate-Code befindet sich am Anfang und am Ende jeder Präsentation und muss immer wieder kopiert werden. Möchte man den Code ändern, muss man alle Präsentationen anfassen, was grundsätzlich dem DRY-Prinzip widerspricht.

Anforderungen an die Lösung

Wie sähe denn der Wunsch-Workflow für meine Präsentationen aus?

  1. Die einzelnen Folien werden in HTML-freien, reinen Markdown-Dokumenten gespeichert. Ein Dokument kann beliebig viele Folien enthalten. Quelltexte können einfach mit der entsprechenden Markdown-Syntax aufgenommen werden.
  2. Die Folien werden durch Überschriften einer bestimmten Ebene untergliedert, ebenso können Kapitel durch Überschriften bestimmt werden.
  3. Innerhalb der Folien können Makros verwendet werden, die wiederkehrende Konstrukte bezeichnen, z.B. eine bestimmten Knopf um eine Demo zu starten.
  4. Verschiedene Dokumente können zu einer Präsentation zusammengefügt werden.
  5. Die Präsentation wird sowohl in HTML für die Vorführung in der Vorlesung als auch als PDF für das Ausdrucken zur Verfügung gestellt.
  6. Der Autor muss nur die Markdown-Dokumente schreiben, den Rest übernimmt eine automatische Toolchain, wobei durch den Einsatz von GnuMake bei Änderungen die Turnaround-Zeiten minimiert werden, da nur die Dateien verarbeitet werden, die sich geändert haben.

Ein echtes Goodie wäre noch, wenn auf den Folien enthaltene JavaScript, CSS oder HTML-Beispiele bei der Erzeugung der Druck-Version automatisch ausgeführt würden, sodass man auf dem Ausdruck nicht nur den Quelltest sondern auch das Ergebnis sehen würde. In der Vorlesung würde man den Code interaktiv ausführen, in der Druckvariante wäre das Ergebnis zu sehen.

Mit diesem Workflow könnte eine Präsentation wie folgt aussehen (verkürzt):

# Selektoren

## Aufbau einer CSS-Regel

Regel besteht aus __Selektor__ und __Deklarationen__

  * Der __Selektor__ legt fest, für welche Elemente die Regel gilt
  * Die __Deklarationen__ bestimmen die Darstellung der Elemente

![CSS Selektor](img/css_regel.svg)


## Unterschiedliche Selektoren

  * _Universal_ (_*_) – Alle Elemente
  * _Typ_ – Alle Elemente eines Typs (z.B. `<h1>`)
  * _ID_ (_#name_) – Element mit einer ID
  * _Kind_ (_a > b_) – Kinder von einem Element sind


## Universalselektor (*)

Wählt alle Elemente aus

    ```css
    /* Alle Elemente in mittelgrau darstellen */
    * { color: #7f7f7f; }

((Live-CSS html1))


## Pseudoklassen

| Klasse     | Beschreibung                             |
|------------|------------------------------------------|
| `:link`    | Link im originalen Zustand               |
| `:visited` | Link nachdem er angeklickt wurde         |
| `:hover`   | Link, wenn die Maus über dem Link steht  |

Die Konstruktion ((Live-CSS html1)) ist kein Markdown sonder eines der oben erwähnten, selbsterfundenen Makros, die automatisch bei der Erzeugung der HTML-Folien ersetzt werden.

Die gewählte Lösung

Um die oben genannten Ziele zu erreichen, habe ich mir folgende Tool-Chain gebaut:

Eine Präsentation besteht aus einem Verzeichnis, in dem sich beliebig viele Markdown Dateien befinden. Zusätzlich gibt es noch eine Metadaten-Datei, die Metadaten zur Präsentation enthält (Titel, Autor etc.). Im übergeordneten Verzeichnis gibt es noch ein Makefile, um die Erzeugung der Folien anzustoßen.

src
|
+--Makefile
|
+--css
|  +--metadata.properties
|  +--01_grundlagen.md
|  +--02_selektoren.md
|
+--javascript
   +--metadata.properties
   +--01_grundlagen.md
   +--02_funktionen.md

Um die Markdown-Dateien in HTML umzuwandeln verwende ich einen kleinen selbstgeschriebenen Markdown-Parser (markdown compiler, mdc). Es gibt zwar eine ganze Reihe von existierenden Parsern, ich wollte aber die volle Kontrolle über die Umwandlung haben, da ich verschiedene HTML-Dokumente für Druck und Anzeige benötige.

Der Parser liest alle Dateien eines Verzeichnisses ein und erzeugt dann zwei html-Dateien: eine für die Präsentation und eine für die PDF-Generierung.

Die HTML-Datei für die Präsentation kann man sofort im Browser anschauen, für das PDF muss man jedoch die Datei aus dem Browser drucken. Da die Toolchain automatisch sein soll, ist ein manueller Druck-Schritt nicht akzeptabel. Leider lässt sich das Drucken im Browser aber nicht skripten. Die Lösung besteht in PhantomJS einem “headless browser”, also einem Browser ohne grafische Oberfläche, den man über die Kommandozeile steuern kann. PhantomJS kann die Anzeige des Browsers als Grafikdateien und PDF ausgeben.

Der Workflow sieht damit wie folgt aus:

  .md-Dateien + Metadaten
            |
            v
      +-- [mdc] --+
      |           |
      v           v
 slide.html   print.html
      |           |
      |           v
      |      [PhantomJS]
      |           |
      v           v
  [Browser]   print.pdf

Mit Hilfe von MathJax können sogar Formeln in LaTeX-Notation in den Markdown-Dateien vorkommen und werden sowohl in der HTML-Datei für die Präsentation als auch im PDF ordentlich gesetzt.

Das Ergebnis kann sich durchaus sehen lassen.

Folie mit Quelltext

Folie mit Bullets

Folie mit ausführbarem Quelltext

Folie mit Tabellen

Folie mit Formeln

Zukünftige Erweiterungen

Die Lösung funktioniert zufriedenstellend. In Zukunft könnte man noch einige Erweiterungen vornehmen:

  • Ausgabe in anderen Formaten statt HTML, z.B. in LaTeX
  • Animationen in den Folien.