Fix error handling for the time func alias

Fixes #8835
This commit is contained in:
Bjørn Erik Pedersen 2021-08-01 12:50:37 +02:00
parent 4d221ce468
commit 6c70e1f22f
53 changed files with 122 additions and 65 deletions

View file

@ -203,3 +203,14 @@ timeZone = "America/LosAngeles" # Should be America/Los_Angeles
b.Assert(err, qt.Not(qt.IsNil)) b.Assert(err, qt.Not(qt.IsNil))
b.Assert(err.Error(), qt.Contains, `failed to load config: invalid timeZone for language "en": unknown time zone America/LosAngeles`) b.Assert(err.Error(), qt.Contains, `failed to load config: invalid timeZone for language "en": unknown time zone America/LosAngeles`)
} }
// Issue 8835
func TestTimeOnError(t *testing.T) {
b := newTestSitesBuilder(t)
b.WithTemplates("index.html", `time: {{ time "2020-10-20" "invalid-timezone" }}`)
b.WithContent("p1.md", "")
b.Assert(b.BuildE(BuildCfg{}), qt.Not(qt.IsNil))
}

View file

@ -26,7 +26,7 @@ func init() {
ns := &internal.TemplateFuncsNamespace{ ns := &internal.TemplateFuncsNamespace{
Name: name, Name: name,
Context: func(args ...interface{}) interface{} { return ctx }, Context: func(args ...interface{}) (interface{}, error) { return ctx, nil },
} }
ns.AddMethodMapping(ctx.ToInt, ns.AddMethodMapping(ctx.ToInt,

View file

@ -37,5 +37,7 @@ func TestInit(t *testing.T) {
} }
c.Assert(found, qt.Equals, true) c.Assert(found, qt.Equals, true)
c.Assert(ns.Context(), hqt.IsSameType, &Namespace{}) ctx, err := ns.Context()
c.Assert(err, qt.IsNil)
c.Assert(ctx, hqt.IsSameType, &Namespace{})
} }

View file

@ -26,7 +26,7 @@ func init() {
ns := &internal.TemplateFuncsNamespace{ ns := &internal.TemplateFuncsNamespace{
Name: name, Name: name,
Context: func(args ...interface{}) interface{} { return ctx }, Context: func(args ...interface{}) (interface{}, error) { return ctx, nil },
} }
ns.AddMethodMapping(ctx.After, ns.AddMethodMapping(ctx.After,

View file

@ -37,5 +37,7 @@ func TestInit(t *testing.T) {
} }
c.Assert(found, qt.Equals, true) c.Assert(found, qt.Equals, true)
c.Assert(ns.Context(), hqt.IsSameType, &Namespace{}) ctx, err := ns.Context()
c.Assert(err, qt.IsNil)
c.Assert(ctx, hqt.IsSameType, &Namespace{})
} }

View file

@ -26,7 +26,7 @@ func init() {
ns := &internal.TemplateFuncsNamespace{ ns := &internal.TemplateFuncsNamespace{
Name: name, Name: name,
Context: func(args ...interface{}) interface{} { return ctx }, Context: func(args ...interface{}) (interface{}, error) { return ctx, nil },
} }
ns.AddMethodMapping(ctx.Default, ns.AddMethodMapping(ctx.Default,

View file

@ -36,5 +36,7 @@ func TestInit(t *testing.T) {
} }
c.Assert(found, qt.Equals, true) c.Assert(found, qt.Equals, true)
c.Assert(ns.Context(), hqt.IsSameType, &Namespace{}) ctx, err := ns.Context()
c.Assert(err, qt.IsNil)
c.Assert(ctx, hqt.IsSameType, &Namespace{})
} }

View file

@ -26,7 +26,7 @@ func init() {
ns := &internal.TemplateFuncsNamespace{ ns := &internal.TemplateFuncsNamespace{
Name: name, Name: name,
Context: func(args ...interface{}) interface{} { return ctx }, Context: func(args ...interface{}) (interface{}, error) { return ctx, nil },
} }
ns.AddMethodMapping(ctx.MD5, ns.AddMethodMapping(ctx.MD5,

View file

@ -36,5 +36,7 @@ func TestInit(t *testing.T) {
} }
c.Assert(found, qt.Equals, true) c.Assert(found, qt.Equals, true)
c.Assert(ns.Context(), hqt.IsSameType, &Namespace{}) ctx, err := ns.Context()
c.Assert(err, qt.IsNil)
c.Assert(ctx, hqt.IsSameType, &Namespace{})
} }

View file

@ -26,7 +26,7 @@ func init() {
ns := &internal.TemplateFuncsNamespace{ ns := &internal.TemplateFuncsNamespace{
Name: name, Name: name,
Context: func(args ...interface{}) interface{} { return ctx }, Context: func(args ...interface{}) (interface{}, error) { return ctx, nil },
} }
ns.AddMethodMapping(ctx.GetCSV, ns.AddMethodMapping(ctx.GetCSV,

View file

@ -41,5 +41,7 @@ func TestInit(t *testing.T) {
} }
c.Assert(found, qt.Equals, true) c.Assert(found, qt.Equals, true)
c.Assert(ns.Context(), hqt.IsSameType, &Namespace{}) ctx, err := ns.Context()
c.Assert(err, qt.IsNil)
c.Assert(ctx, hqt.IsSameType, &Namespace{})
} }

View file

@ -26,7 +26,7 @@ func init() {
ns := &internal.TemplateFuncsNamespace{ ns := &internal.TemplateFuncsNamespace{
Name: name, Name: name,
Context: func(args ...interface{}) interface{} { return ctx }, Context: func(args ...interface{}) (interface{}, error) { return ctx, nil },
} }
ns.AddMethodMapping(ctx.Dump, ns.AddMethodMapping(ctx.Dump,

View file

@ -38,5 +38,7 @@ func TestInit(t *testing.T) {
} }
c.Assert(found, qt.Equals, true) c.Assert(found, qt.Equals, true)
c.Assert(ns.Context(), hqt.IsSameType, &Namespace{}) ctx, err := ns.Context()
c.Assert(err, qt.IsNil)
c.Assert(ctx, hqt.IsSameType, &Namespace{})
} }

View file

@ -26,7 +26,7 @@ func init() {
ns := &internal.TemplateFuncsNamespace{ ns := &internal.TemplateFuncsNamespace{
Name: name, Name: name,
Context: func(args ...interface{}) interface{} { return ctx }, Context: func(args ...interface{}) (interface{}, error) { return ctx, nil },
} }
ns.AddMethodMapping(ctx.Base64Decode, ns.AddMethodMapping(ctx.Base64Decode,

View file

@ -36,5 +36,7 @@ func TestInit(t *testing.T) {
} }
c.Assert(found, qt.Equals, true) c.Assert(found, qt.Equals, true)
c.Assert(ns.Context(), hqt.IsSameType, &Namespace{}) ctx, err := ns.Context()
c.Assert(err, qt.IsNil)
c.Assert(ctx, hqt.IsSameType, &Namespace{})
} }

View file

@ -26,7 +26,7 @@ func init() {
ns := &internal.TemplateFuncsNamespace{ ns := &internal.TemplateFuncsNamespace{
Name: name, Name: name,
Context: func(args ...interface{}) interface{} { return ctx }, Context: func(args ...interface{}) (interface{}, error) { return ctx, nil },
} }
ns.AddMethodMapping(ctx.Print, ns.AddMethodMapping(ctx.Print,

View file

@ -38,5 +38,7 @@ func TestInit(t *testing.T) {
} }
c.Assert(found, qt.Equals, true) c.Assert(found, qt.Equals, true)
c.Assert(ns.Context(), hqt.IsSameType, &Namespace{}) ctx, err := ns.Context()
c.Assert(err, qt.IsNil)
c.Assert(ctx, hqt.IsSameType, &Namespace{})
} }

View file

@ -27,7 +27,7 @@ func init() {
ns := &internal.TemplateFuncsNamespace{ ns := &internal.TemplateFuncsNamespace{
Name: name, Name: name,
Context: func(args ...interface{}) interface{} { return h }, Context: func(args ...interface{}) (interface{}, error) { return h, nil },
} }
// We just add the Hugo struct as the namespace here. No method mappings. // We just add the Hugo struct as the namespace here. No method mappings.

View file

@ -43,5 +43,7 @@ func TestInit(t *testing.T) {
} }
c.Assert(found, qt.Equals, true) c.Assert(found, qt.Equals, true)
c.Assert(ns.Context(), hqt.IsSameType, s.Hugo()) ctx, err := ns.Context()
c.Assert(err, qt.IsNil)
c.Assert(ctx, hqt.IsSameType, s.Hugo())
} }

View file

@ -26,7 +26,7 @@ func init() {
ns := &internal.TemplateFuncsNamespace{ ns := &internal.TemplateFuncsNamespace{
Name: name, Name: name,
Context: func(args ...interface{}) interface{} { return ctx }, Context: func(args ...interface{}) (interface{}, error) { return ctx, nil },
} }
ns.AddMethodMapping(ctx.Config, ns.AddMethodMapping(ctx.Config,

View file

@ -36,5 +36,7 @@ func TestInit(t *testing.T) {
} }
c.Assert(found, qt.Equals, true) c.Assert(found, qt.Equals, true)
c.Assert(ns.Context(), hqt.IsSameType, &Namespace{}) ctx, err := ns.Context()
c.Assert(err, qt.IsNil)
c.Assert(ctx, hqt.IsSameType, &Namespace{})
} }

View file

@ -26,7 +26,7 @@ func init() {
ns := &internal.TemplateFuncsNamespace{ ns := &internal.TemplateFuncsNamespace{
Name: name, Name: name,
Context: func(args ...interface{}) interface{} { return ctx }, Context: func(args ...interface{}) (interface{}, error) { return ctx, nil },
} }
ns.AddMethodMapping(ctx.Humanize, ns.AddMethodMapping(ctx.Humanize,

View file

@ -37,5 +37,7 @@ func TestInit(t *testing.T) {
} }
c.Assert(found, qt.Equals, true) c.Assert(found, qt.Equals, true)
c.Assert(ns.Context(), hqt.IsSameType, &Namespace{}) ctx, err := ns.Context()
c.Assert(err, qt.IsNil)
c.Assert(ctx, hqt.IsSameType, &Namespace{})
} }

View file

@ -49,7 +49,7 @@ type TemplateFuncsNamespace struct {
Name string Name string
// This is the method receiver. // This is the method receiver.
Context func(v ...interface{}) interface{} Context func(v ...interface{}) (interface{}, error)
// Additional info, aliases and examples, per method name. // Additional info, aliases and examples, per method name.
MethodMappings map[string]TemplateFuncMethodMapping MethodMappings map[string]TemplateFuncMethodMapping
@ -172,7 +172,10 @@ func (t *TemplateFuncsNamespace) toJSON() ([]byte, error) {
buf.WriteString(fmt.Sprintf(`%q: {`, t.Name)) buf.WriteString(fmt.Sprintf(`%q: {`, t.Name))
ctx := t.Context() ctx, err := t.Context()
if err != nil {
return nil, err
}
ctxType := reflect.TypeOf(ctx) ctxType := reflect.TypeOf(ctx)
for i := 0; i < ctxType.NumMethod(); i++ { for i := 0; i < ctxType.NumMethod(); i++ {
method := ctxType.Method(i) method := ctxType.Method(i)

View file

@ -26,7 +26,7 @@ func init() {
ns := &internal.TemplateFuncsNamespace{ ns := &internal.TemplateFuncsNamespace{
Name: name, Name: name,
Context: func(args ...interface{}) interface{} { return ctx }, Context: func(args ...interface{}) (interface{}, error) { return ctx, nil },
} }
return ns return ns

View file

@ -27,7 +27,7 @@ func init() {
ns := &internal.TemplateFuncsNamespace{ ns := &internal.TemplateFuncsNamespace{
Name: name, Name: name,
Context: func(args ...interface{}) interface{} { return ctx }, Context: func(args ...interface{}) (interface{}, error) { return ctx, nil },
} }
ns.AddMethodMapping(ctx.Translate, ns.AddMethodMapping(ctx.Translate,

View file

@ -42,5 +42,7 @@ func TestInit(t *testing.T) {
} }
c.Assert(found, qt.Equals, true) c.Assert(found, qt.Equals, true)
c.Assert(ns.Context(), hqt.IsSameType, &Namespace{}) ctx, err := ns.Context()
c.Assert(err, qt.IsNil)
c.Assert(ctx, hqt.IsSameType, &Namespace{})
} }

View file

@ -26,7 +26,7 @@ func init() {
ns := &internal.TemplateFuncsNamespace{ ns := &internal.TemplateFuncsNamespace{
Name: name, Name: name,
Context: func(args ...interface{}) interface{} { return ctx }, Context: func(args ...interface{}) (interface{}, error) { return ctx, nil },
} }
ns.AddMethodMapping(ctx.Add, ns.AddMethodMapping(ctx.Add,

View file

@ -36,5 +36,7 @@ func TestInit(t *testing.T) {
} }
c.Assert(found, qt.Equals, true) c.Assert(found, qt.Equals, true)
c.Assert(ns.Context(), hqt.IsSameType, &Namespace{}) ctx, err := ns.Context()
c.Assert(err, qt.IsNil)
c.Assert(ctx, hqt.IsSameType, &Namespace{})
} }

View file

@ -26,7 +26,7 @@ func init() {
ns := &internal.TemplateFuncsNamespace{ ns := &internal.TemplateFuncsNamespace{
Name: name, Name: name,
Context: func(args ...interface{}) interface{} { return ctx }, Context: func(args ...interface{}) (interface{}, error) { return ctx, nil },
} }
ns.AddMethodMapping(ctx.Unmarshal, ns.AddMethodMapping(ctx.Unmarshal,

View file

@ -26,7 +26,7 @@ func init() {
ns := &internal.TemplateFuncsNamespace{ ns := &internal.TemplateFuncsNamespace{
Name: name, Name: name,
Context: func(args ...interface{}) interface{} { return ctx }, Context: func(args ...interface{}) (interface{}, error) { return ctx, nil },
} }
ns.AddMethodMapping(ctx.Getenv, ns.AddMethodMapping(ctx.Getenv,

View file

@ -36,5 +36,7 @@ func TestInit(t *testing.T) {
} }
c.Assert(found, qt.Equals, true) c.Assert(found, qt.Equals, true)
c.Assert(ns.Context(), hqt.IsSameType, &Namespace{}) ctx, err := ns.Context()
c.Assert(err, qt.IsNil)
c.Assert(ctx, hqt.IsSameType, &Namespace{})
} }

View file

@ -26,7 +26,7 @@ func init() {
ns := &internal.TemplateFuncsNamespace{ ns := &internal.TemplateFuncsNamespace{
Name: name, Name: name,
Context: func(args ...interface{}) interface{} { return ctx }, Context: func(args ...interface{}) (interface{}, error) { return ctx, nil },
} }
ns.AddMethodMapping(ctx.Include, ns.AddMethodMapping(ctx.Include,

View file

@ -40,5 +40,7 @@ func TestInit(t *testing.T) {
} }
c.Assert(found, qt.Equals, true) c.Assert(found, qt.Equals, true)
c.Assert(ns.Context(), hqt.IsSameType, &Namespace{}) ctx, err := ns.Context()
c.Assert(err, qt.IsNil)
c.Assert(ctx, hqt.IsSameType, &Namespace{})
} }

View file

@ -29,7 +29,7 @@ func init() {
ns := &internal.TemplateFuncsNamespace{ ns := &internal.TemplateFuncsNamespace{
Name: name, Name: name,
Context: func(args ...interface{}) interface{} { return ctx }, Context: func(args ...interface{}) (interface{}, error) { return ctx, nil },
} }
ns.AddMethodMapping(ctx.Split, ns.AddMethodMapping(ctx.Split,

View file

@ -37,5 +37,7 @@ func TestInit(t *testing.T) {
} }
c.Assert(found, qt.Equals, true) c.Assert(found, qt.Equals, true)
c.Assert(ns.Context(), hqt.IsSameType, &Namespace{}) ctx, err := ns.Context()
c.Assert(err, qt.IsNil)
c.Assert(ctx, hqt.IsSameType, &Namespace{})
} }

View file

@ -27,7 +27,7 @@ func init() {
ns := &internal.TemplateFuncsNamespace{ ns := &internal.TemplateFuncsNamespace{
Name: name, Name: name,
Context: func(args ...interface{}) interface{} { return ctx }, Context: func(args ...interface{}) (interface{}, error) { return ctx, nil },
} }
ns.AddMethodMapping(ctx.IsMap, ns.AddMethodMapping(ctx.IsMap,

View file

@ -37,5 +37,7 @@ func TestInit(t *testing.T) {
} }
c.Assert(found, qt.Equals, true) c.Assert(found, qt.Equals, true)
c.Assert(ns.Context(), hqt.IsSameType, &Namespace{}) ctx, err := ns.Context()
c.Assert(err, qt.IsNil)
c.Assert(ctx, hqt.IsSameType, &Namespace{})
} }

View file

@ -30,7 +30,7 @@ func init() {
ns := &internal.TemplateFuncsNamespace{ ns := &internal.TemplateFuncsNamespace{
Name: name, Name: name,
Context: func(args ...interface{}) interface{} { return ctx }, Context: func(args ...interface{}) (interface{}, error) { return ctx, nil },
} }
ns.AddMethodMapping(ctx.Get, ns.AddMethodMapping(ctx.Get,

View file

@ -26,7 +26,7 @@ func init() {
ns := &internal.TemplateFuncsNamespace{ ns := &internal.TemplateFuncsNamespace{
Name: name, Name: name,
Context: func(args ...interface{}) interface{} { return ctx }, Context: func(args ...interface{}) (interface{}, error) { return ctx, nil },
} }
ns.AddMethodMapping(ctx.CSS, ns.AddMethodMapping(ctx.CSS,

View file

@ -37,5 +37,7 @@ func TestInit(t *testing.T) {
} }
c.Assert(found, qt.Equals, true) c.Assert(found, qt.Equals, true)
c.Assert(ns.Context(), hqt.IsSameType, &Namespace{}) ctx, err := ns.Context()
c.Assert(err, qt.IsNil)
c.Assert(ctx, hqt.IsSameType, &Namespace{})
} }

View file

@ -27,7 +27,7 @@ func init() {
s := d.Site s := d.Site
ns := &internal.TemplateFuncsNamespace{ ns := &internal.TemplateFuncsNamespace{
Name: name, Name: name,
Context: func(args ...interface{}) interface{} { return s }, Context: func(args ...interface{}) (interface{}, error) { return s, nil },
} }
if s == nil { if s == nil {

View file

@ -43,5 +43,7 @@ func TestInit(t *testing.T) {
} }
c.Assert(found, qt.Equals, true) c.Assert(found, qt.Equals, true)
c.Assert(ns.Context(), hqt.IsSameType, s) ctx, err := ns.Context()
c.Assert(err, qt.IsNil)
c.Assert(ctx, hqt.IsSameType, s)
} }

View file

@ -26,7 +26,7 @@ func init() {
ns := &internal.TemplateFuncsNamespace{ ns := &internal.TemplateFuncsNamespace{
Name: name, Name: name,
Context: func(args ...interface{}) interface{} { return ctx }, Context: func(args ...interface{}) (interface{}, error) { return ctx, nil },
} }
ns.AddMethodMapping(ctx.Chomp, ns.AddMethodMapping(ctx.Chomp,

View file

@ -39,5 +39,7 @@ func TestInit(t *testing.T) {
} }
c.Assert(found, qt.Equals, true) c.Assert(found, qt.Equals, true)
c.Assert(ns.Context(), hqt.IsSameType, &Namespace{}) ctx, err := ns.Context()
c.Assert(err, qt.IsNil)
c.Assert(ctx, hqt.IsSameType, &Namespace{})
} }

View file

@ -26,7 +26,7 @@ func init() {
ns := &internal.TemplateFuncsNamespace{ ns := &internal.TemplateFuncsNamespace{
Name: name, Name: name,
Context: func(args ...interface{}) interface{} { return ctx }, Context: func(args ...interface{}) (interface{}, error) { return ctx, nil },
} }
ns.AddMethodMapping(ctx.Exists, ns.AddMethodMapping(ctx.Exists,

View file

@ -36,5 +36,7 @@ func TestInit(t *testing.T) {
} }
c.Assert(found, qt.Equals, true) c.Assert(found, qt.Equals, true)
c.Assert(ns.Context(), hqt.IsSameType, &Namespace{}) ctx, err := ns.Context()
c.Assert(err, qt.IsNil)
c.Assert(ctx, hqt.IsSameType, &Namespace{})
} }

View file

@ -14,6 +14,8 @@
package time package time
import ( import (
"errors"
"github.com/gohugoio/hugo/deps" "github.com/gohugoio/hugo/deps"
"github.com/gohugoio/hugo/langs" "github.com/gohugoio/hugo/langs"
"github.com/gohugoio/hugo/tpl/internal" "github.com/gohugoio/hugo/tpl/internal"
@ -30,7 +32,7 @@ func init() {
ns := &internal.TemplateFuncsNamespace{ ns := &internal.TemplateFuncsNamespace{
Name: name, Name: name,
Context: func(args ...interface{}) interface{} { Context: func(args ...interface{}) (interface{}, error) {
// Handle overlapping "time" namespace and func. // Handle overlapping "time" namespace and func.
// //
// If no args are passed to `time`, assume namespace usage and // If no args are passed to `time`, assume namespace usage and
@ -40,23 +42,15 @@ func init() {
switch len(args) { switch len(args) {
case 0: case 0:
return ctx return ctx, nil
case 1: case 1:
t, err := ctx.AsTime(args[0]) return ctx.AsTime(args[0])
if err != nil {
return err
}
return t
case 2: case 2:
t, err := ctx.AsTime(args[0], args[1]) return ctx.AsTime(args[0], args[1])
if err != nil {
return err
}
return t
// 3 or more arguments. Currently not supported. // 3 or more arguments. Currently not supported.
default: default:
return "Invalid arguments supplied to `time`. Refer to time documentation: https://gohugo.io/functions/time/" return nil, errors.New("Invalid arguments supplied to `time`. Refer to time documentation: https://gohugo.io/functions/time/")
} }
}, },
} }

View file

@ -42,5 +42,7 @@ func TestInit(t *testing.T) {
} }
c.Assert(found, qt.Equals, true) c.Assert(found, qt.Equals, true)
c.Assert(ns.Context(), hqt.IsSameType, &Namespace{}) ctx, err := ns.Context()
c.Assert(err, qt.IsNil)
c.Assert(ctx, hqt.IsSameType, &Namespace{})
} }

View file

@ -26,7 +26,7 @@ func init() {
ns := &internal.TemplateFuncsNamespace{ ns := &internal.TemplateFuncsNamespace{
Name: name, Name: name,
Context: func(args ...interface{}) interface{} { return ctx }, Context: func(args ...interface{}) (interface{}, error) { return ctx, nil },
} }
ns.AddMethodMapping(ctx.Emojify, ns.AddMethodMapping(ctx.Emojify,

View file

@ -36,5 +36,7 @@ func TestInit(t *testing.T) {
} }
c.Assert(found, qt.Equals, true) c.Assert(found, qt.Equals, true)
c.Assert(ns.Context(), hqt.IsSameType, &Namespace{}) ctx, err := ns.Context()
c.Assert(err, qt.IsNil)
c.Assert(ctx, hqt.IsSameType, &Namespace{})
} }

View file

@ -26,7 +26,7 @@ func init() {
ns := &internal.TemplateFuncsNamespace{ ns := &internal.TemplateFuncsNamespace{
Name: name, Name: name,
Context: func(args ...interface{}) interface{} { return ctx }, Context: func(args ...interface{}) (interface{}, error) { return ctx, nil },
} }
ns.AddMethodMapping(ctx.AbsURL, ns.AddMethodMapping(ctx.AbsURL,

View file

@ -38,5 +38,8 @@ func TestInit(t *testing.T) {
} }
c.Assert(found, qt.Equals, true) c.Assert(found, qt.Equals, true)
c.Assert(ns.Context(), hqt.IsSameType, &Namespace{}) ctx, err := ns.Context()
c.Assert(err, qt.IsNil)
c.Assert(ctx, hqt.IsSameType, &Namespace{})
} }