css.go

 1package pgit
 2
 3import (
 4	"bytes"
 5	"crypto/sha256"
 6	"encoding/hex"
 7	"fmt"
 8	"os"
 9	"path/filepath"
10
11	"github.com/alecthomas/chroma/v2"
12	"github.com/tdewolff/minify/v2"
13	"github.com/tdewolff/minify/v2/css"
14)
15
16func Style(theme chroma.Style) string {
17	bg := theme.Get(chroma.Background)
18	txt := theme.Get(chroma.Text)
19	kw := theme.Get(chroma.Keyword)
20	nv := theme.Get(chroma.NameVariable)
21	cm := theme.Get(chroma.Comment)
22	return fmt.Sprintf(`:root {
23  --bg-color: %s;
24  --text-color: %s;
25  --border: %s;
26  --link-color: %s;
27  --hover: %s;
28  --visited: %s;
29}`,
30		bg.Background.String(),
31		txt.Colour.String(),
32		cm.Colour.String(),
33		nv.Colour.String(),
34		kw.Colour.String(),
35		nv.Colour.String(),
36	)
37}
38
39func (c *Config) BundleCSS() (string, error) {
40	c.Logger.Info("bundling CSS files")
41
42	m := minify.New()
43	m.AddFunc("text/css", css.Minify)
44
45	var buf bytes.Buffer
46
47	pgitCSS, err := StaticFS.ReadFile("static/pgit.css")
48	if err != nil {
49		return "", fmt.Errorf("failed to read pgit.css: %w", err)
50	}
51	buf.Write(pgitCSS)
52	buf.WriteString("\n")
53
54	varsCSS := Style(*c.Theme)
55	buf.WriteString(varsCSS)
56	buf.WriteString("\n")
57
58	var syntaxBuf bytes.Buffer
59	err = c.Formatter.WriteCSS(&syntaxBuf, c.Theme)
60	if err != nil {
61		return "", fmt.Errorf("failed to generate syntax.css: %w", err)
62	}
63	buf.Write(syntaxBuf.Bytes())
64
65	minified, err := m.Bytes("text/css", buf.Bytes())
66	if err != nil {
67		return "", fmt.Errorf("failed to minify CSS: %w", err)
68	}
69
70	hash := sha256.Sum256(minified)
71	hashStr := hex.EncodeToString(hash[:8])
72
73	filename := fmt.Sprintf("styles.%s.css", hashStr)
74
75	outPath := filepath.Join(c.Outdir, filename)
76	err = os.WriteFile(outPath, minified, 0644)
77	if err != nil {
78		return "", fmt.Errorf("failed to write CSS bundle: %w", err)
79	}
80
81	c.Logger.Info("CSS bundle created", "filename", filename, "size", len(minified))
82
83	return filename, nil
84}