fix(markdown): parse a table that follows a text line without a blank line (#1749)

This commit is contained in:
Hampus
2026-08-19 14:24:33 +02:00
committed by GitHub
parent 4a16921242
commit a297f89b83
3 changed files with 51 additions and 0 deletions
@@ -1170,6 +1170,29 @@ pub(crate) fn is_block_start(line: &str, flags: u32) -> bool {
|| is_blockquote_start(line, flags)
}
pub(crate) fn is_table_start(lines: &[Line], index: usize, flags: u32) -> bool {
if !ParserFlags::has(flags, ParserFlags::ALLOW_TABLES) || index + 2 >= lines.len() {
return false;
}
let header_line = trim_table_line(&lines[index]);
let align_line = trim_table_line(&lines[index + 1]);
if !header_line.text.contains('|') || !align_line.text.contains('|') {
return false;
}
let header_cells = split_table_cells(&header_line);
if header_cells.is_empty() || !cells_have_content(&header_cells) {
return false;
}
let Some(alignments) = parse_alignments(&split_table_cells(&align_line)) else {
return false;
};
if header_cells.len() != alignments.len() {
return false;
}
let body_line = trim_table_line(&lines[index + 2]);
body_line.text.contains('|') && !is_table_block_break(&body_line.text)
}
pub(crate) fn is_heading_start(line: &str, flags: u32) -> bool {
if !ParserFlags::has(flags, ParserFlags::ALLOW_HEADINGS) || !starts_with(line, "#") {
return false;
@@ -159,6 +159,11 @@ impl RuntimeState<'_> {
let next_line = &self.lines[self.current_line + consumed].text;
let trimmed_next = trim_start(next_line);
if crate::block::is_block_start(trimmed_next, self.parser.flags())
|| crate::block::is_table_start(
&self.lines,
self.current_line + consumed,
self.parser.flags(),
)
|| trimmed_next.is_empty()
{
break;
@@ -404,3 +404,26 @@ proptest::proptest! {
prop_assert!(serialized.starts_with('['));
}
}
#[test]
fn native_parser_starts_a_table_directly_after_a_text_line() {
let input =
"intro text\r\n| Framework | Type |\r\n| --------- | ---- |\r\n| React | UI library |";
let parsed = parse(input, ParserFlags::ALL, "");
let nodes = parsed["nodes"].as_array().expect("nodes array");
assert!(
nodes.iter().any(|node| node["type"] == "Table"),
"expected a Table node, got {parsed}"
);
}
#[test]
fn native_parser_still_requires_a_delimiter_row_for_a_table() {
let input = "intro text\n| not | a | table |\njust more text";
let parsed = parse(input, ParserFlags::ALL, "");
let nodes = parsed["nodes"].as_array().expect("nodes array");
assert!(
!nodes.iter().any(|node| node["type"] == "Table"),
"pipes alone must not form a table, got {parsed}"
);
}