Fail on partials with return when given none or a zero argument
authorBjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>
Wed, 19 Aug 2020 07:15:14 +0000 (09:15 +0200)
committerBjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>
Wed, 19 Aug 2020 08:01:16 +0000 (10:01 +0200)
We need to make a proper fix for this, but it is better with an error than just silently continue.

Fixes #7572
Updates #7528

hugolib/template_test.go
tpl/partials/partials.go

index a215f09dcf3bd714825296d19dd2cfdb2ba199c8..6f37b416485a29ffc80848b6dbfdb59f7c7dc945 100644 (file)
@@ -424,42 +424,79 @@ Hugo: {{ hugo.Generator }}
 
 func TestPartialWithReturn(t *testing.T) {
 
-       b := newTestSitesBuilder(t).WithSimpleConfigFile()
-
-       b.WithTemplatesAdded(
-               "index.html", `
-Test Partials With Return Values:
+       c := qt.New(t)
 
-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", `
+       newBuilder := func(t testing.TB) *sitesBuilder {
+               b := newTestSitesBuilder(t).WithSimpleConfigFile()
+               b.WithTemplatesAdded(
+                       "partials/add42.tpl", `
                {{ $v := add . 42 }}
                {{ return $v }}
                `,
-               "partials/dollarContext.tpl", `
+                       "partials/dollarContext.tpl", `
 {{ $v := add $ 42 }}
 {{ return $v }}
 `,
-               "partials/dict.tpl", `
+                       "partials/dict.tpl", `
 {{ $v := add $.adder 42 }}
 {{ return $v }}
 `,
-               "partials/complex.tpl", `
+                       "partials/complex.tpl", `
 {{ 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",
-               "add42: 50: 50",
-               "dollarContext: 60: 60",
-               "adder: 70: 70",
-               "complex: 80: 80",
-       )
+               b.AssertFileContent("public/index.html", `
+add42: 50: 50
+hello world: hello world
+dollarContext: 60: 60
+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))
+
+       })
 
 }
 
index e03bf471fa871c28c1ff9d678f3a2cc0bf436a2a..648a9368644e6e769f3fa14f846c5e5a7796fea4 100644 (file)
@@ -25,6 +25,7 @@ import (
        "strings"
        "sync"
 
+       "github.com/gohugoio/hugo/common/hreflect"
        texttemplate "github.com/gohugoio/hugo/tpl/internal/go_templates/texttemplate"
 
        "github.com/gohugoio/hugo/helpers"
@@ -93,14 +94,10 @@ func (c *contextWrapper) Set(in interface{}) string {
 // Else, the rendered output will be returned:
 // 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) {
-       if strings.HasPrefix(name, "partials/") {
-               name = name[8:]
-       }
-       var context interface{}
+       name = strings.TrimPrefix(name, "partials/")
 
-       if len(contextList) == 0 {
-               context = nil
-       } else {
+       var context interface{}
+       if len(contextList) > 0 {
                context = contextList[0]
        }
 
@@ -124,6 +121,10 @@ func (ns *Namespace) Include(name string, contextList ...interface{}) (interface
        var w io.Writer
 
        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.
                // Note that the template is rewritten to make sure that the dot (".")
                // and the $ variable points to Arg.