wayver's git archive


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

sable-markdown/src/parser/blocks/footnote_definition.rs@337ba67f65eaa17b44e371af7c0f0c761d6aa914

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

1use nom::{
2    IResult, Parser,
3    bytes::complete::tag,
4    character::complete::{char, none_of},
5    combinator::{recognize, verify},
6    multi::{many_m_n, many0, many1},
7    sequence::preceded,
8};
9
10use crate::{
11    ast::FootnoteDefinition,
12    parser::util::{line_terminated, not_eof_or_eol1},
13};
14
15pub(super) fn footnote_definition<'a>()
16-> impl FnMut(&'a str) -> IResult<&'a str, FootnoteDefinition> {
17    move |input: &'a str| {
18        let (input, _) = many_m_n(0, 3, char(' ')).parse(input)?;
19        let (input, _) = tag("[^").parse(input)?;
20        let (input, label) = recognize(many1(verify(none_of("]"), |c| *c != ']'))).parse(input)?;
21        let (input, _) = tag("]:").parse(input)?;
22        let (input, _) = many_m_n(0, 3, char(' ')).parse(input)?;
23        let (input, first_line) = line_terminated(not_eof_or_eol1).parse(input)?;
24        let (input, rest_lines) = many0(preceded(
25            many_m_n(3, 3, char(' ')),
26            line_terminated(not_eof_or_eol1),
27        ))
28        .parse(input)?;
29
30        let total_size = first_line.len() + rest_lines.len();
31        let mut footnote_content = String::with_capacity(total_size);
32        if !first_line.is_empty() {
33            footnote_content.push_str(first_line);
34        }
35        for line in rest_lines {
36            footnote_content.push('\n');
37            footnote_content.push_str(line);
38        }
39
40        let (_, blocks) = many0(crate::parser::blocks::block())
41            .parse(&footnote_content)
42            .map_err(|err| err.map_input(|_| input))?;
43
44        let blocks = blocks.into_iter().flatten().collect();
45
46        let v = FootnoteDefinition {
47            label: label.to_owned(),
48            blocks,
49        };
50
51        Ok((input, v))
52    }
53}
54