From 93650bca88f05a0a0d12eb3b43b0e4322ec77692 Mon Sep 17 00:00:00 2001 From: Carlos Scheidegger Date: Wed, 23 Jul 2025 16:17:08 -0400 Subject: [PATCH 1/5] wrap inline in div if one is found (#13121) --- .../filters/quarto-pre/contentsshortcode.lua | 54 ++++++++++++++----- 1 file changed, 40 insertions(+), 14 deletions(-) diff --git a/src/resources/filters/quarto-pre/contentsshortcode.lua b/src/resources/filters/quarto-pre/contentsshortcode.lua index 6e21e30bb08..56b22dd4db5 100644 --- a/src/resources/filters/quarto-pre/contentsshortcode.lua +++ b/src/resources/filters/quarto-pre/contentsshortcode.lua @@ -6,6 +6,27 @@ function contents_shortcode_filter() local divs = {} local spans = {} + local function handle_inline_with_attr(el) + if ids_used[el.attr.identifier] then + spans[el.attr.identifier] = el + return {} + end + + -- remove 'cell-' from identifier, try again + local truncated_id = el.attr.identifier:match("^cell%-(.+)$") + if ids_used[truncated_id] then + spans[truncated_id] = el + -- FIXME: this is a workaround for the fact that we don't have a way to + -- distinguish between divs that appear as the output of code cells + -- (which have a different id creation mechanism) + -- and "regular" divs. + -- We need to fix https://github.com/quarto-dev/quarto-cli/issues/7062 first. + return {} + else + return nil + end + end + return { Pandoc = function(doc) _quarto.ast.walk(doc.blocks, { @@ -43,13 +64,10 @@ function contents_shortcode_filter() return nil end end, - Span = function(el) - if not ids_used[el.attr.identifier] then - return nil - end - spans[el.attr.identifier] = el - return {} - end + Code = handle_inline_with_attr, + Image = handle_inline_with_attr, + Span = handle_inline_with_attr, + Link = handle_inline_with_attr }) local handle_block = function(el) @@ -75,14 +93,22 @@ function contents_shortcode_filter() return {} end local div = divs[data] - if div == nil then - warn( - "[Malformed document] Found `contents` shortcode without a corresponding div with id: " .. tostring(data) .. ".\n" .. - "This might happen because the shortcode is used in div context, while the id corresponds to a span.\n" .. - "Removing from document.") - return {} + if div ~= nil then + -- if we have a div, return it + return div + end + -- if we don't have a div, try to find a span + -- and wrap it in a div + local span = spans[data] + if span ~= nil then + -- if we have a span, return it wrapped in a div + return pandoc.Div(pandoc.Plain({span})) end - return div + warn( + "[Malformed document] Found `contents` shortcode without a corresponding div with id: " .. tostring(data) .. ".\n" .. + "This might happen because the shortcode is used in div context, while the id corresponds to a span.\n" .. + "Removing from document.") + return {} end -- replace div-context entries doc.blocks = _quarto.ast.walk(doc.blocks, { From d2d841f09102e88320550340a4b94515a4dbab39 Mon Sep 17 00:00:00 2001 From: Carlos Scheidegger Date: Wed, 23 Jul 2025 16:28:15 -0400 Subject: [PATCH 2/5] regression test --- .../filters/quarto-pre/contentsshortcode.lua | 2 +- tests/docs/smoke-all/2025/07/23/13121.qmd | 34 +++++++++++++++++++ tests/smoke/smoke-all.test.ts | 3 ++ tests/verify.ts | 3 +- 4 files changed, 40 insertions(+), 2 deletions(-) create mode 100644 tests/docs/smoke-all/2025/07/23/13121.qmd diff --git a/src/resources/filters/quarto-pre/contentsshortcode.lua b/src/resources/filters/quarto-pre/contentsshortcode.lua index 56b22dd4db5..174d9ddfc69 100644 --- a/src/resources/filters/quarto-pre/contentsshortcode.lua +++ b/src/resources/filters/quarto-pre/contentsshortcode.lua @@ -104,7 +104,7 @@ function contents_shortcode_filter() -- if we have a span, return it wrapped in a div return pandoc.Div(pandoc.Plain({span})) end - warn( + quarto.log.warning( "[Malformed document] Found `contents` shortcode without a corresponding div with id: " .. tostring(data) .. ".\n" .. "This might happen because the shortcode is used in div context, while the id corresponds to a span.\n" .. "Removing from document.") diff --git a/tests/docs/smoke-all/2025/07/23/13121.qmd b/tests/docs/smoke-all/2025/07/23/13121.qmd new file mode 100644 index 00000000000..b9677dcea18 --- /dev/null +++ b/tests/docs/smoke-all/2025/07/23/13121.qmd @@ -0,0 +1,34 @@ +--- +format: typst +title: Another section +_quarto: + tests: + typst: + noErrorsOrWarnings: true +--- + +## A section + +Here we define a plot. + +::: {.cell execution_count=1} + +::: {.cell-output .cell-output-display} +`code`{#a-cell} +::: +::: + + + +Here we use the plot, inside a callout: + + +::: callout-note + +## Note the following plot + +{{< contents a-cell >}} + +::: + + diff --git a/tests/smoke/smoke-all.test.ts b/tests/smoke/smoke-all.test.ts index efeaea4439a..c7fd160c1cf 100644 --- a/tests/smoke/smoke-all.test.ts +++ b/tests/smoke/smoke-all.test.ts @@ -180,6 +180,9 @@ function resolveTestSpecs( } else if (key === "noErrors") { checkWarnings = false; verifyFns.push(noErrors); + } if (key === "noErrorsOrWarnings") { + checkWarnings = false; + verifyFns.push(noErrorsOrWarnings); } else { // See if there is a project and grab it's type const projectPath = findRootTestsProjectDir(input) diff --git a/tests/verify.ts b/tests/verify.ts index f871dfe22c3..cd837db34b5 100644 --- a/tests/verify.ts +++ b/tests/verify.ts @@ -152,7 +152,8 @@ export const noErrorsOrWarnings: Verify = { verify: (outputs: ExecuteOutput[]) => { const isErrorOrWarning = (output: ExecuteOutput) => { return output.levelName.toLowerCase() === "warn" || - output.levelName.toLowerCase() === "error"; + output.levelName.toLowerCase() === "error" || + output.msg.startsWith("(W)"); // this is a warning from quarto.log.warning() }; const errorsOrWarnings = outputs.some(isErrorOrWarning); From 46b908554947973b84c95c4ef6cf9d8397d873a0 Mon Sep 17 00:00:00 2001 From: Carlos Scheidegger Date: Wed, 23 Jul 2025 16:28:56 -0400 Subject: [PATCH 3/5] changelog --- news/changelog-1.8.md | 1 + 1 file changed, 1 insertion(+) diff --git a/news/changelog-1.8.md b/news/changelog-1.8.md index 353ea23ff52..1ee9b05f821 100644 --- a/news/changelog-1.8.md +++ b/news/changelog-1.8.md @@ -113,3 +113,4 @@ All changes included in 1.8: - ([#12782](https://github.com/quarto-dev/quarto-cli/pull/12782)): fix bug on `safeRemoveDirSync`'s detection of safe directory boundaries. - ([#12853](https://github.com/quarto-dev/quarto-cli/issues/12853)): fix replaceAll() escaping issue with embedded notebooks containing `$` in their Markdown. - ([#12939](https://github.com/quarto-dev/quarto-cli/pull/12939)): Upgrade `mermaidjs` to 11.6.0. +- ([#13121](https://github.com/quarto-dev/quarto-cli/issues/13121)): Allow `contents` shortcode to find inline elements. From 045de687a00ffbaf4d61e5d283bb062e5022f816 Mon Sep 17 00:00:00 2001 From: Carlos Scheidegger Date: Thu, 24 Jul 2025 08:19:27 -0400 Subject: [PATCH 4/5] revert noErrorsOrWarnings change --- tests/verify.ts | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/tests/verify.ts b/tests/verify.ts index cd837db34b5..bd8689bec0a 100644 --- a/tests/verify.ts +++ b/tests/verify.ts @@ -152,8 +152,12 @@ export const noErrorsOrWarnings: Verify = { verify: (outputs: ExecuteOutput[]) => { const isErrorOrWarning = (output: ExecuteOutput) => { return output.levelName.toLowerCase() === "warn" || - output.levelName.toLowerCase() === "error" || - output.msg.startsWith("(W)"); // this is a warning from quarto.log.warning() + output.levelName.toLowerCase() === "error"; + // I'd like to do this but many many of our tests + // would fail right now because we're assuming noErrorsOrWarnings + // doesn't include warnings from the lua subsystem + // || + // output.msg.startsWith("(W)"); // this is a warning from quarto.log.warning() }; const errorsOrWarnings = outputs.some(isErrorOrWarning); From 7af627505c3a853c1bf68e64c5d8b5d1b4471bc4 Mon Sep 17 00:00:00 2001 From: Carlos Scheidegger Date: Thu, 21 Aug 2025 07:37:35 -0500 Subject: [PATCH 5/5] fix typo --- tests/smoke/smoke-all.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/smoke/smoke-all.test.ts b/tests/smoke/smoke-all.test.ts index 3ae05575f30..03efa8413f3 100644 --- a/tests/smoke/smoke-all.test.ts +++ b/tests/smoke/smoke-all.test.ts @@ -180,7 +180,7 @@ function resolveTestSpecs( } else if (key === "noErrors") { checkWarnings = false; verifyFns.push(noErrors); - } if (key === "noErrorsOrWarnings") { + } else if (key === "noErrorsOrWarnings") { checkWarnings = false; verifyFns.push(noErrorsOrWarnings); } else {