block: parse description list
This commit is contained in:
parent
95bf52a31e
commit
fbd8811c86
2 changed files with 73 additions and 11 deletions
66
src/block.rs
66
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!(
|
||||
|
|
18
src/lib.rs
18
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 {
|
||||
|
|
Loading…
Reference in a new issue