master
1package main
2
3import (
4 "bytes"
5 "os"
6 "path/filepath"
7 "strings"
8
9 "github.com/alecthomas/chroma/v2"
10 "github.com/alecthomas/chroma/v2/formatters/html"
11 "github.com/alecthomas/chroma/v2/styles"
12
13 "github.com/antonmedv/gitmal/pkg/templates"
14)
15
16func generateCSSFiles(params Params) error {
17 out := params.OutputDir
18
19 if err := os.MkdirAll(out, 0o755); err != nil {
20 return err
21 }
22
23 if err := os.WriteFile(filepath.Join(out, "style.css"), []byte(templates.LayoutCSSAdaptive()), 0o644); err != nil {
24 return err
25 }
26
27 // markdown.css with both light and dark
28 var mdLight, mdDark string
29 mdLight = templates.CSSMarkdownLight
30 mdDark = templates.CSSMarkdownDark
31 combinedMD := mdLight + "\n@media (prefers-color-scheme: dark) {\n" + mdDark + "\n}\n"
32 if err := os.WriteFile(filepath.Join(out, "markdown.css"), []byte(combinedMD), 0o644); err != nil {
33 return err
34 }
35
36 // chroma.css with both light and dark themes
37 chromaLight, err := renderChromaCSS(params.StyleLight)
38 if err != nil {
39 return err
40 }
41 chromaDark, err := renderChromaCSS(params.StyleDark)
42 if err != nil {
43 return err
44 }
45 combinedChroma := combineThemeCSS(chromaLight, chromaDark)
46 if combinedChroma != "" {
47 if err := os.WriteFile(filepath.Join(out, "chroma.css"), []byte(combinedChroma), 0o644); err != nil {
48 return err
49 }
50 }
51
52 // diff.css with both light and dark themes
53 diffLight, err := renderDiffCSS(params.StyleLight)
54 if err != nil {
55 return err
56 }
57 diffDark, err := renderDiffCSS(params.StyleDark)
58 if err != nil {
59 return err
60 }
61 combinedDiff := combineThemeCSS(diffLight, diffDark)
62 if combinedDiff != "" {
63 if err := os.WriteFile(filepath.Join(out, "diff.css"), []byte(combinedDiff), 0o644); err != nil {
64 return err
65 }
66 }
67
68 return nil
69}
70
71func renderChromaCSS(theme string) (string, error) {
72 style := styles.Get(theme)
73 if style == nil {
74 return "", nil
75 }
76 formatter := html.New(
77 html.WithClasses(true),
78 html.WithCSSComments(false),
79 )
80 var buf strings.Builder
81 if err := formatter.WriteCSS(&buf, style); err != nil {
82 return "", err
83 }
84 return buf.String(), nil
85}
86
87func combineThemeCSS(light, dark string) string {
88 if light == "" && dark == "" {
89 return ""
90 }
91 if dark == "" || light == dark {
92 return light
93 }
94 return light + "\n@media (prefers-color-scheme: dark) {\n" + dark + "\n}\n"
95}
96
97func renderDiffCSS(theme string) (string, error) {
98 style := styles.Get(theme)
99 if style == nil {
100 return "", nil
101 }
102 formatter := html.New(
103 html.WithClasses(true),
104 html.WithCSSComments(false),
105 html.WithCustomCSS(map[chroma.TokenType]string{
106 chroma.GenericInserted: "display: block;",
107 chroma.GenericDeleted: "display: block;",
108 }),
109 )
110 var buf bytes.Buffer
111 if err := formatter.WriteCSS(&buf, style); err != nil {
112 return "", err
113 }
114 return buf.String(), nil
115}