Skip to content

Commit fd74e00

Browse files
cdervclaude
andauthored
Fix multi-line subtitle escaping its CSS class in HTML output (#14043)
* Fix multi-line subtitle escaping its CSS class in HTML output Convert MetaBlocks to MetaInlines for subtitle field in normalize.lua, preventing nested <p> tags (invalid HTML5) when YAML uses literal block scalar (|). Fixes #13827 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * 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 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
1 parent cb8dcf8 commit fd74e00

3 files changed

Lines changed: 59 additions & 1 deletion

File tree

src/resources/filters/normalize/normalize.lua

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,16 @@ local authors = require 'modules/authors'
2020
local license = require 'modules/license'
2121
local shortcode_ast = require 'modules/astshortcode'
2222

23-
function normalize_filter()
23+
-- Convert block-level metadata to inline for fields rendered inside <p> tags.
24+
-- Multi-line YAML values produce MetaBlocks (Para), which nest <p> in <p> — invalid HTML5.
25+
local function ensureMetaInlines(meta, field)
26+
local val = meta[field]
27+
if val ~= nil and quarto.utils.type(val) == "Blocks" then
28+
meta[field] = quarto.utils.as_inlines(val)
29+
end
30+
end
31+
32+
function normalize_filter()
2433
return {
2534
Meta = function(meta)
2635
-- normalizes the author/affiliation metadata
@@ -32,6 +41,9 @@ function normalize_filter()
3241
-- normalizes the license metadata
3342
normalized = license.processLicenseMeta(normalized)
3443

44+
-- Convert block-level metadata to inline for fields rendered in <p> tags
45+
ensureMetaInlines(normalized, "subtitle")
46+
3547
-- for JATs, forward keywords or categories to tags
3648
if _quarto.format.isJatsOutput() then
3749
if normalized.tags == nil then
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
---
2+
title: Test Title
3+
subtitle: |
4+
First Part
5+
6+
Second Part
7+
format:
8+
html: default
9+
revealjs: default
10+
_quarto:
11+
tests:
12+
html:
13+
ensureHtmlElementContents:
14+
selectors: ['p.subtitle']
15+
matches: ['First Part']
16+
revealjs:
17+
ensureHtmlElementContents:
18+
selectors: ['p.subtitle']
19+
matches: ['First Part']
20+
---
21+
22+
## Test Content
23+
24+
This tests that a multi-paragraph | scalar subtitle stays inside the subtitle class.
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
---
2+
title: Test Title
3+
subtitle: |
4+
A Single Line Subtitle
5+
format:
6+
html: default
7+
revealjs: default
8+
_quarto:
9+
tests:
10+
html:
11+
ensureHtmlElementContents:
12+
selectors: ['p.subtitle']
13+
matches: ['A Single Line Subtitle']
14+
revealjs:
15+
ensureHtmlElementContents:
16+
selectors: ['p.subtitle']
17+
matches: ['A Single Line Subtitle']
18+
---
19+
20+
## Test Content
21+
22+
This tests that a single-line | scalar subtitle stays inside the subtitle class.

0 commit comments

Comments
 (0)