Files
musenalm/templating/templates.go
2025-05-26 17:27:52 +02:00

104 lines
2.1 KiB
Go

package templating
import (
"io/fs"
"log/slog"
"path/filepath"
"slices"
"strings"
"sync"
)
// TODO: redo template parsing to allow for just rendering single components
type File struct {
Name string
Path string
Ext string
}
func FromDirEntry(entry fs.DirEntry, path string) File {
ext := filepath.Ext(entry.Name())
Name := strings.TrimSuffix(entry.Name(), ext)
return File{
Name: Name,
Ext: ext,
Path: path,
}
}
type Directory struct {
Path string
Locals map[string]File
Globals map[string]File
}
type Templates struct {
Directories sync.Map // map[string]*Directory
}
func (t *Templates) NewDirectory(path string, fsys fs.FS) (*Directory, error) {
fspath := PathToFSPath(path)
entries, err := fs.ReadDir(fsys, fspath)
wg := &sync.WaitGroup{}
if err != nil {
return nil, NewError(FileAccessError, fspath)
}
dir := &Directory{}
for _, file := range entries {
if file.IsDir() && file.Name() == TEMPLATE_COMPONENT_DIRECTORY {
wg.Add(1)
go func() {
defer wg.Done()
locals, globals, err := t.ScanComponentDirectory(filepath.Join(fspath, file.Name()), fsys)
if err != nil {
slog.Error("Failed to scan component directory", "path", file.Name(), "error", err)
return
}
dir.Locals = locals
dir.Globals = globals
}()
}
if !slices.Contains(TEMPLATE_FORMATS, filepath.Ext(file.Name())) {
continue
}
}
wg.Wait()
return dir, nil
}
func (t *Templates) ScanComponentDirectory(path string, fsys fs.FS) (map[string]File, map[string]File, error) {
locals := make(map[string]File)
globals := make(map[string]File)
fspath := PathToFSPath(path)
err := fs.WalkDir(fsys, fspath, func(path string, d fs.DirEntry, err error) error {
if err != nil {
return NewError(FileAccessError, path)
}
if d.IsDir() || !slices.Contains(TEMPLATE_FORMATS, filepath.Ext(d.Name())) {
return nil
}
f := FromDirEntry(d, path)
if strings.HasPrefix(f.Name, TEMPLATE_GLOBAL_PREFIX) {
globals[f.Name] = f
} else {
locals[f.Name] = f
}
return nil
})
if err != nil {
return nil, nil, NewError(FileAccessError, path)
}
return locals, globals, nil
}