// css.go — the stylesheet is generated per site: theme colors and the mixed // per-agent coverage colors become custom properties, one block per scheme. package main import ( "fmt" "io" "sort" "strings" texttemplate "text/template" ) type cssVar struct{ K, V string } type synCSS struct{ Class, Style, Weight string } func renderCSS(w io.Writer, site *Site) error { css, err := texttemplate.ParseFS(tfs, "assets/style.css.tmpl") if err != nil { return err } var unionKeys []string seen := map[string]bool{} for _, t := range []*Theme{site.Theme, site.Light} { for k := range t.Syntax { if !seen[k] { seen[k] = true unionKeys = append(unionKeys, k) } } } sort.Strings(unionKeys) masks := site.masks() themeVars := func(t *Theme) []cssVar { vars := []cssVar{ {"--bg", t.Bg}, {"--fg", t.Fg}, {"--panel", t.Panel}, {"--border", t.Border}, {"--ln", t.LineNo}, {"--muted", t.Muted}, {"--accent", t.Accent}, {"--note", t.Note}, {"--hover", t.Hover}, } for _, k := range unionKeys { if s, ok := t.Syntax[k]; ok && s.Color != "" { vars = append(vars, cssVar{"--s-" + strings.ReplaceAll(k, ".", "-"), s.Color}) } } for _, m := range masks { vars = append(vars, cssVar{fmt.Sprintf("--am%d", m), site.maskColor(t, m)}) } return vars } var syn []synCSS for _, k := range unionKeys { s := synCSS{Class: strings.ReplaceAll(k, ".", "-")} if v, ok := site.Theme.Syntax[k]; ok { if v.FontStyle != nil { s.Style = *v.FontStyle } if v.FontWeight != nil { s.Weight = fmt.Sprintf("%.0f", *v.FontWeight) } } syn = append(syn, s) } return css.Execute(w, map[string]any{ "DarkName": site.Theme.Name, "LightName": site.Light.Name, "DarkVars": themeVars(site.Theme), "LightVars": themeVars(site.Light), "Syntax": syn, "MaskList": masks, }) }