bug: fix tightness, ignore end blanklines

This commit is contained in:
Noah Hellman 2023-02-06 18:38:25 +01:00
parent 0d560901eb
commit b572790ac9

View file

@ -139,6 +139,7 @@ struct TreeParser<'s> {
/// The previous block element was a blank line. /// The previous block element was a blank line.
prev_blankline: bool, prev_blankline: bool,
prev_loose: bool,
/// Stack of currently open lists. /// Stack of currently open lists.
open_lists: Vec<OpenList>, open_lists: Vec<OpenList>,
/// Stack of currently open sections. /// Stack of currently open sections.
@ -154,6 +155,7 @@ impl<'s> TreeParser<'s> {
src, src,
tree: TreeBuilder::new(), tree: TreeBuilder::new(),
prev_blankline: false, prev_blankline: false,
prev_loose: false,
open_lists: Vec::new(), open_lists: Vec::new(),
alignments: Vec::new(), alignments: Vec::new(),
open_sections: Vec::new(), open_sections: Vec::new(),
@ -171,8 +173,8 @@ impl<'s> TreeParser<'s> {
} }
line_pos += line_count; line_pos += line_count;
} }
for _ in self.open_lists.drain(..) { while let Some(l) = self.open_lists.pop() {
self.tree.exit(); // list self.close_list(l);
} }
for _ in self.open_sections.drain(..) { for _ in self.open_sections.drain(..) {
self.tree.exit(); // section self.tree.exit(); // section
@ -217,8 +219,8 @@ impl<'s> TreeParser<'s> {
if self.tree.depth() == (*depth).into() if self.tree.depth() == (*depth).into()
&& !matches!(kind, Kind::ListItem { ty: ty_new, .. } if *ty == ty_new) && !matches!(kind, Kind::ListItem { ty: ty_new, .. } if *ty == ty_new)
{ {
self.tree.exit(); // list let l = self.open_lists.pop().unwrap();
self.open_lists.pop(); self.close_list(l);
} }
} }
@ -226,14 +228,19 @@ impl<'s> TreeParser<'s> {
if matches!(kind, Kind::Atom(Atom::Blankline)) { if matches!(kind, Kind::Atom(Atom::Blankline)) {
self.prev_blankline = true; self.prev_blankline = true;
} else { } else {
self.prev_loose = false;
if self.prev_blankline { if self.prev_blankline {
for OpenList { node, depth, .. } in &self.open_lists { if let Some(OpenList { node, depth, .. }) = self.open_lists.last() {
if usize::from(*depth) < self.tree.depth() if usize::from(*depth) >= self.tree.depth()
&& matches!(kind, Kind::ListItem { .. }) || !matches!(kind, Kind::ListItem { .. })
{ {
continue; let mut elem = self.tree.elem(*node);
let ListKind { tight, .. } = elem.list_mut().unwrap();
if *tight {
self.prev_loose = true;
*tight = false;
}
} }
self.tree.elem(*node).list_mut().unwrap().tight = false;
} }
} }
self.prev_blankline = false; self.prev_blankline = false;
@ -401,8 +408,9 @@ impl<'s> TreeParser<'s> {
assert!(usize::from(*depth) <= self.tree.depth()); assert!(usize::from(*depth) <= self.tree.depth());
if self.tree.depth() == (*depth).into() { if self.tree.depth() == (*depth).into() {
self.prev_blankline = false; self.prev_blankline = false;
self.tree.exit(); // list self.prev_loose = false;
self.open_lists.pop(); let l = self.open_lists.pop().unwrap();
self.close_list(l);
} }
} }
@ -545,6 +553,17 @@ impl<'s> TreeParser<'s> {
self.tree.exit(); // table self.tree.exit(); // table
} }
fn close_list(&mut self, list: OpenList) {
if self.prev_loose {
let mut elem = self.tree.elem(list.node);
let ListKind { tight, .. } = elem.list_mut().unwrap();
// ignore blankline at end
*tight = true;
}
self.tree.exit(); // list
}
} }
impl<'t> tree::Element<'t, Node, Atom> { impl<'t> tree::Element<'t, Node, Atom> {
@ -1485,6 +1504,68 @@ mod test {
); );
} }
#[test]
fn parse_list_tight_loose() {
test_parse!(
concat!(
"- a\n", //
"- b\n", //
"\n", //
" - c\n", //
"\n", //
" d\n", //
),
(
Enter(Container(List(ListKind {
ty: Unordered(b'-'),
tight: true,
}))),
"-"
),
(Enter(Container(ListItem(Unordered(b'-')))), "-"),
(Enter(Leaf(Paragraph)), ""),
(Inline, "a"),
(Exit(Leaf(Paragraph)), ""),
(Exit(Container(ListItem(Unordered(b'-')))), "-"),
(Enter(Container(ListItem(Unordered(b'-')))), "-"),
(Enter(Leaf(Paragraph)), ""),
(Inline, "b"),
(Exit(Leaf(Paragraph)), ""),
(Atom(Blankline), "\n"),
(
Enter(Container(List(ListKind {
ty: Unordered(b'-'),
tight: false,
}))),
"-"
),
(Enter(Container(ListItem(Unordered(b'-')))), "-"),
(Enter(Leaf(Paragraph)), ""),
(Inline, "c"),
(Exit(Leaf(Paragraph)), ""),
(Atom(Blankline), "\n"),
(Enter(Leaf(Paragraph)), ""),
(Inline, "d"),
(Exit(Leaf(Paragraph)), ""),
(Exit(Container(ListItem(Unordered(b'-')))), "-"),
(
Exit(Container(List(ListKind {
ty: Unordered(b'-'),
tight: false,
}))),
"-"
),
(Exit(Container(ListItem(Unordered(b'-')))), "-"),
(
Exit(Container(List(ListKind {
ty: Unordered(b'-'),
tight: true,
}))),
"-"
),
);
}
#[test] #[test]
fn parse_list_tight_nest() { fn parse_list_tight_nest() {
test_parse!( test_parse!(
@ -1547,6 +1628,58 @@ mod test {
"-" "-"
), ),
); );
test_parse!(
concat!(
"1. a\n", //
"\n", //
" - b\n", //
"\n", //
" c\n", //
),
(
Enter(Container(List(ListKind {
ty: Ordered(Decimal, Period),
tight: true,
}))),
"1.",
),
(Enter(Container(ListItem(Ordered(Decimal, Period)))), "1."),
(Enter(Leaf(Paragraph)), ""),
(Inline, "a"),
(Exit(Leaf(Paragraph)), ""),
(Atom(Blankline), "\n"),
(
Enter(Container(List(ListKind {
ty: Unordered(b'-'),
tight: true,
}))),
"-",
),
(Enter(Container(ListItem(Unordered(b'-')))), "-"),
(Enter(Leaf(Paragraph)), ""),
(Inline, "b"),
(Exit(Leaf(Paragraph)), ""),
(Atom(Blankline), "\n"),
(Exit(Container(ListItem(Unordered(b'-')))), "-"),
(
Exit(Container(List(ListKind {
ty: Unordered(b'-'),
tight: true,
}))),
"-",
),
(Enter(Leaf(Paragraph)), ""),
(Inline, "c"),
(Exit(Leaf(Paragraph)), ""),
(Exit(Container(ListItem(Ordered(Decimal, Period)))), "1."),
(
Exit(Container(List(ListKind {
ty: Ordered(Decimal, Period),
tight: true,
}))),
"1.",
),
);
} }
#[test] #[test]
@ -1742,7 +1875,7 @@ mod test {
( (
Enter(Container(List(ListKind { Enter(Container(List(ListKind {
ty: Description, ty: Description,
tight: false, tight: true,
}))), }))),
":" ":"
), ),
@ -1758,7 +1891,7 @@ mod test {
( (
Exit(Container(List(ListKind { Exit(Container(List(ListKind {
ty: Description, ty: Description,
tight: false, tight: true,
}))), }))),
":" ":"
), ),