wayver's git archive


an obsidian renderer
git clone https://git.wayver.dev/sable

sable-markdown/src/parser/blocks/link_definition.rs@main

raw
Date Commit Message Author Files + -
2026-02-23 01:55 initial mvp wayverd 139 17808 0
...

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