diff --git a/.checkpoint-pending.txt b/.checkpoint-pending.txt index 3f3076a..4fbff93 100644 --- a/.checkpoint-pending.txt +++ b/.checkpoint-pending.txt @@ -1,2 +1,2 @@ S07 -PDF-Build-Fehler endgueltig behoben. S06-Hotfix (array, calc, providecommand real) loeste das Problem nicht; nach Rebuild kam unveraendert "! LaTeX Error: No counter 'none' defined." Eigentliche Ursache: Pandoc 3.x emittiert fuer unnummerierte Tabellen direkt vor begin{longtable} die Zeile def LTcaptype none, ohne den Counter none zu definieren. Pandocs eigene Default-Vorlage definiert ihn (commit d835461 in Pandoc 3.8.2.1), Custom-Templates muessen das selbst tun (siehe Pandoc-Issue 11201). Fix: eine Zeile newcounter none direkt nach providecommand real im Tabellen-Block des Templates. Sandbox-Reproduktion exakter Fehlertext ohne Fix, sauberes PDF mit Fix. Auf Thomas' System: PDF wird erzeugt, Ausbildungs-Layout im PDF visuell bestaetigt. Iteration A fuer Teilgebiet 01 damit inhaltlich abgeschlossen. Build-UX-Fix: build.ps1 ergaenzt um Start-Sleep -Seconds 3 nach jedem fehlschlagenden Build-Schritt (Pflichtdatei-Check, PDF-Build, DOCX-Build), damit die rote Fehlerzeile lesbar bleibt bevor das PowerShell-Fenster zugeht. teilgebiete/01-lebenslauf.md um beide Fixes ergaenzt (zweistufige Hotfix-Geschichte, PDF-Bestaetigung, UX-Fix). agent-prompt.md Aktueller-Stand-Abschnitt fuer S08 fortgeschrieben mit verbleibender Iterationsreihenfolge B-C-D, Hinweise auf Pandoc-Versionsunterschied praeziser formuliert. +Teilgebiet 01 Iteration B (Iterationen B1, B1.5, B2) durchgezogen. Neue Datei build/build-reference-docx.py baut templates/reference.docx programmatisch aus Pandocs Default-Reference (Python-Stdlib only, kein pip; pandoc --print-default-data-file zur Laufzeit, ZIP entpacken, ElementTree-XML-Anpassungen, repacken). B1: Theme major+minor und alle direkten Schrift-Refs in styles.xml auf Calibri umgestellt (Code-Schriften wie Consolas bleiben), Tabellen-Default-Stil mit tblBorders=none auf allen Sides. B1.5: Body-DocDefault 11 pt, Heading 1/2/3 auf 15/13/12 pt analog PDF. B2: header1.xml (Default ab Seite 2 mit Name links und Lebenslauf rechts), header2.xml (leer fuer Seite 1 via titlePg), footer1.xml (rechts Seite n / m mit PAGE/NUMPAGES-Feldern, doppelt referenziert als default und first damit Seite 1 trotz titlePg den Footer hat). Page-Setup explizit in sectPr: A4 mit 2.2 cm oben/unten und 2.5 cm links/rechts analog PDF, Tab-Stop am rechten Textrand 9072 dxa. Beziehungen mit dynamisch naechster freier rId in document.xml.rels, Content-Types-Overrides in [Content_Types].xml, sectPr regex-ersetzt idempotent. Sandbox-End-to-End mit Pandoc 2.9 verifiziert (sectPr und Header/Footer im generierten DOCX vorhanden). Auf Thomas System: DOCX visuell bestaetigt. teilgebiete/01-lebenslauf.md um vollstaendigen Iteration-B-Block ergaenzt, Naechste-Schritte-Liste auf B3, B4, C, D umstrukturiert. agent-prompt.md Aktueller-Stand-Abschnitt fortgeschrieben mit Hinweisen zur reference-docx-Pipeline (manuell vor build.ps1 aufrufen, nicht von Hand in Word editieren) und zur Edit-Tool-Truncation auf dem NTFS-Mount. Build-UX-Fix in build.ps1 mit 3-Sekunden-Pause pro fehlgeschlagenem Schritt war ebenfalls Teil dieser Session. diff --git a/agent-prompt.md b/agent-prompt.md index 7079296..3307407 100644 --- a/agent-prompt.md +++ b/agent-prompt.md @@ -88,14 +88,19 @@ Setze zwischen sinnvollen Zwischenständen Checkpoints (z.B. nach "Marketing.md **Letzte Session:** S07 (2026-04-26) **Was wurde gemacht:** -- **PDF-Build-Fehler endgültig behoben.** Der S06-Hotfix (array, calc, providecommand real) hat das Problem nicht beseitigt — nach Rebuild auf Thomas' System kam unverändert `! LaTeX Error: No counter 'none' defined.` Eigentliche Ursache: Pandoc 3.x emittiert für unnummerierte Tabellen direkt vor `\begin{longtable}` die Zeile `\def\LTcaptype{none}`, ohne den Counter `none` zu definieren. Sobald longtable intern `\refstepcounter{\LTcaptype}` aufruft, bricht LaTeX ab. Pandocs eigene Default-Vorlage definiert den Counter (commit d835461 in 3.8.2.1), Custom-Templates müssen das selbst tun. Siehe [Pandoc-Issue #11201](https://github.com/jgm/pandoc/issues/11201). Fix: eine Zeile `\newcounter{none}` direkt nach `\providecommand{\real}` im Tabellen-Block des Templates. In der Sandbox sauber reproduziert (gleicher Fehlertext ohne Fix, sauberes PDF mit Fix). Auf Thomas' System: PDF wird erzeugt, Ausbildungs-Layout im PDF visuell bestätigt. -- **Iteration A für Teilgebiet 01 damit inhaltlich abgeschlossen** (Tabellen-Variante mit zwei Spalten ca. 14 % / 80 %, rahmenlos im PDF, native Word-Tabelle im DOCX — Rahmen-Aus folgt in Iteration B). -- **Build-UX-Fix:** `build/build.ps1` ergänzt um `Start-Sleep -Seconds 3` nach jedem fehlschlagenden Build-Schritt (Pflichtdatei-Check, PDF-Build, DOCX-Build). Vorher schloss sich das PowerShell-Fenster bei Doppelklick auf das Skript so schnell, dass die rote Fehlerzeile nicht lesbar war. Bei mehreren Fehlern in einem Lauf akkumulieren sich die Pausen — gewollt. +- **PDF-Build-Fehler endgültig behoben.** Pandoc-3.x-`\def\LTcaptype{none}`-Bug ([Issue #11201](https://github.com/jgm/pandoc/issues/11201)). Fix: `\newcounter{none}` im Template, sandbox-reproduziert. PDF läuft auf Thomas' System, Ausbildungs-Layout visuell bestätigt. **Iteration A damit inhaltlich abgeschlossen.** +- **Build-UX-Fix:** `build/build.ps1` mit `Start-Sleep -Seconds 3` pro fehlschlagendem Schritt, damit das PowerShell-Fenster bei Fehler nicht zu schnell schließt. +- **Iteration B durchgezogen — `reference.docx` programmatisch via `build/build-reference-docx.py` (Python-Stdlib only, kein pip).** Holt Pandoc-Default-Reference per `pandoc --print-default-data-file`, entpackt die DOCX als ZIP, modifiziert XML mit ElementTree, repackt. + - **B1 — Schriften:** Theme `majorFont` und `minorFont` beide auf Calibri (Pandoc 3.x setzt Defaults auf Aptos Display / Aptos). Defensive Maßnahme: alle direkten ``-Referenzen außerhalb von Code-Schriften (Consolas, Courier, ...) auf Calibri. + - **B1 — Tabellen:** Stil `Table` mit `` auf allen Sides. Word-Editor zeigt weiterhin Tabellen-Anzeige-Hilfslinien (kein Druck-Rendering); Druckansicht und PDF-Export sind sauber rahmenlos. + - **B1.5 — Schriftgrößen analog PDF:** DocDefault Body 11 pt, Heading 1/2/3 auf 15/13/12 pt. DOCX schrumpft von 10 auf 9 Seiten. + - **B2 — Header, Footer, Page-Setup:** `header1.xml` (Default ab Seite 2: Name links, „Lebenslauf" rechts), `header2.xml` (leer für Seite 1 via `titlePg`), `footer1.xml` (rechts „Seite n / m" mit `PAGE`/`NUMPAGES`-Feldern, einmal als `default`, einmal als `first` referenziert, damit Seite 1 trotz titlePg den Footer hat). Page-Setup explizit: A4 mit 2.2 cm oben/unten, 2.5 cm links/rechts (analog PDF). Tab-Stop am rechten Textrand 9072 dxa = 16 cm. Beziehungen werden mit dynamisch ermittelter nächster freier `rId` registriert; Content-Types-Overrides ergänzt; sectPr regex-basiert ersetzt (idempotent gegen `` und längere Varianten). Pandoc 2.9 und 3.x übernehmen die sectPr ins generierte DOCX (in der Sandbox end-to-end verifiziert). DOCX-Layout von Thomas visuell bestätigt: Seite 1 ohne Header und mit Footer, Seite 2 ff. Header und Footer wie gewünscht, Tab-Stops bündig am rechten Textrand. -**Nächste Aufgabe:** Teilgebiet 01 — drei verbleibende Iterationen in dieser Reihenfolge: -1. **B) `templates/reference.docx` in Word polieren** — Header/Footer setzen, Schriften auf Calibri vereinheitlichen, Listen-Schutz „Keep with next" und Widow-Control via Word-Stile, Tabellen-Stile so konfigurieren, dass die Ausbildungs-Tabelle ohne Rahmen rendert (Default-Tabellenstil oder benannter Stil). -2. **C) Foto-Einbindung** in cv.md mit Pandoc-Image-Syntax und Template-Anpassung für Position/Größe (z.B. oben rechts neben Name, ca. 3 cm). -3. **D) Hyphenation-Feintuning für PDF** — kurze Wortteile am Zeilenanfang mit höherer Penalty oder gezielten `\hyphenation`-Ausnahmen reduzieren. Iterativ. +**Nächste Aufgabe:** Teilgebiet 01 — verbleibende Iterationen: +1. **B3 — Keep with next + Widow/Orphan-Control für DOCX.** Schusterjungen-Schutz analog `\widowpenalty`/`needspace` im PDF. Auf Stilebene `` für Headings und `` als DocDefault. +2. **B4 (optional) — Heading-Farben auf DesTEngS-Blau und/oder Trennlinien analog PDF.** Eher Kosmetik bei Vorlage für Consulting-Agenturen. +3. **C — Foto-Einbindung** in cv.md mit Pandoc-Image-Syntax und Template-Anpassung für Position/Größe (z.B. oben rechts neben Name, ca. 3 cm). +4. **D — Hyphenation-Feintuning für PDF** — kurze Wortteile am Zeilenanfang mit höherer Penalty oder `\hyphenation`-Ausnahmen reduzieren. Nach D): Status von Teilgebiet 01 in `zentral-index.md` auf „abgeschlossen" setzen (R2-OK von Thomas). Anschließend nächstes Teilgebiet nach Priorität (laut Index Teilgebiet 02 „Zeugnis von ASMPT"). @@ -108,3 +113,5 @@ Nach D): Status von Teilgebiet 01 in `zentral-index.md` auf „abgeschlossen" se - **Sandbox kann nichts an `.git/` schreiben** (NTFS-Permission-Issue): Lock-Files, korrupte Index — alles muss von PowerShell aus repariert werden. - **`checkpoint.ps1` ist robust** gegen Anführungszeichen, Pipes, Whitespace-Anomalien und Index-Lock-Reste. `.checkpoint-pending.txt` darf ganz normal Sonderzeichen enthalten. - **`build.ps1` pausiert bei Fehler 3 Sekunden pro fehlgeschlagenem Schritt.** Nicht überrascht sein, wenn ein fehlerhafter Lauf entsprechend länger braucht. +- **`build/build-reference-docx.py` muss VOR `build.ps1` manuell aufgerufen werden, wenn `templates/reference.docx` neu gebaut werden soll.** Das Skript ist nicht in `build.ps1` integriert (würde jeden Build verlangsamen und Pandoc-Default-Reference jedes Mal neu ziehen). Wenn jemand die `reference.docx` von Hand in Word editiert, gehen die Änderungen beim nächsten Skript-Lauf verloren — Stile gehören also ins Skript, nicht in Word. +- **Edit-Tool kann Dateien beim Schreiben über den NTFS-Mount truncatieren** (mehrfach in S07 erlebt am Python-Skript). `mcp__workspace__bash` mit `cat <<'EOF' > path` ist die zuverlässige Alternative für längere Dateien (>~150 Zeilen). Nach jedem Edit auf NTFS-Mount-Datei: `wc -l` und `tail -c` zur Verifikation. diff --git a/artefakte/01-lebenslauf/build/build-reference-docx.py b/artefakte/01-lebenslauf/build/build-reference-docx.py new file mode 100644 index 0000000..b5d5c99 --- /dev/null +++ b/artefakte/01-lebenslauf/build/build-reference-docx.py @@ -0,0 +1,401 @@ +#!/usr/bin/env python3 +""" +build-reference-docx.py +======================= + +Baut die templates/reference.docx fuer die Pandoc-DOCX-Pipeline aus der +Pandoc-Default-Reference, mit gezielten Anpassungen. + +Iteration B1 + B1.5 + B2 (aktuell): + B1 - Theme-Schriften (majorFont und minorFont) beide auf Calibri. + B1 - Direkte Schriftnamen-Referenzen in styles.xml auf Calibri + (Code-Schriften wie Consolas bleiben). + B1 - Tabellen-Default-Stil "Table" mit tblBorders=none. + B1.5 - Body-DocDefault 11pt, Heading 1/2/3 auf 15/13/12 pt. + B2 - Header (Name links, "Lebenslauf" rechts) ab Seite 2; Seite 1 mit + leerem Header (titlePg-Mechanik). Footer (rechts: Seite n / m) auf + allen Seiten inkl. Seite 1 (footer-Ref fuer "first" zeigt auf den + gleichen Footer wie "default"). Page-Setup explizit: A4, Raender + analog PDF (top/bottom 2.2 cm, left/right 2.5 cm). Damit ist der + Tab-Stop deterministisch unabhaengig von Word-Locale-Defaults. + +Geplant in Folge-Iterationen: + B3 - Heading-Stile mit "keep with next", Widow/Orphan-Control auf Stilebene + B4 - optional Heading-Farben auf DesTEngS-Blau analog PDF + +Vorgehen: + 1. Pandoc-Default-Reference per `pandoc --print-default-data-file + reference.docx` extrahieren. + 2. Als ZIP entpacken. + 3. Relevante XML-Dateien anpassen, neue Header/Footer-XMLs anlegen, + Beziehungen und ContentTypes ergaenzen, sectPr setzen. + 4. Als neue ZIP-Datei (templates/reference.docx) speichern. + +Voraussetzungen: nur Python-Stdlib + Pandoc im PATH. +""" + +from __future__ import annotations + +import re +import subprocess +import sys +import tempfile +import zipfile +from pathlib import Path +from xml.etree import ElementTree as ET + +# --- Pfade ----------------------------------------------------------------- + +SCRIPT_DIR = Path(__file__).resolve().parent +BASE_DIR = SCRIPT_DIR.parent +TEMPLATES_DIR = BASE_DIR / "templates" +OUTPUT_FILE = TEMPLATES_DIR / "reference.docx" + +# --- XML-Namespaces -------------------------------------------------------- + +NS = { + "w": "http://schemas.openxmlformats.org/wordprocessingml/2006/main", + "a": "http://schemas.openxmlformats.org/drawingml/2006/main", + "r": "http://schemas.openxmlformats.org/officeDocument/2006/relationships", + "rel": "http://schemas.openxmlformats.org/package/2006/relationships", + "ct": "http://schemas.openxmlformats.org/package/2006/content-types", +} +for prefix, uri in NS.items(): + ET.register_namespace(prefix, uri) +ET.register_namespace("", NS["rel"]) + +W = "{%s}" % NS["w"] +A = "{%s}" % NS["a"] + +# --- Konfiguration --------------------------------------------------------- + +CODE_FONTS = {"consolas", "courier", "courier new", "liberation mono", + "monaco", "menlo", "fira mono", "fira code"} +TARGET_FONT = "Calibri" + +SIZE_BODY = 22 +SIZE_HEADING1 = 30 +SIZE_HEADING2 = 26 +SIZE_HEADING3 = 24 +HEADING_SIZES = {"Heading1": SIZE_HEADING1, + "Heading2": SIZE_HEADING2, + "Heading3": SIZE_HEADING3} + +# Page-Setup (in DXA, 1cm = 566.929 dxa; 1 inch = 1440 dxa) +# A4: 21.0 x 29.7 cm +PAGE_W = 11906 # A4 Breite +PAGE_H = 16838 # A4 Hoehe +MARGIN_TOP = 1247 # 2.2 cm +MARGIN_BOT = 1247 # 2.2 cm +MARGIN_LEFT = 1417 # 2.5 cm +MARGIN_RIGHT = 1417 # 2.5 cm +HEADER_POS = 720 # 1.27 cm vom oberen Seitenrand +FOOTER_POS = 720 # 1.27 cm vom unteren Seitenrand +# Tab-Stop am rechten Textrand: PAGE_W - LEFT - RIGHT = 9072 dxa = 16 cm +HEADER_RIGHT_TAB = PAGE_W - MARGIN_LEFT - MARGIN_RIGHT + +HEADER_LEFT = "Dr.-Ing. Thomas Langer" +HEADER_RIGHT = "Lebenslauf" + +# --- Hilfsfunktionen ------------------------------------------------------- + +def log(msg: str) -> None: + print(f"[build-reference-docx] {msg}", flush=True) + +XML_DECL = b'\n' + +def write_xml(tree: ET.ElementTree, dest: Path) -> None: + body = ET.tostring(tree.getroot(), encoding="utf-8") + dest.write_bytes(XML_DECL + body) + +def write_xml_bytes(content: bytes, dest: Path) -> None: + dest.write_bytes(XML_DECL + content) + +def fetch_pandoc_default(dest: Path) -> None: + log("Pandoc-Default-Reference extrahieren ...") + result = subprocess.run( + ["pandoc", "--print-default-data-file", "reference.docx"], + capture_output=True, check=False, + ) + if result.returncode != 0: + sys.stderr.write(result.stderr.decode("utf-8", errors="replace")) + raise SystemExit(f"pandoc liefert Exit-Code {result.returncode}") + dest.write_bytes(result.stdout) + log(f" -> {dest} ({dest.stat().st_size} Bytes)") + +def unpack_docx(src: Path, dest_dir: Path) -> None: + with zipfile.ZipFile(src, "r") as z: + z.extractall(dest_dir) + +def repack_docx(src_dir: Path, dest: Path) -> None: + files = [] + for path in src_dir.rglob("*"): + if path.is_file(): + arcname = path.relative_to(src_dir).as_posix() + files.append((path, arcname)) + files.sort(key=lambda t: (0 if t[1] == "[Content_Types].xml" else 1, t[1])) + with zipfile.ZipFile(dest, "w", zipfile.ZIP_DEFLATED) as z: + for path, arcname in files: + z.write(path, arcname) + +def is_code_font(name: str) -> bool: + return (name or "").strip().lower() in CODE_FONTS + +# --- B1: Schriften --------------------------------------------------------- + +def set_theme_fonts_to_calibri(theme_xml: Path) -> None: + tree = ET.parse(theme_xml) + root = tree.getroot() + for kind in ("majorFont", "minorFont"): + font = root.find(f".//{A}{kind}") + if font is None: + raise RuntimeError(f"{kind}-Element nicht im Theme") + latin = font.find(f"{A}latin") + if latin is None: + raise RuntimeError(f"{kind}/latin-Element nicht gefunden") + old = latin.get("typeface") + latin.set("typeface", TARGET_FONT) + log(f" Theme {kind}/latin: {old!r} -> {TARGET_FONT!r}") + write_xml(tree, theme_xml) + +def replace_direct_fonts_in_styles(styles_xml: Path) -> None: + tree = ET.parse(styles_xml) + root = tree.getroot() + changed = 0 + skipped = 0 + for rfonts in root.iter(f"{W}rFonts"): + for attr in (f"{W}ascii", f"{W}hAnsi", f"{W}cs", f"{W}eastAsia"): + val = rfonts.get(attr) + if val is None: + continue + if is_code_font(val): + skipped += 1 + continue + if val != TARGET_FONT: + rfonts.set(attr, TARGET_FONT) + changed += 1 + log(f" styles.xml: {changed} direkte Font-Attribute auf {TARGET_FONT!r}" + f" gesetzt (Code-Fonts unangetastet: {skipped})") + write_xml(tree, styles_xml) + +# --- B1: Tabellen ---------------------------------------------------------- + +def set_table_borders_none(styles_xml: Path) -> None: + tree = ET.parse(styles_xml) + root = tree.getroot() + style = next((s for s in root.findall(f"{W}style") + if s.get(f"{W}styleId") == "Table"), None) + if style is None: + raise RuntimeError("Style 'Table' nicht in styles.xml") + tbl_pr = style.find(f"{W}tblPr") or ET.SubElement(style, f"{W}tblPr") + existing = tbl_pr.find(f"{W}tblBorders") + if existing is not None: + tbl_pr.remove(existing) + borders = ET.SubElement(tbl_pr, f"{W}tblBorders") + for side in ("top", "left", "bottom", "right", "insideH", "insideV"): + e = ET.SubElement(borders, f"{W}{side}") + e.set(f"{W}val", "none") + e.set(f"{W}sz", "0") + e.set(f"{W}space", "0") + e.set(f"{W}color", "auto") + log(" Style 'Table': tblBorders=none auf allen Sides") + write_xml(tree, styles_xml) + +# --- B1.5: Schriftgroessen ------------------------------------------------ + +def set_default_body_size(styles_xml: Path) -> None: + tree = ET.parse(styles_xml) + root = tree.getroot() + docDefaults = root.find(f"{W}docDefaults") or ET.SubElement(root, f"{W}docDefaults") + rPrDefault = docDefaults.find(f"{W}rPrDefault") or ET.SubElement(docDefaults, f"{W}rPrDefault") + rPr = rPrDefault.find(f"{W}rPr") or ET.SubElement(rPrDefault, f"{W}rPr") + for tag in (f"{W}sz", f"{W}szCs"): + elem = rPr.find(tag) or ET.SubElement(rPr, tag) + elem.set(f"{W}val", str(SIZE_BODY)) + log(f" DocDefault Body-Schriftgroesse: {SIZE_BODY/2} pt") + write_xml(tree, styles_xml) + +def set_heading_sizes(styles_xml: Path) -> None: + tree = ET.parse(styles_xml) + root = tree.getroot() + for style in root.findall(f"{W}style"): + sid = style.get(f"{W}styleId") + if sid not in HEADING_SIZES: + continue + target = HEADING_SIZES[sid] + rPr = style.find(f"{W}rPr") or ET.SubElement(style, f"{W}rPr") + for tag in (f"{W}sz", f"{W}szCs"): + elem = rPr.find(tag) or ET.SubElement(rPr, tag) + elem.set(f"{W}val", str(target)) + log(f" Stil {sid!r}: Schriftgroesse {target/2} pt") + write_xml(tree, styles_xml) + +# --- B2: Header und Footer ------------------------------------------------ + +def header_default_xml() -> bytes: + return ( + b'\n' + b' \n' + b' \n' + b' \n' + b' \n' + b' \n' + b' \n' + b' ' + HEADER_LEFT.encode() + b'\n' + b' ' + HEADER_RIGHT.encode() + b'\n' + b' \n' + b'\n' + ) + +def header_first_blank_xml() -> bytes: + return ( + b'\n' + b' \n' + b'\n' + ) + +def footer_default_xml() -> bytes: + return ( + b'\n' + b' \n' + b' \n' + b' \n' + b' \n' + b' \n' + b' \n' + b' Seite \n' + b' \n' + b' 1\n' + b' \n' + b' / \n' + b' \n' + b' 1\n' + b' \n' + b' \n' + b'\n' + ) + +REL_HEADER = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/header" +REL_FOOTER = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/footer" +CT_HEADER = "application/vnd.openxmlformats-officedocument.wordprocessingml.header+xml" +CT_FOOTER = "application/vnd.openxmlformats-officedocument.wordprocessingml.footer+xml" + +def next_free_rel_id(rels_xml: Path) -> int: + text = rels_xml.read_text(encoding="utf-8") + ids = [int(m.group(1)) for m in re.finditer(r'Id="rId(\d+)"', text)] + return (max(ids) + 1) if ids else 1 + +def add_relationship(rels_xml: Path, rid: str, rtype: str, target: str) -> None: + text = rels_xml.read_text(encoding="utf-8") + new_rel = f'' + if new_rel in text: + return + text = text.replace("", new_rel + "") + rels_xml.write_text(text, encoding="utf-8") + +def add_content_type_override(ct_xml: Path, part_name: str, ct: str) -> None: + text = ct_xml.read_text(encoding="utf-8") + new_override = f'' + if part_name in text: + return + text = text.replace("", new_override + "") + ct_xml.write_text(text, encoding="utf-8") + +def update_sectpr_with_headers(document_xml: Path, + header_default_rid: str, + header_first_rid: str, + footer_default_rid: str) -> None: + """Ersetzt sectPr durch Page-Setup + Header/Footer-Refs + titlePg. + Footer-Ref wird zweimal eingebaut (default und first), beide auf + den gleichen Footer — dann hat Seite 1 trotz titlePg den Footer.""" + text = document_xml.read_text(encoding="utf-8") + new_sectpr = ( + f'' + f'' + f'' + f'' + f'' + f'' + f'' + f'' + f'' + ) + new_text, n = re.subn( + r'|.*?', + new_sectpr, text, flags=re.DOTALL, + ) + if n == 0: + new_text = text.replace("", new_sectpr + "") + document_xml.write_text(new_text, encoding="utf-8") + log(f" document.xml sectPr: pgSz/pgMar (A4, 2.2/2.5cm Raender), Header" + f" default+first, Footer default+first auf gleicher rId, titlePg") + +def add_header_footer(unpacked: Path) -> None: + word_dir = unpacked / "word" + rels_xml = word_dir / "_rels" / "document.xml.rels" + ct_xml = unpacked / "[Content_Types].xml" + doc_xml = word_dir / "document.xml" + + write_xml_bytes(header_default_xml(), word_dir / "header1.xml") + write_xml_bytes(header_first_blank_xml(), word_dir / "header2.xml") + write_xml_bytes(footer_default_xml(), word_dir / "footer1.xml") + log(" word/header1.xml (default), header2.xml (first blank)," + " footer1.xml geschrieben") + + next_id = next_free_rel_id(rels_xml) + rid_h_def, rid_h_first, rid_f_def = (f"rId{next_id+i}" for i in range(3)) + add_relationship(rels_xml, rid_h_def, REL_HEADER, "header1.xml") + add_relationship(rels_xml, rid_h_first, REL_HEADER, "header2.xml") + add_relationship(rels_xml, rid_f_def, REL_FOOTER, "footer1.xml") + log(f" Beziehungen: {rid_h_def}=header1, {rid_h_first}=header2," + f" {rid_f_def}=footer1") + + add_content_type_override(ct_xml, "/word/header1.xml", CT_HEADER) + add_content_type_override(ct_xml, "/word/header2.xml", CT_HEADER) + add_content_type_override(ct_xml, "/word/footer1.xml", CT_FOOTER) + log(" [Content_Types].xml: Override-Eintraege fuer header1/2 und footer1") + + update_sectpr_with_headers(doc_xml, rid_h_def, rid_h_first, rid_f_def) + +# --- Hauptablauf ----------------------------------------------------------- + +def main() -> int: + log(f"Ziel: {OUTPUT_FILE}") + TEMPLATES_DIR.mkdir(parents=True, exist_ok=True) + + with tempfile.TemporaryDirectory(prefix="refdocx-") as tmp: + tmp_dir = Path(tmp) + default_docx = tmp_dir / "pandoc-default.docx" + unpacked = tmp_dir / "unpacked" + + fetch_pandoc_default(default_docx) + unpacked.mkdir() + unpack_docx(default_docx, unpacked) + + theme_xml = unpacked / "word" / "theme" / "theme1.xml" + styles_xml = unpacked / "word" / "styles.xml" + + log("Anpassung: Theme major+minor auf Calibri") + set_theme_fonts_to_calibri(theme_xml) + log("Anpassung: Direkte Font-Referenzen in styles.xml -> Calibri") + replace_direct_fonts_in_styles(styles_xml) + log("Anpassung: Tabellen-Default ohne Rahmen") + set_table_borders_none(styles_xml) + log("Anpassung: Body-Schriftgroesse 11 pt (DocDefault)") + set_default_body_size(styles_xml) + log("Anpassung: Heading-Schriftgroessen 15/13/12 pt") + set_heading_sizes(styles_xml) + log("Anpassung: Header und Footer einbauen (B2)") + add_header_footer(unpacked) + + log("Repack als reference.docx") + repack_docx(unpacked, OUTPUT_FILE) + log(f" -> {OUTPUT_FILE} ({OUTPUT_FILE.stat().st_size} Bytes)") + + log("Fertig.") + return 0 + +if __name__ == "__main__": + sys.exit(main()) diff --git a/artefakte/01-lebenslauf/output/Lebenslauf_Dr-Ing_Thomas_Langer.docx b/artefakte/01-lebenslauf/output/Lebenslauf_Dr-Ing_Thomas_Langer.docx index 5b1df74..09bc758 100644 Binary files a/artefakte/01-lebenslauf/output/Lebenslauf_Dr-Ing_Thomas_Langer.docx and b/artefakte/01-lebenslauf/output/Lebenslauf_Dr-Ing_Thomas_Langer.docx differ diff --git a/artefakte/01-lebenslauf/output/Lebenslauf_Dr-Ing_Thomas_Langer.pdf b/artefakte/01-lebenslauf/output/Lebenslauf_Dr-Ing_Thomas_Langer.pdf index a202924..3dbf06b 100644 --- a/artefakte/01-lebenslauf/output/Lebenslauf_Dr-Ing_Thomas_Langer.pdf +++ b/artefakte/01-lebenslauf/output/Lebenslauf_Dr-Ing_Thomas_Langer.pdf @@ -727,7 +727,7 @@ endobj << /Type /Catalog /Pages 89 0 R /Outlines 158 0 R /Names 160 0 R /PageMode/UseOutlines /OpenAction 81 0 R >> endobj 162 0 obj -<< /Author(\376\377\000D\000r\000.\000-\000I\000n\000g\000.\000\040\000T\000h\000o\000m\000a\000s\000\040\000L\000a\000n\000g\000e\000r)/Title(\376\377\000L\000e\000b\000e\000n\000s\000l\000a\000u\000f\000\040\000D\000r\000.\000-\000I\000n\000g\000.\000\040\000T\000h\000o\000m\000a\000s\000\040\000L\000a\000n\000g\000e\000r)/Subject()/Creator(\376\377\000P\000a\000n\000d\000o\000c\000\040\000+\000\040\000L\000u\000a\000L\000a\000T\000e\000X)/Keywords() /Producer (LuaTeX-1.24.0) /CreationDate (D:20260426104140+02'00') /ModDate (D:20260426104140+02'00') /Trapped /False /PTEX.FullBanner (This is LuaHBTeX, Version 1.24.0 (MiKTeX 26.2)) >> +<< /Author(\376\377\000D\000r\000.\000-\000I\000n\000g\000.\000\040\000T\000h\000o\000m\000a\000s\000\040\000L\000a\000n\000g\000e\000r)/Title(\376\377\000L\000e\000b\000e\000n\000s\000l\000a\000u\000f\000\040\000D\000r\000.\000-\000I\000n\000g\000.\000\040\000T\000h\000o\000m\000a\000s\000\040\000L\000a\000n\000g\000e\000r)/Subject()/Creator(\376\377\000P\000a\000n\000d\000o\000c\000\040\000+\000\040\000L\000u\000a\000L\000a\000T\000e\000X)/Keywords() /Producer (LuaTeX-1.24.0) /CreationDate (D:20260426132419+02'00') /ModDate (D:20260426132419+02'00') /Trapped /False /PTEX.FullBanner (This is LuaHBTeX, Version 1.24.0 (MiKTeX 26.2)) >> endobj xref 0 163 @@ -895,7 +895,7 @@ xref 0000065582 00000 n 0000065708 00000 n trailer -<< /Size 163 /Root 161 0 R /Info 162 0 R /ID [ <53CF6B4AF812DB9CEA60519E77C224DA> <53CF6B4AF812DB9CEA60519E77C224DA> ] >> +<< /Size 163 /Root 161 0 R /Info 162 0 R /ID [ ] >> startxref 66368 %%EOF diff --git a/artefakte/01-lebenslauf/output/build.log b/artefakte/01-lebenslauf/output/build.log index 678c02d..03e1de2 100644 --- a/artefakte/01-lebenslauf/output/build.log +++ b/artefakte/01-lebenslauf/output/build.log @@ -1,4 +1,4 @@ -===== Build gestartet: 2026-04-26 10:41:37 ===== +===== Build gestartet: 2026-04-26 13:24:16 ===== Source: Q:\DesTEngS\Pro\Git\marketing\claude_cowork\artefakte\01-lebenslauf\source\cv.md Template-TEX: Q:\DesTEngS\Pro\Git\marketing\claude_cowork\artefakte\01-lebenslauf\templates\template.tex Reference: Q:\DesTEngS\Pro\Git\marketing\claude_cowork\artefakte\01-lebenslauf\templates\reference.docx @@ -9,5 +9,5 @@ Cmd: pandoc --from=markdown+smart --pdf-engine=lualatex --template=Q:\DesTEngS\P PDF OK: Q:\DesTEngS\Pro\Git\marketing\claude_cowork\artefakte\01-lebenslauf\output\Lebenslauf_Dr-Ing_Thomas_Langer.pdf (68.2 KB) --- Pandoc -> DOCX --- Cmd: pandoc --from=markdown+smart --reference-doc=Q:\DesTEngS\Pro\Git\marketing\claude_cowork\artefakte\01-lebenslauf\templates\reference.docx --resource-path=Q:\DesTEngS\Pro\Git\marketing\claude_cowork\artefakte\01-lebenslauf\source --output=Q:\DesTEngS\Pro\Git\marketing\claude_cowork\artefakte\01-lebenslauf\output\Lebenslauf_Dr-Ing_Thomas_Langer.docx Q:\DesTEngS\Pro\Git\marketing\claude_cowork\artefakte\01-lebenslauf\source\cv.md -DOCX OK: Q:\DesTEngS\Pro\Git\marketing\claude_cowork\artefakte\01-lebenslauf\output\Lebenslauf_Dr-Ing_Thomas_Langer.docx (20.1 KB) -===== Build beendet: 2026-04-26 10:41:42, Exit-Code 0 ===== +DOCX OK: Q:\DesTEngS\Pro\Git\marketing\claude_cowork\artefakte\01-lebenslauf\output\Lebenslauf_Dr-Ing_Thomas_Langer.docx (22 KB) +===== Build beendet: 2026-04-26 13:24:21, Exit-Code 0 ===== diff --git a/artefakte/01-lebenslauf/templates/reference.docx b/artefakte/01-lebenslauf/templates/reference.docx index 93cbc54..2ca9064 100644 Binary files a/artefakte/01-lebenslauf/templates/reference.docx and b/artefakte/01-lebenslauf/templates/reference.docx differ diff --git a/changelog.md b/changelog.md index edfa767..70fcb6d 100644 --- a/changelog.md +++ b/changelog.md @@ -43,3 +43,4 @@ Chronologisches Log aller Entscheidungen und Prozessereignisse. 2026-04-25 22:35 | S06 | Tooling-Fix: checkpoint.ps1 robust gegen problematische Eingabedaten gemacht. Commit-Message wird jetzt via Temp-Datei und git commit -F uebergeben statt via -m mit String, damit doppelte Anfuehrungszeichen im Summary nicht mehr das Argument zerlegen (Ursache des fehlgeschlagenen Hotfix-Commits zuvor). Pipe-Zeichen im Summary werden vorab abgelehnt, da sie mit dem Changelog-Format Timestamp Pipe Session Pipe Summary kollidieren. Whitespace und Zeilenumbrueche im Summary werden zu einem einzelnen Leerzeichen normalisiert. Pre-flight-Checks ergaenzt: Existenz von .git, verwaiste .git/index.lock mit klarer Anleitung melden, changelog.md muss vor dem Lauf clean sein. Atomarer Rollback bei Fehler im Hauptablauf: changelog.md wird auf Original-Stand zurueckgeschrieben und Index-Stagung von changelog.md per git restore --staged oder git reset HEAD zurueckgesetzt, sodass der naechste Lauf nicht doppelt anhaengt. Cleanup-Robustheit: Temp-Message-Datei wird in finally geloescht, das Loeschen der Pending-Datei ist nicht mehr fatal sondern nur eine Warnung. 2026-04-25 22:43 | S06 | Session-Abschluss S06. Teilgebiet 01 Iteration A inhaltlich umgesetzt: Ausbildung als 2-Spalten-Layout via Pandoc-Multiline-Tabelle ohne Header, Template um array, calc, booktabs, longtable und providecommand real ergänzt, alle Linienbreiten auf 0pt. DOCX-Layout von Thomas visuell bestätigt (nur Default-Tabellenrahmen offen, Rahmen-Aus in Iteration B). PDF-Build mit Hotfix steht noch aus — erste Aufgabe der nächsten Session ist build.ps1 laufen lassen und das Ausbildungs-Layout im PDF prüfen. Tooling-Fix in checkpoint.ps1 abgeschlossen (Quoting-Bug, Pipe-Validierung, Whitespace-Normalisierung, Pre-flight-Checks, atomarer Rollback bei Fehler). agent-prompt.md Aktueller-Stand-Abschnitt für S07 fortgeschrieben mit verbleibender Iterationsreihenfolge B-C-D, neuen Lehren aus S06 dokumentiert (Sandbox-Reads über NTFS-Mount können stale sein, Sandbox-Pandoc 2.9 vs Thomas' Pandoc 3.x Output-Unterschiede). 2026-04-26 10:58 | S07 | PDF-Build-Fehler endgueltig behoben. S06-Hotfix (array, calc, providecommand real) loeste das Problem nicht; nach Rebuild kam unveraendert "! LaTeX Error: No counter 'none' defined." Eigentliche Ursache: Pandoc 3.x emittiert fuer unnummerierte Tabellen direkt vor begin{longtable} die Zeile def LTcaptype none, ohne den Counter none zu definieren. Pandocs eigene Default-Vorlage definiert ihn (commit d835461 in Pandoc 3.8.2.1), Custom-Templates muessen das selbst tun (siehe Pandoc-Issue 11201). Fix: eine Zeile newcounter none direkt nach providecommand real im Tabellen-Block des Templates. Sandbox-Reproduktion exakter Fehlertext ohne Fix, sauberes PDF mit Fix. Auf Thomas' System: PDF wird erzeugt, Ausbildungs-Layout im PDF visuell bestaetigt. Iteration A fuer Teilgebiet 01 damit inhaltlich abgeschlossen. Build-UX-Fix: build.ps1 ergaenzt um Start-Sleep -Seconds 3 nach jedem fehlschlagenden Build-Schritt (Pflichtdatei-Check, PDF-Build, DOCX-Build), damit die rote Fehlerzeile lesbar bleibt bevor das PowerShell-Fenster zugeht. teilgebiete/01-lebenslauf.md um beide Fixes ergaenzt (zweistufige Hotfix-Geschichte, PDF-Bestaetigung, UX-Fix). agent-prompt.md Aktueller-Stand-Abschnitt fuer S08 fortgeschrieben mit verbleibender Iterationsreihenfolge B-C-D, Hinweise auf Pandoc-Versionsunterschied praeziser formuliert. +2026-04-26 13:29 | S07 | Teilgebiet 01 Iteration B (Iterationen B1, B1.5, B2) durchgezogen. Neue Datei build/build-reference-docx.py baut templates/reference.docx programmatisch aus Pandocs Default-Reference (Python-Stdlib only, kein pip; pandoc --print-default-data-file zur Laufzeit, ZIP entpacken, ElementTree-XML-Anpassungen, repacken). B1: Theme major+minor und alle direkten Schrift-Refs in styles.xml auf Calibri umgestellt (Code-Schriften wie Consolas bleiben), Tabellen-Default-Stil mit tblBorders=none auf allen Sides. B1.5: Body-DocDefault 11 pt, Heading 1/2/3 auf 15/13/12 pt analog PDF. B2: header1.xml (Default ab Seite 2 mit Name links und Lebenslauf rechts), header2.xml (leer fuer Seite 1 via titlePg), footer1.xml (rechts Seite n / m mit PAGE/NUMPAGES-Feldern, doppelt referenziert als default und first damit Seite 1 trotz titlePg den Footer hat). Page-Setup explizit in sectPr: A4 mit 2.2 cm oben/unten und 2.5 cm links/rechts analog PDF, Tab-Stop am rechten Textrand 9072 dxa. Beziehungen mit dynamisch naechster freier rId in document.xml.rels, Content-Types-Overrides in [Content_Types].xml, sectPr regex-ersetzt idempotent. Sandbox-End-to-End mit Pandoc 2.9 verifiziert (sectPr und Header/Footer im generierten DOCX vorhanden). Auf Thomas System: DOCX visuell bestaetigt. teilgebiete/01-lebenslauf.md um vollstaendigen Iteration-B-Block ergaenzt, Naechste-Schritte-Liste auf B3, B4, C, D umstrukturiert. agent-prompt.md Aktueller-Stand-Abschnitt fortgeschrieben mit Hinweisen zur reference-docx-Pipeline (manuell vor build.ps1 aufrufen, nicht von Hand in Word editieren) und zur Edit-Tool-Truncation auf dem NTFS-Mount. Build-UX-Fix in build.ps1 mit 3-Sekunden-Pause pro fehlgeschlagenem Schritt war ebenfalls Teil dieser Session. diff --git a/teilgebiete/01-lebenslauf.md b/teilgebiete/01-lebenslauf.md index 767d51d..3d0b73f 100644 --- a/teilgebiete/01-lebenslauf.md +++ b/teilgebiete/01-lebenslauf.md @@ -140,12 +140,45 @@ Die in S04 mit docx-js erstellte Version hatte strukturelle typographische Mäng **Build-UX-Fix (S07):** `build/build.ps1` ergänzt um `Start-Sleep -Seconds 3` nach jedem fehlschlagenden Build-Schritt (Pflichtdatei-Check, PDF, DOCX). Bei Doppelklick auf `checkpoint.cmd`-artigen Aufruf schließt sich das PowerShell-Fenster sonst sofort und Fehlermeldungen sind nicht lesbar. Bei mehreren Fehlern in einem Lauf akkumulieren sich die Pausen — gewollt. +## Iteration B (S07) — `reference.docx` programmatisch bauen + +**Ansatz:** Anstatt die `reference.docx` manuell in Word zu pflegen (nicht versionierbar, nicht reproduzierbar), wird sie durch ein Python-Skript `build/build-reference-docx.py` aus Pandocs Default-Reference erzeugt und gezielt angepasst. Nur Python-Stdlib (`zipfile`, `xml.etree.ElementTree`, `subprocess`, `re`) — keine pip-Abhängigkeit. Das Skript läuft unter Sandbox-Pandoc 2.9 und Thomas' Pandoc 3.x gleichermaßen, weil es die Pandoc-Default-Reference per `pandoc --print-default-data-file reference.docx` zur Laufzeit zieht. Manueller Aufruf vor jedem `build.ps1`, wenn Stile geändert wurden. + +**B1 — Schriften und Tabellen:** + +- Theme-Schriften `majorFont` und `minorFont` beide auf `Calibri` umgestellt (Pandoc 3.x setzt sie als Default auf `Aptos Display` und `Aptos`, Sandbox-Pandoc 2.9 auf `Calibri` und `Cambria`). +- Defensive Maßnahme: alle direkten Schriftnamen-Referenzen in `styles.xml` (z.B. ``) auf Calibri umgestellt, ausgenommen Code-Schriften (Consolas, Courier, ...). In der Pandoc-3.x-Variante kommt das mit 0 Treffern aus, in zukünftigen Pandoc-Versionen mit direkten Heading-Schriftreferenzen würde es greifen. +- Tabellen-Default-Stil `Table` bekommt explizite `` mit `val="none"` auf allen Sides (`top`, `left`, `bottom`, `right`, `insideH`, `insideV`). Word-Editor zeigt die Default-„Tabellenbegrenzungen" weiterhin als Anzeige-Hilfe an (kein Druck-Rendering), Druckansicht und PDF-Export sind sauber rahmenlos. + +**B1.5 — Schriftgrößen analog PDF:** + +- DocDefault `` auf 22 (= 11 pt Body, analog `template.tex`). +- Heading 1/2/3 explizit auf 30/26/24 (= 15/13/12 pt). Damit ist die Heading-Hierarchie visuell ähnlich zum PDF, ohne den Word-Default-Sprung von 20 pt nach 12 pt. +- Effekt: DOCX schrumpft von 10 auf 9 Seiten (im PDF sind es 7). + +**B2 — Header, Footer, Page-Setup:** + +- `word/header1.xml` (Default ab Seite 2): links „Dr.-Ing. Thomas Langer", rechts „Lebenslauf" (Tab-Stop am rechten Textrand). +- `word/header2.xml` (erste Seite): leerer `` über `` aktiviert. +- `word/footer1.xml`: rechtsbündig „Seite n / m" mit Word-Feldern `PAGE` und `NUMPAGES`. Wird über zwei `footerReference`-Einträge (`type="default"` und `type="first"`) auf alle Seiten inkl. Seite 1 angewendet — ohne den `type="first"`-Eintrag würde `titlePg` Seite 1 ohne Footer lassen. +- Page-Setup explizit in ``: A4 (`pgSz w:w="11906" w:h="16838"`), Ränder 2.2 cm oben/unten, 2.5 cm links/rechts (analog PDF). Damit ist der Tab-Stop an `9072 dxa` (= 16 cm Textbreite) deterministisch unabhängig von Word-Locale-Defaults; ohne explizites Page-Setup waren die Tab-Stops vorher etwa 5 mm zu weit links. +- Beziehungen werden in `word/_rels/document.xml.rels` mit dynamisch ermittelter nächster freier `rId` registriert; Content-Types-Overrides in `[Content_Types].xml` ergänzt; `` in `word/document.xml` regex-basiert ersetzt (idempotent gegenüber Pandoc-Defaults `` und längeren Varianten). Pandoc übernimmt die letzte sectPr aus der reference.docx ins generierte DOCX — End-to-End-Test in der Sandbox bestätigt: alle Header/Footer-Refs, pgMar und titlePg sind im finalen DOCX vorhanden. + +**Visuelle Bestätigung im Word (S07):** + +- Body: Calibri 11 pt; Headings 1/2/3: Calibri 15/13/12 pt. +- Ausbildungs-Tabelle in Druckansicht und PDF-Export rahmenlos. +- Seite 1 ohne Header, mit Footer. +- Seite 2 ff. mit Header (Name links, „Lebenslauf" rechts) und Footer (Seite n / m). +- Tab-Stops „Lebenslauf" und Seitenzahl bündig am rechten Textrand. + ## Nächste Schritte -1. **Iteration B — `templates/reference.docx` in Word polieren:** Header/Footer setzen, Schriften auf Calibri vereinheitlichen, Listen-Schutz „Keep with next" und Widow-Control via Word-Stile, Stile `DefinitionTerm` und `Definition` für 2-Spalten-Verhalten konfigurieren (z.B. fester linker Einzug auf `Definition`, hängende Einrückung). -2. **Iteration C — Foto-Einbindung:** Portraitfoto in `source/cv.md` einbetten (Pandoc-Image-Syntax), Position und Größe im Template absichern (z.B. oben rechts neben Name, ca. 3 cm). -3. **Iteration D — Hyphenation-Feintuning für PDF:** Kurze Wortteile am Zeilenanfang mit höherer Penalty oder gezielten `\hyphenation`-Ausnahmen reduzieren. Iterativ. -4. Teilgebiet nach erfolgreichem Output und Freigabe durch Thomas abschließen (R2-OK von Thomas: Status auf „abgeschlossen" im zentral-index.md). +1. **Iteration B3 — Heading-Stile mit „keep with next" und Widow/Orphan-Control:** Schusterjungen-Schutz für DOCX analog zu `\widowpenalty`/`needspace` im PDF. Auf Stilebene über `` für Headings und `` als DocDefault. +2. **Iteration B4 (optional)** — Heading-Farben auf DesTEngS-Blau und/oder Trennlinien analog PDF, falls das DOCX optisch näher ans PDF heran soll. Bei Vorlage für Consulting-Agenturen, die das Layout ohnehin überschreiben, ist das aber eher Kosmetik. +3. **Iteration C — Foto-Einbindung:** Portraitfoto in `source/cv.md` einbetten (Pandoc-Image-Syntax), Position und Größe im Template absichern (z.B. oben rechts neben Name, ca. 3 cm). +4. **Iteration D — Hyphenation-Feintuning für PDF:** Kurze Wortteile am Zeilenanfang mit höherer Penalty oder gezielten `\hyphenation`-Ausnahmen reduzieren. Iterativ. +5. Teilgebiet nach erfolgreichem Output und Freigabe durch Thomas abschließen (R2-OK von Thomas: Status auf „abgeschlossen" im zentral-index.md). ## Artefakte @@ -153,10 +186,11 @@ Die in S04 mit docx-js erstellte Version hatte strukturelle typographische Mäng - `artefakte/01-lebenslauf/source/cv.md` — **Aktive Quelldatei** (aufbauend auf V10, Draft-Marker entfernt). - `artefakte/01-lebenslauf/source/foto-wrba_2026_6782_1.jpg` — Portraitfoto (umbenannt, noch nicht in cv.md eingebunden). -- `artefakte/01-lebenslauf/templates/template.tex` — Pandoc-LaTeX-Template für LuaLaTeX (erstes Grundgerüst). -- `artefakte/01-lebenslauf/templates/reference.docx` — Pandoc-Default-Reference-Doc als Ausgangsbasis (Styles noch anzupassen). -- `artefakte/01-lebenslauf/build/build.ps1` — PowerShell-Build-Skript (PDF + DOCX). -- `artefakte/01-lebenslauf/output/` — erzeugte Ausgaben plus `build.log` (leer bis zum ersten erfolgreichen Build). +- `artefakte/01-lebenslauf/templates/template.tex` — Pandoc-LaTeX-Template für LuaLaTeX (Iteration A inkl. Pandoc-3.x-Hotfix `\newcounter{none}`). +- `artefakte/01-lebenslauf/templates/reference.docx` — Pandoc-Reference-Doc, **automatisch erzeugt** durch `build/build-reference-docx.py`. Nicht von Hand editieren — Änderungen würden beim nächsten Skript-Lauf überschrieben. +- `artefakte/01-lebenslauf/build/build-reference-docx.py` — Python-Skript zum Bauen der `reference.docx` (Iteration B1+B1.5+B2). Manuell aufrufen, wenn Stile geändert werden sollen, danach normalen `build.ps1` laufen. +- `artefakte/01-lebenslauf/build/build.ps1` — PowerShell-Build-Skript (PDF + DOCX) mit 3-Sekunden-Pause bei Fehler. +- `artefakte/01-lebenslauf/output/` — erzeugte Ausgaben plus `build.log`. ### Historische Entwürfe (unter `artefakte/01-lebenslauf/entwuerfe/`)