Skip to content

Typst: resolve CSS generic font families to an installed font - #788

Merged
gordonwoodhull merged 1 commit into
mainfrom
feature/bd-hkf3r8i1-typst-generic-font-stacks
Oct 3, 2026
Merged

gordonwoodhull merged 1 commit into
mainfrom
feature/bd-hkf3r8i1-typst-generic-font-stacks

Conversation

@gordonwoodhull

@gordonwoodhull gordonwoodhull commented Oct 3, 2026 •

Copy link
Copy Markdown
Member

Typst has no generic font families, but we passed serif, sans-serif, monospace and friends straight through. Any brand or style that used one produced unknown font family: sans-serif warnings on every compile, and Typst then fell back to whatever it liked. system-ui and the ui-* keywords weren't recognized at all, so they were treated as font names.

Each generic keyword is now replaced, at its position in the font list, by the first installed font from an ordered candidate list. The lists are built from Chromium's per-OS defaults, fontconfig's 60-latin.conf, Modern Font Stacks and Bootstrap's stacks, with Typst's bundled fonts last so serif, monospace and math always resolve. The keyword itself is never emitted, so font-family: Roboto, sans-serif becomes Roboto when it's installed and otherwise the first installed sans-serif candidate. The candidate lists are in typst_css.lua with their sources cited. No font is bundled.

When nothing in a generic's list is installed (realistically sans-serif on a bare Linux box), the keyword is dropped. If that leaves the list empty, we use Typst's default text font, because Typst rejects an empty font: (). generic(...) is dropped, as it has no Typst equivalent.

Because the winning font differs per machine, the tests don't assert one. The resolver is a pure function, unit-tested against synthetic font sets. The smoke-all fixtures assert only that no keyword reaches the .typ. The ported font-filtering-generics fixture previously asserted the keyword was preserved, which is the behavior this changes.

This is also being backported to quarto-cli:

Typst has no generic font families, but typst_css.lua passed `serif`,
`sans-serif`, `monospace` and friends straight through, so every compile
warned `unknown font family`. `system-ui` and the `ui-*` keywords were not
recognized at all.

Replace each generic keyword, at its position in the list, with the first
available font from an ordered candidate list built from Chromium's per-OS
defaults, fontconfig's 60-latin.conf, Modern Font Stacks and Bootstrap's
stacks, ending in Typst's bundled fonts so serif, monospace and math always
resolve. The keyword is never emitted. If nothing resolves, the keyword is
dropped, and an otherwise empty list falls back to Typst's default text
font, since Typst rejects an empty font list. No fonts are bundled.

Tracked as bd-hkf3r8i1.
@posit-snyk-bot

posit-snyk-bot commented Oct 3, 2026 •

Copy link
Copy Markdown
Contributor

✅ Snyk checks have passed. No issues have been found so far.

Status Scan Engine Critical High Medium Low Total (0)
✅ Open Source Security 0 0 0 0 0 issues
✅ Licenses 0 0 0 0 0 issues

💻 Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse.

@gordonwoodhull
gordonwoodhull merged commit 7d3564f into main Oct 3, 2026
11 checks passed
@gordonwoodhull
gordonwoodhull deleted the feature/bd-hkf3r8i1-typst-generic-font-stacks branch October 3, 2026 17:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants