diff options
author | Bjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com> | 2017-04-02 14:20:34 +0200 |
---|---|---|
committer | Bjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com> | 2017-04-02 14:20:34 +0200 |
commit | 7eb71ee06419f9ceedfd701ab2a27513ef448829 (patch) | |
tree | 254ba6c75575e067df76b4abe4e566936619adcb /hugolib | |
parent | c97dae40d9cd24c467f5b8cfbe2ac06f3cdef1d2 (diff) |
Revert "tpl: Rework to handle both text and HTML templates"
Will have to take another stab at this ...
This reverts commit 5c5efa03d2512749950b0d05a7d4bde35ecbdc37.
Closes #3260
Diffstat (limited to 'hugolib')
-rw-r--r-- | hugolib/alias.go | 27 | ||||
-rw-r--r-- | hugolib/embedded_shortcodes_test.go | 8 | ||||
-rw-r--r-- | hugolib/hugo_sites.go | 8 | ||||
-rw-r--r-- | hugolib/page.go | 3 | ||||
-rw-r--r-- | hugolib/page_output.go | 24 | ||||
-rw-r--r-- | hugolib/shortcode.go | 16 | ||||
-rw-r--r-- | hugolib/shortcode_test.go | 103 | ||||
-rw-r--r-- | hugolib/site.go | 33 | ||||
-rw-r--r-- | hugolib/site_output_test.go | 16 | ||||
-rw-r--r-- | hugolib/site_test.go | 18 | ||||
-rw-r--r-- | hugolib/sitemap_test.go | 2 | ||||
-rw-r--r-- | hugolib/testhelpers_test.go | 4 |
12 files changed, 124 insertions, 138 deletions
diff --git a/hugolib/alias.go b/hugolib/alias.go index 454744d9b..d5eb35777 100644 --- a/hugolib/alias.go +++ b/hugolib/alias.go @@ -22,8 +22,6 @@ import ( "runtime" "strings" - "github.com/spf13/hugo/tpl" - jww "github.com/spf13/jwalterweatherman" "github.com/spf13/hugo/helpers" @@ -37,19 +35,18 @@ const ( var defaultAliasTemplates *template.Template func init() { - //TODO(bep) consolidate defaultAliasTemplates = template.New("") template.Must(defaultAliasTemplates.New("alias").Parse(alias)) template.Must(defaultAliasTemplates.New("alias-xhtml").Parse(aliasXHtml)) } type aliasHandler struct { - t tpl.TemplateHandler + Templates *template.Template log *jww.Notepad allowRoot bool } -func newAliasHandler(t tpl.TemplateHandler, l *jww.Notepad, allowRoot bool) aliasHandler { +func newAliasHandler(t *template.Template, l *jww.Notepad, allowRoot bool) aliasHandler { return aliasHandler{t, l, allowRoot} } @@ -59,19 +56,12 @@ func (a aliasHandler) renderAlias(isXHTML bool, permalink string, page *Page) (i t = "alias-xhtml" } - var templ *tpl.TemplateAdapter - - if a.t != nil { - templ = a.t.Lookup("alias.html") + template := defaultAliasTemplates + if a.Templates != nil { + template = a.Templates + t = "alias.html" } - if templ == nil { - def := defaultAliasTemplates.Lookup(t) - if def != nil { - templ = &tpl.TemplateAdapter{def} - } - - } data := struct { Permalink string Page *Page @@ -81,7 +71,7 @@ func (a aliasHandler) renderAlias(isXHTML bool, permalink string, page *Page) (i } buffer := new(bytes.Buffer) - err := templ.Execute(buffer, data) + err := template.ExecuteTemplate(buffer, t, data) if err != nil { return nil, err } @@ -93,7 +83,8 @@ func (s *Site) writeDestAlias(path, permalink string, p *Page) (err error) { } func (s *Site) publishDestAlias(allowRoot bool, path, permalink string, p *Page) (err error) { - handler := newAliasHandler(s.Tmpl, s.Log, allowRoot) + + handler := newAliasHandler(s.Tmpl.Lookup("alias.html"), s.Log, allowRoot) isXHTML := strings.HasSuffix(path, ".xhtml") diff --git a/hugolib/embedded_shortcodes_test.go b/hugolib/embedded_shortcodes_test.go index 45de0bf09..92821d0ef 100644 --- a/hugolib/embedded_shortcodes_test.go +++ b/hugolib/embedded_shortcodes_test.go @@ -335,8 +335,8 @@ func TestShortcodeTweet(t *testing.T) { th = testHelper{cfg, fs, t} ) - withTemplate := func(templ tpl.TemplateHandler) error { - templ.(tpl.TemplateTestMocker).SetFuncs(tweetFuncMap) + withTemplate := func(templ tpl.Template) error { + templ.Funcs(tweetFuncMap) return nil } @@ -390,8 +390,8 @@ func TestShortcodeInstagram(t *testing.T) { th = testHelper{cfg, fs, t} ) - withTemplate := func(templ tpl.TemplateHandler) error { - templ.(tpl.TemplateTestMocker).SetFuncs(instagramFuncMap) + withTemplate := func(templ tpl.Template) error { + templ.Funcs(instagramFuncMap) return nil } diff --git a/hugolib/hugo_sites.go b/hugolib/hugo_sites.go index 1f090cf5e..6c737f65a 100644 --- a/hugolib/hugo_sites.go +++ b/hugolib/hugo_sites.go @@ -127,11 +127,11 @@ func NewHugoSites(cfg deps.DepsCfg) (*HugoSites, error) { return newHugoSites(cfg, sites...) } -func (s *Site) withSiteTemplates(withTemplates ...func(templ tpl.TemplateHandler) error) func(templ tpl.TemplateHandler) error { - return func(templ tpl.TemplateHandler) error { - templ.LoadTemplates(s.PathSpec.GetLayoutDirPath(), "") +func (s *Site) withSiteTemplates(withTemplates ...func(templ tpl.Template) error) func(templ tpl.Template) error { + return func(templ tpl.Template) error { + templ.LoadTemplates(s.PathSpec.GetLayoutDirPath()) if s.PathSpec.ThemeSet() { - templ.LoadTemplates(s.PathSpec.GetThemeDir()+"/layouts", "theme") + templ.LoadTemplatesWithPrefix(s.PathSpec.GetThemeDir()+"/layouts", "theme") } for _, wt := range withTemplates { diff --git a/hugolib/page.go b/hugolib/page.go index 5a04c6ce7..fa9f40922 100644 --- a/hugolib/page.go +++ b/hugolib/page.go @@ -1384,14 +1384,13 @@ func (p *Page) prepareLayouts() error { if p.Kind == KindPage { if !p.IsRenderable() { self := "__" + p.UniqueID() - err := p.s.Tmpl.AddLateTemplate(self, string(p.Content)) + _, err := p.s.Tmpl.GetClone().New(self).Parse(string(p.Content)) if err != nil { return err } p.selfLayout = self } } - return nil } diff --git a/hugolib/page_output.go b/hugolib/page_output.go index 58d09d688..f47343cb5 100644 --- a/hugolib/page_output.go +++ b/hugolib/page_output.go @@ -110,29 +110,9 @@ func (p *PageOutput) Render(layout ...string) template.HTML { l, err := p.layouts(layout...) if err != nil { helpers.DistinctErrorLog.Printf("in .Render: Failed to resolve layout %q for page %q", layout, p.pathOrTitle()) - return "" + return template.HTML("") } - - for _, layout := range l { - templ := p.s.Tmpl.Lookup(layout) - if templ == nil { - // This is legacy from when we had only one output format and - // HTML templates only. Some have references to layouts without suffix. - // We default to good old HTML. - templ = p.s.Tmpl.Lookup(layout + ".html") - } - if templ != nil { - res, err := templ.ExecuteToString(p) - if err != nil { - helpers.DistinctErrorLog.Printf("in .Render: Failed to execute template %q for page %q", layout, p.pathOrTitle()) - return template.HTML("") - } - return template.HTML(res) - } - } - - return "" - + return p.s.Tmpl.ExecuteTemplateToHTML(p, l...) } func (p *Page) Render(layout ...string) template.HTML { diff --git a/hugolib/shortcode.go b/hugolib/shortcode.go index d72a96faa..d165c778b 100644 --- a/hugolib/shortcode.go +++ b/hugolib/shortcode.go @@ -177,7 +177,7 @@ var isInnerShortcodeCache = struct { // to avoid potential costly look-aheads for closing tags we look inside the template itself // we could change the syntax to self-closing tags, but that would make users cry // the value found is cached -func isInnerShortcode(t tpl.TemplateExecutor) (bool, error) { +func isInnerShortcode(t *template.Template) (bool, error) { isInnerShortcodeCache.RLock() m, ok := isInnerShortcodeCache.m[t.Name()] isInnerShortcodeCache.RUnlock() @@ -188,7 +188,10 @@ func isInnerShortcode(t tpl.TemplateExecutor) (bool, error) { isInnerShortcodeCache.Lock() defer isInnerShortcodeCache.Unlock() - match, _ := regexp.MatchString("{{.*?\\.Inner.*?}}", t.Tree()) + if t.Tree == nil { + return false, errors.New("Template failed to compile") + } + match, _ := regexp.MatchString("{{.*?\\.Inner.*?}}", t.Tree.Root.String()) isInnerShortcodeCache.m[t.Name()] = match return match, nil @@ -395,6 +398,8 @@ Loop: case tScName: sc.name = currItem.val tmpl := getShortcodeTemplate(sc.name, p.s.Tmpl) + { + } if tmpl == nil { return sc, fmt.Errorf("Unable to locate template for shortcode %q in page %q", sc.name, p.Path()) } @@ -565,10 +570,7 @@ func replaceShortcodeTokens(source []byte, prefix string, replacements map[strin return source, nil } -func getShortcodeTemplate(name string, t tpl.TemplateHandler) *tpl.TemplateAdapter { - isInnerShortcodeCache.RLock() - defer isInnerShortcodeCache.RUnlock() - +func getShortcodeTemplate(name string, t tpl.Template) *template.Template { if x := t.Lookup("shortcodes/" + name + ".html"); x != nil { return x } @@ -578,7 +580,7 @@ func getShortcodeTemplate(name string, t tpl.TemplateHandler) *tpl.TemplateAdapt return t.Lookup("_internal/shortcodes/" + name + ".html") } -func renderShortcodeWithPage(tmpl tpl.Template, data *ShortcodeWithPage) string { +func renderShortcodeWithPage(tmpl *template.Template, data *ShortcodeWithPage) string { buffer := bp.GetBuffer() defer bp.PutBuffer(buffer) diff --git a/hugolib/shortcode_test.go b/hugolib/shortcode_test.go index 3d1922462..28b03aa9b 100644 --- a/hugolib/shortcode_test.go +++ b/hugolib/shortcode_test.go @@ -30,7 +30,7 @@ import ( ) // TODO(bep) remove -func pageFromString(in, filename string, withTemplate ...func(templ tpl.TemplateHandler) error) (*Page, error) { +func pageFromString(in, filename string, withTemplate ...func(templ tpl.Template) error) (*Page, error) { s := newTestSite(nil) if len(withTemplate) > 0 { // Have to create a new site @@ -47,11 +47,11 @@ func pageFromString(in, filename string, withTemplate ...func(templ tpl.Template return s.NewPageFrom(strings.NewReader(in), filename) } -func CheckShortCodeMatch(t *testing.T, input, expected string, withTemplate func(templ tpl.TemplateHandler) error) { +func CheckShortCodeMatch(t *testing.T, input, expected string, withTemplate func(templ tpl.Template) error) { CheckShortCodeMatchAndError(t, input, expected, withTemplate, false) } -func CheckShortCodeMatchAndError(t *testing.T, input, expected string, withTemplate func(templ tpl.TemplateHandler) error, expectError bool) { +func CheckShortCodeMatchAndError(t *testing.T, input, expected string, withTemplate func(templ tpl.Template) error, expectError bool) { cfg, fs := newTestCfg() @@ -100,9 +100,8 @@ func TestNonSC(t *testing.T) { // Issue #929 func TestHyphenatedSC(t *testing.T) { t.Parallel() - wt := func(tem tpl.TemplateHandler) error { - - tem.AddTemplate("_internal/shortcodes/hyphenated-video.html", `Playing Video {{ .Get 0 }}`) + wt := func(tem tpl.Template) error { + tem.AddInternalShortcode("hyphenated-video.html", `Playing Video {{ .Get 0 }}`) return nil } @@ -112,8 +111,8 @@ func TestHyphenatedSC(t *testing.T) { // Issue #1753 func TestNoTrailingNewline(t *testing.T) { t.Parallel() - wt := func(tem tpl.TemplateHandler) error { - tem.AddTemplate("_internal/shortcodes/a.html", `{{ .Get 0 }}`) + wt := func(tem tpl.Template) error { + tem.AddInternalShortcode("a.html", `{{ .Get 0 }}`) return nil } @@ -122,8 +121,8 @@ func TestNoTrailingNewline(t *testing.T) { func TestPositionalParamSC(t *testing.T) { t.Parallel() - wt := func(tem tpl.TemplateHandler) error { - tem.AddTemplate("_internal/shortcodes/video.html", `Playing Video {{ .Get 0 }}`) + wt := func(tem tpl.Template) error { + tem.AddInternalShortcode("video.html", `Playing Video {{ .Get 0 }}`) return nil } @@ -136,8 +135,8 @@ func TestPositionalParamSC(t *testing.T) { func TestPositionalParamIndexOutOfBounds(t *testing.T) { t.Parallel() - wt := func(tem tpl.TemplateHandler) error { - tem.AddTemplate("_internal/shortcodes/video.html", `Playing Video {{ .Get 1 }}`) + wt := func(tem tpl.Template) error { + tem.AddInternalShortcode("video.html", `Playing Video {{ .Get 1 }}`) return nil } CheckShortCodeMatch(t, "{{< video 47238zzb >}}", "Playing Video error: index out of range for positional param at position 1", wt) @@ -147,8 +146,8 @@ func TestPositionalParamIndexOutOfBounds(t *testing.T) { func TestNamedParamSC(t *testing.T) { t.Parallel() - wt := func(tem tpl.TemplateHandler) error { - tem.AddTemplate("_internal/shortcodes/img.html", `<img{{ with .Get "src" }} src="{{.}}"{{end}}{{with .Get "class"}} class="{{.}}"{{end}}>`) + wt := func(tem tpl.Template) error { + tem.AddInternalShortcode("img.html", `<img{{ with .Get "src" }} src="{{.}}"{{end}}{{with .Get "class"}} class="{{.}}"{{end}}>`) return nil } CheckShortCodeMatch(t, `{{< img src="one" >}}`, `<img src="one">`, wt) @@ -162,10 +161,10 @@ func TestNamedParamSC(t *testing.T) { // Issue #2294 func TestNestedNamedMissingParam(t *testing.T) { t.Parallel() - wt := func(tem tpl.TemplateHandler) error { - tem.AddTemplate("_internal/shortcodes/acc.html", `<div class="acc">{{ .Inner }}</div>`) - tem.AddTemplate("_internal/shortcodes/div.html", `<div {{with .Get "class"}} class="{{ . }}"{{ end }}>{{ .Inner }}</div>`) - tem.AddTemplate("_internal/shortcodes/div2.html", `<div {{with .Get 0}} class="{{ . }}"{{ end }}>{{ .Inner }}</div>`) + wt := func(tem tpl.Template) error { + tem.AddInternalShortcode("acc.html", `<div class="acc">{{ .Inner }}</div>`) + tem.AddInternalShortcode("div.html", `<div {{with .Get "class"}} class="{{ . }}"{{ end }}>{{ .Inner }}</div>`) + tem.AddInternalShortcode("div2.html", `<div {{with .Get 0}} class="{{ . }}"{{ end }}>{{ .Inner }}</div>`) return nil } CheckShortCodeMatch(t, @@ -175,10 +174,10 @@ func TestNestedNamedMissingParam(t *testing.T) { func TestIsNamedParamsSC(t *testing.T) { t.Parallel() - wt := func(tem tpl.TemplateHandler) error { - tem.AddTemplate("_internal/shortcodes/byposition.html", `<div id="{{ .Get 0 }}">`) - tem.AddTemplate("_internal/shortcodes/byname.html", `<div id="{{ .Get "id" }}">`) - tem.AddTemplate("_internal/shortcodes/ifnamedparams.html", `<div id="{{ if .IsNamedParams }}{{ .Get "id" }}{{ else }}{{ .Get 0 }}{{end}}">`) + wt := func(tem tpl.Template) error { + tem.AddInternalShortcode("byposition.html", `<div id="{{ .Get 0 }}">`) + tem.AddInternalShortcode("byname.html", `<div id="{{ .Get "id" }}">`) + tem.AddInternalShortcode("ifnamedparams.html", `<div id="{{ if .IsNamedParams }}{{ .Get "id" }}{{ else }}{{ .Get 0 }}{{end}}">`) return nil } CheckShortCodeMatch(t, `{{< ifnamedparams id="name" >}}`, `<div id="name">`, wt) @@ -191,8 +190,8 @@ func TestIsNamedParamsSC(t *testing.T) { func TestInnerSC(t *testing.T) { t.Parallel() - wt := func(tem tpl.TemplateHandler) error { - tem.AddTemplate("_internal/shortcodes/inside.html", `<div{{with .Get "class"}} class="{{.}}"{{end}}>{{ .Inner }}</div>`) + wt := func(tem tpl.Template) error { + tem.AddInternalShortcode("inside.html", `<div{{with .Get "class"}} class="{{.}}"{{end}}>{{ .Inner }}</div>`) return nil } CheckShortCodeMatch(t, `{{< inside class="aspen" >}}`, `<div class="aspen"></div>`, wt) @@ -202,8 +201,8 @@ func TestInnerSC(t *testing.T) { func TestInnerSCWithMarkdown(t *testing.T) { t.Parallel() - wt := func(tem tpl.TemplateHandler) error { - tem.AddTemplate("_internal/shortcodes/inside.html", `<div{{with .Get "class"}} class="{{.}}"{{end}}>{{ .Inner }}</div>`) + wt := func(tem tpl.Template) error { + tem.AddInternalShortcode("inside.html", `<div{{with .Get "class"}} class="{{.}}"{{end}}>{{ .Inner }}</div>`) return nil } CheckShortCodeMatch(t, `{{% inside %}} @@ -216,8 +215,8 @@ func TestInnerSCWithMarkdown(t *testing.T) { func TestInnerSCWithAndWithoutMarkdown(t *testing.T) { t.Parallel() - wt := func(tem tpl.TemplateHandler) error { - tem.AddTemplate("_internal/shortcodes/inside.html", `<div{{with .Get "class"}} class="{{.}}"{{end}}>{{ .Inner }}</div>`) + wt := func(tem tpl.Template) error { + tem.AddInternalShortcode("inside.html", `<div{{with .Get "class"}} class="{{.}}"{{end}}>{{ .Inner }}</div>`) return nil } CheckShortCodeMatch(t, `{{% inside %}} @@ -247,9 +246,9 @@ func TestEmbeddedSC(t *testing.T) { func TestNestedSC(t *testing.T) { t.Parallel() - wt := func(tem tpl.TemplateHandler) error { - tem.AddTemplate("_internal/shortcodes/scn1.html", `<div>Outer, inner is {{ .Inner }}</div>`) - tem.AddTemplate("_internal/shortcodes/scn2.html", `<div>SC2</div>`) + wt := func(tem tpl.Template) error { + tem.AddInternalShortcode("scn1.html", `<div>Outer, inner is {{ .Inner }}</div>`) + tem.AddInternalShortcode("scn2.html", `<div>SC2</div>`) return nil } CheckShortCodeMatch(t, `{{% scn1 %}}{{% scn2 %}}{{% /scn1 %}}`, "<div>Outer, inner is <div>SC2</div>\n</div>", wt) @@ -259,10 +258,10 @@ func TestNestedSC(t *testing.T) { func TestNestedComplexSC(t *testing.T) { t.Parallel() - wt := func(tem tpl.TemplateHandler) error { - tem.AddTemplate("_internal/shortcodes/row.html", `-row-{{ .Inner}}-rowStop-`) - tem.AddTemplate("_internal/shortcodes/column.html", `-col-{{.Inner }}-colStop-`) - tem.AddTemplate("_internal/shortcodes/aside.html", `-aside-{{ .Inner }}-asideStop-`) + wt := func(tem tpl.Template) error { + tem.AddInternalShortcode("row.html", `-row-{{ .Inner}}-rowStop-`) + tem.AddInternalShortcode("column.html", `-col-{{.Inner }}-colStop-`) + tem.AddInternalShortcode("aside.html", `-aside-{{ .Inner }}-asideStop-`) return nil } CheckShortCodeMatch(t, `{{< row >}}1-s{{% column %}}2-**s**{{< aside >}}3-**s**{{< /aside >}}4-s{{% /column %}}5-s{{< /row >}}6-s`, @@ -275,10 +274,10 @@ func TestNestedComplexSC(t *testing.T) { func TestParentShortcode(t *testing.T) { t.Parallel() - wt := func(tem tpl.TemplateHandler) error { - tem.AddTemplate("_internal/shortcodes/r1.html", `1: {{ .Get "pr1" }} {{ .Inner }}`) - tem.AddTemplate("_internal/shortcodes/r2.html", `2: {{ .Parent.Get "pr1" }}{{ .Get "pr2" }} {{ .Inner }}`) - tem.AddTemplate("_internal/shortcodes/r3.html", `3: {{ .Parent.Parent.Get "pr1" }}{{ .Parent.Get "pr2" }}{{ .Get "pr3" }} {{ .Inner }}`) + wt := func(tem tpl.Template) error { + tem.AddInternalShortcode("r1.html", `1: {{ .Get "pr1" }} {{ .Inner }}`) + tem.AddInternalShortcode("r2.html", `2: {{ .Parent.Get "pr1" }}{{ .Get "pr2" }} {{ .Inner }}`) + tem.AddInternalShortcode("r3.html", `3: {{ .Parent.Parent.Get "pr1" }}{{ .Parent.Get "pr2" }}{{ .Get "pr3" }} {{ .Inner }}`) return nil } CheckShortCodeMatch(t, `{{< r1 pr1="p1" >}}1: {{< r2 pr2="p2" >}}2: {{< r3 pr3="p3" >}}{{< /r3 >}}{{< /r2 >}}{{< /r1 >}}`, @@ -343,13 +342,13 @@ func TestExtractShortcodes(t *testing.T) { fmt.Sprintf("Hello %sworld%s. And that's it.", testScPlaceholderRegexp, testScPlaceholderRegexp), ""}, } { - p, _ := pageFromString(simplePage, "simple.md", func(templ tpl.TemplateHandler) error { - templ.AddTemplate("_internal/shortcodes/tag.html", `tag`) - templ.AddTemplate("_internal/shortcodes/sc1.html", `sc1`) - templ.AddTemplate("_internal/shortcodes/sc2.html", `sc2`) - templ.AddTemplate("_internal/shortcodes/inner.html", `{{with .Inner }}{{ . }}{{ end }}`) - templ.AddTemplate("_internal/shortcodes/inner2.html", `{{.Inner}}`) - templ.AddTemplate("_internal/shortcodes/inner3.html", `{{.Inner}}`) + p, _ := pageFromString(simplePage, "simple.md", func(templ tpl.Template) error { + templ.AddInternalShortcode("tag.html", `tag`) + templ.AddInternalShortcode("sc1.html", `sc1`) + templ.AddInternalShortcode("sc2.html", `sc2`) + templ.AddInternalShortcode("inner.html", `{{with .Inner }}{{ . }}{{ end }}`) + templ.AddInternalShortcode("inner2.html", `{{.Inner}}`) + templ.AddInternalShortcode("inner3.html", `{{.Inner}}`) return nil }) @@ -518,14 +517,14 @@ tags: sources[i] = source.ByteSource{Name: filepath.FromSlash(test.contentPath), Content: []byte(test.content)} } - addTemplates := func(templ tpl.TemplateHandler) error { + addTemplates := func(templ tpl.Template) error { templ.AddTemplate("_default/single.html", "{{.Content}}") - templ.AddTemplate("_internal/shortcodes/b.html", `b`) - templ.AddTemplate("_internal/shortcodes/c.html", `c`) - templ.AddTemplate("_internal/shortcodes/d.html", `d`) - templ.AddTemplate("_internal/shortcodes/menu.html", `{{ len (index .Page.Menus "main").Children }}`) - templ.AddTemplate("_internal/shortcodes/tags.html", `{{ len .Page.Site.Taxonomies.tags }}`) + templ.AddInternalShortcode("b.html", `b`) + templ.AddInternalShortcode("c.html", `c`) + templ.AddInternalShortcode("d.html", `d`) + templ.AddInternalShortcode("menu.html", `{{ len (index .Page.Menus "main").Children }}`) + templ.AddInternalShortcode("tags.html", `{{ len .Page.Site.Taxonomies.tags }}`) return nil diff --git a/hugolib/site.go b/hugolib/site.go index 613485864..c42b938e8 100644 --- a/hugolib/site.go +++ b/hugolib/site.go @@ -188,7 +188,7 @@ func NewSite(cfg deps.DepsCfg) (*Site, error) { // NewSiteDefaultLang creates a new site in the default language. // The site will have a template system loaded and ready to use. // Note: This is mainly used in single site tests. -func NewSiteDefaultLang(withTemplate ...func(templ tpl.TemplateHandler) error) (*Site, error) { +func NewSiteDefaultLang(withTemplate ...func(templ tpl.Template) error) (*Site, error) { v := viper.New() loadDefaultSettingsFor(v) return newSiteForLang(helpers.NewDefaultLanguage(v), withTemplate...) @@ -197,15 +197,15 @@ func NewSiteDefaultLang(withTemplate ...func(templ tpl.TemplateHandler) error) ( // NewEnglishSite creates a new site in English language. // The site will have a template system loaded and ready to use. // Note: This is mainly used in single site tests. -func NewEnglishSite(withTemplate ...func(templ tpl.TemplateHandler) error) (*Site, error) { +func NewEnglishSite(withTemplate ...func(templ tpl.Template) error) (*Site, error) { v := viper.New() loadDefaultSettingsFor(v) return newSiteForLang(helpers.NewLanguage("en", v), withTemplate...) } // newSiteForLang creates a new site in the given language. -func newSiteForLang(lang *helpers.Language, withTemplate ...func(templ tpl.TemplateHandler) error) (*Site, error) { - withTemplates := func(templ tpl.TemplateHandler) error { +func newSiteForLang(lang *helpers.Language, withTemplate ...func(templ tpl.Template) error) (*Site, error) { + withTemplates := func(templ tpl.Template) error { for _, wt := range withTemplate { if err := wt(templ); err != nil { return err @@ -1906,14 +1906,13 @@ Your rendered home page is blank: /index.html is zero-length } func (s *Site) renderForLayouts(name string, d interface{}, w io.Writer, layouts ...string) error { - templ := s.findFirstTemplate(layouts...) - if templ == nil { + layout, found := s.findFirstLayout(layouts...) + if !found { helpers.DistinctWarnLog.Printf("[%s] Unable to locate layout for %s: %s\n", s.Language.Lang, name, layouts) - return nil } - if err := templ.Execute(w, d); err != nil { + if err := s.renderThing(d, layout, w); err != nil { // Behavior here should be dependent on if running in server or watch mode. helpers.DistinctErrorLog.Printf("Error while rendering %q: %s", name, err) @@ -1928,13 +1927,23 @@ func (s *Site) renderForLayouts(name string, d interface{}, w io.Writer, layouts return nil } -func (s *Site) findFirstTemplate(layouts ...string) tpl.Template { +func (s *Site) findFirstLayout(layouts ...string) (string, bool) { for _, layout := range layouts { - if templ := s.Tmpl.Lookup(layout); templ != nil { - return templ + if s.Tmpl.Lookup(layout) != nil { + return layout, true } } - return nil + return "", false +} + +func (s *Site) renderThing(d interface{}, layout string, w io.Writer) error { + + // If the template doesn't exist, then return, but leave the Writer open + if templ := s.Tmpl.Lookup(layout); templ != nil { + return templ.Execute(w, d) + } + return fmt.Errorf("Layout not found: %s", layout) + } func (s *Site) publish(path string, r io.Reader) (err error) { diff --git a/hugolib/site_output_test.go b/hugolib/site_output_test.go index 06c55a69c..86e1a55ca 100644 --- a/hugolib/site_output_test.go +++ b/hugolib/site_output_test.go @@ -90,15 +90,9 @@ outputs: %s Alt Output: {{ .Name -}}| {{- end -}}| {{- range .OutputFormats -}} -Output/Rel: {{ .Name -}}/{{ .Rel }}|{{ .MediaType }} +Output/Rel: {{ .Name -}}/{{ .Rel }}| {{- end -}} - {{ with .OutputFormats.Get "JSON" }} -<atom:link href={{ .Permalink }} rel="self" type="{{ .MediaType }}" /> -{{ end }} `, - "layouts/_default/list.html", `List HTML|{{ with .OutputFormats.Get "HTML" -}} -<atom:link href={{ .Permalink }} rel="self" type="{{ .MediaType }}" /> -{{- end -}}`, ) require.Len(t, h.Sites, 1) @@ -119,6 +113,7 @@ Output/Rel: {{ .Name -}}/{{ .Rel }}|{{ .MediaType }} require.Len(t, home.outputFormats, lenOut) + // TODO(bep) output assert template/text // There is currently always a JSON output to make it simpler ... altFormats := lenOut - 1 hasHTML := helpers.InStringArray(outputs, "html") @@ -133,16 +128,9 @@ Output/Rel: {{ .Name -}}/{{ .Rel }}|{{ .MediaType }} "Output/Rel: JSON/alternate|", "Output/Rel: HTML/canonical|", ) - th.assertFileContent("public/index.html", - // The HTML entity is a deliberate part of this test: The HTML templates are - // parsed with html/template. - `List HTML|<atom:link href=http://example.com/blog/ rel="self" type="text/html+html" />`, - ) } else { th.assertFileContent("public/index.json", "Output/Rel: JSON/canonical|", - // JSON is plain text, so no need to safeHTML this and that - `<atom:link href=http://example.com/blog/index.json rel="self" type="application/json+json" />`, ) } diff --git a/hugolib/site_test.go b/hugolib/site_test.go index 5f66b153c..a3ec66880 100644 --- a/hugolib/site_test.go +++ b/hugolib/site_test.go @@ -52,6 +52,24 @@ func pageMust(p *Page, err error) *Page { return p } +func TestDegenerateRenderThingMissingTemplate(t *testing.T) { + t.Parallel() + cfg, fs := newTestCfg() + + writeSource(t, fs, filepath.Join("content", "a", "file.md"), pageSimpleTitle) + + s := buildSingleSite(t, deps.DepsCfg{Fs: fs, Cfg: cfg}, BuildCfg{}) + + require.Len(t, s.RegularPages, 1) + + p := s.RegularPages[0] + + err := s.renderThing(p, "foobar", nil) + if err == nil { + t.Errorf("Expected err to be returned when missing the template.") + } +} + func TestRenderWithInvalidTemplate(t *testing.T) { t.Parallel() cfg, fs := newTestCfg() diff --git a/hugolib/sitemap_test.go b/hugolib/sitemap_test.go index 47f29c947..df342953b 100644 --- a/hugolib/sitemap_test.go +++ b/hugolib/sitemap_test.go @@ -48,7 +48,7 @@ func doTestSitemapOutput(t *testing.T, internal bool) { depsCfg := deps.DepsCfg{Fs: fs, Cfg: cfg} if !internal { - depsCfg.WithTemplate = func(templ tpl.TemplateHandler) error { + depsCfg.WithTemplate = func(templ tpl.Template) error { templ.AddTemplate("sitemap.xml", sitemapTemplate) return nil } diff --git a/hugolib/testhelpers_test.go b/hugolib/testhelpers_test.go index fbaab7192..d50514529 100644 --- a/hugolib/testhelpers_test.go +++ b/hugolib/testhelpers_test.go @@ -164,9 +164,9 @@ func newDebugLogger() *jww.Notepad { func newErrorLogger() *jww.Notepad { return jww.NewNotepad(jww.LevelError, jww.LevelError, os.Stdout, ioutil.Discard, "", log.Ldate|log.Ltime) } -func createWithTemplateFromNameValues(additionalTemplates ...string) func(templ tpl.TemplateHandler) error { +func createWithTemplateFromNameValues(additionalTemplates ...string) func(templ tpl.Template) error { - return func(templ tpl.TemplateHandler) error { + return func(templ tpl.Template) error { for i := 0; i < len(additionalTemplates); i += 2 { err := templ.AddTemplate(additionalTemplates[i], additionalTemplates[i+1]) if err != nil { |