Was macht swiss-pdf?
Wandelt MD / DOCX / TXT / HTML in A4-PDFs im Schweizer Layout um.
Weißer Hintergrund, schwarze Schrift, extrem dünne Trennlinien, große Kapitelnummern, serifenlose Ziffern, einzige Farbe Rot #E5484D.
Das Design stammt aus einer gebundenen Sammlung im Stil der Schweizer Typografie (große Kapitelnummern, extrem dünne Trennlinien, einzelne Akzentfarbe) und wurde in einen automatischen, einspaltigen Seitenumbruch umgesetzt, sodass Dokumente beliebiger Länge direkt verarbeitet werden können.
Verwendung
Variante 1: Drag & Drop (empfohlen)
Datei auf swiss-pdf.bat ziehen → Im selben Verzeichnis wird eine gleichnamige .pdf-Datei erstellt, zusammen mit einer Kopie xxx.pdf-src.html (HTML-Quelle zur Überprüfung).
Variante 2: Kommandozeile
python make.py Eingabedatei # PDF erstellen
python make.py Eingabedatei --html # Nur HTML erstellen (gespeichert als xxx.html, kann im Browser geöffnet und manuell gedruckt werden)
python make.py Eingabedatei -o Ausgabe.pdf
python make.py a.md b.docx c.txt # Batch-Verarbeitung
python make.py Eingabedatei --no-cover --no-toc
python make.py Eingabedatei --title "Titel" --kick "Anmerkung" --date 2026.11.09
Unterstützte Eingabeformate
| Format | Konvertierung | Beschreibung |
|---|---|---|
.md | pandoc | Unterstützt YAML Front-Matter, GFM-Tabellen, Listen, Codeblöcke, Bilder |
.docx | pandoc | Überschriften-Stile → Kapitelüberschriften; Tabellen → formatierte Tabellen; Bilder automatisch extrahiert |
.txt | Eigener Parser | Absätze durch Leerzeilen getrennt; kurze Zeilen mit Nummerierung (一、/ 1. / Kapitel X) → Kapitelüberschriften |
.html | Eigener Parser | <body> wird extrahiert, script/style entfernt; <title> wird als Dokumenttitel verwendet |
Deckblatt: YAML Front-Matter
Direkt am Anfang einer MD-Datei (bei anderen Formaten über Parameter wie --title):
---
title: Stadtverkehrssicherheit – Weißbuch
subtitle: Beobachtungen und Empfehlungen auf Basis einer Stichprobe in drei Städten
kick: Verkehrsforschung
de: Urbane Radverkehrs-Sicherheit
slug: stadtverkehr-sicherheit
nature: Öffentliche Version
project: Forschungsprojekt Langsamverkehr
party_a: Auftraggeber
party_b: Auftragnehmer
stage: Erhebung → Auswertung → Fertigstellung
source: 01_Beobachtungen 02_Interviews 03_Konzept
date: 2026.11.10
version: v2.1
badges: Öffentlich; ! Wichtig; Datenbasiert
---
badgeswerden mit;getrennt, Präfix!für schwarzen Hintergrund mit weißer Schrift.- Fehlt
date, wird automatisch das aktuelle Datum verwendet. - Auch ohne Front-Matter funktioniert es; das Deckblatt zeigt dann nur Titel + Datum + Versionsplatzhalter.
Text: Sechs Stilblöcke
In Markdown mit ::: umschlossen (jede Zeile innerhalb des Blocks = ein Eintrag):
::: note
Ergänzender Hinweis, Erläuterung. Grauer Hintergrund.
:::
::: quote
Schlüsselzitat, linke 3pt-Senkrechte.
:::
::: inverse
Schwarzer Hintergrund mit weißer Schrift für den wichtigsten Satz.
:::
::: warn
Roter Rahmen – die einzige Stelle, an der Farbe erlaubt ist.
:::
::: stat
4.280 | Gesamtzahl der Beobachtungen || 24 | Beobachtungspunkte || 3 | Abgedeckte Städte
:::
::: check
Kreuzung während der morgendlichen Hauptverkehrszeit (Ankunft vor 7:30 erforderlich)
Beleuchtete Abschnitte bei Nacht (Zusatzlicht erforderlich)
:::
::: kv
Seiten | Variante A 20 S. / Variante C 32 S.
Empfehlung | Variante C, aber mit ergänzenden Daten aus der zweiten Stadt
:::
stat verwendet Zahl | Beschreibung pro Feld, || trennt Felder. kv verwendet Schlüssel | Wert.
Automatische Verhaltensweisen
| Verhalten | Regel |
|---|---|
| Kapitelnummerierung | # Überschrift 1 → große Nummer 00/01/02…; bei bereits nummerierten Überschriften („01 “, „一、“) wird die vorhandene Nummer beibehalten |
| Inhaltsverzeichnis | Wird nur erzeugt, wenn Kapitel + ##-Abschnitte insgesamt ≥ 5 sind; sonst wird die Seite weggelassen; Kapitelüberschriften sind verankert und im PDF anklickbar |
| Tabellen | Spaltenanzahl ≥ 6 → Schriftgröße reduziert (table.wide); rein numerische Zellen rechtsbündig + in serifenloser Schrift |
| Kopf- und Fußzeilen | Deckblattseite ohne Kopf-/Fußzeile; Textseiten: Kopfzeile links (Lauftitel), Fußzeile rechts („Seite i / N“) |
| Druck | @page A4, Ränder 14/15/13 mm; Überschriften nicht vom Text getrennt, Tabellenzeilen nicht über Seitenumbrüche getrennt |
Zusätzliche Verarbeitung von HTML-Quellen (empirisch ergänzt)
Wenn die Quelle eine „selbst gestaltete Webseite“ ist, normalisiert dieser Skill automatisch, um isolierte Nummerierungen oder doppelte Überschriften nach dem Umbruch zu vermeiden:
| Quellstruktur | Verarbeitung |
|---|---|
<div class="sec-head"><span class="sec-num">3</span><h2>Titel</h2></div> | Umwandlung in die .sec-Kopfzeile der Vorlage (Nummer aus span, Titel aus h2) |
<h1>03 Titel</h1> / <h1>Titel</h1> | Gleich wie oben; bei fehlender Nummer wird sie automatisch hochgezählt |
Isolierte Absätze mit reiner Zahl <p>0</p> | Verwerfen (häufig als dekorative Kapitelnummer verwendet) |
<header class="masthead"> / <nav> | Verwerfen (Deckblatt wird separat erstellt, wiederholte Kicker/Titel/Inhaltsverzeichnisse würden den Text stören) |
<section>-Abschnitte | Beibehalten als Container; Überschrift muss sec-head oder h1 sein, um ins Inhaltsverzeichnis aufgenommen zu werden |
<div id="xxx" class="chart"> + echarts | Screenshot mit Headless-Browser als PNG und Einbettung; Wartezeit networkidle + 2,5s vor Screenshot |
Voraussetzung für Diagramm-Screenshots: Bei Verwendung von echarts per CDN muss eine Internetverbindung bestehen. In Offline-Umgebungen die echarts.min.js in die Quelle einbetten.
Schriftarten und Zeichensetzung
Schriftart: Im Repository integrierte Source Han Sans SC, per @font-face eingebettet
Im Verzeichnis fonts/ befinden sich zwei Dateien. make.py bettet deren Base64-Code beim Generieren des HTML in das <style> ein und registriert sie als Schriftfamilie Swiss Sans SC:
| Datei | Schriftstärke |
|---|---|
SourceHanSansCN-Regular.subset.ttf | 400 |
SourceHanSansCN-Bold.subset.ttf | 700 |
Der Zeichensatz umfasst ca. 7100 Zeichen (ASCII + chinesische und englische Satzzeichen + alle 6763 chinesischen Schriftzeichen von GB2312). Die Zeichenliste findet sich in fonts/charset.txt.
Vorteil: Auf einem Rechner ohne installierte Source Han Sans wird dennoch eine konsistente Ausgabe erzielt – ohne dass der Benutzer Schriftarten installieren muss.
Der Benutzer kann die Schriftarten austauschen oder herunterladen. Drei Möglichkeiten (Details in fonts/README.md):
- Dateien ersetzen (empfohlen): Eigene TTF-Dateien auf die beiden Namen umbenennen und überschreiben. Zuerst subsetten, sonst enthält das HTML die vollständigen 10 MB:
pyftsubset DeineSchrift-Regular.ttf --text-file=fonts/charset.txt --output-file=fonts/SourceHanSansCN-Regular.subset.ttf fonts/löschen:make.pyüberspringt dann@font-faceund fällt auf den systemeigenen Schriftstapel im CSS zurück (Source Han Sans SC/CN → Noto Sans SC → Noto Sans CJK SC → MonuHan CN → PingFang SC → Segoe UI Symbol).- Nur CSS ändern: Den ersten Schriftartnamen in
--sansam Anfang vontemplates/swiss.cssändern.
⚠️ Es muss .ttf (TrueType-Konturen) sein, nicht .otf (CFF). Chromium stuf bei der PDF-Erstellung CFF-Webfonts zu Type3-Glyphen-Befehlen herunter (jedes Glyph als Zeichenpfad), was die Dateigröße um ein Vielfaches erhöht. Gleiches 4-seitiges Dokument:
OTF → 328 KB / 205 Type3; TTF → 79 KB / 1 Type3.
Microsoft YaHei fehlen unter Chromium die Zeichenformen für · (U+00B7), → ↓ ≤ ≥ etc., die zu Quadraten werden. Daher wurde es aus dem primären Schriftstapel entfernt.
Anführungszeichen: Volltext auf nationale gebogene Anführungszeichen
convert.normalize_quotes() verarbeitet sie im letzten Schritt, deckt Überschriften, Deckblatt, Kopfzeilen, Inhaltsverzeichnis, Tabellen und Stilblöcke ab:
| Eingabe | Ausgabe |
|---|---|
「」 | “” |
『』 | ‘’ |
Gerade Anführungszeichen im Code " ' | Pandoc wandelt Markdown-Anführungszeichen automatisch in gebogene um (+smart); innerhalb von Codeblöcken <code> / <pre> keine Änderung |
Die Implementierung ersetzt nur 4 Codepunkte (U+300C/D/E/F → U+201C/D/8/9) und beeinflusst keine HTML-Tag-Attribute oder CSS/JS.
Validierte Praxisbeispiele
| Eingabe | Größe | Seiten | Dauer |
|---|---|---|---|
| md | 29 KB | 15 | ~6s |
| html | 105 KB + 2 echarts-Diagramme | 21 | ~15s |
| docx | Überschriften-Stile + Tabelle | 2 | ~6s |
txt (aus samples/) | 1,2 KB | 2 | ~5s |
| md langes Dokument (Regression) | 71 KB | 21 | ~24s |
Systemvoraussetzungen
| Abhängigkeit | Status auf eigenem Rechner | Falls fehlend |
|---|---|---|
| pandoc (≥2.19) | pandoc -v ausführen und prüfen | MD/DOCX können nicht konvertiert werden |
| playwright + chromium | Oder systemeigener Chrome/Edge | PDF kann nicht gerendert werden |
| python-docx (optional) | Nur für die Analyse | Beeinträchtigt den Hauptablauf nicht |
Browser festlegen: set SWISS_PDF_CHROME=<Pfad zu chrome.exe>
Dateistruktur
swiss-pdf/
├── SKILL.md Diese Datei
├── swiss-pdf.bat Drag-und-Drop-Einstieg
├── make.py Hauptablauf: Konvertierung → Zusammenbau → Rendern
├── convert.py Formate → HTML-Fragmente + Block-Syntax
├── templates/
│ └── swiss.css Alle Stile (Design-Tokens + Druckregeln)
└── samples/ Beispiele in drei Formaten
Grenzen (Was nicht funktioniert)
- Manueller Seitenumbruch wie in einer Broschüre (jede Seite sorgfältig gestaltet, Doppelseiten-Design). Die Vorlage kann dies nicht leisten. Dieser Skill ist für die schnelle Erstellung von Standarddokumenten gedacht.
- Bild-Layout hängt von den Bildabmessungen im Originaldokument ab; es wird kein Beschneiden oder Anschnitt vorgenommen.
- Seitennummern im Inhaltsverzeichnis (wie bei gedruckten Büchern) werden nicht realisiert (Elemente auf der Seite können die Seitenzahl nicht ermitteln). Kapitelüberschriften sind jedoch anklickbar; die Fußzeile zeigt „Seite i / N“.
- Zu kurze Tabellenblöcke können ganz auf die nächste Seite verschoben werden (um das Auseinanderreißen von Schlüssel-Wert-Tabellen zu vermeiden, sind
.kv-Blöcke als untrennbar markiert). - Komplexe Word-Formatierungen (Textfelder, WordArt, mehrstufige Nummerierungslisten) werden bei der Konvertierung durch Pandoc vereinfacht.