From 3d46c6615e12331f8d96d31ebfa63fcc818c882a Mon Sep 17 00:00:00 2001 From: pi Date: Sat, 11 Jul 2026 20:55:50 +0200 Subject: [PATCH] fix(base): default pandoc typst template font so PDF export works without -V mainfont pandoc's bundled typst template defaults the document font to an empty tuple (font: ()), so a naked `pandoc --pdf-engine=typst` fails with "font fallback list must not be empty". Patch the template default to Libertinus Serif (typst's own bundled default) at build time so PDF export works out of the box. Document usage in README and note the fix in CHANGELOG (Unreleased). Base-affecting. --- CHANGELOG.md | 17 +++++++++++++++++ Dockerfile.base | 13 +++++++++++-- README.md | 20 ++++++++++++++++++++ 3 files changed, 48 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 33ce8a2..d352048 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,23 @@ Pre-v1.0.0 tags followed the pi npm version (`v{pi_version}[letter]`). --- +## Unreleased + +### Fixed + +- **`pandoc --pdf-engine=typst` now works without `-V mainfont`.** pandoc's + bundled typst template (`/usr/share/pandoc/data/templates/template.typst`) + defaults the document font to an empty tuple (`font: ()`), so a naked + `pandoc --pdf-engine=typst` (and `studio_export_pdf` in some cases) failed + with `error: font fallback list must not be empty` unless the caller passed + `-V mainfont="..."`. The base now patches that template default to + `Libertinus Serif` (typst's own bundled default font) at build time, so PDF + export works out of the box. Base-affecting (`Dockerfile.base` RUN), rebuilds + `base-`. README gains a "Generating a PDF with pandoc + typst" section + with the working command and how to override the font via `-V mainfont`. + +--- + ## v1.4.0 — 2026-07-11 Minor release. Headline: **PDF export works out of the box** — the base now diff --git a/Dockerfile.base b/Dockerfile.base index ebc67f1..1da872c 100644 --- a/Dockerfile.base +++ b/Dockerfile.base @@ -14,7 +14,7 @@ # content-addressed over this file, so any byte change invalidates the # cache. Recommended cadence: once per release for security updates. # -# BASE_REBUILD_DATE: 2026-07-11 (Unreleased — typst PDF engine + xz-utils) +# BASE_REBUILD_DATE: 2026-07-11 (Unreleased — typst PDF engine + xz-utils + pandoc typst-template default-font patch) # # ── Lineage note ───────────────────────────────────────────────────── # Adapted from opencode-devbox/Dockerfile.base (commit before v1.16.2). @@ -465,6 +465,13 @@ RUN ARCH=$(case "${TARGETARCH}" in amd64) echo "x86_64" ;; arm64) echo "aarch64" # typst ships a `.tar.xz` asset (hence xz-utils in the apt layer above) # that extracts to typst--unknown-linux-musl/typst. Pin a specific # tag with --build-arg TYPST_VERSION=vX.Y.Z. +# +# We also patch pandoc's bundled typst template +# (/usr/share/pandoc/data/templates/template.typst): its conf() defaults the +# document font to an empty tuple (`font: ()`), so a naked +# `pandoc --pdf-engine=typst` fails with "font fallback list must not be empty" +# unless the caller passes `-V mainfont=...`. We default it to Libertinus Serif +# (typst's own bundled default font) so PDF export works out-of-the-box. ARG TYPST_VERSION=latest RUN ARCH=$(case "${TARGETARCH}" in amd64) echo "x86_64" ;; arm64) echo "aarch64" ;; *) echo "x86_64" ;; esac) && \ V="${TYPST_VERSION}" && \ @@ -476,7 +483,9 @@ RUN ARCH=$(case "${TARGETARCH}" in amd64) echo "x86_64" ;; arm64) echo "aarch64" curl -fsSL --retry 5 --retry-delay 5 --retry-all-errors "https://github.com/typst/typst/releases/download/v${V}/typst-${ARCH}-unknown-linux-musl.tar.xz" | tar -xJ -C /tmp && \ install /tmp/typst-${ARCH}-unknown-linux-musl/typst /usr/local/bin/typst && \ rm -rf /tmp/typst-${ARCH}-unknown-linux-musl && \ - typst --version + typst --version && \ + sed -i 's/^ font: (),$/ font: ("Libertinus Serif",),/' /usr/share/pandoc/data/templates/template.typst && \ + grep -q 'font: ("Libertinus Serif",),' /usr/share/pandoc/data/templates/template.typst # ── yq (mikefarah) — YAML processor, jq's companion for YAML ───────── # Installed as the mikefarah Go binary — NOT Debian's `yq` apt package, which diff --git a/README.md b/README.md index 655e9b8..b2bfae6 100644 --- a/README.md +++ b/README.md @@ -292,6 +292,26 @@ Assuming the compose file publishes `127.0.0.1:8765:8765` (see method B): > LaTeX-exact output you can install `texlive-xetex` on demand as a heavier > fallback. HTML export, KaTeX, Mermaid, and all REPL features work regardless. +### Generating a PDF with pandoc + typst + +The base ships `pandoc` (front-end) and `typst` (PDF engine), so Markdown → PDF +works out of the box: + +```bash +pandoc doc.md --pdf-engine=typst -o doc.pdf +``` + +The base patches pandoc's bundled typst template so it defaults to the +**Libertinus Serif** font. Without that patch a naked `--pdf-engine=typst` +fails with `error: font fallback list must not be empty`, because the upstream +template leaves the font unset. To pick a different face, pass one of the fonts +typst can see (`typst fonts` lists them — DejaVu Serif/Sans/Mono, Libertinus +Serif, New Computer Modern): + +```bash +pandoc doc.md --pdf-engine=typst -V mainfont="New Computer Modern" -o doc.pdf +``` + ### Graphviz diagrams in Studio: `dot-watch` pi-studio renders **Mermaid** natively but has **no Graphviz/DOT renderer**.