# Inside Quarkdown: Die Kompilier-Pipeline in sechs Stufen

> Teil 10 der Quarkdown-Reihe: Wie aus .qd-Quelltext fertiges HTML wird — Lexing, Parsing, Function-Call-Expansion, Tree-Traversal, Rendering, Post-Rendering und das Live-Preview-Doppelpuffern.

Source: https://www.jpkc.com/db/blog/quarkdown-inside-pipeline/

Dieser Teil ist für die Neugierigen. Du musst nichts davon wissen, um Quarkdown zu nutzen — aber wer verstehen will, *wie* aus einer `.qd`-Datei am Ende HTML wird, bekommt hier den Blick hinter die Kulissen. Nach dem [KI-Teil](https://www.jpkc.com/db/blog/quarkdown-ki-agent-skill/) wird es technisch: Quarkdown verarbeitet deinen Quelltext in einer **sequenziellen Pipeline aus sechs Stufen**, bei der die Ausgabe jeder Stufe die Eingabe der nächsten ist. (Die Architektur stammt aus der Bachelorarbeit des Autors — hier in Kurzform.)

## 1. Lexing: Text wird zu Tokens

Wie man einen Satz zuerst in einzelne Wörter zerlegt, scannt der **Lexer** die Quelle — eine reine Zeichenfolge — und zerteilt sie in **Tokens**: kleine Stücke mit Typ, Position und Inhalt. Markdown kennt zwei Kategorien: **Block**-Tokens (Absatz, Liste, Überschrift, Code, Zitat — die äußere Struktur) und **Inline**-Tokens (fett, kursiv, Links, Bilder — Formatierung *innerhalb* eines Blocks). Dafür gibt es zwei Lexer; Funktionsaufrufe werden sowohl als Block als auch als Inline erkannt. Zuerst läuft nur der Block-Lexer — die äußeren Blöcke gehen dann an den Parser.

## 2. Parsing: Tokens werden zum Baum

Der **Parser** ordnet die Tokens in einen **Abstract Syntax Tree (AST)** — eine Baumstruktur, deren Elemente *Nodes* heißen. Aus einer Überschrift, einem Absatz mit fettem Text und einer Liste wird so:

```text
AstRoot
├─ Heading(depth=1) → Text("Titel")
├─ Paragraph → Text("Das ist ") + Strong("fett") + Text(" Text")
└─ UnorderedList → ListItem → Paragraph → Text("Punkt 1")
```

Der Trick ist **rekursives Parsing**: Für jeden Block-Token stößt der Parser das Lexing auf dessen Innenleben erneut an, parst die inneren Tokens wieder, und so weiter — bis nichts Verschachteltes mehr übrig ist.

## 3. Function-Call-Expansion: hier passiert die Magie

Unter den Nodes gibt es einen besonderen: den `FunctionCallNode`. Er ist der **einzige veränderliche** Node — anfangs ohne Kinder, später vom *Function-Call-Expander* gefüllt. Quarkdown-Funktionen geben immer einen typgeprüften **`Value`** zurück, und ein *Value-Node-Mapper* übersetzt diesen in einen renderbaren Node: ein `StringValue` wird Text, ein `BooleanValue` eine Checkbox, ein `DictionaryValue` eine Tabelle, eine Collection eine Liste.

Für jeden Aufruf wird die Funktion in den geladenen Bibliotheken gesucht, Argumente an Parameter gebunden und die Funktion ausgeführt. Hier zeigt sich, wie Quarkdowns [dynamische Typisierung](https://www.jpkc.com/db/blog/quarkdown-funktionen-skripting/) mit der statisch typisierten Kotlin-Stdlib zusammenkommt: Beim Binden konvertiert eine `ValueFactory` dynamische Argumente in den statischen Parametertyp — scheitert das, gibt es einen Fehler. Genau das ist die Grenze zwischen „deinem" Markdown-Skript und der kompilierten Engine.

## 4. Tree-Traversal: das Dokument verstehen

Jetzt wird der fertige Baum **einmal** tiefendurchlaufen, um Querschnitts-Informationen zu sammeln: die Überschriften-Hierarchie fürs Inhaltsverzeichnis, die [Nummerierung](https://www.jpkc.com/db/blog/quarkdown-wissenschaftliches-schreiben/) jedes Elements und die Bindung von Link-Referenzen an ihre Definitionen. Aus Performance-Gründen gibt es nur *einen* Durchlauf — jede Aufgabe hängt ihren eigenen **Hook** an den Iterator, der bei passenden Node-Typen auslöst.

## 5. Rendering: Baum wird zum Zielformat

Der angereicherte AST wird — wieder tiefendurchlaufen — ins Zielformat übersetzt. Jeder Node erzeugt seine Ausgabe, idealerweise eins zu eins:

```html
<h1>Titel</h1>
<p>Das ist <strong>fett</strong> Text</p>
<ul><li>Punkt 1</li></ul>
```

Damit das skaliert, liegt jedes Renderziel in einem eigenen Modul (`quarkdown-html`, `quarkdown-plaintext`), das sich in den Kern einklinkt — so kommen perspektivisch weitere Zielformate dazu.

## 6. Post-Rendering: das ganze Dokument

Das Renderergebnis ist nur der `<body>`-Inhalt — Metadaten, Styling und Laufzeit fehlen noch. Der **Post-Renderer** (für HTML der `HtmlDocumentBuilder` über die `kotlinx.html`-DSL) baut das vollständige Dokument drumherum: Inhalt in den `<body>`, die richtigen Skripte und Stylesheets je nach Dokumenttyp, Titel, Seitenformat und Schriften — und lädt etwa **KaTeX nur dann**, wenn überhaupt eine Formel vorkommt. Am Ende liefert die Pipeline ein Bündel aus HTML, Stylesheets (global + Layout-Theme + Farb-Theme) und Runtime-Skripten zurück, das die CLI in Dateien schreibt.

## Bonus: Wie Live-Preview funktioniert

Die [Live-Preview aus Teil 8](https://www.jpkc.com/db/blog/quarkdown-cli-pdf-deployment/) ist ein hübsches Stück Engineering. Der eingebaute Webserver hält per **WebSocket** (`/reload`) eine Verbindung zum Browser; nach jeder Kompilierung sendet die CLI eine Nachricht, der Server broadcastet sie, der Browser lädt neu. Damit es beim Neuladen nicht flackert, nutzt Quarkdown **Double Buffering** mit zwei Iframes: Während `A` sichtbar bleibt, rendert das Update in `B`; ist es fertig, wird umgeschaltet — inklusive Wiederherstellung der Scroll-Position. Dasselbe Prinzip, mit dem deine GPU Frames zeichnet.

## FAQ

### Muss ich die Pipeline kennen, um Quarkdown zu nutzen?

Nein, kein bisschen. Dieser Teil ist reines Hintergrundwissen für technisch Interessierte. Für die tägliche Arbeit genügt alles aus den Teilen 1 bis 9.

### Warum ist der `FunctionCallNode` der einzige veränderliche Node?

Weil sein Inhalt erst *nach* dem Aufbau des Baums entsteht — nämlich durch das Ausführen der Funktion. Alle anderen Nodes stehen mit ihrer Erzeugung fest; der Funktionsaufruf füllt seine Kinder dagegen erst in der Expansionsstufe.

### Kann Quarkdown andere Formate als HTML ausgeben?

Ja — Rendering und Post-Rendering liegen in austauschbaren Modulen. Neben HTML existiert bereits ein Plaintext-Renderer; die Architektur ist bewusst darauf ausgelegt, weitere Ziele anzudocken.

## Weiterlesen

Den anwendungsnahen Vorgänger bildet [Teil 9: Quarkdown & KI](https://www.jpkc.com/db/blog/quarkdown-ki-agent-skill/). Im letzten Teil dieser Reihe sammle ich **Tipps & Tricks** aus allen vorherigen Themen — die kleinen Kniffe, die den Alltag mit Quarkdown leichter machen. Die ausführliche Pipeline-Dokumentation steht in der [offiziellen Wiki](https://quarkdown.com/wiki/pipeline).

