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}