Typst template: title/subtitle break on keyword text; full-template drops Skylighting #12

Closed
opened 2026-07-09 15:14:31 -04:00 by jared · 0 comments
Owner

Two bugs in inst/quarto/typst/civilytics-typst.typ surface when the template is used for real documents (found while rendering the COG finance API spec PDF with Quarto 1.9 / Typst 0.14).

1. Title/subtitle/date are injected as bare Typst → compile error on keyword text

The Quarto entry point passes these unquoted:

title: $title$,
$if(subtitle)$subtitle: $subtitle$,$endif$
$if(date)$date: $date$,$endif$

So any title/subtitle/date containing a Typst keyword word (e.g. for, in, let) is parsed as code and compilation fails. Example: a subtitle "a web API for exploring …" errors with expected keyword 'in'. Note the abstract line already wraps correctly as [$abstract$].

Fix: wrap in content brackets — title: [$title$], subtitle: [$subtitle$], date: [$date$].

2. Using the file as a full template: drops Quarto's Skylighting definitions

When set via format: typst: { template: civilytics-typst.typ }, any fenced code block fails with unknown variable: Skylighting, because a full template replaces Quarto's auto-generated definitions partial (which defines Skylighting / NormalTok / …).

Fix: ship the template as Quarto template-partials instead — split into typst-template.typ (the #let civilytics(...) = { … } function) and typst-show.typ (the #show: doc => civilytics(...) entry point, without a trailing $body$). Partials keep Quarto's definitions, so code blocks and the branding both render. Worth documenting this usage in inst/quarto/examples/report.qmd (the current example has no visible code blocks, which is why this went unnoticed).

Both are patched locally in the COG API deliverable; folding them upstream fixes every branded Typst doc. Related to #11 (same template file).

Two bugs in `inst/quarto/typst/civilytics-typst.typ` surface when the template is used for real documents (found while rendering the COG finance API spec PDF with Quarto 1.9 / Typst 0.14). ## 1. Title/subtitle/date are injected as bare Typst → compile error on keyword text The Quarto entry point passes these unquoted: ``` title: $title$, $if(subtitle)$subtitle: $subtitle$,$endif$ $if(date)$date: $date$,$endif$ ``` So any title/subtitle/date containing a Typst keyword word (e.g. `for`, `in`, `let`) is parsed as code and compilation fails. Example: a subtitle "a web API **for** exploring …" errors with `expected keyword 'in'`. Note the `abstract` line already wraps correctly as `[$abstract$]`. **Fix:** wrap in content brackets — `title: [$title$]`, `subtitle: [$subtitle$]`, `date: [$date$]`. ## 2. Using the file as a full `template:` drops Quarto's Skylighting definitions When set via `format: typst: { template: civilytics-typst.typ }`, any fenced code block fails with `unknown variable: Skylighting`, because a full template replaces Quarto's auto-generated `definitions` partial (which defines `Skylighting` / `NormalTok` / …). **Fix:** ship the template as Quarto **template-partials** instead — split into `typst-template.typ` (the `#let civilytics(...) = { … }` function) and `typst-show.typ` (the `#show: doc => civilytics(...)` entry point, without a trailing `$body$`). Partials keep Quarto's definitions, so code blocks and the branding both render. Worth documenting this usage in `inst/quarto/examples/report.qmd` (the current example has no visible code blocks, which is why this went unnoticed). Both are patched locally in the COG API deliverable; folding them upstream fixes every branded Typst doc. Related to #11 (same template file).
jared closed this issue 2026-07-09 16:18:29 -04:00
Sign in to join this conversation.
No labels
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: Civilytics/civilyticsR#12