wiki/b-reference/platform-core/document-rendering.md

10 KiB

Dokumenten-Rendering & Style-System

Ueberblick

Der Generation-Service (serviceGeneration / mainServiceGeneration.py) wandelt strukturierten JSON-Content in formatierte Dokumente um. Pipeline: Markdown -> JSON -> Rendered File (PDF, DOCX, PPTX, XLSX, HTML).

Styling wird ueber ein 4-Schichten-Modell aufgeloest — von generischen Defaults bis zu element-spezifischen Overrides. Keine statischen Theme-Presets; stattdessen AI-getriebene kontextuelle Anpassung.


Style-Resolution-Pipeline

flowchart TD
    Default["DEFAULT_STYLE<br/>(Cursor/VS-Code-Aesthetik)"] --> Resolve["resolveStyle()<br/>deep-merge: defaults + agentStyle"]
    Resolve --> AI["_enhanceStyleWithAi()<br/>AI Delta basierend auf<br/>Titel, Typ, User-Request"]
    AI --> Global["Resolved Global Style<br/>(12 Sektionen)"]
    Global --> Convert["_convertUnifiedStyleToInternal()<br/>Renderer-internes Format"]
    Convert --> Renderer["Renderer"]
    Renderer --> PerElement["Per-Element Overrides<br/>z.B. tableStyle pro Tabelle"]
    PerElement --> Final["Gerendertes Element"]

Schicht 1: DEFAULT_STYLE (Basis)

Datei: styleDefaults.py. Neutrale, moderne Basis-Aesthetik inspiriert von Cursor/VS-Code Markdown-Rendering.

Sektion Schluessel Beschreibung
fonts primary, monospace Calibri / Consolas
colors primary, secondary, accent, background GitHub-inspirierte Farbpalette (#24292e, #586069, #0366d6)
documentTitle sizePt, weight, color, align, spaceBeforePt, spaceAfterPt Dokumenttitel-Formatierung
headings h1-h4 mit sizePt, weight, color, spaceBeforePt, spaceAfterPt Ueberschriften-Hierarchie
paragraph sizePt, lineSpacing, color, align Fliesstext
table headerBg/Fg, headerSizePt, bodySizePt, rowBandingEven/Odd, borderColor, borderWidthPt, borderStyle, bandingEnabled, cellPaddingPt Tabellen-Styling
list bulletChar, indentPt, sizePt Aufzaehlungen
image defaultWidthPt, maxWidthPt, alignment Bild-Defaults
codeBlock fontSizePt, background, borderColor Code-Bloecke
coverPage titleSizePt, subtitleSizePt, authorSizePt, dateSizePt, titleColor, subtitleColor Deckblatt
caption sizePt, color, italic, align Bild-/Tabellen-Beschriftungen
page format, marginsPt, showPageNumbers, headerHeight/footerHeight, headerLogo, headerText, footerText Seitenlayout

Schicht 2: Agent Explicit Overrides

Der Agent kann ein style-Objekt in metadata.style des JSON-Dokuments mitgeben. resolveStyle(agentStyle) macht ein rekursives Deep-Merge: DEFAULT_STYLE <- agentStyle. Nur explizit gesetzte Keys werden ueberschrieben.

Schicht 3: AI Style Enhancement

_enhanceStyleWithAi() in mainServiceGeneration.py:

  1. Empfaengt das vollstaendige resolved Style-Set als JSON (~920 Bytes)
  2. Kontext: Dokumenttitel, Dokumenttyp, User-Request (Auszug)
  3. AI liefert ein Delta-JSON mit nur den zu aendernden Properties
  4. deepMerge(resolvedStyle, delta) wendet die Aenderungen an
  5. Bei Fehler: graceful fallback auf den unmodifizierten Style

Beispiele fuer AI-Anpassungen:

  • Rechtsschrift: Serif-Fonts, justified Paragraphs
  • Finanzbericht: konservative Farben, rechtausgerichtete Zahlen-Spalten
  • Marketing: kraeftige Farben, groessere Abstände

Schicht 4: Per-Element Overrides

JSON-Content-Bloecke koennen element-spezifische Style-Overrides tragen. Aktuell unterstuetzt:

  • tableStyle auf Table-Bloecken: content.tableStyle wird per deep-merge mit dem globalen table-Style zusammengefuehrt. Erlaubt pro Tabelle eigene Banding-Farben, Border-Style, Column-Alignments etc.
  • columnAlignments auf Table-Bloecken: Explizite Liste (["left", "right", "center"]) pro Spalte.

Tabellen-Rendering-Modell

Globale Tabellen-Styles

Aus DEFAULT_STYLE["table"]:

Key Default Beschreibung
headerBg / headerFg #f6f8fa / #24292e Header-Hintergrund und -Textfarbe
headerSizePt / bodySizePt 10 / 10 Schriftgroessen
rowBandingEven / rowBandingOdd #f6f8fa / #FFFFFF Alternierende Zeilenfarben
borderColor / borderWidthPt #e1e4e8 / 0.5 Rahmenfarbe und -staerke
borderStyle "grid" grid (Vollraster), horizontal (nur horizontale Linien), none (kein Rahmen)
bandingEnabled true Aktiviert/deaktiviert Zeilenbanding
cellPaddingPt 4 Zellen-Innenabstand

Per-Table Overrides

Ein Table-Block im JSON kann ein tableStyle-Objekt tragen:

{
  "content_type": "table",
  "elements": [{
    "headers": ["Name", "Betrag", "Datum"],
    "rows": [...],
    "tableStyle": {
      "borderStyle": "horizontal",
      "bandingEnabled": false,
      "columnAlignments": ["left", "right", "center"]
    }
  }]
}

Der Renderer mergt: globalTableStyle <- perTableStyle (deep-merge).

Spaltenausrichtung

  1. Explizit: tableStyle.columnAlignments (Array von "left" / "center" / "right")
  2. Auto-Inferenz (_inferColumnAlignments in BaseRenderer):
    • Zahlenspalten (>=60% numerisch) -> right
    • Datumsspalten (>=60% Datumsformat) -> center
    • Sonst -> left

Renderer-Architektur

Basisklasse

DocumentRendererBaseTemplate (ABC) stellt bereit:

  • _convertUnifiedStyleToInternal(style) — Wandelt das 12-Sektionen Unified-Style-Dict in ein flaches internes Format um
  • _inferColumnAlignments(headers, rows, tableStyle) — Spaltenausrichtungs-Heuristik
  • _inlineRunsFromContent() / _inlineRunsForCell() / _inlineRunsForListItem() — Inline-Run-Normalisierung
  • _lazyResolveImageBase64() — On-Demand Bild-Aufloesung fuer Grossdokumente

Format-Renderer

Renderer Bibliothek Formate Besonderheiten
rendererPdf.py ReportLab PDF TTF-Font-Registration (_resolveFontFamily), Temp-File-Bilder fuer Memory-Effizienz, Emoji-Fallback (NotoEmoji)
rendererDocx.py python-docx DOCX XML-basierte Tabellen-Borders, Word-Styles fuer h1-h4, Inline-Run-Formatting
rendererPptx.py python-pptx PPTX Slide-Layout pro Section, RGBColor-Konvertierung, Shape-basierte Bilder
rendererXlsx.py openpyxl XLSX PatternFill fuer Banding, Side/Border fuer Rahmen, Cell-Anchor fuer Bilder
rendererHtml.py Jinja2/String HTML CSS-Generierung aus Unified Style, Inline-Styles

Font-Resolution (PDF)

_resolveFontFamily(fontName) in rendererPdf.py:

  1. Pruefe ob TTF-Datei unter assets/fonts/ registrierbar ist
  2. Registriere bei ReportLab (pdfmetrics.registerFont)
  3. Fallback-Kette: gewuenschter Font -> Helvetica (ReportLab Core) -> Courier

AI Style Enhancement — Details

Prompt-Struktur

You are a document styling expert. [...]
Document title: {docTitle}
Document type: {docType}
User request (excerpt): {userHint}

Current style (full schema):
{vollstaendiges resolvedStyle JSON}

You may adjust any property: fonts, colors, documentTitle, headings, paragraph, table, list, image, codeBlock, coverPage, caption, page.
[...]
Return ONLY a valid JSON object.

Erwartete Antwort

Ein JSON-Delta-Objekt mit NUR den zu aendernden Keys:

{
  "fonts": {"primary": "Georgia"},
  "paragraph": {"align": "justified"},
  "colors": {"primary": "#1a1a2e"}
}

Leeres {} = keine Aenderungen noetig.

Fehlerbehandlung

  • Leere Antwort -> Original-Style beibehalten
  • Ungültiges JSON -> Markdown-Fences strippen, { bis } extrahieren, nochmal parsen
  • Parse-Fehler oder Exception -> Warning loggen, Original-Style beibehalten
  • Operation Type: DATA_GENERATE

Design-Entscheidungen

Datum Entscheidung Begruendung
2026-04-29 Kein Theme-Katalog, kein Mandate-CI-Konzept ADR: Agent fuellt generischen Style-Block
2026-06-02 THEME_PRESETS + documentTheme temporaer eingefuehrt A3-Reconciliation
2026-06-03 THEME_PRESETS + documentTheme entfernt, AI-Enhancement statt Presets Zurueck zum ADR-Original; AI passt kontextbasiert an
2026-06-03 DEFAULT_STYLE: Cursor/VS-Code-Aesthetik Moderne, neutrale Basis; GitHub-Farbpalette
2026-06-03 AI bekommt vollstaendiges Style-Set im Prompt Alle 12 Sektionen muessen anpassbar sein
2026-06-03 Per-Table Overrides via content.tableStyle Jede Tabelle kann eigene Styles haben
2026-06-03 Auto-Column-Alignment via _inferColumnAlignments Zahlen rechts, Daten zentriert — ohne AI-Call

Schluessel-Dateien

Datei Rolle
serviceGeneration/styleDefaults.py DEFAULT_STYLE, resolveStyle(), deepMerge()
serviceGeneration/mainServiceGeneration.py renderReport(), _enhanceStyleWithAi()
serviceGeneration/renderers/documentRendererBaseTemplate.py BaseRenderer, _convertUnifiedStyleToInternal(), _inferColumnAlignments()
serviceGeneration/renderers/rendererPdf.py PDF via ReportLab
serviceGeneration/renderers/rendererDocx.py DOCX via python-docx
serviceGeneration/renderers/rendererPptx.py PPTX via python-pptx
serviceGeneration/renderers/rendererXlsx.py XLSX via openpyxl
serviceGeneration/renderers/rendererHtml.py HTML via String/Jinja
serviceAgent/coreTools/_mediaTools.py renderDocument Agent-Tool

Auch wichtig

  • Grossdokumente: Lazy File-Ref-Bilder (_lazyResolveImageBase64) + Temp-File-Bilder fuer PDF vermeiden OOM bei vielen eingebetteten Bildern. Siehe c-work/4-done/2026-06-po-cleanup-neutralization-docgen.md (A3/AC15).
  • Markdown-Renderer/Text-Renderer ignorieren style (dokumentiert, kein Bug).
  • Agent-Tool renderDocument: Akzeptiert optionalen style-Parameter im Tool-Schema; kein documentTheme-Parameter mehr.