master
parent
f68700b204
commit
98383235f9
@ -0,0 +1,146 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"html/template"
|
||||
"io"
|
||||
"io/fs"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
txttmpl "text/template"
|
||||
)
|
||||
|
||||
// Options for getting a template tree
|
||||
type Options struct {
|
||||
Globs []string
|
||||
Prefix string
|
||||
Suffix string
|
||||
Root string
|
||||
Funcs map[string]interface{}
|
||||
}
|
||||
|
||||
func (o Options) getRoot() string {
|
||||
if o.Root == "" {
|
||||
return "."
|
||||
}
|
||||
return o.Root
|
||||
}
|
||||
|
||||
func (o Options) matchesGlob(path string) (bool, error) {
|
||||
if len(o.Globs) == 0 {
|
||||
return true, nil
|
||||
}
|
||||
for _, glob := range o.Globs {
|
||||
ok, err := filepath.Match(glob, path)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
if ok {
|
||||
return true, nil
|
||||
}
|
||||
}
|
||||
return false, nil
|
||||
}
|
||||
|
||||
func (o Options) trim(path string) string {
|
||||
return strings.TrimSuffix(strings.TrimPrefix(path, o.Prefix), o.Suffix)
|
||||
}
|
||||
|
||||
// Templates returns templates based on a filesystem
|
||||
func Templates(files fs.FS, opts Options) (*template.Template, error) {
|
||||
var ret *template.Template
|
||||
parseTemplates := func(name string, body []byte) error {
|
||||
var tmpl *template.Template
|
||||
if ret == nil {
|
||||
tmpl = template.New(name)
|
||||
if opts.Funcs != nil {
|
||||
tmpl = tmpl.Funcs(template.FuncMap(opts.Funcs))
|
||||
}
|
||||
} else {
|
||||
tmpl = ret.New(name)
|
||||
}
|
||||
tmpl, err := tmpl.Parse(string(body))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ret = tmpl
|
||||
return nil
|
||||
}
|
||||
|
||||
if err := walk(files, opts, parseTemplates); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
// TextTemplates returns templates based on a filesystem
|
||||
func TextTemplates(files fs.FS, opts Options) (*txttmpl.Template, error) {
|
||||
var ret *txttmpl.Template
|
||||
parseTemplates := func(name string, body []byte) error {
|
||||
var tmpl *txttmpl.Template
|
||||
if ret == nil {
|
||||
tmpl = txttmpl.New(name)
|
||||
if opts.Funcs != nil {
|
||||
tmpl = tmpl.Funcs(txttmpl.FuncMap(opts.Funcs))
|
||||
}
|
||||
} else {
|
||||
tmpl = ret.New(name)
|
||||
}
|
||||
tmpl, err := tmpl.Parse(string(body))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ret = tmpl
|
||||
return nil
|
||||
}
|
||||
|
||||
if err := walk(files, opts, parseTemplates); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func walk(files fs.FS, opts Options, handle func(string, []byte) error) error {
|
||||
walker := func(path string, d fs.DirEntry, er error) (err error) {
|
||||
if er != nil {
|
||||
return er
|
||||
}
|
||||
matches, err := opts.matchesGlob(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !matches {
|
||||
return nil
|
||||
}
|
||||
body, err := readfile(files, path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := handle(opts.trim(path), body); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
if err := fs.WalkDir(files, opts.getRoot(), walker); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func readfile(files fs.FS, path string) ([]byte, error) {
|
||||
f, err := files.Open(path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
body, err := io.ReadAll(f)
|
||||
if err != nil {
|
||||
if err := f.Close(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
if err := f.Close(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return body, nil
|
||||
}
|
Loading…
Reference in New Issue