Build Pipeline#
Each document type has its own flow; every flow builds inside data/out/.
Book#
pandocreads the Markdown chapters and writesdata/out/*.tex.lualatexruns once, producing.aux,.bcf,.gloand.nlo.biberresolves the bibliography.makeglossariesbuilds the glossary.makeindexbuilds the nomenclature.lualatexruns twice more to resolve cross-references and produce the final PDF.
Every auxiliary tool runs inside data/out/, so nothing is written next to the sources.
Presentation#
beamer uses Pandoc’s own PDF flow:
Update the local Beamer theme copy.
Run Pandoc with the custom Beamer template.
Pandoc repeats the LuaLaTeX passes until the PDF is stable.
pptx renders the same markdown as a PowerPoint deck:
make_reference.pybuilds a brand-themedreference.pptxfromstyle/brand.json: the Office colour scheme and fonts, plus the beamer look ported into the slide layouts — a white title slide with the beamer title page’s image in a slanted right-hand wedge, bold small-caps titles, section pages accent-on-dark, an accent separator rule under content titles, and the footline strip with its accent block.Pandoc renders the deck against that reference document.
finalize_deck.pyfinishes what Pandoc leaves undone: it re-attaches media that only a layout references, unwraps Microsoft-onlymc:AlternateContentso every viewer renders the content, injects the footline slide numbers, and (viastyle_code.py) lifts each code block into the beamer code box — dark fill, accent frame, sized to fit instead of running off the slide.In strict mode,
verify_brand.pyfails the build if the deck’s colours or theme fonts are not brand values.
The deck must look right in viewers that never re-lay it out:
Code and title sizes are computed, not left to
normAutofit: LibreOffice honours a storedfontScaleonly when it agrees with its own measurement.The slide number is a plain text shape: LibreOffice ignores slide-level
sldNumplaceholders.Unwrapping
mc:AlternateContentre-declares the Choice’s namespace prefixes on<p:sld>, or PowerPoint demands a repair.Pandoc’s repeated
cNvPrids within a slide are renumbered, because ECMA-376 requires them unique.
CV#
cv is a direct LuaLaTeX build:
LuaLaTeX runs once to create the auxiliary files.
LuaLaTeX runs a second time to stabilize the output.
Both runs write to data/out/ with -jobname=CV_Jonas_Heinle_<language>, the filename the CV is
published under, so the deliverable is a build output, not a committed binary. A tailored profile
(CV_PROFILE, one file per application in data/cv/profiles/) swaps the language for its
CV_JOB_SUFFIX.
letter is the same two-pass build over the same class and profile, with the cover letter
data/cv/letters/<CV_PROFILE>.tex as its body; it writes
Cover_Letter_Jonas_Heinle_<suffix>.pdf.
The CV is bilingual from one set of sources: every section file carries an English and a German
variant behind \IfLanguageName, and CV_LANG passes a class option through to myCV_METADATA
that picks one. It also selects the datetime2 style, so a German CV does not print US dates.
CV_LANG=german ./scripts/build_in_container.sh cv
make cv-all # both published variants
Strict Warning Checks#
STRICT_WARNINGS=1 enables strict mode for the container wrapper, --strict-warnings for the
glossary build script. The final log is then inspected, and the build fails on warnings or
bad-box diagnostics. For the book, an underfull \hbox and tcolorbox’s “Using nobreak failed”
hint are reported and counted but not fatal. The full list:
AGENTS.md § What the strict gate fails on.