Implement support for base templates

This commit is contained in:
adnano 2021-05-09 19:28:09 -04:00
parent 4736a6580e
commit 86ab6169a5
3 changed files with 107 additions and 34 deletions

View file

@ -48,18 +48,13 @@ func LoadConfig(path string) (*Config, error) {
return nil, err
}
return c, nil
}
// LoadTemplates loads templates from the provided path.
func (c *Config) LoadTemplates(path string) error {
// Site contains site metadata passed to templates
type Site struct {
Title string
URLs []string
}
// Load templates
// Initialize templates
c.templates = NewTemplates()
c.templates.Funcs(map[string]interface{}{
"site": func() Site {
@ -83,5 +78,10 @@ func (c *Config) LoadTemplates(path string) error {
return template.HTML(s)
},
})
return c.templates.Load(path)
return c, nil
}
func (c *Config) LoadTemplates(path string, exts []string) error {
return c.templates.Load(path, exts)
}

View file

@ -56,7 +56,14 @@ func build() {
if err != nil {
log.Fatal(err)
}
if err := cfg.LoadTemplates("templates"); err != nil {
templateExts := []string{}
for _, task := range cfg.Tasks {
if task.TemplateExt != "" {
templateExts = append(templateExts, task.TemplateExt)
}
}
if err := cfg.LoadTemplates("templates", templateExts); err != nil {
log.Fatal(err)
}

View file

@ -3,6 +3,7 @@ package main
import (
htemplate "html/template"
"io"
"io/fs"
"io/ioutil"
"os"
pathpkg "path"
@ -35,42 +36,107 @@ func (t *Templates) Funcs(funcs map[string]interface{}) {
t.funcs = funcs
}
// LoadTemplate loads a template from the provided path and content.
func (t *Templates) LoadTemplate(path string, content []byte) {
tmpl := template.New(path)
tmpl.Funcs(t.funcs)
template.Must(tmpl.Parse(string(content)))
t.tmpls[path] = tmpl
// LoadTemplate loads a template from the provided filenames.
func (t *Templates) LoadTemplate(name string, filenames ...string) error {
if pathpkg.Ext(name) == ".html" {
return t.loadHTMLTemplate(name, filenames...)
}
return t.loadTextTemplate(name, filenames...)
}
func (t *Templates) LoadHTMLTemplate(path string, content []byte) {
tmpl := htemplate.New(path)
tmpl.Funcs(htemplate.FuncMap(t.funcs))
htemplate.Must(tmpl.Parse(string(content)))
t.tmpls[path] = tmpl
}
// Load loads templates from the provided directory
func (t *Templates) Load(dir string) error {
return filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
func (t *Templates) loadTextTemplate(name string, filenames ...string) error {
tmpl := template.New(name).Funcs(t.funcs)
for i := range filenames {
b, err := ioutil.ReadFile(filenames[i])
if err != nil {
return err
}
if info.Mode().IsRegular() {
b, err := ioutil.ReadFile(path)
if err != nil {
return err
if _, err := tmpl.Parse(string(b)); err != nil {
return err
}
}
t.tmpls[name] = tmpl
return nil
}
func (t *Templates) loadHTMLTemplate(name string, filenames ...string) error {
tmpl := htemplate.New(name).Funcs(t.funcs)
for i := range filenames {
b, err := ioutil.ReadFile(filenames[i])
if err != nil {
return err
}
if _, err := tmpl.Parse(string(b)); err != nil {
return err
}
}
t.tmpls[name] = tmpl
return nil
}
// Load loads templates from the provided directory.
func (t *Templates) Load(dir string, exts []string) error {
err := filepath.WalkDir(dir, func(path string, d fs.DirEntry, err error) error {
if err != nil {
return err
}
if d.IsDir() {
name := d.Name()
if strings.HasPrefix(name, "_") && name != "_default" {
return fs.SkipDir
}
// Remove directory from beginning of path
path = strings.TrimPrefix(path, dir)
if pathpkg.Ext(path) == ".html" {
t.LoadHTMLTemplate(path, b)
} else {
t.LoadTemplate(path, b)
// Load atom.xml template
atom := pathpkg.Join(path, "atom.xml")
if _, err := os.Stat(atom); err == nil {
name := strings.TrimPrefix(atom, dir)
t.loadHTMLTemplate(name, atom)
}
// Load page templates
for _, ext := range exts {
for _, name := range []string{"index" + ext, "page" + ext} {
filename := pathpkg.Join(path, name)
if _, err := os.Stat(filename); err != nil {
// Template does not exist
continue
}
filenames := []string{filename}
base := pathpkg.Join(path, "base"+ext)
if _, err := os.Stat(base); err == nil {
filenames = append(filenames, base)
}
name := strings.TrimPrefix(filename, dir)
if err := t.LoadTemplate(name, filenames...); err != nil {
return err
}
}
}
}
return nil
})
if err != nil && !os.IsNotExist(err) {
return err
}
// Load partial templates
partials := pathpkg.Join(dir, "_partials")
err = filepath.WalkDir(partials, func(path string, d fs.DirEntry, err error) error {
if err != nil {
return err
}
if d.Type().IsRegular() {
name := strings.TrimPrefix(path, dir)
t.LoadTemplate(name, path)
}
return nil
})
if err != nil && !os.IsNotExist(err) {
return err
}
return nil
}
// FindTemplate returns the template for the given path.