Skip to content

Commit eef95a1

Browse files
committed
Add try
Updates gohugoio#9737
1 parent d913f46 commit eef95a1

File tree

4 files changed

+62
-2
lines changed

4 files changed

+62
-2
lines changed

tpl/internal/go_templates/texttemplate/hugo_template.go

+24-1
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ package template
1515

1616
import (
1717
"context"
18+
"fmt"
1819
"io"
1920
"reflect"
2021

@@ -255,10 +256,27 @@ func (s *state) evalField(dot reflect.Value, fieldName string, node parse.Node,
255256
panic("not reached")
256257
}
257258

259+
type TryValue struct {
260+
Value any
261+
Err error
262+
}
263+
258264
// evalCall executes a function or method call. If it's a method, fun already has the receiver bound, so
259265
// it looks just like a function call. The arg list, if non-nil, includes (in the manner of the shell), arg[0]
260266
// as the function itself.
261-
func (s *state) evalCall(dot, fun reflect.Value, isBuiltin bool, node parse.Node, name string, args []parse.Node, final reflect.Value, first ...reflect.Value) reflect.Value {
267+
func (s *state) evalCall(dot, fun reflect.Value, isBuiltin bool, node parse.Node, name string, args []parse.Node, final reflect.Value, first ...reflect.Value) (val reflect.Value) {
268+
// Added for Hugo.
269+
if name == "try" {
270+
defer func() {
271+
if r := recover(); r != nil {
272+
if err, ok := r.(error); ok {
273+
val = reflect.ValueOf(TryValue{nil, err})
274+
} else {
275+
val = reflect.ValueOf(TryValue{nil, fmt.Errorf("%v", r)})
276+
}
277+
}
278+
}()
279+
}
262280
if args != nil {
263281
args = args[1:] // Zeroth arg is function name/node; not passed to function.
264282
}
@@ -371,6 +389,11 @@ func (s *state) evalCall(dot, fun reflect.Value, isBuiltin bool, node parse.Node
371389
s.helper.OnCalled(s.ctx, s.prep, name, argv, vv)
372390
}
373391

392+
// Added for Hugo.
393+
if name == "try" {
394+
return reflect.ValueOf(TryValue{vv.Interface(), nil})
395+
}
396+
374397
return vv
375398
}
376399

tpl/partials/init.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ func init() {
3838
},
3939
)
4040

41-
// TODO(bep) we need the return to be a valid identifier, but
41+
// TODO(bep) we need the return to be a valid identifiers, but
4242
// should consider another way of adding it.
4343
ns.AddMethodMapping(func() string { return "" },
4444
[]string{"return"},

tpl/safe/init.go

+7
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,13 @@ func init() {
7070
},
7171
)
7272

73+
ns.AddMethodMapping(func(v any) (any, error) {
74+
return v, nil
75+
},
76+
[]string{"try"},
77+
[][2]string{},
78+
)
79+
7380
return ns
7481
}
7582

tpl/templates/templates_integration_test.go

+30
Original file line numberDiff line numberDiff line change
@@ -93,3 +93,33 @@ Home: true
9393
9494
`)
9595
}
96+
97+
func TestTry(t *testing.T) {
98+
t.Parallel()
99+
100+
files := `
101+
-- config.toml --
102+
baseURL = 'http://example.com/'
103+
-- layouts/index.html --
104+
Home.
105+
{{ $g := try ("hello = \"Hello Hugo\"" | transform.Unmarshal) }}
106+
{{ with $g.Err }}
107+
Err1: {{ . }}
108+
{{ else }}
109+
Value1: {{ $g.Value.hello | safeHTML }}|
110+
{{ end }}
111+
{{ $g := try ("hello != \"Hello Hugo\"" | transform.Unmarshal) }}
112+
{{ with $g.Err }}
113+
Err2: {{ . | safeHTML }}
114+
{{ else }}
115+
Value2: {{ $g.Value.hello | safeHTML }}|
116+
{{ end }}
117+
`
118+
119+
b := hugolib.Test(t, files)
120+
121+
b.AssertFileContent("public/index.html",
122+
"Value1: Hello Hugo|",
123+
"Err2: template: index.html:",
124+
)
125+
}

0 commit comments

Comments
 (0)