Add a check for unclosed elements on the stack

This checks for any unclosed elements when processing is finished. This
is intended to detect invalid HTML in the source, or bugs in the tree
builder. Raw HTML elements generate a warning (which in the future will
be a configurable lint). All other sync errors are internal errors as
they are not expected, and it would be helpful to know if they ever
happen.
This commit is contained in:
Eric Huss 2025-11-05 11:14:39 -08:00
parent 4417f8cb0a
commit 1e190137c3
2 changed files with 38 additions and 0 deletions

View file

@ -378,6 +378,7 @@ where
}
}
}
self.finish_stack();
self.collect_footnote_defs();
}
@ -736,6 +737,40 @@ where
output
}
/// Deals with any unclosed elements on the stack.
fn finish_stack(&mut self) {
while let Some(node_id) = self.tag_stack.pop() {
let node = self.tree.get(node_id).unwrap().value();
match node {
Node::Fragment => {}
Node::Element(el) => {
if el.was_raw {
warn!(
"unclosed HTML tag `<{}>` found in `{}`",
el.name.local,
self.options.path.display()
);
} else {
panic!(
"internal error: expected empty tag stack.\n
path: `{}`\n\
element={el:?}",
self.options.path.display()
);
}
}
node => {
panic!(
"internal error: expected empty tag stack.\n
path: `{}`\n\
node={node:?}",
self.options.path.display()
);
}
}
}
}
/// Appends a new footnote reference.
fn footnote_reference(&mut self, name: CowStr<'event>) {
let len = self.footnote_numbers.len() + 1;

View file

@ -252,6 +252,9 @@ fn unclosed_html_tags() {
cmd.expect_stderr(str![[r#"
INFO Book building has started
INFO Running the html backend
WARN unclosed HTML tag `<i>` found in `chapter_1.md`
WARN unclosed HTML tag `<span>` found in `chapter_1.md`
WARN unclosed HTML tag `<div>` found in `chapter_1.md`
INFO HTML book written to `[ROOT]/book`
"#]]);