prose/stylemap/stylemap.go
Naman Sood 1981a291aa
All checks were successful
/ Deploy blog to deuterium (push) Successful in 1m9s
rewrite code a bit
Signed-off-by: Naman Sood <mail@nsood.in>
2024-11-23 02:53:25 -05:00

117 lines
2.8 KiB
Go

package stylemap
import (
"fmt"
"io"
"log"
"os"
"prose/watcher"
"strings"
"sync"
"github.com/bep/godartsass/v2"
)
type styleMap struct {
mu sync.RWMutex
stylesheets map[string]string
transpiler *godartsass.Transpiler
}
// New returns a new styleMap.
func New() (watcher.AutoMap[string, string], error) {
folder, err := os.ReadDir("styles/")
if err != nil {
return nil, fmt.Errorf("could not load styles directory: %w", err)
}
sassTranspiler, err := godartsass.Start(godartsass.Options{})
if err != nil {
return nil, fmt.Errorf("could not start sass transpiler: %w", err)
}
sm := &styleMap{
stylesheets: make(map[string]string),
transpiler: sassTranspiler,
}
for _, s := range folder {
err := sm.fetchLocked(s.Name())
if err != nil {
return nil, fmt.Errorf("could not generate styles for %s: %w", s.Name(), err)
}
log.Printf("loaded stylesheet %q", s.Name())
}
go watcher.Watch("styles/", sm)
return sm, nil
}
func (sm *styleMap) Get(filename string) (string, bool) {
sm.mu.RLock()
defer sm.mu.RUnlock()
contents, ok := sm.stylesheets[filename]
return contents, ok
}
func (sm *styleMap) Delete(filename string) error {
sm.mu.Lock()
defer sm.mu.Unlock()
if s, ok := strings.CutSuffix(filename, ".scss"); ok {
filename = s + ".css"
}
delete(sm.stylesheets, filename)
return nil
}
func (sm *styleMap) Fetch(filename string) (err error) {
sm.mu.Lock()
defer sm.mu.Unlock()
return sm.fetchLocked(filename)
}
func (sm *styleMap) fetchLocked(filename string) (err error) {
var outfile, contents string
if strings.HasSuffix(filename, ".scss") {
outfile, contents, err = sm.loadSCSS(filename)
} else {
outfile, contents, err = sm.loadCSS(filename)
}
if err != nil {
return
}
sm.stylesheets[outfile] = contents
return
}
func (sm *styleMap) loadSCSS(filename string) (string, string, error) {
in, err := os.Open("styles/" + filename)
if err != nil {
return "", "", fmt.Errorf("could not open stylesheet %s: %w", filename, err)
}
stylesheet, err := io.ReadAll(in)
if err != nil {
return "", "", fmt.Errorf("could not read stylesheet %s: %w", filename, err)
}
res, err := sm.transpiler.Execute(godartsass.Args{
Source: string(stylesheet),
})
if err != nil {
return "", "", fmt.Errorf("could not generate stylesheet %s: %w", filename, err)
}
return strings.TrimSuffix(filename, ".scss") + ".css", res.CSS, nil
}
func (sm *styleMap) loadCSS(filename string) (string, string, error) {
in, err := os.Open("styles/" + filename)
if err != nil {
return "", "", fmt.Errorf("could not open style infile %s: %w", filename, err)
}
var buf strings.Builder
_, err = io.Copy(&buf, in)
if err != nil {
return "", "", fmt.Errorf("could not copy stylesheet %s: %w", filename, err)
}
return filename, buf.String(), nil
}