Add support for appendices: landscape diagrams, tables, and images; implement Kroki URL configurability; enhance directive parsing logic.

This commit is contained in:
Sebastian Unterschütz
2026-05-12 21:44:37 +02:00
parent 436cdcc516
commit 67f9d63f24
12 changed files with 1025 additions and 221 deletions
+278 -40
View File
@@ -19,20 +19,25 @@ abbreviations:
meaning: "Abstract Syntax Tree"
- abbr: "DIN"
meaning: "Deutsches Institut für Normung"
- abbr: "YAML"
meaning: "YAML Ain't Markup Language"
glossary:
- term: "Goldmark"
definition: "Ein in Go geschriebener Markdown-Parser, der den CommonMark-Standard implementiert."
definition: "Ein in Go geschriebener Markdown-Parser, der den CommonMark-Standard implementiert und durch Erweiterungen (Tabellen, YAML-Frontmatter) ergänzt werden kann."
- term: "FPDF"
definition: "Eine Go-Bibliothek zur Erzeugung von PDF-Dokumenten ohne externe Abhängigkeiten."
definition: "Eine Go-Bibliothek zur Erzeugung von PDF-Dokumenten ohne externe Systemabhängigkeiten."
- term: "Kroki"
definition: "Ein Webdienst, der verschiedene Diagramm-Beschreibungssprachen (Mermaid, PlantUML u.a.) in Bilder umwandelt."
definition: "Ein Webdienst, der verschiedene Diagramm-Beschreibungssprachen (Mermaid, PlantUML u.a.) serverseitig in Bilder umwandelt."
- term: "Zwei-Pass-Rendering"
definition: "Verfahren, bei dem ein Dokument zweimal gerendert wird: Der erste Durchlauf ermittelt Seitenzahlen, der zweite nutzt diese für das Inhaltsverzeichnis."
---
# Vorwort
Dieses Projekt entstand im Rahmen der Abschlussprüfung zum Fachinformatiker
Fachrichtung Anwendungsentwicklung. Es soll zeigen, dass technische Dokumentationen
effizient und normgerecht erstellt werden können.
Fachrichtung Anwendungsentwicklung. Es soll zeigen, dass technische
Dokumentationen effizient und normgerecht erstellt werden können ohne
manuelle Nachbearbeitung in einer Textverarbeitung.
# 1. Problemstellung
@@ -41,70 +46,303 @@ effizient und normgerecht erstellt werden können.
Aktuell müssen IHK-Dokumentationen mühsam in Word formatiert werden, was
fehleranfällig ist und viel Zeit kostet. Besonders die Einhaltung der
Formvorgaben Schriftgröße, Zeilenabstand und Seitenränder erfordert
manuelle Sorgfalt bei jedem Absatz.
manuelle Sorgfalt bei jedem Absatz. Änderungen am Inhalt erzwingen
regelmäßig manuelle Korrekturen an der Formatierung.
## 1.2 Zielsetzung
Ziel ist ein Go-Tool, das **Markdown** in PDF umwandelt und dabei alle
formalen Anforderungen der IHK Chemnitz erfüllt. Es soll:
formalen Anforderungen der IHK Chemnitz automatisch erfüllt. Das Tool soll:
- die Prüfungsvorbereitung erleichtern, die Qualität der Dokumente *einheitlich* sicherstellen unddie Qualität der Dokumente *einheitlich* sicherstellen unddie Qualität der Dokumente *einheitlich* sicherstellen unddie Qualität der Dokumente *einheitlich* sicherstellen unddie Qualität der Dokumente *einheitlich* sicherstellen unddie Qualität der Dokumente *einheitlich* sicherstellen unddie Qualität der Dokumente *einheitlich* sicherstellen unddie Qualität der Dokumente *einheitlich* sicherstellen unddie Qualität der Dokumente *einheitlich* sicherstellen unddie Qualität der Dokumente *einheitlich* sicherstellen unddie Qualität der Dokumente *einheitlich* sicherstellen unddie Qualität der Dokumente *einheitlich* sicherstellen unddie Qualität der Dokumente *einheitlich* sicherstellen unddie Qualität der Dokumente *einheitlich* sicherstellen unddie Qualität der Dokumente *einheitlich* sicherstellen und
- die Prüfungsvorbereitung erleichtern,
- die Qualität der Dokumente *einheitlich* sicherstellen und
- den Prozess vollständig automatisieren.
- den gesamten Formatierungsprozess vollständig automatisieren.
Besondere Anforderung ist die Einhaltung der **DIN 5008**-Norm sowie der
spezifischen Vorgaben der IHK Chemnitz (Korrekturrand 4 cm rechts,
Schriftart Arial/Helvetica 12 pt, 1½-zeiliger Abstand).
# 2. Projektablauf
## 2.1 Planung
## 2.1 Planung und Zeitrahmen
Die Planung umfasst die Analyse der IHK-Vorgaben und das Design der
Software-Architektur. Der Projektzeitraum beträgt maximal 80 Stunden
gemäß Ausbildungsverordnung.
### Architektur-Übersicht
@Tabelle: Projektphasen mit Zeitplanung
| Phase | Aufgabe | Stunden |
|-------|---------|---------|
| 1 | Anforderungsanalyse und Recherche der IHK-Vorgaben sowie DIN 5008 Normen | 8 |
| 2 | Architekturentwurf und Auswahl geeigneter Go-Bibliotheken (Goldmark, FPDF) | 10 |
| 3 | Implementierung des Markdown-Parsers mit AST-Traversierung | 20 |
| 4 | Implementierung des PDF-Renderers mit allen IHK-Elementen | 24 |
| 5 | Tests, Fehlerkorrektur und Dokumentation | 12 |
| 6 | Puffer und Abnahme | 6 |
## 2.2 Architektur
Die Software ist in Go implementiert und folgt einer klaren Trennung
zwischen Parsing und Rendering. Das Zwei-Pass-Verfahren ermöglicht ein
korrektes Inhaltsverzeichnis mit Seitenzahlen.
@DiagrammQuer: Systemarchitektur des Konverters Zwei-Pass-Rendering
```mermaid
graph TD
A[Markdown] --> B(Go Parser)
B --> C{Metadaten?}
C -->|Ja| D[Config]
C -->|Nein| E[Standard]
D --> F[PDF Renderer]
E --> F
F --> G[IHK-konformes PDF]
graph LR
subgraph Eingabe
MD[report.md]
CFG[YAML Frontmatter]
end
subgraph Parsing
P(ParseMarkdown)
AST[Goldmark AST]
end
subgraph Pass1[Pass 1 - Seitenzahlen ermitteln]
R1[IHKRenderer]
TOC[tocItems mit Seitenzahlen]
end
subgraph Pass2[Pass 2 - Finales PDF]
R2[IHKRenderer]
PDF[projektarbeit.pdf]
end
MD --> P
CFG --> P
P --> AST
AST --> R1
R1 --> TOC
TOC --> R2
AST --> R2
R2 --> PDF
```
## 2.2 Realisierung
### Modulstruktur
Die Realisierung erfolgt in Go unter Verwendung von `goldmark` und `fpdf`.
Der Konverter verarbeitet die Markdown-Datei in zwei Durchläufen, um das
Inhaltsverzeichnis korrekt mit Seitenangaben zu befüllen.
Der Konverter ist in neun fokussierte Go-Dateien aufgeteilt:
| Werkzeug | Zweck | Version |
|----------|-------|---------|
| Go | Programmiersprache | 1.22+ |
| Goldmark | Markdown-Parser (AST) | v1.8 |
| FPDF | PDF-Erzeugung | v0.9 |
| Kroki | Diagramm-Rendering | online |
- **`main.go`** Einstiegspunkt, CLI-Flags, Zwei-Pass-Pipeline
- **`config.go`** YAML-Konfigurationsstruktur
- **`markdown_parser.go`** Goldmark-AST-Traversierung
- **`pdf_renderer.go`** Kern-Struct `IHKRenderer`, DIN-5008-Konstanten
- **`pdf_content.go`** Inhalts-Renderer (Absätze, Listen, Tabellen, Code, Bilder)
- **`pdf_toc.go`** Verzeichnis-Renderer (Inhalts-, Tabellen-, Abbildungsverzeichnis)
- **`pdf_pages.go`** Seiten-Renderer (Titelseite, Anhang, Erklärung, Glossar)
- **`pdf_numbering.go`** Seitennummerierung (Römisch / Arabisch)
- **`diagram.go`** Kroki-Diagramm-Rendering mit SHA-256-Cache
## 2.3 Realisierung
Die Realisierung erfolgt in Go unter Verwendung von `goldmark` für das
Markdown-Parsing und `fpdf` für die PDF-Erzeugung.
@Tabelle: Eingesetzte Bibliotheken und Werkzeuge
| Werkzeug | Zweck | Version | Lizenz |
|----------|-------|---------|--------|
| Go | Programmiersprache und Laufzeitumgebung | 1.22+ | BSD |
| Goldmark | Markdown-Parser mit CommonMark-konformem AST | v1.8 | MIT |
| goldmark-meta | YAML-Frontmatter-Erweiterung für Goldmark | v1.1 | MIT |
| FPDF | PDF-Erzeugung ohne externe Systemabhängigkeiten | v0.9 | MIT |
| Kroki | Diagramm-Rendering für Mermaid und PlantUML | online | Apache 2.0 |
@Quelle: Goldmark Documentation, https://github.com/yuin/goldmark, 2024
@Quelle: Go-PDF/Fpdf Documentation, https://github.com/go-pdf/fpdf, 2025
## 2.3 Test und Qualitätssicherung
### Implementierungsbeispiel: Tabellen-Renderer
Das Tool wurde anhand eines Musterdokuments getestet. Folgende Kriterien
Der folgende Ausschnitt zeigt die Kernlogik des mehrzeiligen Tabellen-Renderers.
Jede Zelle wird mit `SplitLines` vorgemessen; anschließend werden alle Zellen
einer Zeile auf einheitliche Höhe gebracht:
```go
func (r *IHKRenderer) prepareRow(rawCells []string, numCols int,
colW, lineHt float64, bold bool) tableRowData {
r.pdf.SetFont("Helvetica", map[bool]string{true: "B", false: ""}[bold], dinFontCaption)
cells := make([][]string, numCols)
maxLines := 0
for j := 0; j < numCols; j++ {
raw := ""
if j < len(rawCells) {
raw = rawCells[j]
}
split := r.pdf.SplitLines([]byte(r.tr(raw)), colW-2)
lines := make([]string, len(split))
for k, b := range split {
lines[k] = string(b)
}
if len(lines) == 0 {
lines = []string{""}
}
cells[j] = lines
if len(lines) > maxLines {
maxLines = len(lines)
}
}
return tableRowData{cells: cells, height: float64(maxLines) * lineHt}
}
```
## 2.4 Test und Qualitätssicherung
Das Tool wurde anhand dieses Musterdokuments getestet. Folgende Kriterien
wurden geprüft:
1. Korrekte Seitenränder gemäß DIN 5008
2. Seitennummerierung (römisch im Vorspann, arabisch im Textteil)
3. Schriftart Helvetica, 12 Punkt, 1½-zeilig
4. Automatische Abbildungs- und Tabellenverzeichnisse
1. Korrekte Seitenränder gemäß DIN 5008 (links 3 cm, rechts 4 cm Korrekturrand)
2. Seitennummerierung römisch im Vorspann (ab II), arabisch im Textteil (ab 1)
3. Schriftart Helvetica, 12 Punkt, 1½-zeiliger Abstand (6,35 mm Zeilenhöhe)
4. Automatisch generierte Verzeichnisse (Inhalt, Tabellen, Abbildungen)
5. Mehrzeilige Tabellenzellen mit einheitlicher Zeilenhöhe pro Tabellenzeile
6. Nummerierende Code-Blöcke mit Zeilennummern-Gutter
7. Listen mit korrektem hängendem Einzug (zweite Zeile bündig mit Text)
8. Tabellen als Anhang über die Direktive `@TabelleAnhang:`
# 3. Zusammenfassung
@Tabelle: Testergebnisse der Qualitätssicherung
Das Tool ermöglicht eine effiziente Erstellung von IHK-Dokumentationen unter
Einhaltung **aller** Formatvorgaben. Durch die Trennung von Inhalt (Markdown)
und Formatierung (Go-Renderer) ist eine konsistente Ausgabe garantiert.
| Kriterium | Erwartet | Ergebnis | Status |
|-----------|----------|----------|--------|
| Linker Seitenrand | 30 mm | 30 mm | Bestanden |
| Rechter Seitenrand (Korrekturrand) | 40 mm | 40 mm | Bestanden |
| Schriftgröße Fließtext | 12 pt | 12 pt | Bestanden |
| Zeilenabstand Fließtext | 6,35 mm (1,5-fach) | 6,35 mm | Bestanden |
| Römische Nummerierung Vorspann | ab Seite II | ab Seite II | Bestanden |
| Arabische Nummerierung Textteil | ab Seite 1 | ab Seite 1 | Bestanden |
| Mehrzeilige Tabellenzellen | einheitliche Zeilenhöhe | einheitliche Zeilenhöhe | Bestanden |
# 3. Verwendung der Direktiven
## 3.1 Quellenangaben und Bibliografie
Quellenangaben werden mit der Direktive `@Quelle:` eingefügt und am Ende
des Dokuments alphabetisch sortiert im Literaturverzeichnis ausgegeben.
Die Direktive kann an beliebiger Stelle im Dokument stehen.
## 3.2 Benannte Tabellen
Mit `@Tabelle: Tabellenname` unmittelbar vor einer Markdown-Tabelle wird
der Tabelle ein Name gegeben. Dieser erscheint im Tabellenverzeichnis:
```
@Tabelle: Übersicht der Programmiersprachen
| Sprache | Paradigma | Typsystem |
|---------|-----------|-----------|
| Go | Imperativ | Statisch |
| Python | Multi | Dynamisch |
```
## 3.3 Tabellen als Anhang
Mit `@TabelleAnhang: Anlagenname` wird die folgende Tabelle nicht im
Fließtext gerendert, sondern als eigene Anlage im Anhang platziert:
```
@TabelleAnhang: Vollständige Fehlerliste
| Code | Beschreibung | Schwere |
|------|--------------|---------|
| E001 | Datei nicht gefunden | Kritisch |
```
## 3.4 Diagramme als Anhang
Mit `@AnhangUML:` gefolgt von einem Mermaid- oder PlantUML-Codeblock wird
das Diagramm als Anlage eingebettet statt im Fließtext:
```
@AnhangUML: Datenbankschema
\`\`\`plantuml
@startuml
entity User { ... }
@enduml
\`\`\`
```
# 4. Zusammenfassung
Das Tool ermöglicht eine effiziente Erstellung von IHK-Dokumentationen
unter Einhaltung **aller** Formatvorgaben. Durch die Trennung von Inhalt
(Markdown) und Formatierung (Go-Renderer) ist eine konsistente Ausgabe
garantiert. Künftige Erweiterungen könnten Fußnoten, Querverweise und
eine konfigurierbare Spaltenbreite für Tabellen umfassen.
@Quelle: IHK Chemnitz, Hinweise zur Erarbeitung der Dokumentation über die Projektarbeit, 2020
@Quelle: DIN 5008:2020-03, Schreib- und Gestaltungsregeln für die Textverarbeitung, Beuth Verlag
@Anhang: Architektur-Diagramm Übersicht | test.png
@TabelleAnhang: Vollständige Liste der unterstützten Markdown-Direktiven
| Direktive | Syntax | Beschreibung |
|-----------|--------|--------------|
| Quelle | @Quelle: Text | Fügt einen Literaturverweis hinzu, der alphabetisch im Literaturverzeichnis erscheint |
| Tabelle | @Tabelle: Name | Gibt der folgenden Tabelle einen Namen für das Tabellenverzeichnis |
| Tabellenanhang | @TabelleAnhang: Name | Sendet die folgende Tabelle als nummerierte Anlage in den Anhang |
| Bildanhang | @Anhang: Titel \| Pfad | Fügt ein Bild als nummerierte Anlage in den Anhang ein |
| Diagrammanhang | @AnhangUML: Titel | Rendert den folgenden Mermaid/PlantUML-Block als Anlage |
@AnhangUML: Systemarchitektur Datenflussdiagramm
```mermaid
graph LR
MD[report.md] -->|ParseMarkdown| AST[Goldmark AST]
AST -->|Pass 1| R1[IHKRenderer Pass 1]
R1 -->|tocItems| R2[IHKRenderer Pass 2]
AST -->|Pass 2| R2
R2 -->|Save| OUT[projektarbeit.pdf]
```
@AnhangUMLQuer: Vollständige Modulübersicht Querformat
```mermaid
graph TD
subgraph Eingabe
MD[report.md]
CFG[YAML Frontmatter]
end
subgraph Parser
MP[markdown_parser.go]
AST[Goldmark AST]
end
subgraph Renderer
IR[pdf_renderer.go]
IC[pdf_content.go]
IT[pdf_toc.go]
IP[pdf_pages.go]
IN[pdf_numbering.go]
end
subgraph Diagramme
DG[diagram.go]
KR[Kroki API]
end
subgraph Ausgabe
PDF[projektarbeit.pdf]
end
MD --> MP
CFG --> MP
MP --> AST
AST --> IR
IR --> IC
IR --> IT
IR --> IP
IR --> IN
IC --> DG
DG --> KR
KR --> DG
IP --> PDF
```
@TabelleAnhangQuer: Vollständige Direktiven-Referenz im Querformat
| Direktive | Syntax | Beschreibung | Querformat |
|-----------|--------|--------------|------------|
| Quelle | @Quelle: Text | Literaturverweis, alphabetisch sortiert im Literaturverzeichnis | |
| Tabelle | @Tabelle: Name | Gibt der nächsten Tabelle einen Namen für das Tabellenverzeichnis | |
| Tabellenanhang | @TabelleAnhang: Name | Sendet die nächste Tabelle als Anlage in den Anhang | |
| Tabellenanhang Quer | @TabelleAnhangQuer: Name | Tabelle als Anlage im Querformat (297×210 mm, 15 mm Rand) | Ja |
| Bildanhang | @Anhang: Titel \| Pfad | Bild als nummerierte Anlage (Hochformat) | |
| Bildanhang Quer | @AnhangBildQuer: Titel \| Pfad | Bild als nummerierte Anlage im Querformat | Ja |
| Diagrammanhang | @AnhangUML: Titel | Nächster Mermaid/PlantUML-Block als Anlage (Hochformat) | |
| Diagrammanhang Quer | @AnhangUMLQuer: Titel | Nächster Mermaid/PlantUML-Block als Anlage im Querformat | Ja |
| Diagramm Querseite | @DiagrammQuer: Titel | Nächster Mermaid/PlantUML-Block inline als Querformat-Seite | |