tl/loader.go

110 lines
2.5 KiB
Go
Raw Permalink Normal View History

2025-07-01 13:21:08 +05:00
package tl
import (
"html/template"
"io/fs"
"os"
"path"
"path/filepath"
"strings"
)
// Template collection.
type Collection struct {
// Path to the directory with templates.
RootDir string
// By default, template name is it's path relative to [RootDir].
// This prefix will be prepended to a template name: Prefix + "/" + RelativePath.
// You can leave it empty, then it will be ignored.
Prefix string
}
// Advanced options.
type Options struct {
// Files from shared collections will be available in every main template.
SharedCollections []Collection
2025-07-10 23:03:23 +05:00
FuncMap template.FuncMap
2025-07-01 13:21:08 +05:00
}
// Load templates from specified directories with default options.
// Files from the main collection will be added to the returned map.
func Load(mainCollection Collection) (map[string]*template.Template, error) {
return LoadWithOptions(mainCollection, Options{})
}
// Load templates from specified directories.
// Files from [mainTemplates] collection will be added to the returned map.
func LoadWithOptions(
mainCollection Collection,
options Options,
) (map[string]*template.Template, error) {
sharedTemplate := template.New("")
2025-07-10 23:03:23 +05:00
2025-07-01 13:21:08 +05:00
for _, stp := range options.SharedCollections {
files, err := getFiles(stp.RootDir, stp.Prefix)
if err != nil {
return nil, err
}
for name, contents := range files {
2025-07-10 23:03:23 +05:00
sharedTemplate = sharedTemplate.New(name)
if options.FuncMap != nil {
sharedTemplate = sharedTemplate.Funcs(options.FuncMap)
}
sharedTemplate, err = sharedTemplate.Parse(contents)
2025-07-01 13:21:08 +05:00
if err != nil {
return nil, err
}
}
}
templateFiles, err := getFiles(mainCollection.RootDir, mainCollection.Prefix)
if err != nil {
return nil, err
}
res := make(map[string]*template.Template)
for name, contents := range templateFiles {
clone, err := sharedTemplate.Clone()
if err != nil {
return nil, err
}
res[name], err = clone.New(name).Parse(contents)
if err != nil {
return nil, err
}
}
return res, nil
}
func getFiles(root string, keyPrefix string) (map[string]string, error) {
res := make(map[string]string)
if !strings.HasSuffix(root, "/") {
root += "/"
}
err := filepath.WalkDir(root, func(entrypath string, d fs.DirEntry, err error) error {
if err != nil {
return err
}
if d.IsDir() {
return nil
}
shortPath := path.Join(keyPrefix, strings.TrimPrefix(entrypath, root))
contents, err := os.ReadFile(entrypath)
if err != nil {
return err
}
res[shortPath] = string(contents)
return nil
})
return res, err
}