Skip to content
quarry Artifact [7226c479b9]
Login

Artifact [7226c479b9]

Artifact 7226c479b989360b6b0df5f916e38cd4a93738008b2e7d6a02cb405177dec9db:


// 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})`)
)