From e515629a1e5bc9a00733d00fc7d3d8042d80bcf1 Mon Sep 17 00:00:00 2001 From: Christophe Dervieux Date: Mon, 16 Feb 2026 16:57:57 +0100 Subject: [PATCH 1/2] Fix multi-line subtitle escaping its CSS class in HTML output Convert MetaBlocks to MetaInlines for subtitle field in normalize.lua, preventing nested

tags (invalid HTML5) when YAML uses literal block scalar (|). Fixes #13827 Co-Authored-By: Claude Opus 4.6 --- src/resources/filters/normalize/normalize.lua | 14 +++++++++++- .../docs/smoke-all/2026/02/16/issue-13827.qmd | 22 +++++++++++++++++++ 2 files changed, 35 insertions(+), 1 deletion(-) create mode 100644 tests/docs/smoke-all/2026/02/16/issue-13827.qmd diff --git a/src/resources/filters/normalize/normalize.lua b/src/resources/filters/normalize/normalize.lua index 121b571ddc7..08439f53f21 100644 --- a/src/resources/filters/normalize/normalize.lua +++ b/src/resources/filters/normalize/normalize.lua @@ -20,7 +20,16 @@ local authors = require 'modules/authors' local license = require 'modules/license' local shortcode_ast = require 'modules/astshortcode' -function normalize_filter() +-- Convert block-level metadata to inline for fields rendered inside

tags. +-- Multi-line YAML values produce MetaBlocks (Para), which nest

in

— invalid HTML5. +local function ensureMetaInlines(meta, field) + local val = meta[field] + if val ~= nil and quarto.utils.type(val) == "Blocks" then + meta[field] = quarto.utils.as_inlines(val) + end +end + +function normalize_filter() return { Meta = function(meta) -- normalizes the author/affiliation metadata @@ -32,6 +41,9 @@ function normalize_filter() -- normalizes the license metadata normalized = license.processLicenseMeta(normalized) + -- Convert block-level metadata to inline for fields rendered in

tags + ensureMetaInlines(normalized, "subtitle") + -- for JATs, forward keywords or categories to tags if _quarto.format.isJatsOutput() then if normalized.tags == nil then diff --git a/tests/docs/smoke-all/2026/02/16/issue-13827.qmd b/tests/docs/smoke-all/2026/02/16/issue-13827.qmd new file mode 100644 index 00000000000..01d462d5bf5 --- /dev/null +++ b/tests/docs/smoke-all/2026/02/16/issue-13827.qmd @@ -0,0 +1,22 @@ +--- +title: Test Title +subtitle: | + A Single Line Subtitle +format: + html: default + revealjs: default +_quarto: + tests: + html: + ensureHtmlElementContents: + selectors: ['p.subtitle'] + matches: ['A Single Line Subtitle'] + revealjs: + ensureHtmlElementContents: + selectors: ['p.subtitle'] + matches: ['A Single Line Subtitle'] +--- + +## Test Content + +This tests that a single-line | scalar subtitle stays inside the subtitle class. From b87f64493af2e61dbc8e5318cd18d86bb0dca1fa Mon Sep 17 00:00:00 2001 From: Christophe Dervieux Date: Mon, 16 Feb 2026 17:11:49 +0100 Subject: [PATCH 2/2] Add multi-paragraph subtitle test case for #13827 Exercises the MetaBlocks-with-multiple-Para path where blocks_to_inlines joins paragraphs with LineBreak separators. Co-Authored-By: Claude Opus 4.6 --- .../2026/02/16/issue-13827-multiline.qmd | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 tests/docs/smoke-all/2026/02/16/issue-13827-multiline.qmd diff --git a/tests/docs/smoke-all/2026/02/16/issue-13827-multiline.qmd b/tests/docs/smoke-all/2026/02/16/issue-13827-multiline.qmd new file mode 100644 index 00000000000..c6ca79c9f4d --- /dev/null +++ b/tests/docs/smoke-all/2026/02/16/issue-13827-multiline.qmd @@ -0,0 +1,24 @@ +--- +title: Test Title +subtitle: | + First Part + + Second Part +format: + html: default + revealjs: default +_quarto: + tests: + html: + ensureHtmlElementContents: + selectors: ['p.subtitle'] + matches: ['First Part'] + revealjs: + ensureHtmlElementContents: + selectors: ['p.subtitle'] + matches: ['First Part'] +--- + +## Test Content + +This tests that a multi-paragraph | scalar subtitle stays inside the subtitle class.