#Requires -Version 5.1 <# .SYNOPSIS Baut den DesTEngS-Lebenslauf aus source/cv.md in PDF und DOCX. .DESCRIPTION Deterministischer Build ohne GUI oder Komfortfunktionen. - PDF via Pandoc + LuaLaTeX, nutzt templates/template.tex - DOCX via Pandoc, nutzt templates/reference.docx - DOCX-Post-Processing via build/post-process-docx.py (Listen-Bullet-Schutz nach 3-3-Regel) - Log in output/build.log (ueberschrieben pro Build) - Fortschritt wird zusaetzlich in der Konsole angezeigt - Exit-Code 0 = alle Schritte erfolgreich, 1 = mindestens ein Fehler .NOTES Voraussetzungen auf dem System: - Pandoc (im PATH) - MiKTeX mit LuaLaTeX - Python 3 (im PATH) fuer Post-Processing - System-Fonts: IBM Plex Sans und IBM Plex Mono fuer Windows installiert MiKTeX mit "Install missing packages on the fly: Yes" zieht fehlende LaTeX-Pakete beim ersten Lauf automatisch. Hinweis: templates/reference.docx wird NICHT bei jedem Build neu gebaut. Bei Stiländerungen vorher manuell `python build/build-reference-docx.py` aufrufen. #> $ErrorActionPreference = 'Continue' $PSNativeCommandUseErrorActionPreference = $false # --- Pfade (alle relativ zum Speicherort dieses Skripts) --------------------- $scriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path $baseDir = Split-Path -Parent $scriptDir $sourceFile = Join-Path $baseDir 'source\cv.md' $sourceDir = Join-Path $baseDir 'source' $templateTex = Join-Path $baseDir 'templates\template.tex' $referenceDoc = Join-Path $baseDir 'templates\reference.docx' $outputDir = Join-Path $baseDir 'output' $outputPdf = Join-Path $outputDir 'Lebenslauf_Dr-Ing_Thomas_Langer.pdf' $outputDocx = Join-Path $outputDir 'Lebenslauf_Dr-Ing_Thomas_Langer.docx' $logFile = Join-Path $outputDir 'build.log' $luaFilter = Join-Path $scriptDir 'header-image-wrap.lua' # --- Output-Ordner sicherstellen --------------------------------------------- if (-not (Test-Path $outputDir)) { New-Item -ItemType Directory -Path $outputDir -Force | Out-Null } # --- Log initialisieren (UTF-8 ohne BOM) ------------------------------------- $utf8NoBom = New-Object System.Text.UTF8Encoding $false function Write-Log { param([string]$Line) [System.IO.File]::AppendAllText($logFile, $Line + [Environment]::NewLine, $utf8NoBom) } [System.IO.File]::WriteAllText($logFile, '', $utf8NoBom) $startTs = Get-Date -Format 'yyyy-MM-dd HH:mm:ss' Write-Host "" Write-Host "===== Build gestartet: $startTs =====" -ForegroundColor Cyan Write-Log "===== Build gestartet: $startTs =====" Write-Log "Source: $sourceFile" Write-Log "Template-TEX: $templateTex" Write-Log "Reference: $referenceDoc" Write-Log "Output-Dir: $outputDir" Write-Log '' $overallExit = 0 # --- Pflichtdateien pruefen -------------------------------------------------- foreach ($f in @($sourceFile, $templateTex, $referenceDoc, $luaFilter)) { if (-not (Test-Path $f)) { Write-Host "FEHLER: Pflichtdatei fehlt: $f" -ForegroundColor Red Write-Log "FEHLER: Pflichtdatei fehlt: $f" $overallExit = 1 } } if ($overallExit -ne 0) { Write-Host "===== Abbruch: Pflichtdateien fehlen =====" -ForegroundColor Red Write-Log "===== Abbruch: Pflichtdateien fehlen =====" Start-Sleep -Seconds 3 exit $overallExit } # --- PDF-Build --------------------------------------------------------------- Write-Host "" Write-Host "[1/3] PDF wird erzeugt (Pandoc + LuaLaTeX) ..." -ForegroundColor Yellow Write-Log "--- Pandoc -> PDF (LuaLaTeX) ---" $pdfArgs = @( '--from=markdown+smart', '--pdf-engine=lualatex', "--template=$templateTex", "--lua-filter=$luaFilter", "--resource-path=$sourceDir", "--output=$outputPdf", $sourceFile ) Write-Log ('Cmd: pandoc ' + ($pdfArgs -join ' ')) $pdfOutput = & pandoc @pdfArgs 2>&1 $pdfExit = $LASTEXITCODE $pdfOutput | ForEach-Object { Write-Log ([string]$_) } if ($pdfExit -eq 0 -and (Test-Path $outputPdf)) { $sizeKB = [math]::Round((Get-Item $outputPdf).Length / 1KB, 1) Write-Host " PDF OK ($sizeKB KB): $outputPdf" -ForegroundColor Green Write-Log "PDF OK: $outputPdf ($sizeKB KB)" } else { Write-Host " PDF FEHLER (Exit $pdfExit) - Details siehe build.log" -ForegroundColor Red Write-Log "PDF FEHLER (Exit $pdfExit)" $overallExit = 1 Start-Sleep -Seconds 3 } # --- DOCX-Build -------------------------------------------------------------- Write-Host "" Write-Host "[2/3] DOCX wird erzeugt (Pandoc) ..." -ForegroundColor Yellow Write-Log "--- Pandoc -> DOCX ---" $docxArgs = @( '--from=markdown+smart', "--reference-doc=$referenceDoc", "--lua-filter=$luaFilter", "--resource-path=$sourceDir", "--output=$outputDocx", $sourceFile ) Write-Log ('Cmd: pandoc ' + ($docxArgs -join ' ')) $docxOutput = & pandoc @docxArgs 2>&1 $docxExit = $LASTEXITCODE $docxOutput | ForEach-Object { Write-Log ([string]$_) } if ($docxExit -eq 0 -and (Test-Path $outputDocx)) { $sizeKB = [math]::Round((Get-Item $outputDocx).Length / 1KB, 1) Write-Host " DOCX OK ($sizeKB KB): $outputDocx" -ForegroundColor Green Write-Log "DOCX OK: $outputDocx ($sizeKB KB)" # --- Post-Processing: Listen-Bullet-Schutz (3-3-Regel) ------------------ Write-Host "" Write-Host "[3/3] DOCX-Post-Processing (Listen-Bullet-Schutz) ..." -ForegroundColor Yellow Write-Log "--- Post-Process DOCX ---" $postScript = Join-Path $scriptDir 'post-process-docx.py' if (Test-Path $postScript) { $ppOutput = & python $postScript 2>&1 $ppExit = $LASTEXITCODE $ppOutput | ForEach-Object { Write-Log ([string]$_) Write-Host " $_" } if ($ppExit -ne 0) { Write-Host " POST-PROCESS FEHLER (Exit $ppExit)" -ForegroundColor Red Write-Log "POST-PROCESS FEHLER (Exit $ppExit)" $overallExit = 1 Start-Sleep -Seconds 3 } } else { Write-Host " Hinweis: $postScript nicht vorhanden, uebersprungen" -ForegroundColor Yellow Write-Log "Hinweis: post-process-docx.py nicht vorhanden, uebersprungen" } } else { Write-Host " DOCX FEHLER (Exit $docxExit) - Details siehe build.log" -ForegroundColor Red Write-Log "DOCX FEHLER (Exit $docxExit)" $overallExit = 1 Start-Sleep -Seconds 3 } $endTs = Get-Date -Format 'yyyy-MM-dd HH:mm:ss' Write-Host "" if ($overallExit -eq 0) { Write-Host "===== Build beendet: $endTs, Exit-Code $overallExit (OK) =====" -ForegroundColor Cyan } else { Write-Host "===== Build beendet: $endTs, Exit-Code $overallExit (FEHLER) =====" -ForegroundColor Red } Write-Log "===== Build beendet: $endTs, Exit-Code $overallExit =====" # Bei Fehler: auf Enter warten, damit Fenster nicht zumacht und User die # rote Fehlermeldung im Scrollback in Ruhe lesen kann. Die Start-Sleep-3 # nach jedem fehlgeschlagenen Schritt allein reicht nicht, weil nachfolgende # Schritte (DOCX, Post-Process) die rote Zeile aus dem sichtbaren Bereich # scrollen koennen. if ($overallExit -ne 0) { # Bei Fehler: 3 Sekunden Pause, damit ein Mensch die rote Fehlermeldung # im Scrollback noch lesen kann, bevor das PowerShell-Fenster zugeht. # KEIN Read-Host: das Skript muss auch nicht-interaktiv von AI-Agents # oder CI-Systemen ausfuehrbar sein. Die zusaetzliche Pause kommt OBEN- # DRAUF zur Start-Sleep-3-pro-Fehler-Schritt-Pause weiter oben. Write-Host "" Write-Host "Build hatte Fehler. Details siehe build.log." -ForegroundColor Yellow Write-Host "Fenster schliesst in 3 Sekunden ..." -ForegroundColor Yellow Start-Sleep -Seconds 3 } exit $overallExit