Fail on partials with return when given none or a zero argument

We need to make a proper fix for this, but it is better with an error than just silently continue.

Fixes #7572
Updates #7528
This commit is contained in:
Bjørn Erik Pedersen 2020-08-19 09:15:14 +02:00
parent e627449c0a
commit ae63c2b5c9
No known key found for this signature in database
GPG key ID: 330E6E2BD4859D8F
2 changed files with 71 additions and 33 deletions

View file

@ -424,17 +424,11 @@ Hugo: {{ hugo.Generator }}
func TestPartialWithReturn(t *testing.T) { func TestPartialWithReturn(t *testing.T) {
c := qt.New(t)
newBuilder := func(t testing.TB) *sitesBuilder {
b := newTestSitesBuilder(t).WithSimpleConfigFile() b := newTestSitesBuilder(t).WithSimpleConfigFile()
b.WithTemplatesAdded( b.WithTemplatesAdded(
"index.html", `
Test Partials With Return Values:
add42: 50: {{ partial "add42.tpl" 8 }}
dollarContext: 60: {{ partial "dollarContext.tpl" 18 }}
adder: 70: {{ partial "dict.tpl" (dict "adder" 28) }}
complex: 80: {{ partial "complex.tpl" 38 }}
`,
"partials/add42.tpl", ` "partials/add42.tpl", `
{{ $v := add . 42 }} {{ $v := add . 42 }}
{{ return $v }} {{ return $v }}
@ -449,18 +443,61 @@ complex: 80: {{ partial "complex.tpl" 38 }}
`, `,
"partials/complex.tpl", ` "partials/complex.tpl", `
{{ return add . 42 }} {{ return add . 42 }}
`, "partials/hello.tpl", `
{{ $v := printf "hello %s" . }}
{{ return $v }}
`,
)
return b
}
c.Run("Return", func(c *qt.C) {
b := newBuilder(c)
b.WithTemplatesAdded(
"index.html", `
Test Partials With Return Values:
add42: 50: {{ partial "add42.tpl" 8 }}
hello world: {{ partial "hello.tpl" "world" }}
dollarContext: 60: {{ partial "dollarContext.tpl" 18 }}
adder: 70: {{ partial "dict.tpl" (dict "adder" 28) }}
complex: 80: {{ partial "complex.tpl" 38 }}
`, `,
) )
b.CreateSites().Build(BuildCfg{}) b.CreateSites().Build(BuildCfg{})
b.AssertFileContent("public/index.html", b.AssertFileContent("public/index.html", `
"add42: 50: 50", add42: 50: 50
"dollarContext: 60: 60", hello world: hello world
"adder: 70: 70", dollarContext: 60: 60
"complex: 80: 80", adder: 70: 70
complex: 80: 80
`,
) )
})
c.Run("Zero argument", func(c *qt.C) {
b := newBuilder(c)
b.WithTemplatesAdded(
"index.html", `
Test Partials With Return Values:
add42: fail: {{ partial "add42.tpl" 0 }}
`,
)
e := b.CreateSites().BuildE(BuildCfg{})
b.Assert(e, qt.Not(qt.IsNil))
})
} }
func TestPartialCached(t *testing.T) { func TestPartialCached(t *testing.T) {

View file

@ -25,6 +25,7 @@ import (
"strings" "strings"
"sync" "sync"
"github.com/gohugoio/hugo/common/hreflect"
texttemplate "github.com/gohugoio/hugo/tpl/internal/go_templates/texttemplate" texttemplate "github.com/gohugoio/hugo/tpl/internal/go_templates/texttemplate"
"github.com/gohugoio/hugo/helpers" "github.com/gohugoio/hugo/helpers"
@ -93,14 +94,10 @@ func (c *contextWrapper) Set(in interface{}) string {
// Else, the rendered output will be returned: // Else, the rendered output will be returned:
// A string if the partial is a text/template, or template.HTML when html/template. // A string if the partial is a text/template, or template.HTML when html/template.
func (ns *Namespace) Include(name string, contextList ...interface{}) (interface{}, error) { func (ns *Namespace) Include(name string, contextList ...interface{}) (interface{}, error) {
if strings.HasPrefix(name, "partials/") { name = strings.TrimPrefix(name, "partials/")
name = name[8:]
}
var context interface{}
if len(contextList) == 0 { var context interface{}
context = nil if len(contextList) > 0 {
} else {
context = contextList[0] context = contextList[0]
} }
@ -124,6 +121,10 @@ func (ns *Namespace) Include(name string, contextList ...interface{}) (interface
var w io.Writer var w io.Writer
if info.HasReturn { if info.HasReturn {
if !hreflect.IsTruthful(context) {
// TODO(bep) we need to fix this, but it is non-trivial.
return nil, errors.New("partials that returns a value needs a non-zero argument.")
}
// Wrap the context sent to the template to capture the return value. // Wrap the context sent to the template to capture the return value.
// Note that the template is rewritten to make sure that the dot (".") // Note that the template is rewritten to make sure that the dot (".")
// and the $ variable points to Arg. // and the $ variable points to Arg.