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}