spinne_html/
lib.rs

1use serde_json::Value;
2use std::fs;
3use std::path::Path;
4
5const HTML_TEMPLATE: &str = include_str!("./component-graph.html");
6
7/// Generates an HTML report from a component graph.
8/// Uses d3.js to render the graph.
9pub struct HtmlGenerator {
10    template: String,
11}
12
13impl HtmlGenerator {
14    pub fn new(workspace_data: Value) -> Self {
15        let template = HTML_TEMPLATE.replace(
16            "{{GRAPH_DATA}}",
17            &serde_json::to_string(&workspace_data).unwrap_or_default(),
18        );
19        Self { template }
20    }
21
22    pub fn save(&self, output_path: &Path) -> std::io::Result<()> {
23        fs::write(output_path, self.template.clone())
24    }
25}
26
27#[cfg(test)]
28mod tests {
29    use super::*;
30    use serde_json::json;
31
32    #[test]
33    fn test_html_generation() {
34        let project_data = json!([{
35            "name": "test-project",
36            "graph": {
37                "nodes": [
38                    {
39                        "name": "ComponentA",
40                        "file_path": "/path/to/ComponentA.tsx",
41                        "prop_usage": {}
42                    }
43                ],
44                "edges": []
45            }
46        }]);
47
48        let generator = HtmlGenerator::new(project_data);
49
50        assert!(generator.template.contains("ComponentA"));
51        assert!(!generator.template.contains("{{GRAPH_DATA}}"));
52    }
53
54    #[test]
55    fn test_html() {
56        let graph_data = json!({
57            "projects": [
58                {
59                    "nodes": [
60                        {
61                            "name": "ComponentA",
62                            "file_path": "/path/to/ComponentA.tsx",
63                            "prop_usage": {}
64                        },
65                        {
66                            "name": "ComponentB",
67                            "file_path": "/path/to/ComponentB.tsx",
68                            "prop_usage": {}
69                        }
70                    ],
71                    "edges": [
72                        [0, 1]
73                    ]
74                },
75                {
76                    "nodes": [
77                        {
78                            "name": "ComponentC",
79                            "file_path": "/path/to/ComponentC.tsx",
80                            "prop_usage": {}
81                        }
82                    ],
83                    "edges": []
84                }
85            ]
86        });
87
88        let generator = HtmlGenerator::new(graph_data);
89        let output_path = Path::new("test.html");
90        generator.save(output_path).unwrap();
91        open::that(output_path).unwrap();
92    }
93}