Skip to main content

drft/builders/
markdown.rs

1//! The `markdown` builder: emits link edges from `[text](path)` body links. It
2//! contributes no node metadata — cross-graph linkage to `fs` nodes happens at
3//! compose by path coincidence.
4
5use globset::GlobSet;
6
7use crate::builders::link_edges;
8use crate::model::Graph;
9use crate::parsers::Parser;
10use crate::parsers::markdown::MarkdownParser;
11
12/// Build the `markdown` graph fragment from text files, labeled `label`.
13/// `filter` scopes which paths the builder reads (`None` reads all). The
14/// fragment carries only edges.
15pub fn build(label: &str, texts: &[(String, String)], filter: Option<GlobSet>) -> Graph {
16    let parser = MarkdownParser {
17        file_filter: filter,
18    };
19    let mut graph = Graph::labeled(label);
20
21    for (path, content) in texts {
22        if !parser.matches(path) {
23            continue;
24        }
25        for edge in link_edges(path, &parser.parse(path, content).links) {
26            graph.add_edge(edge);
27        }
28    }
29
30    graph.sort_edges();
31    graph
32}
33
34#[cfg(test)]
35mod tests {
36    use super::*;
37
38    fn texts(pairs: &[(&str, &str)]) -> Vec<(String, String)> {
39        pairs
40            .iter()
41            .map(|(p, c)| (p.to_string(), c.to_string()))
42            .collect()
43    }
44
45    #[test]
46    fn emits_resolved_edges() {
47        let t = texts(&[("docs/index.md", "[setup](setup.md) and [faq](../faq.md)")]);
48        let graph = build("markdown", &t, None);
49        assert_eq!(graph.label.as_deref(), Some("markdown"));
50        assert!(graph.nodes.is_empty(), "markdown contributes no nodes");
51        let targets: Vec<&str> = graph.edges.iter().map(|e| e.target.as_str()).collect();
52        assert_eq!(targets, vec!["docs/setup.md", "faq.md"]);
53    }
54
55    #[test]
56    fn filter_scopes_files() {
57        let mut builder = globset::GlobSetBuilder::new();
58        builder.add(globset::Glob::new("**/*.md").unwrap());
59        let filter = builder.build().unwrap();
60
61        let t = texts(&[("a.md", "[x](x.md)"), ("notes.txt", "[y](y.md)")]);
62        let graph = build("markdown", &t, Some(filter));
63        assert_eq!(graph.edges.len(), 1);
64        assert_eq!(graph.edges[0].source, "a.md");
65    }
66}