bug: fix tightness, ignore end blanklines
This commit is contained in:
parent
0d560901eb
commit
b572790ac9
1 changed files with 146 additions and 13 deletions
159
src/block.rs
159
src/block.rs
|
@ -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,
|
||||||
}))),
|
}))),
|
||||||
":"
|
":"
|
||||||
),
|
),
|
||||||
|
|
Loading…
Reference in a new issue