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