block: parse div fences

This commit is contained in:
Noah Hellman 2023-01-28 10:49:25 +01:00
parent dc2647910c
commit fee50d36fb

View file

@ -187,12 +187,10 @@ impl<'s> TreeParser<'s> {
lines[0] = lines[0].skip(2); lines[0] = lines[0].skip(2);
} }
// skip closing fence of code blocks / divs // skip fences of code blocks / divs
let lines = if !truncated let lines = if matches!(kind, Block::Leaf(CodeBlock) | Block::Container(Div)) {
&& matches!(kind, Block::Leaf(CodeBlock) | Block::Container(Div)) let l = lines.len() - usize::from(!truncated);
{ &mut lines[1..l]
let l = lines.len();
&mut lines[..l - 1]
} else { } else {
lines lines
}; };
@ -270,26 +268,13 @@ impl<'s> TreeParser<'s> {
} }
} }
// skip first inline if empty (e.g. code block)
let lines = if lines[0].is_empty() {
&mut lines[1..]
} else {
lines
};
lines.iter().for_each(|line| self.tree.inline(*line)); lines.iter().for_each(|line| self.tree.inline(*line));
self.tree.exit(); self.tree.exit();
} }
fn parse_container(&mut self, c: Container, lines: &mut [Span], span: Span, indent: usize) { fn parse_container(&mut self, c: Container, lines: &mut [Span], span: Span, indent: usize) {
let line_count_inner = lines.len() - usize::from(matches!(c, Div));
// update spans, remove indentation / container prefix // update spans, remove indentation / container prefix
lines lines.iter_mut().skip(1).for_each(|sp| {
.iter_mut()
.skip(1)
.take(line_count_inner)
.for_each(|sp| {
let src = sp.of(self.src); let src = sp.of(self.src);
let src_t = src.trim(); let src_t = src.trim();
let spaces = src.len() - src.trim_start().len(); let spaces = src.len() - src.trim_start().len();
@ -334,8 +319,8 @@ impl<'s> TreeParser<'s> {
self.tree.enter(Node::Container(c), span); self.tree.enter(Node::Container(c), span);
let mut l = 0; let mut l = 0;
while l < line_count_inner { while l < lines.len() {
l += self.parse_block(&mut lines[l..line_count_inner]); l += self.parse_block(&mut lines[l..]);
} }
if let Some(OpenList { depth, .. }) = self.open_lists.last() { if let Some(OpenList { depth, .. }) = self.open_lists.last() {
@ -657,10 +642,11 @@ impl BlockParser {
empty || spaces > self.indent empty || spaces > self.indent
} }
Block::Container(Div) | Block::Leaf(CodeBlock) => { Block::Container(Div) | Block::Leaf(CodeBlock) => {
let (fence, fence_length) = self.fence.unwrap(); let (fence_char, l0) = self.fence.unwrap();
let mut c = line.chars(); let l1 = line_t.len();
!((&mut c).take(fence_length).all(|c| c == fence) let is_end_fence = line_t.chars().all(|c| c == fence_char)
&& c.next().map_or(true, char::is_whitespace)) && (l0 == l1 || (l0 < l1 && matches!(self.kind, Block::Container(..))));
!is_end_fence
} }
Block::Container(Table) if self.caption => !empty, Block::Container(Table) if self.caption => !empty,
Block::Container(Table) => { Block::Container(Table) => {
@ -1577,6 +1563,30 @@ mod test {
); );
} }
#[test]
fn parse_div() {
test_parse!(
concat!("::: cls\n", "abc\n", ":::\n",),
(Enter(Container(Div)), "cls"),
(Enter(Leaf(Paragraph)), ""),
(Inline, "abc"),
(Exit(Leaf(Paragraph)), ""),
(Exit(Container(Div)), "cls"),
);
}
#[test]
fn parse_div_no_class() {
test_parse!(
concat!(":::\n", "abc\n", ":::\n",),
(Enter(Container(Div)), ""),
(Enter(Leaf(Paragraph)), ""),
(Inline, "abc"),
(Exit(Leaf(Paragraph)), ""),
(Exit(Container(Div)), ""),
);
}
macro_rules! test_block { macro_rules! test_block {
($src:expr, $kind:expr, $str:expr, $len:expr $(,)?) => { ($src:expr, $kind:expr, $str:expr, $len:expr $(,)?) => {
let lines = super::lines($src).map(|sp| sp.of($src)); let lines = super::lines($src).map(|sp| sp.of($src));