@@ -11,8 +11,10 @@ import (
1111)
1212
1313type Node struct {
14- ID string
15- Label string
14+ ID string
15+ Label string
16+ Count int
17+ Provider string
1618}
1719
1820type Edge struct {
@@ -21,114 +23,118 @@ type Edge struct {
2123}
2224
2325type Graph struct {
24- Nodes []Node
25- Edges []Edge
26+ Nodes []Node
27+ Edges []Edge
28+ NodeMap map [string ]int
2629}
2730
28- // Removes unnecessary parts from the label
31+ var labelCleaner = regexp .MustCompile (`\s*\(expand\)|\s*\(close\)|\[root\]\s*|"` )
32+
33+ // CleanLabel removes unnecessary parts from the label
2934func CleanLabel (label string ) string {
30- re := regexp .MustCompile (`\s*\(expand\)|\s*\(close\)|\[root\]\s*|"` )
31- return re .ReplaceAllString (label , "" )
35+ return labelCleaner .ReplaceAllString (label , "" )
3236}
3337
34- // Removes unnecessary parts from the ID
38+ // CleanID removes unnecessary parts from the ID
3539func CleanID (id string ) string {
36- re := regexp .MustCompile (`\s*\(expand\)|\s*\(close\)|\[root\]\s*|"` )
37- return re .ReplaceAllString (id , "" )
40+ return labelCleaner .ReplaceAllString (id , "" )
3841}
3942
40- // Extracts the provider for separate subgraph
43+ // ExtractProvider extracts the provider for separate subgraph
4144func ExtractProvider (label string ) string {
42- if strings .Contains (label , "provider" ) {
43- parts := strings .Split (label , "/" )
44- if len (parts ) > 2 {
45- return parts [len (parts )- 2 ]
46- }
45+ parts := strings .Split (label , "_" )
46+ if len (parts ) > 0 {
47+ // Remove quotes from the provider name
48+ return strings .ReplaceAll (parts [0 ], "\" " , "" )
4749 }
4850 return ""
4951}
5052
51- // Transforms the parsed graph into cleaned nodes and edges
53+ // TransformGraph transforms the parsed graph into cleaned nodes and edges
5254func TransformGraph (graph * gographviz.Graph ) Graph {
5355 nodes := []Node {}
5456 edges := []Edge {}
57+ nodeMap := make (map [string ]int )
5558
5659 for _ , node := range graph .Nodes .Nodes {
5760 cleanedID := CleanID (node .Name )
5861 cleanedLabel := CleanLabel (node .Attrs ["label" ])
59- if cleanedLabel != "" && ! strings .Contains (cleanedLabel , "provider" ) {
60- nodes = append (nodes , Node {ID : cleanedID , Label : cleanedLabel })
62+ provider := ExtractProvider (cleanedLabel )
63+ if cleanedLabel != "" {
64+ nodeMap [cleanedLabel ]++
65+ nodes = append (nodes , Node {ID : cleanedID , Label : cleanedLabel , Count : nodeMap [cleanedLabel ], Provider : provider })
6166 }
6267 }
6368
6469 for _ , edge := range graph .Edges .Edges {
6570 fromLabel := CleanLabel (graph .Nodes .Lookup [edge .Src ].Attrs ["label" ])
6671 toLabel := CleanLabel (graph .Nodes .Lookup [edge .Dst ].Attrs ["label" ])
67- if fromLabel != "" && toLabel != "" && ! strings . Contains ( fromLabel , "provider" ) && ! strings . Contains ( toLabel , "provider" ) {
72+ if fromLabel != "" && toLabel != "" {
6873 edges = append (edges , Edge {From : CleanID (edge .Src ), To : CleanID (edge .Dst )})
6974 }
7075 }
7176
72- return Graph {Nodes : nodes , Edges : edges }
77+ return Graph {Nodes : nodes , Edges : edges , NodeMap : nodeMap }
7378}
7479
75- // Converts a gographviz graph to a Mermaid.js compatible string.
80+ // ConvertToMermaidFlowchart converts a gographviz graph to a Mermaid.js compatible string.
7681// It accepts a graph, direction, and an optional subgraph name.
7782func ConvertToMermaidFlowchart (graph * gographviz.Graph , direction string , subgraphName string ) (string , error ) {
7883 var sb strings.Builder
7984
80- // Capitalize the provider name
8185 caser := cases .Title (language .English )
82- // Validate the direction of the flowchart. Valid options are: TB, TD, BT, RL, LR
8386 validDirections := map [string ]bool {
8487 "TB" : true , "TD" : true , "BT" : true , "RL" : true , "LR" : true ,
8588 }
8689 if ! validDirections [direction ] {
8790 return "" , fmt .Errorf ("invalid direction %s: valid options are: TB, TD, BT, RL, LR" , direction )
8891 }
89- // Start Mermaid graph definition
92+
9093 sb .WriteString ("```mermaid\n " )
9194 sb .WriteString ("flowchart " + direction + "\n " )
9295
93- // Add subgraph for providers
96+ if subgraphName != "" {
97+ sb .WriteString (fmt .Sprintf ("\t subgraph %s\n " , subgraphName ))
98+ }
99+
94100 providerSubgraphs := make (map [string ]bool )
95101 for _ , n := range graph .Nodes .Nodes {
96- label := n .Attrs ["label" ]
97- provider := ExtractProvider (label )
102+ provider := ExtractProvider (n .Attrs ["label" ])
98103 if provider != "" && ! providerSubgraphs [provider ] {
99- sb .WriteString (fmt .Sprintf ("\t subgraph %s\n " , caser .String (provider )))
104+ sb .WriteString (fmt .Sprintf ("\t \ t subgraph %s\n " , caser .String (provider )))
100105 providerSubgraphs [provider ] = true
101106 }
102107 }
103108
104- if subgraphName != "" {
105- sb .WriteString (fmt .Sprintf ("\t subgraph %s\n " , subgraphName ))
106- }
107-
108- // Iterate over nodes to add them to the Mermaid graph
109+ nodeMap := make (map [string ]int )
109110 for _ , n := range graph .Nodes .Nodes {
110111 label := CleanLabel (n .Attrs ["label" ])
111112 nodeName := CleanID (n .Name )
112- if label != "" && nodeName != "" && ! strings .Contains (label , "provider" ) {
113- sb .WriteString (fmt .Sprintf ("\t \t %s[\" %s\" ]\n " , nodeName , label ))
113+ if label != "" && nodeName != "" {
114+ nodeMap [label ]++
115+ count := nodeMap [label ]
116+ if count > 1 {
117+ sb .WriteString (fmt .Sprintf ("\t \t \t %s[\" %s\\ nCount: %d\" ]\n " , nodeName , label , count ))
118+ } else {
119+ sb .WriteString (fmt .Sprintf ("\t \t \t %s[\" %s\" ]\n " , nodeName , label ))
120+ }
114121 }
115122 }
116123
117- // Iterate over edges to add them to the Mermaid graph
124+ for range providerSubgraphs {
125+ sb .WriteString ("\t \t end\n " )
126+ }
127+
118128 for _ , edge := range graph .Edges .Edges {
119129 srcLabel := CleanLabel (graph .Nodes .Lookup [edge .Src ].Attrs ["label" ])
120130 dstLabel := CleanLabel (graph .Nodes .Lookup [edge .Dst ].Attrs ["label" ])
121131 srcName := CleanID (edge .Src )
122132 dstName := CleanID (edge .Dst )
123- if srcLabel != "" && dstLabel != "" && ! strings . Contains ( srcLabel , "provider" ) && ! strings . Contains ( dstLabel , "provider" ) {
133+ if srcLabel != "" && dstLabel != "" {
124134 sb .WriteString (fmt .Sprintf ("\t \t %s --> %s\n " , srcName , dstName ))
125135 }
126136 }
127137
128- // Close all open subgraphs
129- for range providerSubgraphs {
130- sb .WriteString ("\t end\n " )
131- }
132138 if subgraphName != "" {
133139 sb .WriteString ("\t end\n " )
134140 }
0 commit comments