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 alt((
36 value((), crate::parser::inline::wikilink::wikilink()),
37 value((), crate::parser::inline::autolink::autolink),
38 value((), crate::parser::inline::reference_link::reference_link()),
39 value((), crate::parser::inline::hard_newline::hard_newline),
40 value((), crate::parser::inline::html_entity::html_entity()),
41 value((), crate::parser::inline::image::image()),
42 )),
43 alt((
44 value((), crate::parser::inline::inline_link::inline_link()),
45 value((), crate::parser::inline::code_span::code_span),
46 value((), crate::parser::inline::emphasis::emphasis()),
47 value(
48 (),
49 crate::parser::inline::footnote_reference::footnote_reference,
50 ),
51 value((), crate::parser::inline::strikethrough::strikethrough()),
52 )),
53 value(
54 (),
55 crate::parser::inline::environment_variable::environment_variable,
56 ),
57 value((), crate::parser::inline::tag::tag()),
58 ))
59 .map(|v| vec![v])
60 .parse(input)
61 }
62}
63
64fn escaped_char(input: &str) -> IResult<&str, char> {
65 preceded(char('\\'), one_of("!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~")).parse(input)
66}
67