internal/httpd/theme.go
61 lines · 1999 bytes
4 symbols in this file
1package httpd
2
3import (
4 "regexp"
5 "strings"
6
7 "gitbay.org/gitbay/internal/web"
8)
9
10// themedCSS derives the served stylesheet from style.css. The source keeps
11// one dark token block under the media query, which the token tests read;
12// served, that block is guarded so a page stamped data-theme="light" keeps
13// the light tokens under a dark OS, and a copy of it applies, outside any
14// media query, when the page is stamped data-theme="dark" (#232).
15func themedCSS(src []byte) []byte {
16 const open = "@media (prefers-color-scheme: dark) {\n :root {"
17 const close = "\n }\n}"
18 s := string(src)
19 i := strings.Index(s, open)
20 if i < 0 {
21 return src
22 }
23 start := i + len(open)
24 n := strings.Index(s[start:], close)
25 if n < 0 {
26 return src
27 }
28 body := s[start : start+n]
29 var b strings.Builder
30 b.WriteString(s[:i])
31 b.WriteString("@media (prefers-color-scheme: dark) {\n :root:not([data-theme=\"light\"]) {")
32 b.WriteString(body)
33 b.WriteString(close)
34 b.WriteString("\n:root[data-theme=\"dark\"] {")
35 b.WriteString(body)
36 b.WriteString("\n}")
37 b.WriteString(s[start+n+len(close):])
38 return []byte(b.String())
39}
40
41// styleCSS is what /static/style.css serves, minus the syntax palettes.
42var styleCSS = themedCSS(web.StyleCSS)
43
44// chromaRule matches the start of one rule in chroma's generated CSS: an
45// optional token-name comment, then the .chroma or .bg selector.
46var chromaRule = regexp.MustCompile(`(?m)^((?:/\*[^*]*\*/ )?)(\.chroma|\.bg)`)
47
48// scopeChroma prefixes every rule of a chroma palette with a selector, so
49// the palette applies only under that scheme. The LineLink rule is dropped:
50// it sets outline: none on the line-number links, which hid the focus ring;
51// style.css carries the rest of it.
52func scopeChroma(css, prefix string) string {
53 var out []string
54 for _, line := range strings.Split(css, "\n") {
55 if strings.Contains(line, ".lnlinks") {
56 continue
57 }
58 out = append(out, chromaRule.ReplaceAllString(line, "${1}"+prefix+" $2"))
59 }
60 return strings.Join(out, "\n")
61}