raw
1use nom::{
2 IResult, Parser,
3 branch::alt,
4 character::complete::{char, line_ending, space0, space1},
5 combinator::{opt, recognize, verify},
6 multi::{many_m_n, many1},
7 sequence::preceded,
8};
9
10use crate::{
11 ast::LinkDefinition,
12 parser::link_util::{link_destination, link_label, link_title},
13};
14
15use super::eof_or_eol;
16
17pub(super) fn link_definition<'a>() -> impl FnMut(&'a str) -> IResult<&'a str, LinkDefinition> {
18 move |input: &'a str| {
19 let mut one_line_whitespace0 = (space0, opt(line_ending), space0);
20 let one_line_whitespace1 = verify(
21 recognize(many1(alt((line_ending, space1)))),
22 |chars: &str| {
23 let mut newlines = 0;
24 for ch in chars.chars() {
25 if ch == '\n' {
26 newlines += 1;
27 }
28 }
29 newlines <= 1
30 },
31 );
32
33 let (input, label) = preceded(many_m_n(0, 3, char(' ')), link_label()).parse(input)?;
34 let (input, _) = char(':').parse(input)?;
35 let (input, _) = one_line_whitespace0.parse(input)?;
36 let (input, destination) = link_destination.parse(input)?;
37 let (input, title) = opt(preceded(one_line_whitespace1, link_title)).parse(input)?;
38 let (input, _) = eof_or_eol.parse(input)?;
39
40 let v = LinkDefinition {
41 label,
42 destination,
43 title,
44 };
45
46 Ok((input, v))
47 }
48}
49