Skip to content

fix: evaluate theorem title strings as Typst markup#13

Merged
mcanouil merged 8 commits intomainfrom
fix/title-scaffold-inline-code
Mar 29, 2026
Merged

fix: evaluate theorem title strings as Typst markup#13
mcanouil merged 8 commits intomainfrom
fix/title-scaffold-inline-code

Conversation

@mcanouil
Copy link
Copy Markdown
Owner

@mcanouil mcanouil commented Mar 24, 2026

Inline code and other markup in theorem/example titles was being stringified in Typst output because Quarto renders custom type titles as string parameters. This adds a post-quarto filter (typst-title-fix) that wraps Typst theorem functions to evaluate string titles as markup via eval(mode: "markup").

The Skylighting inline code filter now distinguishes title scaffolds from normal blocks, emitting plain backtick code in scaffolds to avoid breaking the string parameter that Quarto generates.

Hotfix configuration is reworked: the global hotfix.quarto-version key is replaced with per-hotfix quarto-version thresholds, since upstream fixes are unlikely to land in the same Quarto release. Each hotfix value can be a boolean or a map with enabled and quarto-version keys.

Quarto wraps theorem/example titles in __quarto_custom_scaffold Divs
with inline-only content. Both the code-window box wrapping and Pandoc's
Skylighting generate Typst function calls (#box(...), #NormalTok(...))
that get stringified as literal text when Quarto renders the title
parameter as a string.

Replace the global Code filter with a selective document walk that
converts Code to plain Typst backtick code inside title scaffolds and
applies the full box styling everywhere else.
@mcanouil mcanouil added the Type: Bug 🐛 Issues related to bugs, errors, or mistakes label Mar 24, 2026
@mcanouil mcanouil self-assigned this Mar 24, 2026
Quarto renders custom type titles as title: "..." (string mode) which
stringifies any Typst markup. Inline code in titles produces Skylighting
tokens with inner quotes that break the Typst string syntax.

Two-part fix:
- Pre-quarto: convert Code in title scaffolds to plain Typst backtick
  code, avoiding Skylighting tokens that contain unescaped quotes.
- Post-quarto: inject a Typst override of simple-theorem-render that
  evaluates string titles with eval(mode: "markup"), giving title: [...]
  semantics even though Quarto emits title: "...".
The previous approach redefined simple-theorem-render, but make-frame
captures the render function by value at definition time, so the
override had no effect.

Instead, scan the Typst preamble for make-frame definitions, extract
the generated function names (e.g., example, theorem), and inject
wrapper functions that evaluate string title parameters with
eval(mode: "markup") before delegating to the original function.
header-includes is placed before template definitions in the Typst
preamble, so the theorem functions are not yet defined. RawBlocks
inserted into doc.blocks appear after the template preamble, where
make-frame has already created the theorem functions.

Also scan the source file for cross-reference div IDs (e.g., #exm-,
#thm-) to determine which theorem functions to wrap, since this
information is not available in the AST at filter time.
Each hotfix can now have its own quarto-version threshold for
auto-disable, since upstream fixes are unlikely to land in the same
Quarto release. The hotfix value can be a boolean or a map with
enabled and quarto-version keys:

  hotfix:
    code-annotations:
      quarto-version: "1.10.0"
    skylighting:
      quarto-version: "1.11.0"
    typst-title:
      quarto-version: "1.10.0"

The global quarto-version key is still supported as a fallback.
Add typst-title as a new hotfix key for the theorem title fix.
Remove the global hotfix.quarto-version fallback in favour of per-hotfix
thresholds only. Update _schema.yml to use type: [boolean, object] instead
of anyOf (unsupported by quarto-wizard schema). Document the new
typst-title hotfix and per-hotfix map form in README. Add fragility
comments for internal Quarto dependencies.
Use pandoc.MetaMap() instead of a plain Lua table when storing hotfix
state in document metadata, ensuring correct serialisation across filter
boundaries. Wrap f:read in pcall so the file handle is always closed
even if the read fails.
Guard the hotfix metadata bridge with CONFIG.enabled so the post-quarto
typst-title-fix filter does not inject wrappers when the extension is
turned off.
@mcanouil mcanouil changed the title fix: neutralise inline code in title scaffolds for Typst output fix: evaluate theorem title strings as Typst markup Mar 29, 2026
@mcanouil mcanouil merged commit 00c8a15 into main Mar 29, 2026
@mcanouil mcanouil deleted the fix/title-scaffold-inline-code branch March 29, 2026 14:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Type: Bug 🐛 Issues related to bugs, errors, or mistakes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant