Communitygithub.com

mariosakka/report-to-pdf

Wandelt einen Markdown-Bericht (mit Überschriften, Absätzen, Listen, Code-Blöcken mit Pygments-Syntax-Highlighting, Tabellen, Formatierungen) in ein professionell gestaltetes PDF um – mit Titelseite, Kopf-/Fußzeile, automatisch generiertem verlinktem Inhaltsverzeichnis, mehrstufiger Überschriftenhierarchie, Zebrastreifen-Tabellen und optionalem Dark-Mode.

Was ist report-to-pdf?

Dieses Skill ermöglicht die deterministische, skriptgesteuerte Umwandlung von Markdown-Dokumenten in professionell formatierte PDFs, die sich für die Weitergabe an Kunden oder Mentoren eignen. Es parst einen eingeschränkten Markdown-Satz mit einem eigenen Blockparser (ohne externe Bibliotheken) und erzeugt über fpdf2 ein PDF mit konsistentem, wiederholbarem Layout – ideal für Berichte, die jedes Mal gleich aussehen sollen, ohne dass ein LLM das Format ändert. Die Ausgabe enthält eine Titelseite mit optionalem Logo und Akzentbalken, Kopf- und Fußzeilen, ein automatisch erstelltes, verlinktes Inhaltsverzeichnis (TOC) sowie eine dreistufige Überschriftenhierarchie. Code-Blöcke werden mit echten Pygments-Lexern (z. B. für Python, TypeScript, SQL) farbig hervorgehoben, und es stehen helle und dunkle Farbschemata zur Wahl. Der Skill wird über die Kommandozeile gesteuert (z. B. über Optionsflags für Titel, Logo, Dark-Mode) und unterstützt auch YAML-Frontmatter im Markdown-Dokument. Das Skill ist besonders nützlich, wenn Entwickler oder technische Redakteure Markdown-Reports, technische Dokumentationen oder Code-Reviews in ein einheitliches, brand-konformes PDF-Exportformat bringen müssen, ohne sich jedes Mal manuell um Layout oder Formatierung kümmern zu müssen. Die Skripte (build_report_pdf.py, run_checks.py) sind im Skill-Verzeichnis enthalten und können mit Python 3 und optionalen Abhängigkeiten (fpdf2, Pillow, Pygments) direkt ausgeführt werden.

Funktioniert mit✓Claude Code~Codex CLI✓Cursor
npx skills add https://github.com/mariosakka/my-agent-skills/tree/HEAD/plugins/general/skills/report-to-pdf

In Ihrer bevorzugten KI fragen

Öffnet einen neuen Chat, in dem dieser Agent-Skill bereits geladen ist.

Vorschau

Aus dem Skill-README

alt
alt

Dokumentation

report-to-pdf – Markdown-Bericht zu poliertem PDF

Deterministischer, skriptgesteuerter Markdown-zu-PDF-Renderer. Er parst einen eingeschränkten „Report"-Markdown-Subset mit einem kleinen handgeschriebenen Block- Parser (keine externe Markdown-Bibliothek) und setzt ihn über fpdf2 mit den gleichen visuellen Konventionen wie der ColeteOnline-Magento-Modul- build-user-guide.py-Generator um – Titelseite, Kopf-/Fußzeile, TOC, Akzentbalken-Abschnittsüberschriften, schattierte Code-Blöcke, umrandete/Zebrastreifen- Tabellen. Das Layout ändert sich nie zwischen Durchläufen mit demselben Input: Gleicher Bericht rein, gleiches PDF raus, jedes Mal – kein LLM im Render-Loop.

Wann verwenden

  • „Wandel diesen Markdown-Review in ein PDF für den Mentor um.“
  • „Exportiere meinen Bericht als poliertes PDF.“
  • „Ich möchte, dass das jedes Mal gleich aussieht, nicht von einem LLM bei jedem Durchlauf neu formatiert.“
  • Jeder .md-Report/-Text, der Überschriften, Listen, Code-Blöcke oder Tabellen enthält und eine Client-/Mentor-/Markenqualitäts-PDF-Version benötigt.

So führen Sie es aus

python3 <skill-verz>/scripts/build_report_pdf.py <eingabe.md> [optionen]

(<skill-verz> ist das Basisverzeichnis dieses Skills, der Ordner, der diese SKILL.md enthält.)

Optionen:

  • -o / --output <pfad> – Ausgabe-PDF-Pfad (Standard: <eingabe>.pdf neben der Quelldatei).
  • --logo <pfad> – optionales Logobild (PNG/WebP/JPEG, alles, was Pillow öffnen kann) auf der Titelseite. Wiederholen Sie das Flag für mehrere Logos, die nebeneinander in einer Reihe gezeichnet werden (auch über Frontmatter logo: a.png, b.png einstellbar, Pfade relativ zur .md-Datei).
  • --title, --subtitle, --version, --vendor, --author – Überschreiben der entsprechenden Frontmatter-Werte (siehe unten); CLI-Flags gewinnen.
  • --cover center|left – Titelseitenlayout. Der gesamte Titelblock (Logo, Titel, Untertitel, Autor, Version) wird in beiden Modi vertikal zentriert; center (Standard) zentriert ihn auch horizontal, left linksbündig. Auch über Frontmatter cover: einstellbar.
  • --no-header – Lässt den laufenden Kopf und den dafür reservierten Platz weg, sodass der Inhalt jeder Seite am gleichen oberen Rand beginnt (auch über Frontmatter header: false einstellbar).
  • --accent "R,G,B" – Überschreibt die Akzentfarbe für den oberen Balken der Titelseite und die Akzentbalken der Abschnittsüberschriften (Standard 220,50,50, ColeteOnline-Rot).
  • --dark – Rendert mit dem dunklen Farbschema anstelle des standardmäßigen hellen (auch über Frontmatter theme: dark einstellbar; --dark gewinnt, wenn beide vorhanden sind). Siehe „Dark theme" unten.

Das Skript installiert automatisch fpdf2, Pillow und Pygments via pip install --user, falls ein Import fehlschlägt, und spiegelt damit die Pillow-Autoinstallation des Referenzskripts wider. Alle drei waren importierbar bestätigt und das Skript wurde während der Entwicklung End-to-End ausgeführt (siehe Testing unten).

Markdown-Konventionen, die es erwartet

Optionaler Frontmatter-Block ganz oben in der Datei:

---
title: Mein Berichtstitel
subtitle: Ein einzeiliger Untertitel
version: 1.0
vendor: ColeteOnline SRL
accent: 220,50,50
---

Alle Schlüssel sind optional und fallen sinnvoll zurück:

  • title – fällt auf die erste # H1-Überschrift im Textkörper zurück, dann auf den Eingabedateinamen.
  • subtitle – fällt auf leer zurück (wird auf der Titelseite weggelassen).
  • version – fällt auf das heutige Datum zurück (YYYY-MM-DD); setzen Sie version: none, um die Versionszeile auszublenden.
  • vendor – fällt auf leer zurück (Copyright-Zeile wird in der Fußzeile der Titelseite weggelassen, wenn nicht gesetzt).
  • author – Autorenname(n), werden auf dem Cover unter dem Untertitel angezeigt (z. B. author: Jane Doe, John Smith). Wird weggelassen, wenn nicht gesetzt.
  • cover – center (Standard) oder left; siehe --cover oben.
  • header – false lässt den laufenden Kopf weg; siehe --no-header.
  • justify – true sorgt für Blocksatz im Textkörper, Überschriften und Tabellenzellen; der Standard ist linksbündig (Blocksatz dehnt Wortabstände bei kurzen umbrochenen Zeilen, z. B. einer zweizeiligen Überschrift).
  • accent – fällt auf das ColeteOnline-Markenrot 220,50,50 zurück.

Textkörper-Markdown und wie jedes Element gerendert wird:

MarkdownWird gerendert als
# TitelDas allererste # in der Datei ist nur der Titel der Titelseite (verbraucht, nicht im Textkörper wiederholt). Jedes spätere # ist eine echte Hauptüberschrift (siehe unten).
# Hauptabschnitt (nach dem ersten #)Hauptüberschrift. Beginnt immer auf einer eigenen frischen Seite (außer der Cursor ist bereits oben auf einer leeren Seite), großer farbiger linker Balken, fett 16pt, schwarzer Text – und erhält einen TOC-Eintrag. Nur für echte Top-Level-Abschnitte verwenden; jeder kostet eine Seite.
## UnterabschnittZwischenüberschrift. Fett 13pt, Akzentfarb-Text mit einer kurzen akzentfarbigen Unterstreichung (visuell unterschiedlich zu beiden Ebenen darüber und darunter) – erzwingt keinen Seitenumbruch, setzt den Fluss fort. Erhält trotzdem einen TOC-Eintrag. Hat eine eigene Überprüfung, dass eine Überschrift nicht ganz unten auf einer Seite hängen bleibt.
### Unter-Unterabschnitt (und ####+)Tertiäre Überschrift. Fett 12pt, neutrales Grau, dünne durchgehende Linie, kein Seitenumbruch, kein TOC-Eintrag (hält das TOC überschaubar).
AbsatztextLinksbündiger Fließtextabsatz, 10pt.
- item / * itemAufzählungsliste (•).
1. itemNummerierte Liste.
```sprache ... ```Schattierter, umrandeter Monospace-Codeblock; der Sprach-Tag (falls vorhanden) wird als kleine kursive Bezeichnung über dem Block gedruckt und steuert das echte Pygments-Syntax-Highlighting – siehe unten.
`a
--- / *** / ___ in einer eigenen ZeileVertikaler Abstandshalter (kein Seitenumbruch).
<br> in einer eigenen ZeileEine explizite leere Textzeile (5,5 mm). Stapeln Sie mehrere für mehr Platz. Der Renderer fügt oben auf einer Seite keine eigenen Abstände hinzu, also verwenden Sie dies, wenn Sie zusätzlichen Platz wünschen.
<!-- pagebreak --> in einer eigenen ZeileBeginnt eine neue Seite (kein Effekt, wenn bereits oben auf einer).
![alt](pfad) in einer eigenen ZeileZentriertes, umrandetes Bild, skaliert, um zu passen; relative Pfade werden relativ zum Ordner der .md-Datei aufgelöst. PNG/JPEG/WebP und SVG (siehe „Abbildungen, Boxen und Mathematik"). Ein reines Rasterbild unter 900 px Breite wird auf ~130x105mm begrenzt; eine Abbildung (Bild gefolgt von einer Bildunterschrift), jedes SVG und jedes Bild mit 900 px oder mehr Breite darf die volle Textbreite nutzen (max. Höhe 120mm). Eine Abbildung, die nicht in den verbleibenden Platz auf der Seite passt, wird auf den Platz verkleinert (bis auf 70 % ihrer Höhe), anstatt auf die nächste Seite zu springen und eine Lücke zu hinterlassen.
*Abbildung: ...* (eine ganze kursive Zeile direkt nach einem Bild)Die Bildunterschrift des Bildes: klein, zentriert, kursiv, auf derselben Seite wie das Bild gehalten. Alt-Text wird nie gedruckt.
> text ZeilenDefinitionsbox: eine umrandete, leicht schattierte Box pro Blockquote (fetter Begriff und Inline-Mathematik funktionieren darin; eine >-Zeile ohne weiteren Inhalt beginnt einen neuen Absatz in derselben Box).
$...$Inline-Mathematik, in Unicode-Text umgewandelt (griechische Buchstaben, ≤ ≥ × ·, tief-/hochgestellte Zeichen, \frac{a}{b} -> (a)/b, \sqrt, \text{}, Akzente). Ein Preis wie $5 ist keine Mathematik.
$$...$$ (eine Zeile oder in eigenen Zeilen)Display-Mathematik, ein zentriertes Bild vom ersten funktionierenden Mathe-Backend (siehe „Abbildungen, Boxen und Mathematik").
4-Leerzeichen eingerückter Block nach einer leeren ZeileCodeblock ohne Sprach-Tag (Notebook-Exporte drucken Zellenausgabe auf diese Weise). Wird nicht direkt nach einer Liste angewendet.
**fett**Echter fetter Text, über fpdf2s integrierten markdown=True-Renderer.
[text](url)Ein echter, klickbarer PDF-Link-Annotation – nur der Anzeigetext wird gezeigt, nicht die rohe URL – in einer deutlichen Linkfarbe gestaltet.
*kursiv* / _kursiv_Gerendert kursiv (intern in fpdf2s native __italic__-Form gefaltet).
`code`Inline-Code-Backticks werden entfernt – keine Monospace-Inline-Unterstützung, wird als Klartext gerendert.

Überschriften, Absätze, Aufzählungen, nummerierte Elemente und Tabellenzellen werden alle über fpdf2s markdown=True-Pfad gerendert, daher funktionieren fett und [text](url)-Links überall, wo Text erscheint, einschließlich in Überschriften und Tabellenzellen. Fenced-Code-Blöcke sind die eine Ausnahme – ihr Inhalt wird vollständig wörtlich gerendert (keine Markdown-Analyse), daher wird ein Codebeispiel, das wörtliche **, __ oder []() enthält, nicht falsch interpretiert.

Abbildungen, Boxen und Mathematik

Geschrieben, damit der Markdown-Begleiter eines Notebooks (nbconvert-Ausgabe) direkt rendert: report-to-pdf notebook.md ersetzt einen separaten Chrome-basierten PDF-Schritt.

SVG-Bilder. ![alt](figure.svg) funktioniert. fpdf2s eigenes SVG-Zeichnen überspringt <marker>-Pfeilspitzen, Filter und Masken, zeichnet Text in einer Kernschriftart (kein Griechisch) und färbt Text ohne fill falsch, daher wird jedes SVG mit 2,5x gerastert und als PNG eingebettet, wobei in dieser Reihenfolge verwendet wird: ein kopfloser Chrome/Edge (automatisch gefunden; setzen Sie REPORT_PDF_BROWSER auf einen Browserpfad, um zu überschreiben), dann cairosvg, falls importierbar. Ohne beides wird das SVG nativ von fpdf2 gezeichnet und eine Warnung sagt, dass es unvollständig sein könnte. Das Rastern wird pro Durchlauf zwischengespeichert.

Display-Mathematik-Backends (--math auto|latex|mathtext|unicode oder Frontmatter math:; Standard auto). Das Skript gibt aus, welches Backend verwendet wurde.

  1. latex: echtes LaTeX, wenn pdflatex, xelatex oder tectonic im PATH ist (plus pdftocairo, PyMuPDF oder dvisvgm, um das Bild zu erstellen), oder latex + dvipng. Jede Formel wird mit standalone, amsmath, amssymb und xcolor in 12 pt kompiliert und dann auf ein transparentes 300-dpi-PNG in der Textfarbe zugeschnitten. Installation: MiKTeX (Windows), TeX Live (apt install texlive-latex-base texlive-latex-extra poppler-utils, macOS brew install --cask mactex-no-gui) oder tectonic (einzelne Binärdatei, lädt Pakete bei Bedarf herunter; conda install -c conda-forge tectonic oder scoop install tectonic; End-to-End auf Windows mit PyMuPDF als Bildkonverter getestet).
  2. mathtext: matplotlibs LaTeX-Teilmenge (Brüche, Summen, Griechisch, \text{} wird auf \mathrm abgebildet). Kein TeX nötig, nur matplotlib. Umgebungen wie aligned werden nicht unterstützt und fallen durch.
  3. unicode: die gleiche Textumwandlung wie Inline-Mathematik, zentriert.

Ein Backend, das fehlt oder fehlschlägt (z. B. eine Formel, die TeX ablehnt), fällt stillschweigend auf das nächste zurück; --math latex degradiert auf die gleiche Weise.

Test: python tests/run_checks.py (Mathematik-Konvertierung, Parser, SVG-Routing, Backend-Fallback mit gemocktem PATH, End-to-End-Erstellung von tests/fixture.md). Rendern eines Begleiters: python scripts/build_report_pdf.py notebook.md -o notebook.pdf.

Syntax-Highlighting

Fenced-Code-Blöcke werden mit echten Pygments-Lexern tokenisiert (kein handgestrickter Regex-Highlighter – Code ist genau die Art von Ding, die ein kleiner Ad-hoc-Parser subtil falsch versteht: String-Escapes, verschachtelte Kommentare, Template-Literale). Der Sprach-Tag auf der Abgrenzung (```typescript, ```sql, ```python, ...) wählt den Lexer aus; eine Handvoll gängiger Aliase werden normalisiert (ts/ tsx → typescript, js/jsx → javascript, sh/shell/zsh → bash, yml → yaml, prisma → graphql – der nächstgelegene eingebaute Lexer und eine gute Übereinstimmung in der Praxis, da Prismas @attribute(...)- Syntax und GraphQLs @directive(...)-Syntax fast identisch tokenisieren).

Highlighting ist ein Bonus, niemals eine harte Anforderung zum Rendern eines Code- Blocks – ein fehlender Sprach-Tag, eine Sprache, die Pygments nicht erkennt (selbst nach der Alias-Tabelle), oder Pygments selbst, das nicht importierbar ist, fallen alle auf das exakte Verhalten vor dem Highlighting zurück: der gesamte Block in einer flachen Farbe, kein Absturz, kein fehlender Inhalt.

Farbpalette (gewählt für Lesbarkeit vor dem hellgrauen Hintergrund des Codeblocks, nicht an ein bestimmtes Pygments-Theme gebunden):

Token-KategorieFarbe
Schlüsselwörter (interface, async, const, NOT NULL, Typ-Schlüsselwörter wie string/number)Magenta
ZeichenkettenGrün
ZahlenBraun/Orange
KommentareGrau
Funktions-/Klassennamen, Dekorateure/Attribute (@map, @relation)Blau / Braun
Builtins (Promise usw.)Blaugrün
Alles andere (Bezeichner, Satzzeichen, Operatoren)Die Basis-Code-Farbe

Ein Token-Typ ohne exakten Eintrag in der Palette wird aufgelöst, indem die Hierarchie der Pygments-Token-Typen durchlaufen wird (z. B. Keyword.Declaration hat keinen eigenen Eintrag, aber sein Elternteil Keyword schon), bis ein Treffer gefunden wird – die nackte Token-Wurzel stimmt immer, daher schlägt dies nie fehl, irgendeine Farbe aufzulösen.

Die Monospace-Shrink-to-Fit-Logik (eine Codezeile, die zu breit für die Seite ist, verkleinert gleichmäßig die Schriftgröße des gesamten Blocks, anstatt überzulaufen) wird durch Highlighting nicht beeinflusst – sie misst einfache Zeichenbreiten, die sich nicht ändern, je nachdem, welche Farbe ein Token letztendlich erhält.

Dark theme

Übergeben Sie --dark oder setzen Sie theme: dark im Frontmatter, um das gesamte Dokument in einem dunklen Theme anstelle des standardmäßig hellen zu rendern. Jede Farbe im Dokument wechselt zu einem dunkel-angepassten Gegenstück – nicht nur die Code-Blöcke:

  • Der Seitenhintergrund selbst wird dunkel gefüllt (fpdf2 hat keine native „Seitenhintergrundfarbe"-Einstellung, daher wird dies durch Füllen der vollen Seite im header()-Hook erreicht, bevor irgendetwas anderes darauf gezeichnet wird – auch auf der Titelseite).
  • Textkörper, Überschriften (alle drei Ebenen), dezenter/footer-Text, Regel- linien, Tabellen-Zebrastreifen und die laufende Kopf-/Fußzeile verwenden alle einen separaten Dark-Mode-Farbsatz, nicht nur eine gedimmte helle Version.
  • Syntax-Highlighting verwendet seine eigene Dark-Mode-Palette (hellere Pink-/Grün-/Blautöne für Kontrast vor dem dunklen Code- Hintergrund), nicht die hellen Farben abgedimmt.
  • Linkfarbe (sowohl [text](url)-Markdown-Links als auch die Sprung-zu-Seiten-Links des TOC) wechselt zu einem helleren Blau, das auf dunklem Hintergrund lesbar bleibt.

Die --accent-Farbe (der obere Balken, der linke Balken der Hauptüberschrift und der Unterüberschrift-Text/Unterstreichung) wird in beiden Themes unverändert verwendet – wählen Sie eine aus, die sowohl vor einem weißen als auch vor einem fast schwarzen Hintergrund funktioniert, wenn Sie denselben Bericht in beiden Themes generieren möchten, oder überschreiben Sie --accent pro Theme, wenn nicht.

Inhaltsverzeichnis

Das rückwirkend befüllte TOC (siehe „Wie das rendert" oben) wird …

[Rest des Inhalts gekürzt für die Übersetzung]

Verwandte Skills