mirror of
https://github.com/gohugoio/hugo.git
synced 2025-08-31 22:41:53 +02:00
@@ -7,13 +7,12 @@ package template
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/gohugoio/hugo/tpl/internal/go_templates/fmtsort"
|
||||
"github.com/gohugoio/hugo/tpl/internal/go_templates/texttemplate/parse"
|
||||
"io"
|
||||
"reflect"
|
||||
"runtime"
|
||||
"strings"
|
||||
|
||||
"github.com/gohugoio/hugo/tpl/internal/go_templates/fmtsort"
|
||||
"github.com/gohugoio/hugo/tpl/internal/go_templates/texttemplate/parse"
|
||||
)
|
||||
|
||||
// maxExecDepth specifies the maximum stack depth of templates within
|
||||
@@ -95,7 +94,7 @@ type missingValType struct{}
|
||||
|
||||
var missingVal = reflect.ValueOf(missingValType{})
|
||||
|
||||
var missingValReflectType = reflect.TypeOf(missingValType{})
|
||||
var missingValReflectType = reflect.TypeFor[missingValType]()
|
||||
|
||||
func isMissing(v reflect.Value) bool {
|
||||
return v.IsValid() && v.Type() == missingValReflectType
|
||||
@@ -202,8 +201,8 @@ func (t *Template) ExecuteTemplate(wr io.Writer, name string, data any) error {
|
||||
// A template may be executed safely in parallel, although if parallel
|
||||
// executions share a Writer the output may be interleaved.
|
||||
//
|
||||
// If data is a reflect.Value, the template applies to the concrete
|
||||
// value that the reflect.Value holds, as in fmt.Print.
|
||||
// If data is a [reflect.Value], the template applies to the concrete
|
||||
// value that the reflect.Value holds, as in [fmt.Print].
|
||||
func (t *Template) Execute(wr io.Writer, data any) error {
|
||||
return t.execute(wr, data)
|
||||
}
|
||||
@@ -229,7 +228,7 @@ func (t *Template) execute(wr io.Writer, data any) (err error) {
|
||||
// DefinedTemplates returns a string listing the defined templates,
|
||||
// prefixed by the string "; defined templates are: ". If there are none,
|
||||
// it returns the empty string. For generating an error message here
|
||||
// and in html/template.
|
||||
// and in [html/template].
|
||||
func (t *Template) DefinedTemplates() string {
|
||||
if t.common == nil {
|
||||
return ""
|
||||
@@ -409,8 +408,8 @@ func (s *state) walkRange(dot reflect.Value, r *parse.RangeNode) {
|
||||
break
|
||||
}
|
||||
om := fmtsort.Sort(val)
|
||||
for i, key := range om.Key {
|
||||
oneIteration(key, om.Value[i])
|
||||
for _, m := range om {
|
||||
oneIteration(m.Key, m.Value)
|
||||
}
|
||||
return
|
||||
case reflect.Chan:
|
||||
@@ -480,7 +479,7 @@ func (s *state) evalPipeline(dot reflect.Value, pipe *parse.PipeNode) (value ref
|
||||
value = s.evalCommand(dot, cmd, value) // previous value is this one's final arg.
|
||||
// If the object has type interface{}, dig down one level to the thing inside.
|
||||
if value.Kind() == reflect.Interface && value.Type().NumMethod() == 0 {
|
||||
value = reflect.ValueOf(value.Interface()) // lovely!
|
||||
value = value.Elem()
|
||||
}
|
||||
}
|
||||
for _, variable := range pipe.Decl {
|
||||
@@ -709,9 +708,9 @@ func (s *state) evalFieldOld(dot reflect.Value, fieldName string, node parse.Nod
|
||||
}
|
||||
|
||||
var (
|
||||
errorType = reflect.TypeOf((*error)(nil)).Elem()
|
||||
fmtStringerType = reflect.TypeOf((*fmt.Stringer)(nil)).Elem()
|
||||
reflectValueType = reflect.TypeOf((*reflect.Value)(nil)).Elem()
|
||||
errorType = reflect.TypeFor[error]()
|
||||
fmtStringerType = reflect.TypeFor[fmt.Stringer]()
|
||||
reflectValueType = reflect.TypeFor[reflect.Value]()
|
||||
)
|
||||
|
||||
// evalCall executes a function or method call. If it's a method, fun already has the receiver bound, so
|
||||
@@ -735,9 +734,8 @@ func (s *state) evalCallOld(dot, fun reflect.Value, isBuiltin bool, node parse.N
|
||||
} else if numIn != typ.NumIn() {
|
||||
s.errorf("wrong number of args for %s: want %d got %d", name, typ.NumIn(), numIn)
|
||||
}
|
||||
if !goodFunc(typ) {
|
||||
// TODO: This could still be a confusing error; maybe goodFunc should provide info.
|
||||
s.errorf("can't call method/function %q with %d results", name, typ.NumOut())
|
||||
if err := goodFunc(name, typ); err != nil {
|
||||
s.errorf("%v", err)
|
||||
}
|
||||
|
||||
unwrap := func(v reflect.Value) reflect.Value {
|
||||
@@ -801,6 +799,15 @@ func (s *state) evalCallOld(dot, fun reflect.Value, isBuiltin bool, node parse.N
|
||||
}
|
||||
argv[i] = s.validateType(final, t)
|
||||
}
|
||||
|
||||
// Special case for the "call" builtin.
|
||||
// Insert the name of the callee function as the first argument.
|
||||
if isBuiltin && name == "call" {
|
||||
calleeName := args[0].String()
|
||||
argv = append([]reflect.Value{reflect.ValueOf(calleeName)}, argv...)
|
||||
fun = reflect.ValueOf(call)
|
||||
}
|
||||
|
||||
v, err := safeCall(fun, argv)
|
||||
// If we have an error that is not nil, stop execution and return that
|
||||
// error to the caller.
|
||||
|
Reference in New Issue
Block a user