From f68f86594b7c976c1d165035f1459dc3845d47bb Mon Sep 17 00:00:00 2001 From: adnano Date: Wed, 12 May 2021 03:35:30 -0400 Subject: [PATCH] templates: Parse all templates in the directory To allow for specifying custom templates in frontmatter in the future. --- templates.go | 109 ++++++++++++++++++++++++++++----------------------- 1 file changed, 59 insertions(+), 50 deletions(-) diff --git a/templates.go b/templates.go index 94bd899..6e34631 100644 --- a/templates.go +++ b/templates.go @@ -10,11 +10,48 @@ import ( "path/filepath" "strings" "text/template" + "text/template/parse" ) // Template represents a template. type Template interface { + AddParseTree(*parse.Tree) error Execute(io.Writer, interface{}) error + Tree() *parse.Tree +} + +type textTemplate struct { + tmpl *template.Template +} + +func (t textTemplate) AddParseTree(tree *parse.Tree) error { + _, err := t.tmpl.AddParseTree(t.tmpl.Name(), tree) + return err +} + +func (t textTemplate) Execute(w io.Writer, data interface{}) error { + return t.tmpl.Execute(w, data) +} + +func (t textTemplate) Tree() *parse.Tree { + return t.tmpl.Tree +} + +type htmlTemplate struct { + tmpl *htemplate.Template +} + +func (t htmlTemplate) AddParseTree(tree *parse.Tree) error { + _, err := t.tmpl.AddParseTree(t.tmpl.Name(), tree) + return err +} + +func (t htmlTemplate) Execute(w io.Writer, data interface{}) error { + return t.tmpl.Execute(w, data) +} + +func (t htmlTemplate) Tree() *parse.Tree { + return t.tmpl.Tree } // Templates contains site templates. @@ -38,7 +75,7 @@ func (t *Templates) Funcs(funcs map[string]interface{}) { // LoadTemplate loads a template from the provided filenames. func (t *Templates) LoadTemplate(name string, filenames ...string) error { - if pathpkg.Ext(name) == ".html" { + if ext := pathpkg.Ext(name); ext == ".html" || ext == ".xml" { return t.loadHTMLTemplate(name, filenames...) } return t.loadTextTemplate(name, filenames...) @@ -55,7 +92,7 @@ func (t *Templates) loadTextTemplate(name string, filenames ...string) error { return err } } - t.tmpls[name] = tmpl + t.tmpls[name] = textTemplate{tmpl} return nil } @@ -70,60 +107,13 @@ func (t *Templates) loadHTMLTemplate(name string, filenames ...string) error { return err } } - t.tmpls[name] = tmpl + t.tmpls[name] = htmlTemplate{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 - } - - // 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 } @@ -136,6 +126,25 @@ func (t *Templates) Load(dir string, exts []string) error { if err != nil && !os.IsNotExist(err) { return err } + + // Add base templates + var extsMap = map[string]struct{}{} + for _, ext := range exts { + extsMap[ext] = struct{}{} + } + for path := range t.tmpls { + ext := pathpkg.Ext(path) + if _, ok := extsMap[ext]; !ok { + continue + } + base := pathpkg.Join(pathpkg.Dir(path), "base"+ext) + if tmpl, ok := t.tmpls[base]; ok { + err := t.tmpls[path].AddParseTree(tmpl.Tree()) + if err != nil { + return err + } + } + } return nil }