sable-markdown/src/parser/blocks/paragraph.rs@main
raw
1use nom::{
2 IResult, Parser,
3 branch::alt,
4 character::complete::{char, line_ending, space0},
5 combinator::{not, peek, value},
6 multi::{many_m_n, separated_list0},
7 sequence::preceded,
8};
9
10use crate::{
11 ast::Inline,
12 parser::util::{line_terminated, not_eof_or_eol1},
13};
14
15pub(super) fn paragraph<'a>(
16 check_first_line: bool,
17) -> impl FnMut(&'a str) -> IResult<&'a str, Vec<Inline>> {
18 move |input: &'a str| {
19 let mut lines = Vec::new();
20 let input = if check_first_line {
21 input
22 } else {
23 let (input, first_line) =
25 preceded(many_m_n(0, 3, char(' ')), not_eof_or_eol1).parse(input)?;
26 lines.push(first_line);
27 input
28 };
29
30 let paragraph_parser = separated_list0(
31 line_ending,
32 preceded(
33 is_paragraph_line_start(),
34 preceded(many_m_n(0, 3, char(' ')), not_eof_or_eol1),
35 ),
36 );
37 let (input, rest_lines) = line_terminated(paragraph_parser).parse(input)?;
38 lines.extend(rest_lines);
39
40 let content = lines.join("\n");
41
42 let (_, content) = crate::parser::inline::inline_many1()
43 .parse(content.as_str())
44 .map_err(|err| err.map_input(|_| input))?;
45
46 Ok((input, content))
47 }
48}
49
50pub(super) fn is_paragraph_line_start<'a>() -> impl FnMut(&'a str) -> IResult<&'a str, ()> {
51 move |input: &'a str| {
52 peek(not(alt((
53 value((), crate::parser::blocks::heading::heading_v1()),
54 value((), crate::parser::blocks::heading::heading_v2_level()),
55 crate::parser::blocks::thematic_break::thematic_break(),
56 value((), crate::parser::blocks::blockquote::blockquote()),
57 value((), crate::parser::blocks::list::list_item()),
58 value((), crate::parser::blocks::code_block::code_block_fenced()),
59 value((), crate::parser::blocks::html_block::html_block()),
60 value(
61 (),
62 crate::parser::blocks::link_definition::link_definition(),
63 ),
64 value(
65 (),
66 crate::parser::blocks::footnote_definition::footnote_definition(),
67 ),
68 value((), crate::parser::blocks::table::table()),
69 value((), line_terminated(space0)),
70 ))))
71 .parse(input)
72 }
73}
74