output: Rework the base template logic
authorBjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>
Sun, 19 Mar 2017 20:09:31 +0000 (21:09 +0100)
committerBjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>
Mon, 27 Mar 2017 13:43:56 +0000 (15:43 +0200)
Extract the logic to a testable function and add support for custom output types.

Fixes #2995

helpers/pathspec.go
hugolib/page.go
hugolib/site_render.go
output/layout_base.go [new file with mode: 0644]
output/layout_base_test.go [new file with mode: 0644]
output/outputFormat.go
output/outputFormat_test.go
tpl/tplimpl/template.go

index ffca4df8ec203b03d88e7daab97b5c479a30410b..de7665c87296a47d4578031b8216dd94a6a9ec99 100644 (file)
@@ -94,3 +94,18 @@ func NewPathSpec(fs *hugofs.Fs, cfg config.Provider) *PathSpec {
 func (p *PathSpec) PaginatePath() string {
        return p.paginatePath
 }
+
+// WorkingDir returns the configured workingDir.
+func (p *PathSpec) WorkingDir() string {
+       return p.workingDir
+}
+
+// LayoutDir returns the relative layout dir in the currenct Hugo project.
+func (p *PathSpec) LayoutDir() string {
+       return p.layoutDir
+}
+
+// Theme returns the theme name if set.
+func (p *PathSpec) Theme() string {
+       return p.theme
+}
index f477e6a1427fb2ee6e62125cd0f627927ef0b2d8..390df8070f67dc8488b8c25760376cb0241aaa2a 100644 (file)
@@ -923,10 +923,11 @@ func (p *Page) update(f interface{}) error {
                                p.s.Log.ERROR.Printf("Failed to parse lastmod '%v' in page %s", v, p.File.Path())
                        }
                case "outputs":
-                       outputs := cast.ToStringSlice(v)
-                       if len(outputs) > 0 {
+                       o := cast.ToStringSlice(v)
+                       if len(o) > 0 {
                                // Output formats are exlicitly set in front matter, use those.
-                               outFormats, err := output.GetTypes(outputs...)
+                               outFormats, err := output.GetFormats(o...)
+
                                if err != nil {
                                        p.s.Log.ERROR.Printf("Failed to resolve output formats: %s", err)
                                } else {
index 6ab67c4083afa9c3d687d2b95d3d3b2394517612..2da02ef539e71841104769e870288eace8a7c3c3 100644 (file)
@@ -63,7 +63,9 @@ func pageRenderer(s *Site, pages <-chan *Page, results chan<- error, wg *sync.Wa
        var mainPageOutput *PageOutput
 
        for page := range pages {
+
                for i, outFormat := range page.outputFormats {
+
                        pageOutput, err := newPageOutput(page, i > 0, outFormat)
 
                        if err != nil {
diff --git a/output/layout_base.go b/output/layout_base.go
new file mode 100644 (file)
index 0000000..929ee07
--- /dev/null
@@ -0,0 +1,175 @@
+// Copyright 2017-present The Hugo Authors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package output
+
+import (
+       "fmt"
+       "path/filepath"
+       "strings"
+
+       "github.com/spf13/hugo/helpers"
+)
+
+const baseFileBase = "baseof"
+
+var (
+       aceTemplateInnerMarkers = [][]byte{[]byte("= content")}
+       goTemplateInnerMarkers  = [][]byte{[]byte("{{define"), []byte("{{ define")}
+)
+
+type TemplateNames struct {
+       Name            string
+       OverlayFilename string
+       MasterFilename  string
+}
+
+// TODO(bep) output this is refactoring in progress.
+type TemplateLookupDescriptor struct {
+       // The full path to the site or theme root.
+       WorkingDir string
+
+       // Main project layout dir, defaults to "layouts"
+       LayoutDir string
+
+       // The path to the template relative the the base.
+       //  I.e. shortcodes/youtube.html
+       RelPath string
+
+       // The template name prefix to look for, i.e. "theme".
+       Prefix string
+
+       // The theme name if active.
+       Theme string
+
+       FileExists  func(filename string) (bool, error)
+       ContainsAny func(filename string, subslices [][]byte) (bool, error)
+}
+
+func CreateTemplateID(d TemplateLookupDescriptor) (TemplateNames, error) {
+
+       var id TemplateNames
+
+       name := filepath.FromSlash(d.RelPath)
+
+       if d.Prefix != "" {
+               name = strings.Trim(d.Prefix, "/") + "/" + name
+       }
+
+       baseLayoutDir := filepath.Join(d.WorkingDir, d.LayoutDir)
+       fullPath := filepath.Join(baseLayoutDir, d.RelPath)
+
+       // The filename will have a suffix with an optional type indicator.
+       // Examples:
+       // index.html
+       // index.amp.html
+       // index.json
+       filename := filepath.Base(d.RelPath)
+
+       var ext, outFormat string
+
+       parts := strings.Split(filename, ".")
+       if len(parts) > 2 {
+               outFormat = parts[1]
+               ext = parts[2]
+       } else if len(parts) > 1 {
+               ext = parts[1]
+       }
+
+       filenameNoSuffix := parts[0]
+
+       id.OverlayFilename = fullPath
+       id.Name = name
+
+       // Ace and Go templates may have both a base and inner template.
+       pathDir := filepath.Dir(fullPath)
+
+       if ext == "amber" || strings.HasSuffix(pathDir, "partials") || strings.HasSuffix(pathDir, "shortcodes") {
+               // No base template support
+               return id, nil
+       }
+
+       innerMarkers := goTemplateInnerMarkers
+
+       var baseFilename string
+
+       if outFormat != "" {
+               baseFilename = fmt.Sprintf("%s.%s.%s", baseFileBase, outFormat, ext)
+       } else {
+               baseFilename = fmt.Sprintf("%s.%s", baseFileBase, ext)
+       }
+
+       if ext == "ace" {
+               innerMarkers = aceTemplateInnerMarkers
+       }
+
+       // This may be a view that shouldn't have base template
+       // Have to look inside it to make sure
+       needsBase, err := d.ContainsAny(fullPath, innerMarkers)
+       if err != nil {
+               return id, err
+       }
+
+       if needsBase {
+               currBaseFilename := fmt.Sprintf("%s-%s", filenameNoSuffix, baseFilename)
+
+               templateDir := filepath.Dir(fullPath)
+               themeDir := filepath.Join(d.WorkingDir, d.Theme)
+
+               baseTemplatedDir := strings.TrimPrefix(templateDir, baseLayoutDir)
+               baseTemplatedDir = strings.TrimPrefix(baseTemplatedDir, helpers.FilePathSeparator)
+
+               // Look for base template in the follwing order:
+               //   1. <current-path>/<template-name>-baseof.<outputFormat>(optional).<suffix>, e.g. list-baseof.<outputFormat>(optional).<suffix>.
+               //   2. <current-path>/baseof.<outputFormat>(optional).<suffix>
+               //   3. _default/<template-name>-baseof.<outputFormat>(optional).<suffix>, e.g. list-baseof.<outputFormat>(optional).<suffix>.
+               //   4. _default/baseof.<outputFormat>(optional).<suffix>
+               // For each of the steps above, it will first look in the project, then, if theme is set,
+               // in the theme's layouts folder.
+               // Also note that the <current-path> may be both the project's layout folder and the theme's.
+               pairsToCheck := [][]string{
+                       []string{baseTemplatedDir, currBaseFilename},
+                       []string{baseTemplatedDir, baseFilename},
+                       []string{"_default", currBaseFilename},
+                       []string{"_default", baseFilename},
+               }
+
+       Loop:
+               for _, pair := range pairsToCheck {
+                       pathsToCheck := basePathsToCheck(pair, baseLayoutDir, themeDir)
+
+                       for _, pathToCheck := range pathsToCheck {
+                               if ok, err := d.FileExists(pathToCheck); err == nil && ok {
+                                       id.MasterFilename = pathToCheck
+                                       break Loop
+                               }
+                       }
+               }
+       }
+
+       return id, nil
+
+}
+
+func basePathsToCheck(path []string, layoutDir, themeDir string) []string {
+       // Always look in the project.
+       pathsToCheck := []string{filepath.Join((append([]string{layoutDir}, path...))...)}
+
+       // May have a theme
+       if themeDir != "" {
+               pathsToCheck = append(pathsToCheck, filepath.Join((append([]string{themeDir, "layouts"}, path...))...))
+       }
+
+       return pathsToCheck
+
+}
diff --git a/output/layout_base_test.go b/output/layout_base_test.go
new file mode 100644 (file)
index 0000000..60d9b8c
--- /dev/null
@@ -0,0 +1,159 @@
+// Copyright 2017-present The Hugo Authors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package output
+
+import (
+       "path/filepath"
+       "strings"
+       "testing"
+
+       "github.com/stretchr/testify/require"
+)
+
+func TestLayoutBase(t *testing.T) {
+
+       var (
+               workingDir     = "/sites/mysite/"
+               layoutBase1    = "layouts"
+               layoutPath1    = "_default/single.html"
+               layoutPathAmp  = "_default/single.amp.html"
+               layoutPathJSON = "_default/single.json"
+       )
+
+       for _, this := range []struct {
+               name                 string
+               d                    TemplateLookupDescriptor
+               needsBase            bool
+               basePathMatchStrings string
+               expect               TemplateNames
+       }{
+               {"No base", TemplateLookupDescriptor{WorkingDir: workingDir, LayoutDir: layoutBase1, RelPath: layoutPath1}, false, "",
+                       TemplateNames{
+                               Name:            "_default/single.html",
+                               OverlayFilename: "/sites/mysite/layouts/_default/single.html",
+                       }},
+               {"Base", TemplateLookupDescriptor{WorkingDir: workingDir, LayoutDir: layoutBase1, RelPath: layoutPath1}, true, "",
+                       TemplateNames{
+                               Name:            "_default/single.html",
+                               OverlayFilename: "/sites/mysite/layouts/_default/single.html",
+                               MasterFilename:  "/sites/mysite/layouts/_default/single-baseof.html",
+                       }},
+               {"Base in theme", TemplateLookupDescriptor{WorkingDir: workingDir, LayoutDir: layoutBase1, RelPath: layoutPath1, Theme: "mytheme"}, true,
+                       "mytheme/layouts/_default/baseof.html",
+                       TemplateNames{
+                               Name:            "_default/single.html",
+                               OverlayFilename: "/sites/mysite/layouts/_default/single.html",
+                               MasterFilename:  "/sites/mysite/mytheme/layouts/_default/baseof.html",
+                       }},
+               {"Template in theme, base in theme", TemplateLookupDescriptor{WorkingDir: filepath.Join(workingDir, "mytheme"), LayoutDir: layoutBase1, RelPath: layoutPath1, Theme: "mytheme"}, true,
+                       "mytheme/layouts/_default/baseof.html",
+                       TemplateNames{
+                               Name:            "_default/single.html",
+                               OverlayFilename: "/sites/mysite/mytheme/layouts/_default/single.html",
+                               MasterFilename:  "/sites/mysite/mytheme/layouts/_default/baseof.html",
+                       }},
+               {"Template in theme, base in site", TemplateLookupDescriptor{WorkingDir: filepath.Join(workingDir, "mytheme"), LayoutDir: layoutBase1, RelPath: layoutPath1, Theme: "mytheme"}, true,
+                       "mytheme/layouts/_default/baseof.html",
+                       TemplateNames{
+                               Name:            "_default/single.html",
+                               OverlayFilename: "/sites/mysite/mytheme/layouts/_default/single.html",
+                               MasterFilename:  "/sites/mysite/mytheme/layouts/_default/baseof.html",
+                       }},
+               {"Template in site, base in theme", TemplateLookupDescriptor{WorkingDir: workingDir, LayoutDir: layoutBase1, RelPath: layoutPath1, Theme: "mytheme"}, true,
+                       "/sites/mysite/mytheme/layouts/_default/baseof.html",
+                       TemplateNames{
+                               Name:            "_default/single.html",
+                               OverlayFilename: "/sites/mysite/layouts/_default/single.html",
+                               MasterFilename:  "/sites/mysite/mytheme/layouts/_default/baseof.html",
+                       }},
+               {"With prefix, base in theme", TemplateLookupDescriptor{WorkingDir: workingDir, LayoutDir: layoutBase1, RelPath: layoutPath1,
+                       Theme: "mytheme", Prefix: "someprefix"}, true,
+                       "mytheme/layouts/_default/baseof.html",
+                       TemplateNames{
+                               Name:            "someprefix/_default/single.html",
+                               OverlayFilename: "/sites/mysite/layouts/_default/single.html",
+                               MasterFilename:  "/sites/mysite/mytheme/layouts/_default/baseof.html",
+                       }},
+               {"Partial", TemplateLookupDescriptor{WorkingDir: workingDir, LayoutDir: layoutBase1, RelPath: "partials/menu.html"}, true,
+                       "mytheme/layouts/_default/baseof.html",
+                       TemplateNames{
+                               Name:            "partials/menu.html",
+                               OverlayFilename: "/sites/mysite/layouts/partials/menu.html",
+                       }},
+               {"AMP, no base", TemplateLookupDescriptor{WorkingDir: workingDir, LayoutDir: layoutBase1, RelPath: layoutPathAmp}, false, "",
+                       TemplateNames{
+                               Name:            "_default/single.amp.html",
+                               OverlayFilename: "/sites/mysite/layouts/_default/single.amp.html",
+                       }},
+               {"JSON, no base", TemplateLookupDescriptor{WorkingDir: workingDir, LayoutDir: layoutBase1, RelPath: layoutPathJSON}, false, "",
+                       TemplateNames{
+                               Name:            "_default/single.json",
+                               OverlayFilename: "/sites/mysite/layouts/_default/single.json",
+                       }},
+               {"AMP with base", TemplateLookupDescriptor{WorkingDir: workingDir, LayoutDir: layoutBase1, RelPath: layoutPathAmp}, true, "single-baseof.html|single-baseof.amp.html",
+                       TemplateNames{
+                               Name:            "_default/single.amp.html",
+                               OverlayFilename: "/sites/mysite/layouts/_default/single.amp.html",
+                               MasterFilename:  "/sites/mysite/layouts/_default/single-baseof.amp.html",
+                       }},
+               {"AMP with no match in base", TemplateLookupDescriptor{WorkingDir: workingDir, LayoutDir: layoutBase1, RelPath: layoutPathAmp}, true, "single-baseof.html",
+                       TemplateNames{
+                               Name:            "_default/single.amp.html",
+                               OverlayFilename: "/sites/mysite/layouts/_default/single.amp.html",
+                               // There is a single-baseof.html, but that makes no sense.
+                               MasterFilename: "",
+                       }},
+
+               {"JSON with base", TemplateLookupDescriptor{WorkingDir: workingDir, LayoutDir: layoutBase1, RelPath: layoutPathJSON}, true, "single-baseof.json",
+                       TemplateNames{
+                               Name:            "_default/single.json",
+                               OverlayFilename: "/sites/mysite/layouts/_default/single.json",
+                               MasterFilename:  "/sites/mysite/layouts/_default/single-baseof.json",
+                       }},
+       } {
+               t.Run(this.name, func(t *testing.T) {
+
+                       fileExists := func(filename string) (bool, error) {
+                               stringsToMatch := strings.Split(this.basePathMatchStrings, "|")
+                               for _, s := range stringsToMatch {
+                                       if strings.Contains(filename, s) {
+                                               return true, nil
+                                       }
+
+                               }
+                               return false, nil
+                       }
+
+                       needsBase := func(filename string, subslices [][]byte) (bool, error) {
+                               return this.needsBase, nil
+                       }
+
+                       this.d.WorkingDir = filepath.FromSlash(this.d.WorkingDir)
+                       this.d.LayoutDir = filepath.FromSlash(this.d.LayoutDir)
+                       this.d.RelPath = filepath.FromSlash(this.d.RelPath)
+                       this.d.ContainsAny = needsBase
+                       this.d.FileExists = fileExists
+
+                       this.expect.MasterFilename = filepath.FromSlash(this.expect.MasterFilename)
+                       this.expect.OverlayFilename = filepath.FromSlash(this.expect.OverlayFilename)
+
+                       id, err := CreateTemplateID(this.d)
+
+                       require.NoError(t, err)
+                       require.Equal(t, this.expect, id, this.name)
+
+               })
+       }
+
+}
index 8c99aa139936c5937b295fb2bf0600d63858d468..cc04bcbe491204d0f8da3ceb55f856e98e7a723c 100644 (file)
@@ -92,7 +92,7 @@ type Format struct {
        NoUgly bool
 }
 
-func GetType(key string) (Format, bool) {
+func GetFormat(key string) (Format, bool) {
        found, ok := builtInTypes[key]
        if !ok {
                found, ok = builtInTypes[strings.ToLower(key)]
@@ -101,11 +101,11 @@ func GetType(key string) (Format, bool) {
 }
 
 // TODO(bep) outputs rewamp on global config?
-func GetTypes(keys ...string) (Formats, error) {
+func GetFormats(keys ...string) (Formats, error) {
        var types []Format
 
        for _, key := range keys {
-               tpe, ok := GetType(key)
+               tpe, ok := GetFormat(key)
                if !ok {
                        return types, fmt.Errorf("OutputFormat with key %q not found", key)
                }
index 3eb56d8d3c5762d35d2a44e0975126e66dc1c301..21375bf561950791c5d1d3a792322cafe49555ca 100644 (file)
@@ -34,10 +34,10 @@ func TestDefaultTypes(t *testing.T) {
 }
 
 func TestGetType(t *testing.T) {
-       tp, _ := GetType("html")
+       tp, _ := GetFormat("html")
        require.Equal(t, HTMLType, tp)
-       tp, _ = GetType("HTML")
+       tp, _ = GetFormat("HTML")
        require.Equal(t, HTMLType, tp)
-       _, found := GetType("FOO")
+       _, found := GetFormat("FOO")
        require.False(t, found)
 }
index b625f570b9c1cfd437e0b5fc6337a779b99920d5..bf4587e8ef86336660c567e5e96aaa1fe82832bb 100644 (file)
@@ -14,7 +14,6 @@
 package tplimpl
 
 import (
-       "fmt"
        "html/template"
        "io"
        "os"
@@ -28,6 +27,7 @@ import (
        bp "github.com/spf13/hugo/bufferpool"
        "github.com/spf13/hugo/deps"
        "github.com/spf13/hugo/helpers"
+       "github.com/spf13/hugo/output"
        "github.com/yosssi/ace"
 )
 
@@ -478,80 +478,44 @@ func (t *GoHTMLTemplate) loadTemplates(absPath string, prefix string) {
                                return nil
                        }
 
-                       tplName := t.GenerateTemplateNameFrom(absPath, path)
+                       workingDir := t.PathSpec.WorkingDir()
+                       themeDir := t.PathSpec.GetThemeDir()
 
-                       if prefix != "" {
-                               tplName = strings.Trim(prefix, "/") + "/" + tplName
+                       if themeDir != "" && strings.HasPrefix(absPath, themeDir) {
+                               workingDir = themeDir
                        }
 
-                       var baseTemplatePath string
-
-                       // Ace and Go templates may have both a base and inner template.
-                       pathDir := filepath.Dir(path)
-                       if filepath.Ext(path) != ".amber" && !strings.HasSuffix(pathDir, "partials") && !strings.HasSuffix(pathDir, "shortcodes") {
-
-                               innerMarkers := goTemplateInnerMarkers
-                               baseFileName := fmt.Sprintf("%s.html", baseFileBase)
-
-                               if filepath.Ext(path) == ".ace" {
-                                       innerMarkers = aceTemplateInnerMarkers
-                                       baseFileName = fmt.Sprintf("%s.ace", baseFileBase)
-                               }
-
-                               // This may be a view that shouldn't have base template
-                               // Have to look inside it to make sure
-                               needsBase, err := helpers.FileContainsAny(path, innerMarkers, t.Fs.Source)
-                               if err != nil {
-                                       return err
-                               }
-                               if needsBase {
-
-                                       layoutDir := t.PathSpec.GetLayoutDirPath()
-                                       currBaseFilename := fmt.Sprintf("%s-%s", helpers.Filename(path), baseFileName)
-                                       templateDir := filepath.Dir(path)
-                                       themeDir := filepath.Join(t.PathSpec.GetThemeDir())
-                                       relativeThemeLayoutsDir := filepath.Join(t.PathSpec.GetRelativeThemeDir(), "layouts")
-
-                                       var baseTemplatedDir string
-
-                                       if strings.HasPrefix(templateDir, relativeThemeLayoutsDir) {
-                                               baseTemplatedDir = strings.TrimPrefix(templateDir, relativeThemeLayoutsDir)
-                                       } else {
-                                               baseTemplatedDir = strings.TrimPrefix(templateDir, layoutDir)
-                                       }
-
-                                       baseTemplatedDir = strings.TrimPrefix(baseTemplatedDir, helpers.FilePathSeparator)
-
-                                       // Look for base template in the follwing order:
-                                       //   1. <current-path>/<template-name>-baseof.<suffix>, e.g. list-baseof.<suffix>.
-                                       //   2. <current-path>/baseof.<suffix>
-                                       //   3. _default/<template-name>-baseof.<suffix>, e.g. list-baseof.<suffix>.
-                                       //   4. _default/baseof.<suffix>
-                                       // For each of the steps above, it will first look in the project, then, if theme is set,
-                                       // in the theme's layouts folder.
-
-                                       pairsToCheck := [][]string{
-                                               []string{baseTemplatedDir, currBaseFilename},
-                                               []string{baseTemplatedDir, baseFileName},
-                                               []string{"_default", currBaseFilename},
-                                               []string{"_default", baseFileName},
-                                       }
-
-                               Loop:
-                                       for _, pair := range pairsToCheck {
-                                               pathsToCheck := basePathsToCheck(pair, layoutDir, themeDir)
-                                               for _, pathToCheck := range pathsToCheck {
-                                                       if ok, err := helpers.Exists(pathToCheck, t.Fs.Source); err == nil && ok {
-                                                               baseTemplatePath = pathToCheck
-                                                               break Loop
-                                                       }
-                                               }
-                                       }
-                               }
+                       li := strings.LastIndex(path, t.PathSpec.LayoutDir()) + len(t.PathSpec.LayoutDir()) + 1
+
+                       if li < 0 {
+                               // Possibly a theme
+                               li = strings.LastIndex(path, "layouts") + 8
+                       }
+
+                       relPath := path[li:]
+
+                       descriptor := output.TemplateLookupDescriptor{
+                               WorkingDir: workingDir,
+                               LayoutDir:  t.PathSpec.LayoutDir(),
+                               RelPath:    relPath,
+                               Prefix:     prefix,
+                               Theme:      t.PathSpec.Theme(),
+                               FileExists: func(filename string) (bool, error) {
+                                       return helpers.Exists(filename, t.Fs.Source)
+                               },
+                               ContainsAny: func(filename string, subslices [][]byte) (bool, error) {
+                                       return helpers.FileContainsAny(filename, subslices, t.Fs.Source)
+                               },
+                       }
+
+                       tplID, err := output.CreateTemplateID(descriptor)
+                       if err != nil {
+                               t.Log.ERROR.Printf("Failed to resolve template in path %q: %s", path, err)
+                               return nil
                        }
 
-                       if err := t.AddTemplateFile(tplName, baseTemplatePath, path); err != nil {
-                               t.Log.ERROR.Printf("Failed to add template %s in path %s: %s", tplName, path, err)
+                       if err := t.AddTemplateFile(tplID.Name, tplID.MasterFilename, tplID.OverlayFilename); err != nil {
+                               t.Log.ERROR.Printf("Failed to add template %q in path %q: %s", tplID.Name, path, err)
                        }
 
                }
@@ -562,19 +526,6 @@ func (t *GoHTMLTemplate) loadTemplates(absPath string, prefix string) {
        }
 }
 
-func basePathsToCheck(path []string, layoutDir, themeDir string) []string {
-       // Always look in the project.
-       pathsToCheck := []string{filepath.Join((append([]string{layoutDir}, path...))...)}
-
-       // May have a theme
-       if themeDir != "" {
-               pathsToCheck = append(pathsToCheck, filepath.Join((append([]string{themeDir, "layouts"}, path...))...))
-       }
-
-       return pathsToCheck
-
-}
-
 func (t *GoHTMLTemplate) LoadTemplatesWithPrefix(absPath string, prefix string) {
        t.loadTemplates(absPath, prefix)
 }