~gitpocket/gitpocket

1
77f60fb7beaa2579dafa975799bf02dcbd4019d0
mainfeed-discovery
gitpocket/highlight.go -rw-r--r--1.9 KiB ViewLogBlameView rawPermalink 8fb214d48b feat(settings): add a dark theme 8 days ago
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
package main

import (
	"bytes"
	"fmt"
	"html/template"
	"path/filepath"
	"strings"

	"github.com/alecthomas/chroma/v2"
	"github.com/alecthomas/chroma/v2/formatters/html"
	"github.com/alecthomas/chroma/v2/lexers"
	"github.com/alecthomas/chroma/v2/styles"
)

var formatter = html.New(
	html.WithClasses(true),
	html.WithLineNumbers(true),
	html.LineNumbersInTable(true),
	html.WithLinkableLineNumbers(true, "L"),
	html.TabWidth(4),
)

var highlightStyle = styles.Get("pygments")

func highlightLimited(name string, content []byte) (template.HTML, bool) {
	if len(content) > maxHighlight {
		return "", false
	}
	return highlight(name, content)
}

func highlight(name string, content []byte) (template.HTML, bool) {
	lexer := lexers.Match(filepath.Base(name))
	if lexer == nil {
		lexer = lexers.Analyse(string(content))
	}
	if lexer == nil {
		return "", false
	}
	lexer = chroma.Coalesce(lexer)
	iterator, err := lexer.Tokenise(nil, string(content))
	if err != nil {
		return "", false
	}
	var buf bytes.Buffer
	if err := formatter.Format(&buf, highlightStyle, iterator); err != nil {
		return "", false
	}
	return template.HTML(buf.String()), true
}

func scoped(rules []string, scope string) string {
	var b strings.Builder
	for _, r := range rules {
		b.WriteString(scope + r + "\n")
	}
	return b.String()
}

func highlightCSS() []byte {
	var buf, dark bytes.Buffer
	formatter.WriteCSS(&buf, highlightStyle)
	formatter.WriteCSS(&dark, styles.Get("github-dark"))
	var rules []string
	for line := range strings.Lines(dark.String()) {
		_, rule, ok := strings.Cut(line, "*/ ")
		if !ok || !strings.HasPrefix(rule, ".chroma .") || strings.Contains(rule, "background-color") {
			continue
		}
		rules = append(rules, strings.TrimSpace(rule))
	}
	fmt.Fprintf(&buf, "%s\n@media (prefers-color-scheme:dark){\n%s}\n", scoped(rules, ":root[data-theme=dark] "), scoped(rules, ":root:not([data-theme=light]) "))
	return buf.Bytes()
}