// render.go — Go-based IEC 62443-3-3 SL2 compliance report renderer. // // Loads a JSON report produced by ansible-test and renders it through // an external Go template file (report.gohtml by default). // // Usage: // go run render.go [template.gohtml] // // The template receives the full JSON document as an untyped map. // Registered template functions: // passIcon — maps passed value to ✅/❌/🔍/❓ // severityIcon — maps severity string to 🔴/🟠/🟡/🟢/⚪ // title — capitalizes first letter of each word // divf — float64 division (a/b*100) for percentages // add, sub — integer arithmetic // // Dependencies: // golang.org/x/text v0.14.0 (for cases.Title) package main import ( "encoding/json" "fmt" "os" "text/template" "golang.org/x/text/cases" "golang.org/x/text/language" ) func main() { if len(os.Args) < 2 { fmt.Fprintf(os.Stderr, "Usage: gomplate-report [template.gohtml]\n") os.Exit(1) } jsonPath := os.Args[1] tmplPath := "reports/report.gohtml" if len(os.Args) >= 3 { tmplPath = os.Args[2] } data, err := os.ReadFile(jsonPath) if err != nil { fmt.Fprintf(os.Stderr, "Error reading JSON: %v\n", err) os.Exit(1) } var report map[string]any if err := json.Unmarshal(data, &report); err != nil { fmt.Fprintf(os.Stderr, "Error parsing JSON: %v\n", err) os.Exit(1) } funcMap := template.FuncMap{ "passIcon": func(v any) string { b, ok := v.(bool) if !ok { return "❓ MANUAL" } if b { return "✅ PASS" } return "❌ FAIL" }, "severityIcon": func(s string) string { switch s { case "critical": return "🔴" case "high": return "🟠" case "medium": return "🟡" case "low": return "🟢" } return "⚪" }, "title": cases.Title(language.English).String, "divf": func(a, b int) float64 { if b == 0 { return 0 } return float64(a) / float64(b) * 100.0 }, "add": func(a, b int) int { return a + b }, "sub": func(a, b int) int { return a - b }, } tmpl, err := template.New("report.gohtml").Funcs(funcMap).ParseFiles(tmplPath) if err != nil { fmt.Fprintf(os.Stderr, "Error parsing template: %v\n", err) os.Exit(1) } if err := tmpl.ExecuteTemplate(os.Stdout, "report.gohtml", report); err != nil { fmt.Fprintf(os.Stderr, "Error rendering: %v\n", err) os.Exit(1) } }