block: allow repeating '#' in headings

This commit is contained in:
Noah Hellman 2023-01-29 11:25:44 +01:00
parent 451b2360f4
commit bfa58dfc0d
2 changed files with 51 additions and 1 deletions

View file

@ -293,6 +293,11 @@ impl<'s> TreeParser<'s> {
self.open_sections.push(*level); self.open_sections.push(*level);
self.tree.enter(Node::Container(Section), span); self.tree.enter(Node::Container(Section), span);
} }
// trim '#' characters
for line in lines[1..].iter_mut() {
*line = line.trim_start_matches(self.src, |c| c == '#' || c.is_whitespace());
}
} }
self.tree.enter(Node::Leaf(leaf), span); self.tree.enter(Node::Leaf(leaf), span);
@ -797,7 +802,10 @@ impl Kind {
.. ..
} => false, } => false,
Self::Blockquote => matches!(next, Self::Blockquote | Self::Paragraph), Self::Blockquote => matches!(next, Self::Blockquote | Self::Paragraph),
Self::Heading { .. } => matches!(next, Self::Paragraph), Self::Heading { level } => {
matches!(next, Self::Paragraph)
|| matches!(next, Self::Heading { level: l } if l == *level )
}
Self::Paragraph | Self::Table { caption: true } => { Self::Paragraph | Self::Table { caption: true } => {
!matches!(next, Self::Atom(Blankline)) !matches!(next, Self::Atom(Blankline))
} }
@ -964,6 +972,26 @@ mod test {
); );
} }
#[test]
fn parse_heading() {
test_parse!(
concat!(
"# a\n",
"## b\n", //
),
(Enter(Container(Section)), "#"),
(Enter(Leaf(Heading)), "#"),
(Inline, "a"),
(Exit(Leaf(Heading)), "#"),
(Enter(Container(Section)), "##"),
(Enter(Leaf(Heading)), "##"),
(Inline, "b"),
(Exit(Leaf(Heading)), "##"),
(Exit(Container(Section)), "##"),
(Exit(Container(Section)), "#"),
);
}
#[test] #[test]
fn parse_heading_multi() { fn parse_heading_multi() {
test_parse!( test_parse!(
@ -990,6 +1018,24 @@ mod test {
); );
} }
#[test]
fn parse_heading_multi_repeat() {
test_parse!(
concat!(
"# a\n",
"# b\n",
"c\n", //
),
(Enter(Container(Section)), "#"),
(Enter(Leaf(Heading)), "#"),
(Inline, "a\n"),
(Inline, "b\n"),
(Inline, "c"),
(Exit(Leaf(Heading)), "#"),
(Exit(Container(Section)), "#"),
);
}
#[test] #[test]
fn parse_section() { fn parse_section() {
test_parse!( test_parse!(

View file

@ -89,6 +89,10 @@ impl Span {
&s[self.start()..self.end()] &s[self.start()..self.end()]
} }
pub fn trim_start_matches<P: FnMut(char) -> bool>(self, s: &str, pat: P) -> Self {
Self::from_slice(s, self.of(s).trim_start_matches(pat))
}
pub fn trim_start(self, s: &str) -> Self { pub fn trim_start(self, s: &str) -> Self {
Self::from_slice(s, self.of(s).trim_start()) Self::from_slice(s, self.of(s).trim_start())
} }