1use serde_json::Value;
2use std::fs;
3use std::path::Path;
4
5const HTML_TEMPLATE: &str = include_str!("./component-graph.html");
6
7pub 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}