mirror of
https://github.com/gohugoio/hugo.git
synced 2025-04-26 13:40:38 +03:00
parent
723e3f4342
commit
5d2cbee989
4 changed files with 71 additions and 2 deletions
|
@ -15,6 +15,7 @@ package template
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"reflect"
|
"reflect"
|
||||||
|
|
||||||
|
@ -255,10 +256,32 @@ func (s *state) evalField(dot reflect.Value, fieldName string, node parse.Node,
|
||||||
panic("not reached")
|
panic("not reached")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TryValue is what gets returned when using the "try" keyword.
|
||||||
|
type TryValue struct {
|
||||||
|
// Value is the value returned by the function or method wrapped with "try".
|
||||||
|
// This will always be nil if Err is set.
|
||||||
|
Value any
|
||||||
|
// Err is the error returned by the function or method wrapped with "try".
|
||||||
|
// This will always be nil if Value is set.
|
||||||
|
Err error
|
||||||
|
}
|
||||||
|
|
||||||
// evalCall executes a function or method call. If it's a method, fun already has the receiver bound, so
|
// evalCall executes a function or method call. If it's a method, fun already has the receiver bound, so
|
||||||
// it looks just like a function call. The arg list, if non-nil, includes (in the manner of the shell), arg[0]
|
// it looks just like a function call. The arg list, if non-nil, includes (in the manner of the shell), arg[0]
|
||||||
// as the function itself.
|
// as the function itself.
|
||||||
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 {
|
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) {
|
||||||
|
// Added for Hugo.
|
||||||
|
if name == "try" {
|
||||||
|
defer func() {
|
||||||
|
if r := recover(); r != nil {
|
||||||
|
if err, ok := r.(error); ok {
|
||||||
|
val = reflect.ValueOf(TryValue{nil, err})
|
||||||
|
} else {
|
||||||
|
val = reflect.ValueOf(TryValue{nil, fmt.Errorf("%v", r)})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
}
|
||||||
if args != nil {
|
if args != nil {
|
||||||
args = args[1:] // Zeroth arg is function name/node; not passed to function.
|
args = args[1:] // Zeroth arg is function name/node; not passed to function.
|
||||||
}
|
}
|
||||||
|
@ -371,6 +394,11 @@ func (s *state) evalCall(dot, fun reflect.Value, isBuiltin bool, node parse.Node
|
||||||
s.helper.OnCalled(s.ctx, s.prep, name, argv, vv)
|
s.helper.OnCalled(s.ctx, s.prep, name, argv, vv)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Added for Hugo.
|
||||||
|
if name == "try" {
|
||||||
|
return reflect.ValueOf(TryValue{vv.Interface(), nil})
|
||||||
|
}
|
||||||
|
|
||||||
return vv
|
return vv
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -38,7 +38,7 @@ func init() {
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
// TODO(bep) we need the return to be a valid identifier, but
|
// TODO(bep) we need the return to be a valid identifiers, but
|
||||||
// should consider another way of adding it.
|
// should consider another way of adding it.
|
||||||
ns.AddMethodMapping(func() string { return "" },
|
ns.AddMethodMapping(func() string { return "" },
|
||||||
[]string{"return"},
|
[]string{"return"},
|
||||||
|
|
|
@ -70,6 +70,13 @@ func init() {
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
ns.AddMethodMapping(func(v any) (any, error) {
|
||||||
|
return v, nil
|
||||||
|
},
|
||||||
|
[]string{"try"},
|
||||||
|
[][2]string{},
|
||||||
|
)
|
||||||
|
|
||||||
return ns
|
return ns
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -93,3 +93,37 @@ Home: true
|
||||||
|
|
||||||
`)
|
`)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestTry(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
files := `
|
||||||
|
-- config.toml --
|
||||||
|
baseURL = 'http://example.com/'
|
||||||
|
-- layouts/index.html --
|
||||||
|
Home.
|
||||||
|
{{ $g := try ("hello = \"Hello Hugo\"" | transform.Unmarshal) }}
|
||||||
|
{{ with $g.Err }}
|
||||||
|
Err1: {{ . }}
|
||||||
|
{{ else }}
|
||||||
|
Value1: {{ $g.Value.hello | safeHTML }}|
|
||||||
|
{{ end }}
|
||||||
|
{{ $g := try ("hello != \"Hello Hugo\"" | transform.Unmarshal) }}
|
||||||
|
{{ with $g.Err }}
|
||||||
|
Err2: {{ . | safeHTML }}
|
||||||
|
{{ else }}
|
||||||
|
Value2: {{ $g.Value.hello | safeHTML }}|
|
||||||
|
{{ end }}
|
||||||
|
Try upper: {{ (try ("hello" | upper)).Value }}
|
||||||
|
Try printf: {{ (try (printf "hello %s" "world")).Value }}
|
||||||
|
`
|
||||||
|
|
||||||
|
b := hugolib.Test(t, files)
|
||||||
|
|
||||||
|
b.AssertFileContent("public/index.html",
|
||||||
|
"Value1: Hello Hugo|",
|
||||||
|
"Err2: template: index.html:",
|
||||||
|
"Try upper: HELLO",
|
||||||
|
"Try printf: hello world",
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue