From fbd8811c868f892342d48f69c703894839abd464 Mon Sep 17 00:00:00 2001 From: Noah Hellman Date: Sat, 4 Feb 2023 10:20:05 +0100 Subject: [PATCH] block: parse description list --- src/block.rs | 66 +++++++++++++++++++++++++++++++++++++++++++++++++++- src/lib.rs | 18 +++++++------- 2 files changed, 73 insertions(+), 11 deletions(-) diff --git a/src/block.rs b/src/block.rs index 616614c..3164932 100644 --- a/src/block.rs +++ b/src/block.rs @@ -60,6 +60,9 @@ pub enum Leaf { /// Each inline is a line. Heading { has_section: bool }, + /// Span is empty. + DescriptionTerm, + /// Span is '|'. /// Has zero or one inline for the cell contents. TableCell(Alignment), @@ -354,12 +357,39 @@ impl<'s> TreeParser<'s> { } } - self.tree.enter(Node::Container(c), span); + let dt = if let ListItem(Description) = c { + let dt = self + .tree + .enter(Node::Leaf(DescriptionTerm), span.empty_after()); + self.tree.exit(); + Some(dt) + } else { + None + }; + + let node = self.tree.enter(Node::Container(c), span); let mut l = 0; while l < lines.len() { l += self.parse_block(&mut lines[l..], false); } + if let Some(node_dt) = dt { + let node_child = if let Some(node_child) = self.tree.children(node).next() { + if let tree::Element::Container(Node::Leaf(l @ Paragraph)) = node_child.elem { + *l = DescriptionTerm; + Some(node_child.index) + } else { + None + } + } else { + None + }; + if let Some(node_child) = node_child { + self.tree.swap_prev(node_child); + self.tree.remove(node_dt); + } + } + if let Some(OpenList { depth, .. }) = self.open_lists.last() { assert!(usize::from(*depth) <= self.tree.depth()); if self.tree.depth() == (*depth).into() { @@ -1684,6 +1714,40 @@ mod test { ); } + #[test] + fn parse_description_list() { + test_parse!( + concat!( + ": term\n", // + "\n", // + " description\n", // + ), + ( + Enter(Container(List { + ty: Description, + tight: false + })), + ":" + ), + (Enter(Leaf(DescriptionTerm)), ""), + (Inline, "term"), + (Exit(Leaf(DescriptionTerm)), ""), + (Enter(Container(ListItem(Description))), ":"), + (Atom(Blankline), "\n"), + (Enter(Leaf(Paragraph)), ""), + (Inline, "description"), + (Exit(Leaf(Paragraph)), ""), + (Exit(Container(ListItem(Description))), ":"), + ( + Exit(Container(List { + ty: Description, + tight: false + })), + ":" + ), + ); + } + #[test] fn parse_table() { test_parse!( diff --git a/src/lib.rs b/src/lib.rs index ed46d78..8553d4b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -721,6 +721,7 @@ impl<'s> Parser<'s> { .to_string() .into(), }, + block::Leaf::DescriptionTerm => Container::DescriptionTerm, block::Leaf::CodeBlock => { if let Some(format) = content.strip_prefix('=') { Container::RawBlock { format } @@ -771,16 +772,13 @@ impl<'s> Parser<'s> { Container::List { kind, tight } } } - block::Container::ListItem(ty) => { - if matches!(ty, block::ListType::Task) { - let marker = ev.span.of(self.src); - Container::TaskListItem { - checked: marker.as_bytes()[3] != b' ', - } - } else { - Container::ListItem - } - } + block::Container::ListItem(ty) => match ty { + block::ListType::Task => Container::TaskListItem { + checked: content.as_bytes()[3] != b' ', + }, + block::ListType::Description => Container::DescriptionDetails, + _ => Container::ListItem, + }, block::Container::Table => Container::Table, block::Container::TableRow { head } => { if enter {