1use markdown_it::parser::inline::{InlineRule, InlineState};
2use markdown_it::{Node, NodeValue, Renderer};
3
4/// Custom autolink for relative paths (./path and ../path)
5#[derive(Debug)]
6pub struct RelativeAutolink {
7 pub href: String,
8}
9
10impl NodeValue for RelativeAutolink {
11 fn render(&self, _node: &Node, fmt: &mut dyn Renderer) {
12 fmt.open("a", &[("href", self.href.clone())]);
13 fmt.text(&self.href);
14 fmt.close("a");
15 }
16}
17
18/// Parse relative path autolinks: <./path> and <../path>
19pub struct Rule;
20
21impl InlineRule for Rule {
22 const MARKER: char = '<';
23
24 fn run(state: &mut InlineState) -> Option<(Node, usize)> {
25 let input = &state.src[state.pos..state.pos_max];
26
27 if !input.starts_with('<') {
28 return None;
29 }
30
31 let after_bracket = &input[1..];
32
33 if !after_bracket.starts_with("./") && !after_bracket.starts_with("../") {
34 return None;
35 }
36
37 let end = after_bracket.find('>')?;
38 let href = &after_bracket[..end];
39 let node = Node::new(RelativeAutolink {
40 href: href.to_string(),
41 });
42
43 // Return node and number of characters consumed (including < and >)
44 Some((node, end + 2))
45 }
46}