package main import "fmt" func init() { register(Check{ Seq: 60, ID: "6", Title: "No hardcoded colors in frontend (use theme tokens)", Run: func(ctx *ScanContext, rep *Reporter) { // Check 6: Hardcoded colors in frontend and .templ files fmt.Println("=== Check 6: No hardcoded colors in frontend (use theme tokens) ===") var colorViolations []colorViolation for _, target := range ctx.frontendTargets { for _, v := range checkColors(target.dir) { v.file = prefixDisplayPath(target.label, v.file) colorViolations = append(colorViolations, v) } } // Also scan .templ files in backend and plugin roots (templ lives in backend/, not web/src/). seenTemplRoots := make(map[string]bool) var templColorViolations []colorViolation for _, target := range ctx.backendTargets { if seenTemplRoots[target.root] { continue } seenTemplRoots[target.root] = true for _, v := range checkTemplColors(target.root) { v.file = prefixDisplayPath(target.display, v.file) templColorViolations = append(templColorViolations, v) } } for _, target := range ctx.pluginTargets { if seenTemplRoots[target.root] { continue } seenTemplRoots[target.root] = true for _, v := range checkTemplColors(target.root) { v.file = prefixDisplayPath(target.display, v.file) templColorViolations = append(templColorViolations, v) } } hasColorSources := len(ctx.frontendTargets) > 0 || len(templColorViolations) > 0 || len(seenTemplRoots) > 0 if !hasColorSources && len(ctx.backendTargets) == 0 { fmt.Println(" SKIP: no frontend or templ sources found") } else { hadColorViolations := false if len(colorViolations) > 0 { fmt.Println(formatColorViolations("frontend", colorViolations)) hadColorViolations = true rep.Fail() } else if len(ctx.frontendTargets) > 0 { fmt.Println(" OK: No hardcoded colors in frontend components") printPerTargetOKLines(frontendTargetLabels(ctx.frontendTargets)) } if len(templColorViolations) > 0 { fmt.Println(formatColorViolations(".templ files", templColorViolations)) hadColorViolations = true rep.Fail() } else if len(seenTemplRoots) > 0 { fmt.Println(" OK: No hardcoded colors in .templ files") } // Scan .ninjatpl block templates in plugin roots for hardcoded colors. // Use resolvedPluginTargets (pre-filter) so plugin-as-cwd roots aren't skipped. seenNinjaTplRoots := make(map[string]bool) var ninjaTplColorViolations []colorViolation for _, target := range ctx.resolvedPluginTargets { if seenNinjaTplRoots[target.root] { continue } seenNinjaTplRoots[target.root] = true for _, v := range checkNinjaTplColors(target.root) { v.file = prefixDisplayPath(target.display, v.file) ninjaTplColorViolations = append(ninjaTplColorViolations, v) } } if len(ninjaTplColorViolations) > 0 { fmt.Println(formatColorViolations(".ninjatpl files", ninjaTplColorViolations)) hadColorViolations = true rep.Fail() } else if len(seenNinjaTplRoots) > 0 { fmt.Println(" OK: No hardcoded colors in .ninjatpl files") } if hadColorViolations { printColorFixInstructions(colorViolations, templColorViolations, ninjaTplColorViolations) } } fmt.Println() }, }) }