Artifact 7226c479b989360b6b0df5f916e38cd4a93738008b2e7d6a02cb405177dec9db:
- File
internal/highlight/highlight.go
— part of check-in
[4fe9a80214]
at
2026-08-15 16:15:53
on branch trunk
— highlight: dark theme covers every light token class (030)
Classes github-dark omits get explicit overrides at the dark base color; regression test pins full coverage incl. nx/p/na/nb/bp. (user: dmestas, size: 2840) [annotate] [blame] [check-ins using]
// Package highlight is quarry's thin chroma wrapper (0002 §2 lists the // Forgejo one as [COPY]; theirs is coupled to their settings and caches, // so this is a smaller fresh write). Output uses CSS classes, never // inline styles, so the two-theme story stays in one stylesheet. package highlight import ( "bytes" "fmt" "regexp" "strings" "github.com/alecthomas/chroma/v2" chromahtml "github.com/alecthomas/chroma/v2/formatters/html" "github.com/alecthomas/chroma/v2/lexers" "github.com/alecthomas/chroma/v2/styles" ) var formatter = chromahtml.New( chromahtml.WithClasses(true), chromahtml.PreventSurroundingPre(false), ) // Code highlights source for the given language hint and/or filename; // either may be empty. ok is false when no lexer matched — callers fall // back to an escaped <pre>. func Code(code []byte, language, filename string) (string, bool) { var lexer chroma.Lexer if language != "" { lexer = lexers.Get(language) } if lexer == nil && filename != "" { lexer = lexers.Match(filename) } if lexer == nil { lexer = lexers.Analyse(string(code)) } if lexer == nil { return "", false } lexer = chroma.Coalesce(lexer) it, err := lexer.Tokenise(nil, string(code)) if err != nil { return "", false } var buf bytes.Buffer if err := formatter.Format(&buf, styles.Get("github"), it); err != nil { return "", false } return buf.String(), true } // CSS returns the chroma class rules for both themes: light rules bare, // dark rules inside a prefers-color-scheme block — matching the page // layout's theming (0002 §4 item 5: both themes). // // A chroma style only emits rules for token classes it colors // explicitly, so a class present in the light output but absent from // the dark output would fall through to its light (near-black) color on // the dark background — invisible text (ticket 030). Every such class // gets an explicit dark override at the base text color. func CSS() string { var light, dark strings.Builder formatter.WriteCSS(&light, styles.Get("github")) formatter.WriteCSS(&dark, styles.Get("github-dark")) darkCSS := dark.String() darkClasses := map[string]bool{} for _, m := range classRule.FindAllStringSubmatch(darkCSS, -1) { darkClasses[m[1]] = true } base := "#e6edf3" if m := baseColor.FindStringSubmatch(darkCSS); m != nil { base = m[1] } var missing strings.Builder for _, m := range classRule.FindAllStringSubmatch(light.String(), -1) { if !darkClasses[m[1]] { fmt.Fprintf(&missing, ".chroma .%s { color: %s }\n", m[1], base) darkClasses[m[1]] = true } } return light.String() + "\n@media (prefers-color-scheme: dark) {\n" + darkCSS + missing.String() + "\n}\n" } var ( classRule = regexp.MustCompile(`\.chroma \.([a-zA-Z0-9]+) `) baseColor = regexp.MustCompile(`\.chroma \{[^}]*?color: (#[0-9a-fA-F]{3,8})`) )