All checks were successful
/ Deploy blog to deuterium (push) Successful in 1m9s
Signed-off-by: Naman Sood <mail@nsood.in>
117 lines
2.8 KiB
Go
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
|
|
}
|