Skip to content
quarry Artifact [e9cd9d02cc]
Login

Artifact [e9cd9d02cc]

Artifact e9cd9d02cc4b2810564a80c2ff602d78729e16879bdce965e1d47ce489c10f40:


package highlight

import (
	"regexp"
	"strings"
	"testing"
)

func TestCodeByFilename(t *testing.T) {
	out, ok := Code([]byte("package main\n"), "", "src/main.go")
	if !ok {
		t.Fatal("go file not highlighted")
	}
	if !strings.Contains(out, "<span class=") || !strings.Contains(out, "package") {
		t.Fatalf("no classed spans:\n%s", out)
	}
	if strings.Contains(out, "style=") {
		t.Fatalf("inline styles leak into output (classes only):\n%s", out)
	}
}

func TestCodeByLanguage(t *testing.T) {
	if _, ok := Code([]byte("SELECT 1;\n"), "sql", ""); !ok {
		t.Fatal("language hint not used")
	}
}

func TestCodeNoLexer(t *testing.T) {
	// Pure binary-ish content with no filename or language: callers get
	// ok=false and fall back to escaped <pre>.
	if out, ok := Code([]byte{0x00, 0x01, 0x02}, "", "data.zzzunknown"); ok {
		t.Fatalf("unexpected lexer match:\n%s", out)
	}
}

func TestCSSHasBothThemes(t *testing.T) {
	css := CSS()
	if !strings.Contains(css, ".chroma") {
		t.Fatal("no chroma rules")
	}
	if !strings.Contains(css, "prefers-color-scheme: dark") {
		t.Fatal("no dark theme block")
	}
}

func TestDarkThemeCoversEveryLightClass(t *testing.T) {
	// Ticket 030: every token class colored in light mode must also be
	// colored inside the dark block, or identifiers/punctuation render
	// near-black on the dark background.
	css := CSS()
	i := strings.Index(css, "prefers-color-scheme: dark")
	if i < 0 {
		t.Fatal("no dark block")
	}
	light, dark := css[:i], css[i:]
	re := regexp.MustCompile(`\.chroma \.([a-zA-Z0-9]+) `)
	darkClasses := map[string]bool{}
	for _, m := range re.FindAllStringSubmatch(dark, -1) {
		darkClasses[m[1]] = true
	}
	for _, m := range re.FindAllStringSubmatch(light, -1) {
		if !darkClasses[m[1]] {
			t.Errorf("class .%s colored in light mode but not in dark", m[1])
		}
	}
	// The classes the test round found invisible must now be covered.
	for _, c := range []string{"nx", "p", "na", "nb", "bp"} {
		if !darkClasses[c] {
			t.Errorf("known-invisible class .%s still missing from dark block", c)
		}
	}
}

// The page offers three theme states, so this stylesheet must too. A
// bare prefers-color-scheme block leaves a reader who picks light on a
// dark-mode device with dark code colours on a light page, and makes
// picking dark on a light-mode device do nothing at all — the failure
// only ever shows up on someone else's device.
func TestDarkRulesAreThemeGuarded(t *testing.T) {
	css := CSS()
	media := strings.Index(css, "@media (prefers-color-scheme: dark)")
	if media < 0 {
		t.Fatal("no dark block at all")
	}
	inMedia := strings.Count(css[media:], `:root:not([data-theme="light"]) .chroma`)
	explicit := strings.Count(css, `:root[data-theme="dark"] .chroma`)
	if inMedia == 0 {
		t.Error("the dark media query is unguarded: an explicit light choice cannot override it")
	}
	if explicit == 0 {
		t.Error("no rules under an explicit dark choice: picking dark on a light-mode device does nothing")
	}
	if inMedia != explicit {
		t.Errorf("guarded %d rules but repeated %d under explicit dark; the two states would disagree", inMedia, explicit)
	}
}