From eca5dda9d62bdac48d1af74fd073c6ed3e44b004 Mon Sep 17 00:00:00 2001 From: Adnan Maolood Date: Sun, 9 May 2021 19:28:09 -0400 Subject: [PATCH] Implement support for base templates --- config.go | 14 +++--- main.go | 9 +++- templates.go | 118 +++++++++++++++++++++++++++++++++++++++------------ 3 files changed, 107 insertions(+), 34 deletions(-) diff --git a/config.go b/config.go index 778c548..380b2e7 100644 --- a/config.go +++ b/config.go @@ -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) } diff --git a/main.go b/main.go index 70e2fe0..a6ee2af 100644 --- a/main.go +++ b/main.go @@ -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) } diff --git a/templates.go b/templates.go index 9b46c3b..94bd899 100644 --- a/templates.go +++ b/templates.go @@ -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.