Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions news/changelog-1.9.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ All changes included in 1.9:
- ([#13452](https://github.com/quarto-dev/quarto-cli/issues/13452)): Wraps subfigure captions generated by `quarto_super()` in `block` function to avoid emitting `par` elements. (author: @christopherkenny)
- ([#13474](https://github.com/quarto-dev/quarto-cli/issues/13474)): Heading font for title should default to `mainfont`.
- ([#13555](https://github.com/quarto-dev/quarto-cli/issues/13555)): Add support for `icon=false` in callouts when used in `format: typst`.
- ([#13589](https://github.com/quarto-dev/quarto-cli/issues/13589)): Fix callouts with invalid ID prefixes crashing with "attempt to index a nil value". Callouts with unknown reference types now render as non-crossreferenceable callouts with a warning, ignoring the invalid ID.

## Projects

Expand Down
13 changes: 10 additions & 3 deletions src/resources/filters/customnodes/callout.lua
Original file line number Diff line number Diff line change
Expand Up @@ -275,7 +275,16 @@ function _callout_main()
end
end
end
if callout.attr.identifier == "" then
-- Check if identifier has a valid crossref category
local ref_type = refType(callout.attr.identifier)
local category = ref_type ~= nil and crossref.categories.by_ref_type[ref_type] or nil

-- Warn if identifier was provided but category is invalid
if callout.attr.identifier ~= "" and category == nil then
warn("Callout ID '" .. callout.attr.identifier .. "' has unknown reference type '" .. (ref_type or "none") .. "'. Rendering as regular callout without cross-reference support.")
end

if category == nil then
return _quarto.format.typst.function_call("callout", {
{ "body", _quarto.format.typst.as_typst_content(callout.content) },
{ "title", _quarto.format.typst.as_typst_content(
Expand All @@ -298,8 +307,6 @@ function _callout_main()
{ "icon", pandoc.RawInline("typst", callout.icon == false and "none" or ("" .. icon .. "()"))},
{ "body_background_color", pandoc.RawInline("typst", body_background_color)}
})

local category = crossref.categories.by_ref_type[refType(callout.attr.identifier)]
return make_typst_figure {
content = typst_callout,
caption_location = "top",
Expand Down
34 changes: 34 additions & 0 deletions tests/docs/smoke-all/2025/10/21/13589-valid.qmd
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
---
title: "Callout with valid ID prefix"
format:
typst:
keep-typ: true
_quarto:
tests:
typst:
ensureTypstFileRegexMatches:
-
- '#figure\(\[(\r\n?|\n)#block\[(\r\n?|\n)#callout'
- []
printsMessage:
level: INFO
regex: 'WARNING(.*)Callout ID(.*)unknown reference type'
negate: true
noErrors: true
---

## Test callout with valid crossref ID

This tests that callouts with valid ID prefixes (matching known crossref categories)
are properly wrapped in figures for cross-reference support.

::: {#nte-valid .callout-note}

## Note with valid ID

This callout uses `#nte-valid` which has the valid prefix "nte" (for notes).
This should be wrapped in a `figure` for cross-referencing support.

:::

As mentioned in @nte-valid, valid callout IDs should work correctly.
38 changes: 38 additions & 0 deletions tests/docs/smoke-all/2025/10/21/13589.qmd
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
---
title: "Callout with invalid ID prefix (#13589)"
format:
typst:
keep-typ: true
_quarto:
tests:
typst:
ensureTypstFileRegexMatches:
-
# Should render as plain callout with body parameter
- '#callout\(\s*body:'
-
# Should NOT be wrapped in figure+block structure
- '#figure\(\[(\r\n?|\n)#block\[(\r\n?|\n)#callout'
printsMessage:
level: INFO
regex: 'WARNING(.*)Callout ID ''random-id'' has unknown reference type ''random'''
noErrors: true
---

## Test callout with invalid crossref ID

This tests the fix for issue #13589: callouts with invalid ID prefixes
(not matching any known crossref category) should render with a warning
instead of crashing with "attempt to index a nil value".

::: {#random-id .callout-note}

## Note with invalid ID

This callout uses `#random-id` with unknown prefix "random".

Valid prefixes are: fig, tbl, lst, nte, wrn, cau, tip, imp, prf, rem, sol.

Expected behavior: renders as plain callout (no figure wrapping) with warning.

:::
Loading