mirror of
https://github.com/fluxerapp/fluxer
synced 2026-10-07 19:22:14 +09:00
fix(markdown): parse a table that follows a text line without a blank line (#1749)
This commit is contained in:
@@ -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}"
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user