summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorBjørn Erik Pedersen <[email protected]>2017-03-19 21:09:31 +0100
committerBjørn Erik Pedersen <[email protected]>2017-03-27 15:43:56 +0200
commitbaa29f6534fcd324dbade7dd6c32c90547e3fa4f (patch)
tree71a7524c25365cfc4a7cc1bbaab9d63988525d5e
parentc7c6b47ba8bb098cf9fac778f7818afba40a1e2f (diff)
downloadhugo-baa29f6534fcd324dbade7dd6c32c90547e3fa4f.tar.gz
hugo-baa29f6534fcd324dbade7dd6c32c90547e3fa4f.zip
output: Rework the base template logic
Extract the logic to a testable function and add support for custom output types. Fixes #2995
-rw-r--r--helpers/pathspec.go15
-rw-r--r--hugolib/page.go7
-rw-r--r--hugolib/site_render.go2
-rw-r--r--output/layout_base.go175
-rw-r--r--output/layout_base_test.go159
-rw-r--r--output/outputFormat.go6
-rw-r--r--output/outputFormat_test.go6
-rw-r--r--tpl/tplimpl/template.go117
8 files changed, 395 insertions, 92 deletions
diff --git a/helpers/pathspec.go b/helpers/pathspec.go
index ffca4df8e..de7665c87 100644
--- a/helpers/pathspec.go
+++ b/helpers/pathspec.go
@@ -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
+}
diff --git a/hugolib/page.go b/hugolib/page.go
index f477e6a14..390df8070 100644
--- a/hugolib/page.go
+++ b/hugolib/page.go
@@ -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 {
diff --git a/hugolib/site_render.go b/hugolib/site_render.go
index 6ab67c408..2da02ef53 100644
--- a/hugolib/site_render.go
+++ b/hugolib/site_render.go
@@ -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
index 000000000..929ee07a2
--- /dev/null
+++ b/output/layout_base.go
@@ -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
index 000000000..60d9b8c62
--- /dev/null
+++ b/output/layout_base_test.go
@@ -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)
+
+ })
+ }
+
+}
diff --git a/output/outputFormat.go b/output/outputFormat.go
index 8c99aa139..cc04bcbe4 100644
--- a/output/outputFormat.go
+++ b/output/outputFormat.go
@@ -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)
}
diff --git a/output/outputFormat_test.go b/output/outputFormat_test.go
index 3eb56d8d3..21375bf56 100644
--- a/output/outputFormat_test.go
+++ b/output/outputFormat_test.go
@@ -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)
}
diff --git a/tpl/tplimpl/template.go b/tpl/tplimpl/template.go
index b625f570b..bf4587e8e 100644
--- a/tpl/tplimpl/template.go
+++ b/tpl/tplimpl/template.go
@@ -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)
}