This commit is contained in:
Noah Hellman 2022-11-28 20:30:18 +01:00
parent 680e8ef65f
commit 5d601c0fff

View file

@ -85,52 +85,59 @@ impl<'s> Parser<'s> {
}) })
.count(); .count();
let lines = &mut lines[blanklines..]; let lines = &mut lines[blanklines..];
Block::parse(lines.iter().map(|sp| sp.of(self.src))).map_or(0, |(kind, span, len)| { Block::parse(lines.iter().map(|sp| sp.of(self.src))).map_or(
let start = lines.get(0).map(|sp| sp.start()).unwrap(); blanklines,
let span = span.translate(start); |(kind, span, len)| {
match &kind { let start = lines.get(0).map(|sp| sp.start()).unwrap();
Block::Leaf(_) => { let span = span.translate(start);
self.tree.enter(kind, span); match &kind {
lines[0] = lines[0].with_start(span.end()); Block::Leaf(l) => {
for line in lines.iter().take(len) { self.tree.enter(kind, span);
self.tree.elem(Atom::Inline, *line); lines[0] = lines[0].with_start(span.end());
let len = match l {
CodeBlock { .. } => len - 2,
_ => len,
};
for line in &lines[0..len] {
self.tree.elem(Atom::Inline, *line);
}
}
Block::Container(c) => {
let (skip_chars, skip_lines_suffix) = match &c {
Blockquote => (2, 0),
ListItem { indent } | Footnote { indent } => (*indent, 0),
Div { .. } => (0, 1),
};
let line_count_inner = lines.len() - skip_lines_suffix;
// update spans, remove indentation / container prefix
lines[0] = lines[0].with_start(span.end());
lines
.iter_mut()
.skip(1)
.take(line_count_inner)
.for_each(|sp| {
let skip = (sp
.of(self.src)
.chars()
.take_while(|c| c.is_whitespace())
.count()
+ usize::from(skip_chars))
.min(sp.len());
*sp = sp.trim_start(skip);
});
self.tree.enter(kind, span);
let mut l = 0;
while l < line_count_inner {
l += self.parse_block(&mut lines[l..line_count_inner]);
}
} }
} }
Block::Container(c) => { self.tree.exit();
let (skip_chars, skip_lines_suffix) = match &c { blanklines + len
Blockquote => (2, 0), },
ListItem { indent } | Footnote { indent } => (*indent, 0), )
Div { .. } => (0, 1),
};
let line_count_inner = lines.len() - skip_lines_suffix;
// update spans, remove indentation / container prefix
lines[0] = lines[0].with_start(span.end());
lines
.iter_mut()
.skip(1)
.take(line_count_inner)
.for_each(|sp| {
let skip = (sp
.of(self.src)
.chars()
.take_while(|c| c.is_whitespace())
.count()
+ usize::from(skip_chars))
.min(sp.len());
*sp = sp.trim_start(skip);
});
self.tree.enter(kind, span);
let mut l = 0;
while l < line_count_inner {
l += self.parse_block(&mut lines[l..line_count_inner]);
}
}
}
self.tree.exit();
blanklines + len
})
} }
} }
@ -139,12 +146,13 @@ impl Block {
fn parse<'b, I: Iterator<Item = &'b str>>(mut lines: I) -> Option<(Block, Span, usize)> { fn parse<'b, I: Iterator<Item = &'b str>>(mut lines: I) -> Option<(Block, Span, usize)> {
lines.next().map(|l| { lines.next().map(|l| {
let (kind, sp) = Block::start(l); let (kind, sp) = Block::start(l);
let has_end_delimiter = matches!(
kind,
Self::Leaf(CodeBlock { .. }) | Self::Container(Div { .. })
);
let line_count = 1 let line_count = 1
+ lines.take_while(|l| kind.continues(l)).count() + lines.take_while(|l| kind.continues(l)).count()
+ usize::from(matches!( + usize::from(has_end_delimiter);
kind,
Self::Leaf(CodeBlock { .. }) | Self::Container(Div { .. })
));
(kind, sp, line_count) (kind, sp, line_count)
}) })
} }
@ -195,7 +203,7 @@ impl Block {
':' => Self::Container(Div { fence_length }), ':' => Self::Container(Div { fence_length }),
_ => unreachable!(), _ => unreachable!(),
}, },
Span::by_len(start, line.len()), Span::by_len(start, fence_length.into()),
) )
}) })
}) })
@ -361,23 +369,35 @@ mod test {
); );
} }
/*
#[test] #[test]
fn parse_code_block() { fn parse_code_block() {
test_parse!( test_parse!(
concat!( concat!(
"```lang\n", "```\n",
"l0\n", "l0\n",
"l1\n",
"```", // "```", //
), ),
(Event::Enter(Leaf(CodeBlock { fence_length: 3 })), "```lang\n"), (Enter(Leaf(CodeBlock { fence_length: 3 })), "```"),
(Event::Element(Inline), "l0\n"), (Element(Inline), "\n"),
(Event::Element(Inline), "l1\n"), (Element(Inline), "l0\n"),
(Event::Exit, "```lang\n"), (Exit, "```"),
);
test_parse!(
concat!(
"````lang\n",
"l0\n",
"```\n",
" l1\n",
"````", //
),
(Enter(Leaf(CodeBlock { fence_length: 4 })), "````"),
(Element(Inline), "lang\n"),
(Element(Inline), "l0\n"),
(Element(Inline), "```\n"),
(Element(Inline), " l1\n"),
(Exit, "````"),
); );
} }
*/
macro_rules! test_block { macro_rules! test_block {
($src:expr, $kind:expr, $str:expr, $len:expr $(,)?) => { ($src:expr, $kind:expr, $str:expr, $len:expr $(,)?) => {