sable-markdown/src/render/index.rs@main
raw
1use std::collections::HashMap;
2
3use crate::ast::{Block, Document, Inline, LinkDefinition};
4
5struct Index {
6 footnote_indices: HashMap<String, usize>,
7 link_definitions: HashMap<Vec<Inline>, LinkDefinition>,
8 last_footnote_index: usize,
9}
10
11impl Index {
12 pub(crate) fn new() -> Self {
13 Self {
14 footnote_indices: HashMap::new(),
15 link_definitions: HashMap::new(),
16 last_footnote_index: 1,
17 }
18 }
19
20 pub(crate) fn add_footnote(&mut self, label: String) {
21 if let std::collections::hash_map::Entry::Vacant(e) = self.footnote_indices.entry(label) {
22 e.insert(self.last_footnote_index);
23 self.last_footnote_index += 1;
24 }
25 }
26}
27
28pub(super) fn get_indicies(
29 ast: &Document,
30) -> (HashMap<String, usize>, HashMap<Vec<Inline>, LinkDefinition>) {
31 let mut index = Index::new();
32
33 for block in &ast.blocks {
34 get_block_indicies(&mut index, block);
35 }
36
37 (index.footnote_indices, index.link_definitions)
38}
39
40fn get_block_indicies(index: &mut Index, block: &Block) {
41 match block {
42 Block::Paragraph(v) => {
43 for inline in v {
44 get_inline_indicies(index, inline);
45 }
46 }
47 Block::Heading(v) => {
48 for inline in &v.content {
49 get_inline_indicies(index, inline);
50 }
51 }
52 Block::BlockQuote(v) => {
53 for block in v {
54 get_block_indicies(index, block);
55 }
56 }
57 Block::List(v) => {
58 for item in &v.items {
59 for block in &item.blocks {
60 get_block_indicies(index, block);
61 }
62 }
63 }
64 Block::Definition(v) => {
65 index.link_definitions.insert(v.label.clone(), v.clone());
66 for inline in &v.label {
67 get_inline_indicies(index, inline);
68 }
69 }
70 Block::Table(v) => {
71 for row in &v.rows {
72 for cell in row {
73 for inline in cell {
74 get_inline_indicies(index, inline);
75 }
76 }
77 }
78 }
79 Block::FootnoteDefinition(v) => {
80 for block in &v.blocks {
81 get_block_indicies(index, block);
82 }
83 }
84 Block::Callout(v) => {
85 for block in &v.blocks {
86 get_block_indicies(index, block);
87 }
88 }
89 Block::Empty | Block::CodeBlock(_) | Block::HtmlBlock(_) | Block::ThematicBreak => (),
90 }
91}
92
93fn get_inline_indicies(index: &mut Index, inline: &Inline) {
94 if let Inline::FootnoteReference(label) = inline {
95 index.add_footnote(label.clone());
96 }
97}
98