1use std::fmt::Write;
4
5use crate::graph::{EdgeKind, ModuleGraph};
6
7fn sanitize_id(path: &str) -> String {
10 path.replace("::", "_")
11}
12
13fn emit_nodes(graph: &ModuleGraph, output: &mut String) {
15 let mut paths: Vec<_> = graph.modules().map(|m| m.path.as_str()).collect();
16 paths.sort_unstable();
17
18 for path in paths {
19 let id = sanitize_id(path);
20 let _ = writeln!(output, " {id}[\"{path}\"]");
21 }
22}
23
24fn emit_edges(graph: &ModuleGraph, output: &mut String) {
26 let mut edges: Vec<_> = graph
27 .edges()
28 .map(|(from, to, kind)| (from.as_str(), to.as_str(), kind))
29 .collect();
30 edges.sort_unstable();
31
32 for (from, to, kind) in edges {
33 let from_id = sanitize_id(from);
34 let to_id = sanitize_id(to);
35 let arrow = match kind {
37 EdgeKind::ModDeclaration => "-->",
38 EdgeKind::UseImport => "-.->",
39 };
40 let _ = writeln!(output, " {from_id} {arrow} {to_id}");
41 }
42}
43
44impl ModuleGraph {
45 #[must_use]
47 pub fn to_mermaid(&self) -> String {
48 let mut output = String::from("flowchart TD\n");
49
50 emit_nodes(self, &mut output);
51 output.push('\n');
52 emit_edges(self, &mut output);
53
54 output
55 }
56}