mirror of
https://github.com/gohugoio/hugo.git
synced 2025-08-21 21:35:28 +02:00
Reimplement and simplify Hugo's template system
See #13541 for details. Fixes #13545 Fixes #13515 Closes #7964 Closes #13365 Closes #12988 Closes #4891
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
// Copyright 2017-present The Hugo Authors. All rights reserved.
|
||||
// Copyright 2025 The Hugo Authors. All rights reserved.
|
||||
//
|
||||
// Portions Copyright The Go Authors.
|
||||
|
||||
@@ -25,46 +25,7 @@ import (
|
||||
"github.com/gohugoio/hugo/identity"
|
||||
"github.com/gohugoio/hugo/tpl"
|
||||
|
||||
template "github.com/gohugoio/hugo/tpl/internal/go_templates/htmltemplate"
|
||||
texttemplate "github.com/gohugoio/hugo/tpl/internal/go_templates/texttemplate"
|
||||
|
||||
"github.com/gohugoio/hugo/deps"
|
||||
|
||||
"github.com/gohugoio/hugo/tpl/internal"
|
||||
|
||||
// Init the namespaces
|
||||
_ "github.com/gohugoio/hugo/tpl/cast"
|
||||
_ "github.com/gohugoio/hugo/tpl/collections"
|
||||
_ "github.com/gohugoio/hugo/tpl/compare"
|
||||
_ "github.com/gohugoio/hugo/tpl/crypto"
|
||||
_ "github.com/gohugoio/hugo/tpl/css"
|
||||
_ "github.com/gohugoio/hugo/tpl/data"
|
||||
_ "github.com/gohugoio/hugo/tpl/debug"
|
||||
_ "github.com/gohugoio/hugo/tpl/diagrams"
|
||||
_ "github.com/gohugoio/hugo/tpl/encoding"
|
||||
_ "github.com/gohugoio/hugo/tpl/fmt"
|
||||
_ "github.com/gohugoio/hugo/tpl/hash"
|
||||
_ "github.com/gohugoio/hugo/tpl/hugo"
|
||||
_ "github.com/gohugoio/hugo/tpl/images"
|
||||
_ "github.com/gohugoio/hugo/tpl/inflect"
|
||||
_ "github.com/gohugoio/hugo/tpl/js"
|
||||
_ "github.com/gohugoio/hugo/tpl/lang"
|
||||
_ "github.com/gohugoio/hugo/tpl/math"
|
||||
_ "github.com/gohugoio/hugo/tpl/openapi/openapi3"
|
||||
_ "github.com/gohugoio/hugo/tpl/os"
|
||||
_ "github.com/gohugoio/hugo/tpl/page"
|
||||
_ "github.com/gohugoio/hugo/tpl/partials"
|
||||
_ "github.com/gohugoio/hugo/tpl/path"
|
||||
_ "github.com/gohugoio/hugo/tpl/reflect"
|
||||
_ "github.com/gohugoio/hugo/tpl/resources"
|
||||
_ "github.com/gohugoio/hugo/tpl/safe"
|
||||
_ "github.com/gohugoio/hugo/tpl/site"
|
||||
_ "github.com/gohugoio/hugo/tpl/strings"
|
||||
_ "github.com/gohugoio/hugo/tpl/templates"
|
||||
_ "github.com/gohugoio/hugo/tpl/time"
|
||||
_ "github.com/gohugoio/hugo/tpl/transform"
|
||||
_ "github.com/gohugoio/hugo/tpl/urls"
|
||||
maps0 "maps"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -212,89 +173,3 @@ func (t *templateExecHelper) trackDependencies(ctx context.Context, tmpl texttem
|
||||
|
||||
return ctx
|
||||
}
|
||||
|
||||
func newTemplateExecuter(d *deps.Deps) (texttemplate.Executer, map[string]reflect.Value) {
|
||||
funcs := createFuncMap(d)
|
||||
funcsv := make(map[string]reflect.Value)
|
||||
|
||||
for k, v := range funcs {
|
||||
vv := reflect.ValueOf(v)
|
||||
funcsv[k] = vv
|
||||
}
|
||||
|
||||
// Duplicate Go's internal funcs here for faster lookups.
|
||||
for k, v := range template.GoFuncs {
|
||||
if _, exists := funcsv[k]; !exists {
|
||||
vv, ok := v.(reflect.Value)
|
||||
if !ok {
|
||||
vv = reflect.ValueOf(v)
|
||||
}
|
||||
funcsv[k] = vv
|
||||
}
|
||||
}
|
||||
|
||||
for k, v := range texttemplate.GoFuncs {
|
||||
if _, exists := funcsv[k]; !exists {
|
||||
funcsv[k] = v
|
||||
}
|
||||
}
|
||||
|
||||
exeHelper := &templateExecHelper{
|
||||
watching: d.Conf.Watching(),
|
||||
funcs: funcsv,
|
||||
site: reflect.ValueOf(d.Site),
|
||||
siteParams: reflect.ValueOf(d.Site.Params()),
|
||||
}
|
||||
|
||||
return texttemplate.NewExecuter(
|
||||
exeHelper,
|
||||
), funcsv
|
||||
}
|
||||
|
||||
func createFuncMap(d *deps.Deps) map[string]any {
|
||||
if d.TmplFuncMap != nil {
|
||||
return d.TmplFuncMap
|
||||
}
|
||||
funcMap := template.FuncMap{}
|
||||
|
||||
nsMap := make(map[string]any)
|
||||
var onCreated []func(namespaces map[string]any)
|
||||
|
||||
// Merge the namespace funcs
|
||||
for _, nsf := range internal.TemplateFuncsNamespaceRegistry {
|
||||
ns := nsf(d)
|
||||
if _, exists := funcMap[ns.Name]; exists {
|
||||
panic(ns.Name + " is a duplicate template func")
|
||||
}
|
||||
funcMap[ns.Name] = ns.Context
|
||||
contextV, err := ns.Context(context.Background())
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
nsMap[ns.Name] = contextV
|
||||
for _, mm := range ns.MethodMappings {
|
||||
for _, alias := range mm.Aliases {
|
||||
if _, exists := funcMap[alias]; exists {
|
||||
panic(alias + " is a duplicate template func")
|
||||
}
|
||||
funcMap[alias] = mm.Method
|
||||
}
|
||||
}
|
||||
|
||||
if ns.OnCreated != nil {
|
||||
onCreated = append(onCreated, ns.OnCreated)
|
||||
}
|
||||
}
|
||||
|
||||
for _, f := range onCreated {
|
||||
f(nsMap)
|
||||
}
|
||||
|
||||
if d.OverloadedTemplateFuncs != nil {
|
||||
maps0.Copy(funcMap, d.OverloadedTemplateFuncs)
|
||||
}
|
||||
|
||||
d.TmplFuncMap = funcMap
|
||||
|
||||
return d.TmplFuncMap
|
||||
}
|
||||
|
Reference in New Issue
Block a user