raw
1use nom::{
2 IResult, Parser,
3 branch::alt,
4 character::complete::{anychar, char, one_of},
5 combinator::{map, not, peek, recognize, value},
6 multi::many1,
7 sequence::preceded,
8};
9
10use crate::ast::Inline;
11
12pub(super) fn text<'a>() -> impl FnMut(&'a str) -> IResult<&'a str, Inline> {
13 move |input: &'a str| {
14 map(
15 many1(alt((
16 map(escaped_char, |c| c.to_string()),
17 crate::parser::inline::html_entity::html_entity(),
18 map(recognize(many1(preceded(peek(is_text()), anychar))), |c| {
19 c.to_string()
20 }),
21 ))),
22 |vec| Inline::Text(vec.join("")),
23 )
24 .parse(input)
25 }
26}
27
28fn is_text<'a>() -> impl FnMut(&'a str) -> IResult<&'a str, ()> {
29 move |input: &'a str| not(not_a_text()).parse(input)
30}
31
32fn not_a_text<'a>() -> impl FnMut(&'a str) -> IResult<&'a str, Vec<()>> {
33 move |input: &'a str| {
34 alt((
35 value((), crate::parser::inline::wikilink::wikilink()),
36 value((), crate::parser::inline::autolink::autolink),
37 value((), crate::parser::inline::reference_link::reference_link()),
38 value((), crate::parser::inline::hard_newline::hard_newline),
39 value((), crate::parser::inline::html_entity::html_entity()),
40 value((), crate::parser::inline::image::image()),
41 value((), crate::parser::inline::inline_link::inline_link()),
42 value((), crate::parser::inline::code_span::code_span),
43 value((), crate::parser::inline::emphasis::emphasis()),
44 value(
45 (),
46 crate::parser::inline::footnote_reference::footnote_reference,
47 ),
48 value((), crate::parser::inline::strikethrough::strikethrough()),
49 value((), crate::parser::inline::tag::tag()),
50 ))
51 .map(|v| vec![v])
52 .parse(input)
53 }
54}
55
56fn escaped_char(input: &str) -> IResult<&str, char> {
57 preceded(char('\\'), one_of("!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~")).parse(input)
58}
59