From 608ecabb707839d1fcf5864dfce84d9bdf4cb47f Mon Sep 17 00:00:00 2001 From: Christophe Dervieux Date: Tue, 13 Oct 2026 18:16:38 +0200 Subject: [PATCH 1/2] Fix revealjs and epub callout id rendered on two divs The revealjs/epub callout renderer wraps the `.callout` div in an outer div when the callout has leftover classes or attributes, so that user classes such as `.fragment` survive (#5208, #6853). The wrapper was also created whenever the callout had an id, and it was given the whole attribute set, identifier included. Since xref callouts (v1.4.458) the inner `.callout` div carries the id too, so every callout with an id emitted it twice. Duplicate ids are invalid HTML: `getElementById()` returns the wrapper, and a CSS `#id` rule applies to both divs. Keep the id on the `.callout` div only, as in HTML output, so `.callout#x` selectors match in every format. The wrapper is now created only when classes or attributes are left over, and it gets a copy of the attributes without the identifier. An id-only callout renders as a single div. Fixes #15036 --- news/changelog-1.11.md | 1 + src/resources/filters/customnodes/callout.lua | 11 ++-- tests/docs/smoke-all/revealjs/callout-id.qmd | 65 +++++++++++++++++++ 3 files changed, 73 insertions(+), 4 deletions(-) create mode 100644 tests/docs/smoke-all/revealjs/callout-id.qmd diff --git a/news/changelog-1.11.md b/news/changelog-1.11.md index ba13a185842..285d40f4374 100644 --- a/news/changelog-1.11.md +++ b/news/changelog-1.11.md @@ -56,6 +56,7 @@ All changes included in 1.11: - ([#14996](https://github.com/quarto-dev/quarto-cli/pull/14996)): Fix `controls: auto` and `previewLinks: auto` set at the top level of a revealjs document's front matter producing a presentation that fails to load, because `auto` was written unquoted into the generated JavaScript. - ([#15007](https://github.com/quarto-dev/quarto-cli/pull/15007)): Fix Home/End on a focused tabset tab also jumping to the first or last slide in addition to switching tabs. - ([#15014](https://github.com/quarto-dev/quarto-cli/issues/15014)): Fix code blocks at the end of a callout losing their bottom spacing, which made the code block border touch the callout border in untitled `appearance="simple"` callouts (regression introduced in v1.8.15). +- ([#15036](https://github.com/quarto-dev/quarto-cli/issues/15036)): Fix callouts with an id rendering that id twice, on the callout and on a wrapper div, in `revealjs` and `epub` output. The id is now only on the `.callout` div, as in `html` output. - ([#15037](https://github.com/quarto-dev/quarto-cli/pull/15037)): Fix `dracula` theme coloring a `` in a callout title with the theme's bold color, unlike ``. ### `typst` diff --git a/src/resources/filters/customnodes/callout.lua b/src/resources/filters/customnodes/callout.lua index 96442077321..390cbd75e30 100644 --- a/src/resources/filters/customnodes/callout.lua +++ b/src/resources/filters/customnodes/callout.lua @@ -188,10 +188,13 @@ function _callout_main() attributes:insert("callout-style-" .. calloutAppearance) local result = pandoc.Div({ calloutBody }, pandoc.Attr(node.attr.identifier or "", attributes)) - -- in revealjs or epub, if the leftover attr is non-trivial, - -- then we need to wrap the callout in a div (#5208, #6853) - if node.attr.identifier ~= "" or #node.attr.classes > 0 or #node.attr.attributes > 0 then - return pandoc.Div({ result }, node.attr) + -- in revealjs or epub, if there are leftover classes or attributes, + -- then we need to wrap the callout in a div (#5208, #6853). + -- The identifier stays on the callout div only, so it isn't duplicated. + if #node.attr.classes > 0 or #node.attr.attributes > 0 then + local wrapperAttr = node.attr:clone() + wrapperAttr.identifier = "" + return pandoc.Div({ result }, wrapperAttr) else return result end diff --git a/tests/docs/smoke-all/revealjs/callout-id.qmd b/tests/docs/smoke-all/revealjs/callout-id.qmd new file mode 100644 index 00000000000..0b37969d65c --- /dev/null +++ b/tests/docs/smoke-all/revealjs/callout-id.qmd @@ -0,0 +1,65 @@ +--- +title: Callout ids appear once in revealjs +format: revealjs +_quarto: + tests: + revealjs: + ensureHtmlElements: + - - 'div.callout#titled' + - 'section > div.callout#untitled' # id-only callout: no wrapper + - 'div.callout#tip-xref' + - 'a.quarto-xref[href="#/tip-xref"]' + - 'div.fragment > div.callout#with-fragment' + - 'div[data-x="1"] > div.callout#with-attr' + - 'div.fragment.test-no-id > div.callout' # no-id wrapper unchanged + - - '[id="titled"] [id="titled"]' + - '[id="untitled"] [id="untitled"]' + - '[id="tip-xref"] [id="tip-xref"]' + - '[id="with-fragment"] [id="with-fragment"]' + - '[id="with-attr"] [id="with-attr"]' +--- + +The revealjs callout renderer wraps the callout in a div carrying the +user's leftover attributes (classes such as `.fragment`, extra attributes). +The identifier must end up on exactly one element, the `.callout` div, and +an id-only callout needs no wrapper at all. A callout with a leftover +`data-*` attribute keeps it on the wrapper, and a callout with a fragment +class but no id keeps its wrapper unchanged. + +## Titled callout with an id + +::: {#titled .callout-note title="Titled"} +Body. +::: + +## Untitled callout with an id + +::: {#untitled .callout-warning} +Body. +::: + +## Cross-referenceable callout + +::: {#tip-xref .callout-tip title="Xref"} +Body. +::: + +See @tip-xref. + +## Callout with an id and a fragment class + +::: {#with-fragment .callout-note .fragment} +Body. +::: + +## Callout with an id and a data attribute + +::: {#with-attr .callout-note data-x="1"} +Body. +::: + +## Callout with a fragment class and no id + +::: {.callout-note .fragment .test-no-id} +Body. +::: From a61407045a3b9300b31125bbc1bc9802bfb3405c Mon Sep 17 00:00:00 2001 From: Christophe Dervieux Date: Tue, 13 Oct 2026 18:44:00 +0200 Subject: [PATCH 2/2] test gitignore update --- tests/docs/playwright/revealjs/heading-color/.gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/docs/playwright/revealjs/heading-color/.gitignore b/tests/docs/playwright/revealjs/heading-color/.gitignore index 075b2542afb..0e3521a7d0f 100644 --- a/tests/docs/playwright/revealjs/heading-color/.gitignore +++ b/tests/docs/playwright/revealjs/heading-color/.gitignore @@ -1 +1,3 @@ /.quarto/ + +**/*.quarto_ipynb