p1-3: doc-comment + test pin Quote drops non-text children
`ParsedPayload::Quote { text, inlines }` cannot represent block-level
children (lists, code, tables, images), so the BlockQuote end handler
silently drops them when assembling the Quote payload. This matches
§3.4 for now but is non-obvious and easy to regress without an
explicit pin.
Add a TODO(P1-future) comment near the Quote emission code and a
regression test (`quote_with_list_inside_drops_list`) that fixes the
current shape: a `> - item` blockquote produces a Quote with empty
text and empty inlines.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -797,6 +797,15 @@ impl<'a> WalkState<'a> {
|
||||
Event::End(TagEnd::BlockQuote(_)) => {
|
||||
if let Some(Frame::Quote { range, children }) = self.frames.pop() {
|
||||
// Concatenate child text for the Quote payload.
|
||||
//
|
||||
// TODO(P1-future): `ParsedPayload::Quote { text, inlines }`
|
||||
// cannot represent block-level children structurally
|
||||
// (lists, code, tables, images), so they are silently
|
||||
// dropped here. Only Paragraph / Quote / Heading text
|
||||
// contributes to the assembled `text`. This matches
|
||||
// §3.4 for now but should be revisited when Quote
|
||||
// grows a `children: Vec<ParsedBlock>` field — see
|
||||
// pin test `quote_with_list_inside_drops_list`.
|
||||
let mut text = String::new();
|
||||
let mut inlines: Vec<Inline> = Vec::new();
|
||||
for c in &children {
|
||||
@@ -1503,6 +1512,32 @@ mod tests {
|
||||
}
|
||||
}
|
||||
|
||||
// ---- quote child handling (pinned) --------------------------------------
|
||||
|
||||
/// Pins current behavior: a list inside a blockquote contributes nothing
|
||||
/// to the Quote's text/inlines because `ParsedPayload::Quote` cannot
|
||||
/// represent non-text/non-paragraph block children. The list itself is
|
||||
/// also not retained as a separate block — it lives only in the popped
|
||||
/// `Frame::Quote.children` and is dropped. Tracked in TODO(P1-future)
|
||||
/// near the Quote emission code.
|
||||
#[test]
|
||||
fn quote_with_list_inside_drops_list() {
|
||||
let body = "> - a\n> - b\n";
|
||||
let (blocks, _) = parse(body, 1);
|
||||
// Exactly one Quote block, with empty text/inlines.
|
||||
assert_eq!(blocks.len(), 1);
|
||||
match &blocks[0].payload {
|
||||
ParsedPayload::Quote { text, inlines } => {
|
||||
assert_eq!(text, "", "list content should not appear in quote text");
|
||||
assert!(
|
||||
inlines.is_empty(),
|
||||
"list content should not appear in quote inlines"
|
||||
);
|
||||
}
|
||||
_ => panic!("expected quote, got {:?}", blocks[0].payload),
|
||||
}
|
||||
}
|
||||
|
||||
// ---- block content inside list items ------------------------------------
|
||||
|
||||
#[test]
|
||||
|
||||
Reference in New Issue
Block a user