Skip to content

typst: report citations to inline-only references before Typst runs (bd-yjf99rzx) - #1166

Merged
cscheid merged 3 commits into
mainfrom
bugfix/bd-yjf99rzx-typst-citations-inline-front
Nov 10, 2026
Merged

cscheid merged 3 commits into
mainfrom
bugfix/bd-yjf99rzx-typst-citations-inline-front

Conversation

@cscheid

@cscheid cscheid commented Nov 10, 2026

Copy link
Copy Markdown
Member

Problem

Typst output keeps Quarto 1's default of formatting citations with Typst's own bibliography, which reads only the files listed in bibliography:. A citation whose key exists only in front-matter references: reached Typst as @key and failed typst compile with a bare label <key> does not exist in the document (Q-21-3). Quarto 1 fails the same way.

Decision

We keep Quarto 1's behavior, so no automatic citeproc and no conversion of references: for Typst. But when q2 knows Typst will fail, it stops first with a clear error. Documents that Quarto 1 renders still render.

Typst, citeproc unset Quarto 1 before after
cites a key defined only in references: fails fails (raw Typst error) Q-21-5 error at the citation
key in references: and a bibliography: file (Typst uses the file's entry) renders renders renders, Q-21-6 warning
references: present but not cited; or cited keys all in .bib renders renders renders
citation-location: margin (single document or book) with an inline-only key fails fails Q-21-5 error
book, default citation mode fails renders (book merge runs citeproc) renders
citeproc: true renders renders renders, no check

Full investigation, including the q2 vs Quarto 1 probes: claude-notes/plans/2026-11-07-typst-inline-references.md.

Changes

  • crates/quarto-core/src/typst_citations.rs (new) is the check.
    • It looks only at Cite nodes still in the final AST, i.e. the ones Typst will see as @key, and only at keys defined in references:.
    • It reads keys from BibLaTeX .bib files (via the biblatex crate pampa already uses) and Hayagriva .yml files.
    • If any bibliography: file can't be read or parsed, Q-21-5 is suppressed, so q2 never refuses a file Typst might read.
  • PandocWriteStage::prepare() runs the check for Typst. That one call covers native renders and browser (PandocPrepareStage) renders. Bibliography paths resolve with the same helper the PDF request uses.
  • New catalog entries Q-21-5 and Q-21-6, error pages under docs/errors/typst/, sidebar entries, and a "Citations" section in the Typst guide.
  • Both Cargo.lock files gain one line: quarto-core now depends on biblatex 0.12.0, which was already in both lockfiles.

For review

  • Typst source only. With an output-ext other than pdf, Typst never runs, so Q-21-5 is a warning there and the .typ is still written. This wasn't in the plan; I decided it during implementation.
  • citeproc: true turns the check off entirely. In margin mode the vendored Lua margin handler then formats citations inside Pandoc, after prepare(). I verified with a keep-typ render that no @key remains.
  • Possible false positive: a document where @key matches a Typst label, e.g. a heading with that id, and the same key is defined only in references:. Typst would resolve that as a cross-reference. I judged it too unlikely to special-case.

Tests

  • 12 unit tests in typst_citations.rs: each rule, citeproc: true, an unreadable file, source-only output, .bib and Hayagriva key reading.
  • 7 smoke-all fixtures:
    • single-document Typst fixtures: inline-only, margin, shadowed by .bib, shadowed by Hayagriva .yml, citeproc: true, source-only;
    • a margin-mode Typst book (typst/inline-references-book-margin/).
  • With the check disabled, all 5 fixtures that expect a Q-21-5/Q-21-6 diagnostic fail, and the citeproc: true fixture still passes.

Local verification

  • Rust: 19,207 of 19,208 tests pass before the merge from main, and 8,715 of 8,716 quarto-core and smoke-all tests after it, with pandoc 3.13 (CI's new pin).
    • The single failure in both runs is knitr::capture_tests::capture_classifies_pieces: this machine's R reports rlang_error where the test expects simpleError. It passes in CI and on main.
  • cargo xtask verify steps 1–4 and 6–14 pass, including the WASM hub-client build and tests. Lints, fmt and clippy are clean.
  • A full q2 render docs succeeds: 421 of 421 pages, with no warnings from the new or edited pages.
  • Windows: quarto-core can't be cross-checked from macOS (wasmtime compiles C). The new code uses no platform-specific APIs; CI's Clippy (Windows) job covers it.

Follow-up

  • bd-74zz2qko: report a cited key that is defined nowhere (a typo), which still fails with Typst's raw label error. It can reuse this key reading.

🤖 Generated with Claude Code

cscheid and others added 3 commits November 9, 2026 16:14
Typst renders that cite a key defined only in front-matter `references:`
fail with Typst's raw label error, exactly as in Quarto 1. The plan keeps
Quarto 1's behavior but stops before Typst with a new Q-21-5 error, warns
with Q-21-6 when a bibliography file shadows an inline entry, and covers
book renders. Unknown keys are split off to bd-74zz2qko.

Includes the repro fixtures and probe scripts comparing q2 with Quarto 1.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…bd-yjf99rzx)

Typst keeps Quarto 1's native-bibliography default, which reads only
`bibliography:` files. A citation whose key exists only in front-matter
`references:` therefore failed `typst compile` with a bare
`label <key> does not exist` error, in Quarto 1 too.

Keep that behavior, but check it before Typst runs:

- Q-21-5 (error): a cited key is defined in `references:` and in no
  `bibliography:` file. It points at the citation and suggests
  `citeproc: true` or moving the entry into a .bib/.yml file. With a
  non-pdf `output-ext` Typst never runs, so it is a warning there.
- Q-21-6 (warning): a cited key is also defined in a `bibliography:`
  file, so Typst silently ignores the inline entry.

The check runs in PandocWriteStage::prepare(), shared by native and
browser renders, and sees only citations that will reach Typst as
`@key`, so it covers single documents, margin citations, and margin-mode
books. Keys come from BibLaTeX (biblatex crate) and Hayagriva files; a
file that cannot be read or parsed suppresses Q-21-5. `citeproc: true`
turns the check off.

Adds catalog entries, error pages, a Citations section in the Typst
guide, and smoke-all fixtures for each case.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@posit-snyk-bot

posit-snyk-bot commented Nov 10, 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.

@cscheid
cscheid merged commit 3743b5d into main Nov 10, 2026
17 checks passed
@cscheid
cscheid deleted the bugfix/bd-yjf99rzx-typst-citations-inline-front branch November 10, 2026 22:50
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