2018-07-31 05:35:38 -04:00
|
|
|
// Copyright 2018 The Hugo Authors. All rights reserved.
|
|
|
|
//
|
|
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
// you may not use this file except in compliance with the License.
|
|
|
|
// You may obtain a copy of the License at
|
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
//
|
|
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
// See the License for the specific language governing permissions and
|
|
|
|
// limitations under the License.
|
|
|
|
|
2018-11-29 22:32:53 -05:00
|
|
|
// Package templates provides template functions for working with templates.
|
|
|
|
package templates
|
2018-07-31 05:35:38 -04:00
|
|
|
|
|
|
|
import (
|
2024-06-08 05:52:22 -04:00
|
|
|
"context"
|
|
|
|
"fmt"
|
|
|
|
"strconv"
|
|
|
|
"sync/atomic"
|
|
|
|
|
2018-07-31 05:35:38 -04:00
|
|
|
"github.com/gohugoio/hugo/deps"
|
2024-06-08 05:52:22 -04:00
|
|
|
"github.com/gohugoio/hugo/helpers"
|
|
|
|
"github.com/gohugoio/hugo/tpl"
|
|
|
|
"github.com/mitchellh/mapstructure"
|
2018-07-31 05:35:38 -04:00
|
|
|
)
|
|
|
|
|
|
|
|
// New returns a new instance of the templates-namespaced template functions.
|
|
|
|
func New(deps *deps.Deps) *Namespace {
|
2024-06-08 05:52:22 -04:00
|
|
|
ns := &Namespace{
|
2018-07-31 05:35:38 -04:00
|
|
|
deps: deps,
|
|
|
|
}
|
2024-06-08 05:52:22 -04:00
|
|
|
|
|
|
|
return ns
|
2018-07-31 05:35:38 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
// Namespace provides template functions for the "templates" namespace.
|
|
|
|
type Namespace struct {
|
|
|
|
deps *deps.Deps
|
|
|
|
}
|
|
|
|
|
|
|
|
// Exists returns whether the template with the given name exists.
|
|
|
|
// Note that this is the Unix-styled relative path including filename suffix,
|
|
|
|
// e.g. partials/header.html
|
|
|
|
func (ns *Namespace) Exists(name string) bool {
|
2022-02-09 09:51:44 -05:00
|
|
|
return ns.deps.Tmpl().HasTemplate(name)
|
2018-07-31 05:35:38 -04:00
|
|
|
}
|
2024-06-08 05:52:22 -04:00
|
|
|
|
|
|
|
// Defer defers the execution of a template block.
|
|
|
|
func (ns *Namespace) Defer(args ...any) (bool, error) {
|
|
|
|
// Prevent defer from being used in content adapters,
|
|
|
|
// that just doesn't work.
|
|
|
|
ns.deps.Site.CheckReady()
|
|
|
|
|
|
|
|
if len(args) != 0 {
|
|
|
|
return false, fmt.Errorf("Defer does not take any arguments")
|
|
|
|
}
|
|
|
|
return true, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
var defferedIDCounter atomic.Uint64
|
|
|
|
|
|
|
|
type DeferOpts struct {
|
|
|
|
// Optional cache key. If set, the deferred block will be executed
|
|
|
|
// once per unique key.
|
|
|
|
Key string
|
|
|
|
|
|
|
|
// Optional data context to use when executing the deferred block.
|
|
|
|
Data any
|
|
|
|
}
|
|
|
|
|
|
|
|
// DoDefer defers the execution of a template block.
|
|
|
|
// For internal use only.
|
|
|
|
func (ns *Namespace) DoDefer(ctx context.Context, id string, optsv any) string {
|
|
|
|
var opts DeferOpts
|
|
|
|
if optsv != nil {
|
|
|
|
if err := mapstructure.WeakDecode(optsv, &opts); err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
templateName := id
|
|
|
|
var key string
|
|
|
|
if opts.Key != "" {
|
|
|
|
key = helpers.MD5String(opts.Key)
|
|
|
|
} else {
|
|
|
|
key = strconv.FormatUint(defferedIDCounter.Add(1), 10)
|
|
|
|
}
|
|
|
|
|
|
|
|
id = fmt.Sprintf("%s_%s%s", id, key, tpl.HugoDeferredTemplateSuffix)
|
|
|
|
|
|
|
|
_ = ns.deps.BuildState.DeferredExecutions.Executions.GetOrCreate(id,
|
|
|
|
func() *tpl.DeferredExecution {
|
|
|
|
return &tpl.DeferredExecution{
|
|
|
|
TemplateName: templateName,
|
|
|
|
Ctx: ctx,
|
|
|
|
Data: opts.Data,
|
|
|
|
Executed: false,
|
|
|
|
}
|
|
|
|
})
|
|
|
|
|
|
|
|
return id
|
|
|
|
}
|