11package renderer
22
33import (
4+ "bytes"
45 "fmt"
56 "os"
7+ "sort"
68 "strings"
79 "time"
810 "unicode"
@@ -82,8 +84,13 @@ func WriteMermaid(idx *schema.Index, path string) error {
8284 }
8385 }
8486
85- // Write classDef entries for used languages.
87+ // Write classDef entries for used languages in deterministic order.
88+ langs := make ([]string , 0 , len (usedLangs ))
8689 for lang := range usedLangs {
90+ langs = append (langs , lang )
91+ }
92+ sort .Strings (langs )
93+ for _ , lang := range langs {
8794 colors := langColors [lang ]
8895 sb .WriteString (fmt .Sprintf (" classDef %s fill:%s,color:%s,stroke:%s\n " ,
8996 lang , colors [0 ], colors [1 ], colors [0 ]))
@@ -92,8 +99,14 @@ func WriteMermaid(idx *schema.Index, path string) error {
9299 // Determine primary language for node class assignment.
93100 primaryLang := strings .ToLower (idx .Tech .PrimaryLanguage )
94101
95- // Write node definitions.
96- for name , mod := range idx .Modules {
102+ // Write node definitions in deterministic order.
103+ moduleNames := make ([]string , 0 , len (idx .Modules ))
104+ for name := range idx .Modules {
105+ moduleNames = append (moduleNames , name )
106+ }
107+ sort .Strings (moduleNames )
108+ for _ , name := range moduleNames {
109+ mod := idx .Modules [name ]
97110 id := sanitizeMermaidID (name )
98111 label := truncate (mod .Purpose , 40 )
99112 nodeClass := primaryLang
@@ -115,5 +128,9 @@ func WriteMermaid(idx *schema.Index, path string) error {
115128 }
116129
117130 sb .WriteString ("```\n " )
118- return os .WriteFile (path , []byte (sb .String ()), 0644 )
131+ data := []byte (sb .String ())
132+ if existing , err := os .ReadFile (path ); err == nil && bytes .Equal (existing , data ) {
133+ return nil
134+ }
135+ return os .WriteFile (path , data , 0644 )
119136}
0 commit comments