mirror of
https://github.com/gohugoio/hugo.git
synced 2024-11-21 20:46:30 -05:00
parent
2662faf61f
commit
ce524d0b5e
54 changed files with 436 additions and 108 deletions
|
@ -577,7 +577,7 @@ func (c *commandeer) serve(s *serverCmd) error {
|
||||||
// to cached values if nil.
|
// to cached values if nil.
|
||||||
templ, handler := getErrorTemplateAndHandler(c.hugoTry())
|
templ, handler := getErrorTemplateAndHandler(c.hugoTry())
|
||||||
b := &bytes.Buffer{}
|
b := &bytes.Buffer{}
|
||||||
err := handler.Execute(templ, b, ctx)
|
err := handler.ExecuteWithContext(context.Background(), templ, b, ctx)
|
||||||
return b, err
|
return b, err
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -208,6 +208,23 @@ func AsTime(v reflect.Value, loc *time.Location) (time.Time, bool) {
|
||||||
return time.Time{}, false
|
return time.Time{}, false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func CallMethodByName(cxt context.Context, name string, v reflect.Value) []reflect.Value {
|
||||||
|
fn := v.MethodByName(name)
|
||||||
|
var args []reflect.Value
|
||||||
|
tp := fn.Type()
|
||||||
|
if tp.NumIn() > 0 {
|
||||||
|
if tp.NumIn() > 1 {
|
||||||
|
panic("not supported")
|
||||||
|
}
|
||||||
|
first := tp.In(0)
|
||||||
|
if first.Implements(ContextInterface) {
|
||||||
|
args = append(args, reflect.ValueOf(cxt))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return fn.Call(args)
|
||||||
|
}
|
||||||
|
|
||||||
// Based on: https://github.com/golang/go/blob/178a2c42254166cffed1b25fb1d3c7a5727cada6/src/text/template/exec.go#L931
|
// Based on: https://github.com/golang/go/blob/178a2c42254166cffed1b25fb1d3c7a5727cada6/src/text/template/exec.go#L931
|
||||||
func indirectInterface(v reflect.Value) reflect.Value {
|
func indirectInterface(v reflect.Value) reflect.Value {
|
||||||
if v.Kind() != reflect.Interface {
|
if v.Kind() != reflect.Interface {
|
||||||
|
|
|
@ -15,6 +15,7 @@ package hugolib
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
@ -64,8 +65,10 @@ func (a aliasHandler) renderAlias(permalink string, p page.Page) (io.Reader, err
|
||||||
p,
|
p,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ctx := tpl.SetPageInContext(context.Background(), p)
|
||||||
|
|
||||||
buffer := new(bytes.Buffer)
|
buffer := new(bytes.Buffer)
|
||||||
err := a.t.Execute(templ, buffer, data)
|
err := a.t.ExecuteWithContext(ctx, templ, buffer, data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -767,10 +767,11 @@ func (h *HugoSites) renderCrossSitesSitemap() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
s := h.Sites[0]
|
s := h.Sites[0]
|
||||||
|
// We don't have any page context to pass in here.
|
||||||
|
ctx := context.Background()
|
||||||
|
|
||||||
templ := s.lookupLayouts("sitemapindex.xml", "_default/sitemapindex.xml", "_internal/_default/sitemapindex.xml")
|
templ := s.lookupLayouts("sitemapindex.xml", "_default/sitemapindex.xml", "_internal/_default/sitemapindex.xml")
|
||||||
|
return s.renderAndWriteXML(ctx, &s.PathSpec.ProcessingStats.Sitemaps, "sitemapindex",
|
||||||
return s.renderAndWriteXML(&s.PathSpec.ProcessingStats.Sitemaps, "sitemapindex",
|
|
||||||
s.siteCfg.sitemap.Filename, h.toSiteInfos(), templ)
|
s.siteCfg.sitemap.Filename, h.toSiteInfos(), templ)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -740,6 +740,7 @@ func (cp *pageContentOutput) ParseContent(ctx context.Context, content []byte) (
|
||||||
return nil, ok, nil
|
return nil, ok, nil
|
||||||
}
|
}
|
||||||
rctx := converter.RenderContext{
|
rctx := converter.RenderContext{
|
||||||
|
Ctx: ctx,
|
||||||
Src: content,
|
Src: content,
|
||||||
RenderTOC: true,
|
RenderTOC: true,
|
||||||
GetRenderer: cp.renderHooks.getRenderer,
|
GetRenderer: cp.renderHooks.getRenderer,
|
||||||
|
@ -758,6 +759,7 @@ func (cp *pageContentOutput) RenderContent(ctx context.Context, content []byte,
|
||||||
return nil, ok, nil
|
return nil, ok, nil
|
||||||
}
|
}
|
||||||
rctx := converter.RenderContext{
|
rctx := converter.RenderContext{
|
||||||
|
Ctx: ctx,
|
||||||
Src: content,
|
Src: content,
|
||||||
RenderTOC: true,
|
RenderTOC: true,
|
||||||
GetRenderer: cp.renderHooks.getRenderer,
|
GetRenderer: cp.renderHooks.getRenderer,
|
||||||
|
@ -777,6 +779,7 @@ func (cp *pageContentOutput) RenderContent(ctx context.Context, content []byte,
|
||||||
func (cp *pageContentOutput) renderContentWithConverter(ctx context.Context, c converter.Converter, content []byte, renderTOC bool) (converter.ResultRender, error) {
|
func (cp *pageContentOutput) renderContentWithConverter(ctx context.Context, c converter.Converter, content []byte, renderTOC bool) (converter.ResultRender, error) {
|
||||||
r, err := c.Convert(
|
r, err := c.Convert(
|
||||||
converter.RenderContext{
|
converter.RenderContext{
|
||||||
|
Ctx: ctx,
|
||||||
Src: content,
|
Src: content,
|
||||||
RenderTOC: renderTOC,
|
RenderTOC: renderTOC,
|
||||||
GetRenderer: cp.renderHooks.getRenderer,
|
GetRenderer: cp.renderHooks.getRenderer,
|
||||||
|
|
|
@ -1710,12 +1710,12 @@ func (s *Site) lookupLayouts(layouts ...string) tpl.Template {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Site) renderAndWriteXML(statCounter *uint64, name string, targetPath string, d any, templ tpl.Template) error {
|
func (s *Site) renderAndWriteXML(ctx context.Context, statCounter *uint64, name string, targetPath string, d any, templ tpl.Template) error {
|
||||||
s.Log.Debugf("Render XML for %q to %q", name, targetPath)
|
s.Log.Debugf("Render XML for %q to %q", name, targetPath)
|
||||||
renderBuffer := bp.GetBuffer()
|
renderBuffer := bp.GetBuffer()
|
||||||
defer bp.PutBuffer(renderBuffer)
|
defer bp.PutBuffer(renderBuffer)
|
||||||
|
|
||||||
if err := s.renderForTemplate(name, "", d, renderBuffer, templ); err != nil {
|
if err := s.renderForTemplate(ctx, name, "", d, renderBuffer, templ); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1739,8 +1739,9 @@ func (s *Site) renderAndWritePage(statCounter *uint64, name string, targetPath s
|
||||||
defer bp.PutBuffer(renderBuffer)
|
defer bp.PutBuffer(renderBuffer)
|
||||||
|
|
||||||
of := p.outputFormat()
|
of := p.outputFormat()
|
||||||
|
ctx := tpl.SetPageInContext(context.Background(), p)
|
||||||
|
|
||||||
if err := s.renderForTemplate(p.Kind(), of.Name, p, renderBuffer, templ); err != nil {
|
if err := s.renderForTemplate(ctx, p.Kind(), of.Name, p, renderBuffer, templ); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1797,16 +1798,16 @@ type hookRendererTemplate struct {
|
||||||
resolvePosition func(ctx any) text.Position
|
resolvePosition func(ctx any) text.Position
|
||||||
}
|
}
|
||||||
|
|
||||||
func (hr hookRendererTemplate) RenderLink(w io.Writer, ctx hooks.LinkContext) error {
|
func (hr hookRendererTemplate) RenderLink(cctx context.Context, w io.Writer, ctx hooks.LinkContext) error {
|
||||||
return hr.templateHandler.Execute(hr.templ, w, ctx)
|
return hr.templateHandler.ExecuteWithContext(cctx, hr.templ, w, ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (hr hookRendererTemplate) RenderHeading(w io.Writer, ctx hooks.HeadingContext) error {
|
func (hr hookRendererTemplate) RenderHeading(cctx context.Context, w io.Writer, ctx hooks.HeadingContext) error {
|
||||||
return hr.templateHandler.Execute(hr.templ, w, ctx)
|
return hr.templateHandler.ExecuteWithContext(cctx, hr.templ, w, ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (hr hookRendererTemplate) RenderCodeblock(w hugio.FlexiWriter, ctx hooks.CodeblockContext) error {
|
func (hr hookRendererTemplate) RenderCodeblock(cctx context.Context, w hugio.FlexiWriter, ctx hooks.CodeblockContext) error {
|
||||||
return hr.templateHandler.Execute(hr.templ, w, ctx)
|
return hr.templateHandler.ExecuteWithContext(cctx, hr.templ, w, ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (hr hookRendererTemplate) ResolvePosition(ctx any) text.Position {
|
func (hr hookRendererTemplate) ResolvePosition(ctx any) text.Position {
|
||||||
|
@ -1817,13 +1818,15 @@ func (hr hookRendererTemplate) IsDefaultCodeBlockRenderer() bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Site) renderForTemplate(name, outputFormat string, d any, w io.Writer, templ tpl.Template) (err error) {
|
func (s *Site) renderForTemplate(ctx context.Context, name, outputFormat string, d any, w io.Writer, templ tpl.Template) (err error) {
|
||||||
if templ == nil {
|
if templ == nil {
|
||||||
s.logMissingLayout(name, "", "", outputFormat)
|
s.logMissingLayout(name, "", "", outputFormat)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx := context.Background()
|
if ctx == nil {
|
||||||
|
panic("nil context")
|
||||||
|
}
|
||||||
|
|
||||||
if err = s.Tmpl().ExecuteWithContext(ctx, templ, w, d); err != nil {
|
if err = s.Tmpl().ExecuteWithContext(ctx, templ, w, d); err != nil {
|
||||||
return fmt.Errorf("render of %q failed: %w", name, err)
|
return fmt.Errorf("render of %q failed: %w", name, err)
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
package hugolib
|
package hugolib
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"path"
|
"path"
|
||||||
"strings"
|
"strings"
|
||||||
|
@ -197,7 +198,7 @@ func (s *Site) renderPaginator(p *pageState, templ tpl.Template) error {
|
||||||
d.Addends = fmt.Sprintf("/%s/%d", paginatePath, 1)
|
d.Addends = fmt.Sprintf("/%s/%d", paginatePath, 1)
|
||||||
targetPaths := page.CreateTargetPaths(d)
|
targetPaths := page.CreateTargetPaths(d)
|
||||||
|
|
||||||
if err := s.writeDestAlias(targetPaths.TargetFilename, p.Permalink(), f, nil); err != nil {
|
if err := s.writeDestAlias(targetPaths.TargetFilename, p.Permalink(), f, p); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -278,6 +279,7 @@ func (s *Site) renderSitemap() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
targetPath := p.targetPaths().TargetFilename
|
targetPath := p.targetPaths().TargetFilename
|
||||||
|
ctx := tpl.SetPageInContext(context.Background(), p)
|
||||||
|
|
||||||
if targetPath == "" {
|
if targetPath == "" {
|
||||||
return errors.New("failed to create targetPath for sitemap")
|
return errors.New("failed to create targetPath for sitemap")
|
||||||
|
@ -285,7 +287,7 @@ func (s *Site) renderSitemap() error {
|
||||||
|
|
||||||
templ := s.lookupLayouts("sitemap.xml", "_default/sitemap.xml", "_internal/_default/sitemap.xml")
|
templ := s.lookupLayouts("sitemap.xml", "_default/sitemap.xml", "_internal/_default/sitemap.xml")
|
||||||
|
|
||||||
return s.renderAndWriteXML(&s.PathSpec.ProcessingStats.Sitemaps, "sitemap", targetPath, p, templ)
|
return s.renderAndWriteXML(ctx, &s.PathSpec.ProcessingStats.Sitemaps, "sitemap", targetPath, p, templ)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Site) renderRobotsTXT() error {
|
func (s *Site) renderRobotsTXT() error {
|
||||||
|
|
|
@ -15,6 +15,7 @@ package converter
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"context"
|
||||||
|
|
||||||
"github.com/gohugoio/hugo/common/hexec"
|
"github.com/gohugoio/hugo/common/hexec"
|
||||||
"github.com/gohugoio/hugo/common/loggers"
|
"github.com/gohugoio/hugo/common/loggers"
|
||||||
|
@ -141,6 +142,9 @@ type DocumentContext struct {
|
||||||
|
|
||||||
// RenderContext holds contextual information about the content to render.
|
// RenderContext holds contextual information about the content to render.
|
||||||
type RenderContext struct {
|
type RenderContext struct {
|
||||||
|
// Ctx is the context.Context for the current Page render.
|
||||||
|
Ctx context.Context
|
||||||
|
|
||||||
// Src is the content to render.
|
// Src is the content to render.
|
||||||
Src []byte
|
Src []byte
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
package hooks
|
package hooks
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"io"
|
"io"
|
||||||
|
|
||||||
"github.com/gohugoio/hugo/common/hugio"
|
"github.com/gohugoio/hugo/common/hugio"
|
||||||
|
@ -85,12 +86,12 @@ type AttributesOptionsSliceProvider interface {
|
||||||
}
|
}
|
||||||
|
|
||||||
type LinkRenderer interface {
|
type LinkRenderer interface {
|
||||||
RenderLink(w io.Writer, ctx LinkContext) error
|
RenderLink(cctx context.Context, w io.Writer, ctx LinkContext) error
|
||||||
identity.Provider
|
identity.Provider
|
||||||
}
|
}
|
||||||
|
|
||||||
type CodeBlockRenderer interface {
|
type CodeBlockRenderer interface {
|
||||||
RenderCodeblock(w hugio.FlexiWriter, ctx CodeblockContext) error
|
RenderCodeblock(cctx context.Context, w hugio.FlexiWriter, ctx CodeblockContext) error
|
||||||
identity.Provider
|
identity.Provider
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -119,7 +120,7 @@ type HeadingContext interface {
|
||||||
// HeadingRenderer describes a uniquely identifiable rendering hook.
|
// HeadingRenderer describes a uniquely identifiable rendering hook.
|
||||||
type HeadingRenderer interface {
|
type HeadingRenderer interface {
|
||||||
// Render writes the rendered content to w using the data in w.
|
// Render writes the rendered content to w using the data in w.
|
||||||
RenderHeading(w io.Writer, ctx HeadingContext) error
|
RenderHeading(cctx context.Context, w io.Writer, ctx HeadingContext) error
|
||||||
identity.Provider
|
identity.Provider
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -124,6 +124,7 @@ func (r *htmlRenderer) renderCodeBlock(w util.BufWriter, src []byte, node ast.No
|
||||||
cr := renderer.(hooks.CodeBlockRenderer)
|
cr := renderer.(hooks.CodeBlockRenderer)
|
||||||
|
|
||||||
err := cr.RenderCodeblock(
|
err := cr.RenderCodeblock(
|
||||||
|
ctx.RenderContext().Ctx,
|
||||||
w,
|
w,
|
||||||
cbctx,
|
cbctx,
|
||||||
)
|
)
|
||||||
|
|
|
@ -181,6 +181,7 @@ func (r *hookedRenderer) renderImage(w util.BufWriter, source []byte, node ast.N
|
||||||
attrs := r.filterInternalAttributes(n.Attributes())
|
attrs := r.filterInternalAttributes(n.Attributes())
|
||||||
|
|
||||||
err := lr.RenderLink(
|
err := lr.RenderLink(
|
||||||
|
ctx.RenderContext().Ctx,
|
||||||
w,
|
w,
|
||||||
imageLinkContext{
|
imageLinkContext{
|
||||||
linkContext: linkContext{
|
linkContext: linkContext{
|
||||||
|
@ -271,6 +272,7 @@ func (r *hookedRenderer) renderLink(w util.BufWriter, source []byte, node ast.No
|
||||||
ctx.Buffer.Truncate(pos)
|
ctx.Buffer.Truncate(pos)
|
||||||
|
|
||||||
err := lr.RenderLink(
|
err := lr.RenderLink(
|
||||||
|
ctx.RenderContext().Ctx,
|
||||||
w,
|
w,
|
||||||
linkContext{
|
linkContext{
|
||||||
page: ctx.DocumentContext().Document,
|
page: ctx.DocumentContext().Document,
|
||||||
|
@ -340,6 +342,7 @@ func (r *hookedRenderer) renderAutoLink(w util.BufWriter, source []byte, node as
|
||||||
}
|
}
|
||||||
|
|
||||||
err := lr.RenderLink(
|
err := lr.RenderLink(
|
||||||
|
ctx.RenderContext().Ctx,
|
||||||
w,
|
w,
|
||||||
linkContext{
|
linkContext{
|
||||||
page: ctx.DocumentContext().Document,
|
page: ctx.DocumentContext().Document,
|
||||||
|
@ -428,6 +431,7 @@ func (r *hookedRenderer) renderHeading(w util.BufWriter, source []byte, node ast
|
||||||
anchor := anchori.([]byte)
|
anchor := anchori.([]byte)
|
||||||
|
|
||||||
err := hr.RenderHeading(
|
err := hr.RenderHeading(
|
||||||
|
ctx.RenderContext().Ctx,
|
||||||
w,
|
w,
|
||||||
headingContext{
|
headingContext{
|
||||||
page: ctx.DocumentContext().Document,
|
page: ctx.DocumentContext().Document,
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
package highlight
|
package highlight
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
gohtml "html"
|
gohtml "html"
|
||||||
"html/template"
|
"html/template"
|
||||||
|
@ -122,7 +123,7 @@ func (h chromaHighlighter) HighlightCodeBlock(ctx hooks.CodeblockContext, opts a
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h chromaHighlighter) RenderCodeblock(w hugio.FlexiWriter, ctx hooks.CodeblockContext) error {
|
func (h chromaHighlighter) RenderCodeblock(cctx context.Context, w hugio.FlexiWriter, ctx hooks.CodeblockContext) error {
|
||||||
cfg := h.cfg
|
cfg := h.cfg
|
||||||
|
|
||||||
attributes := ctx.(hooks.AttributesOptionsSliceProvider).AttributesSlice()
|
attributes := ctx.(hooks.AttributesOptionsSliceProvider).AttributesSlice()
|
||||||
|
|
|
@ -135,3 +135,7 @@ func (e *errorResource) DecodeImage() (image.Image, error) {
|
||||||
func (e *errorResource) Transform(...ResourceTransformation) (ResourceTransformer, error) {
|
func (e *errorResource) Transform(...ResourceTransformation) (ResourceTransformer, error) {
|
||||||
panic(e.ResourceError)
|
panic(e.ResourceError)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (e *errorResource) TransformWithContext(context.Context, ...ResourceTransformation) (ResourceTransformer, error) {
|
||||||
|
panic(e.ResourceError)
|
||||||
|
}
|
||||||
|
|
|
@ -159,12 +159,7 @@ func (p Pages) GroupBy(ctx context.Context, key string, order ...string) (PagesG
|
||||||
case reflect.StructField:
|
case reflect.StructField:
|
||||||
fv = ppv.Elem().FieldByName(key)
|
fv = ppv.Elem().FieldByName(key)
|
||||||
case reflect.Method:
|
case reflect.Method:
|
||||||
var args []reflect.Value
|
fv = hreflect.CallMethodByName(ctx, key, ppv)[0]
|
||||||
fn := hreflect.GetMethodByName(ppv, key)
|
|
||||||
if fn.Type().NumIn() > 0 && fn.Type().In(0).Implements(hreflect.ContextInterface) {
|
|
||||||
args = []reflect.Value{reflect.ValueOf(ctx)}
|
|
||||||
}
|
|
||||||
fv = fn.Call(args)[0]
|
|
||||||
}
|
}
|
||||||
if !fv.IsValid() {
|
if !fv.IsValid() {
|
||||||
continue
|
continue
|
||||||
|
|
|
@ -104,6 +104,7 @@ type ResourceTransformer interface {
|
||||||
|
|
||||||
type Transformer interface {
|
type Transformer interface {
|
||||||
Transform(...ResourceTransformation) (ResourceTransformer, error)
|
Transform(...ResourceTransformation) (ResourceTransformer, error)
|
||||||
|
TransformWithContext(context.Context, ...ResourceTransformation) (ResourceTransformer, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewFeatureNotAvailableTransformer(key string, elements ...any) ResourceTransformation {
|
func NewFeatureNotAvailableTransformer(key string, elements ...any) ResourceTransformation {
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
package templates
|
package templates
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/gohugoio/hugo/helpers"
|
"github.com/gohugoio/hugo/helpers"
|
||||||
|
@ -61,11 +62,11 @@ func (t *executeAsTemplateTransform) Transform(ctx *resources.ResourceTransforma
|
||||||
|
|
||||||
ctx.OutPath = t.targetPath
|
ctx.OutPath = t.targetPath
|
||||||
|
|
||||||
return t.t.Tmpl().Execute(templ, ctx.To, t.data)
|
return t.t.Tmpl().ExecuteWithContext(ctx.Ctx, templ, ctx.To, t.data)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) ExecuteAsTemplate(res resources.ResourceTransformer, targetPath string, data any) (resource.Resource, error) {
|
func (c *Client) ExecuteAsTemplate(ctx context.Context, res resources.ResourceTransformer, targetPath string, data any) (resource.Resource, error) {
|
||||||
return res.Transform(&executeAsTemplateTransform{
|
return res.TransformWithContext(ctx, &executeAsTemplateTransform{
|
||||||
rs: c.rs,
|
rs: c.rs,
|
||||||
targetPath: helpers.ToSlashTrimLeading(targetPath),
|
targetPath: helpers.ToSlashTrimLeading(targetPath),
|
||||||
t: c.t,
|
t: c.t,
|
||||||
|
|
|
@ -69,6 +69,7 @@ func newResourceAdapter(spec *Spec, lazyPublish bool, target transformableResour
|
||||||
return &resourceAdapter{
|
return &resourceAdapter{
|
||||||
resourceTransformations: &resourceTransformations{},
|
resourceTransformations: &resourceTransformations{},
|
||||||
resourceAdapterInner: &resourceAdapterInner{
|
resourceAdapterInner: &resourceAdapterInner{
|
||||||
|
ctx: context.TODO(),
|
||||||
spec: spec,
|
spec: spec,
|
||||||
publishOnce: po,
|
publishOnce: po,
|
||||||
target: target,
|
target: target,
|
||||||
|
@ -84,6 +85,9 @@ type ResourceTransformation interface {
|
||||||
}
|
}
|
||||||
|
|
||||||
type ResourceTransformationCtx struct {
|
type ResourceTransformationCtx struct {
|
||||||
|
// The context that started the transformation.
|
||||||
|
Ctx context.Context
|
||||||
|
|
||||||
// The content to transform.
|
// The content to transform.
|
||||||
From io.Reader
|
From io.Reader
|
||||||
|
|
||||||
|
@ -180,6 +184,7 @@ func (r *resourceAdapter) Data() any {
|
||||||
func (r resourceAdapter) cloneTo(targetPath string) resource.Resource {
|
func (r resourceAdapter) cloneTo(targetPath string) resource.Resource {
|
||||||
newtTarget := r.target.cloneTo(targetPath)
|
newtTarget := r.target.cloneTo(targetPath)
|
||||||
newInner := &resourceAdapterInner{
|
newInner := &resourceAdapterInner{
|
||||||
|
ctx: r.ctx,
|
||||||
spec: r.spec,
|
spec: r.spec,
|
||||||
target: newtTarget.(transformableResource),
|
target: newtTarget.(transformableResource),
|
||||||
}
|
}
|
||||||
|
@ -278,11 +283,17 @@ func (r *resourceAdapter) Title() string {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r resourceAdapter) Transform(t ...ResourceTransformation) (ResourceTransformer, error) {
|
func (r resourceAdapter) Transform(t ...ResourceTransformation) (ResourceTransformer, error) {
|
||||||
|
return r.TransformWithContext(context.Background(), t...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r resourceAdapter) TransformWithContext(ctx context.Context, t ...ResourceTransformation) (ResourceTransformer, error) {
|
||||||
|
|
||||||
r.resourceTransformations = &resourceTransformations{
|
r.resourceTransformations = &resourceTransformations{
|
||||||
transformations: append(r.transformations, t...),
|
transformations: append(r.transformations, t...),
|
||||||
}
|
}
|
||||||
|
|
||||||
r.resourceAdapterInner = &resourceAdapterInner{
|
r.resourceAdapterInner = &resourceAdapterInner{
|
||||||
|
ctx: ctx,
|
||||||
spec: r.spec,
|
spec: r.spec,
|
||||||
publishOnce: &publishOnce{},
|
publishOnce: &publishOnce{},
|
||||||
target: r.target,
|
target: r.target,
|
||||||
|
@ -377,6 +388,7 @@ func (r *resourceAdapter) transform(publish, setContent bool) error {
|
||||||
defer bp.PutBuffer(b2)
|
defer bp.PutBuffer(b2)
|
||||||
|
|
||||||
tctx := &ResourceTransformationCtx{
|
tctx := &ResourceTransformationCtx{
|
||||||
|
Ctx: r.ctx,
|
||||||
Data: make(map[string]any),
|
Data: make(map[string]any),
|
||||||
OpenResourcePublisher: r.target.openPublishFileForWriting,
|
OpenResourcePublisher: r.target.openPublishFileForWriting,
|
||||||
}
|
}
|
||||||
|
@ -599,6 +611,9 @@ func (r *resourceAdapter) initTransform(publish, setContent bool) {
|
||||||
}
|
}
|
||||||
|
|
||||||
type resourceAdapterInner struct {
|
type resourceAdapterInner struct {
|
||||||
|
// The context that started this transformation.
|
||||||
|
ctx context.Context
|
||||||
|
|
||||||
target transformableResource
|
target transformableResource
|
||||||
|
|
||||||
spec *Spec
|
spec *Spec
|
||||||
|
|
|
@ -14,6 +14,8 @@
|
||||||
package cast
|
package cast
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
"github.com/gohugoio/hugo/deps"
|
"github.com/gohugoio/hugo/deps"
|
||||||
"github.com/gohugoio/hugo/tpl/internal"
|
"github.com/gohugoio/hugo/tpl/internal"
|
||||||
)
|
)
|
||||||
|
@ -26,7 +28,7 @@ func init() {
|
||||||
|
|
||||||
ns := &internal.TemplateFuncsNamespace{
|
ns := &internal.TemplateFuncsNamespace{
|
||||||
Name: name,
|
Name: name,
|
||||||
Context: func(args ...any) (any, error) { return ctx, nil },
|
Context: func(cctx context.Context, args ...any) (any, error) { return ctx, nil },
|
||||||
}
|
}
|
||||||
|
|
||||||
ns.AddMethodMapping(ctx.ToInt,
|
ns.AddMethodMapping(ctx.ToInt,
|
||||||
|
|
|
@ -40,7 +40,7 @@ func (ns *Namespace) Apply(ctx context.Context, c any, fname string, args ...any
|
||||||
return nil, errors.New("can't iterate over a nil value")
|
return nil, errors.New("can't iterate over a nil value")
|
||||||
}
|
}
|
||||||
|
|
||||||
fnv, found := ns.lookupFunc(fname)
|
fnv, found := ns.lookupFunc(ctx, fname)
|
||||||
if !found {
|
if !found {
|
||||||
return nil, errors.New("can't find function " + fname)
|
return nil, errors.New("can't find function " + fname)
|
||||||
}
|
}
|
||||||
|
@ -106,7 +106,7 @@ func applyFnToThis(ctx context.Context, fn, this reflect.Value, args ...any) (re
|
||||||
return reflect.ValueOf(nil), res[1].Interface().(error)
|
return reflect.ValueOf(nil), res[1].Interface().(error)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ns *Namespace) lookupFunc(fname string) (reflect.Value, bool) {
|
func (ns *Namespace) lookupFunc(ctx context.Context, fname string) (reflect.Value, bool) {
|
||||||
namespace, methodName, ok := strings.Cut(fname, ".")
|
namespace, methodName, ok := strings.Cut(fname, ".")
|
||||||
if !ok {
|
if !ok {
|
||||||
templ := ns.deps.Tmpl().(tpl.TemplateFuncGetter)
|
templ := ns.deps.Tmpl().(tpl.TemplateFuncGetter)
|
||||||
|
@ -114,16 +114,16 @@ func (ns *Namespace) lookupFunc(fname string) (reflect.Value, bool) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Namespace
|
// Namespace
|
||||||
nv, found := ns.lookupFunc(namespace)
|
nv, found := ns.lookupFunc(ctx, namespace)
|
||||||
if !found {
|
if !found {
|
||||||
return reflect.Value{}, false
|
return reflect.Value{}, false
|
||||||
}
|
}
|
||||||
|
|
||||||
fn, ok := nv.Interface().(func(...any) (any, error))
|
fn, ok := nv.Interface().(func(context.Context, ...any) (any, error))
|
||||||
if !ok {
|
if !ok {
|
||||||
return reflect.Value{}, false
|
return reflect.Value{}, false
|
||||||
}
|
}
|
||||||
v, err := fn()
|
v, err := fn(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,6 +14,8 @@
|
||||||
package collections
|
package collections
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
"github.com/gohugoio/hugo/deps"
|
"github.com/gohugoio/hugo/deps"
|
||||||
"github.com/gohugoio/hugo/tpl/internal"
|
"github.com/gohugoio/hugo/tpl/internal"
|
||||||
)
|
)
|
||||||
|
@ -26,7 +28,7 @@ func init() {
|
||||||
|
|
||||||
ns := &internal.TemplateFuncsNamespace{
|
ns := &internal.TemplateFuncsNamespace{
|
||||||
Name: name,
|
Name: name,
|
||||||
Context: func(args ...any) (any, error) { return ctx, nil },
|
Context: func(cctx context.Context, args ...any) (any, error) { return ctx, nil },
|
||||||
}
|
}
|
||||||
|
|
||||||
ns.AddMethodMapping(ctx.After,
|
ns.AddMethodMapping(ctx.After,
|
||||||
|
|
|
@ -14,6 +14,8 @@
|
||||||
package compare
|
package compare
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
"github.com/gohugoio/hugo/deps"
|
"github.com/gohugoio/hugo/deps"
|
||||||
"github.com/gohugoio/hugo/langs"
|
"github.com/gohugoio/hugo/langs"
|
||||||
"github.com/gohugoio/hugo/tpl/internal"
|
"github.com/gohugoio/hugo/tpl/internal"
|
||||||
|
@ -31,7 +33,7 @@ func init() {
|
||||||
|
|
||||||
ns := &internal.TemplateFuncsNamespace{
|
ns := &internal.TemplateFuncsNamespace{
|
||||||
Name: name,
|
Name: name,
|
||||||
Context: func(args ...any) (any, error) { return ctx, nil },
|
Context: func(cctx context.Context, args ...any) (any, error) { return ctx, nil },
|
||||||
}
|
}
|
||||||
|
|
||||||
ns.AddMethodMapping(ctx.Default,
|
ns.AddMethodMapping(ctx.Default,
|
||||||
|
|
|
@ -14,6 +14,8 @@
|
||||||
package crypto
|
package crypto
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
"github.com/gohugoio/hugo/deps"
|
"github.com/gohugoio/hugo/deps"
|
||||||
"github.com/gohugoio/hugo/tpl/internal"
|
"github.com/gohugoio/hugo/tpl/internal"
|
||||||
)
|
)
|
||||||
|
@ -26,7 +28,7 @@ func init() {
|
||||||
|
|
||||||
ns := &internal.TemplateFuncsNamespace{
|
ns := &internal.TemplateFuncsNamespace{
|
||||||
Name: name,
|
Name: name,
|
||||||
Context: func(args ...any) (any, error) { return ctx, nil },
|
Context: func(cctx context.Context, args ...any) (any, error) { return ctx, nil },
|
||||||
}
|
}
|
||||||
|
|
||||||
ns.AddMethodMapping(ctx.MD5,
|
ns.AddMethodMapping(ctx.MD5,
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
package css
|
package css
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
"github.com/gohugoio/hugo/common/types/css"
|
"github.com/gohugoio/hugo/common/types/css"
|
||||||
"github.com/gohugoio/hugo/deps"
|
"github.com/gohugoio/hugo/deps"
|
||||||
"github.com/gohugoio/hugo/tpl/internal"
|
"github.com/gohugoio/hugo/tpl/internal"
|
||||||
|
@ -31,7 +33,7 @@ func init() {
|
||||||
|
|
||||||
ns := &internal.TemplateFuncsNamespace{
|
ns := &internal.TemplateFuncsNamespace{
|
||||||
Name: name,
|
Name: name,
|
||||||
Context: func(args ...any) (any, error) { return ctx, nil },
|
Context: func(cctx context.Context, args ...any) (any, error) { return ctx, nil },
|
||||||
}
|
}
|
||||||
|
|
||||||
return ns
|
return ns
|
||||||
|
|
|
@ -14,6 +14,8 @@
|
||||||
package data
|
package data
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
"github.com/gohugoio/hugo/deps"
|
"github.com/gohugoio/hugo/deps"
|
||||||
"github.com/gohugoio/hugo/tpl/internal"
|
"github.com/gohugoio/hugo/tpl/internal"
|
||||||
)
|
)
|
||||||
|
@ -26,7 +28,7 @@ func init() {
|
||||||
|
|
||||||
ns := &internal.TemplateFuncsNamespace{
|
ns := &internal.TemplateFuncsNamespace{
|
||||||
Name: name,
|
Name: name,
|
||||||
Context: func(args ...any) (any, error) { return ctx, nil },
|
Context: func(cctx context.Context, args ...any) (any, error) { return ctx, nil },
|
||||||
}
|
}
|
||||||
|
|
||||||
ns.AddMethodMapping(ctx.GetCSV,
|
ns.AddMethodMapping(ctx.GetCSV,
|
||||||
|
|
|
@ -14,6 +14,8 @@
|
||||||
package debug
|
package debug
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
"github.com/gohugoio/hugo/deps"
|
"github.com/gohugoio/hugo/deps"
|
||||||
"github.com/gohugoio/hugo/tpl/internal"
|
"github.com/gohugoio/hugo/tpl/internal"
|
||||||
)
|
)
|
||||||
|
@ -26,7 +28,7 @@ func init() {
|
||||||
|
|
||||||
ns := &internal.TemplateFuncsNamespace{
|
ns := &internal.TemplateFuncsNamespace{
|
||||||
Name: name,
|
Name: name,
|
||||||
Context: func(args ...any) (any, error) { return ctx, nil },
|
Context: func(cctx context.Context, args ...any) (any, error) { return ctx, nil },
|
||||||
}
|
}
|
||||||
|
|
||||||
ns.AddMethodMapping(ctx.Dump,
|
ns.AddMethodMapping(ctx.Dump,
|
||||||
|
|
|
@ -15,6 +15,8 @@
|
||||||
package diagrams
|
package diagrams
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
"github.com/gohugoio/hugo/deps"
|
"github.com/gohugoio/hugo/deps"
|
||||||
"github.com/gohugoio/hugo/tpl/internal"
|
"github.com/gohugoio/hugo/tpl/internal"
|
||||||
)
|
)
|
||||||
|
@ -29,7 +31,7 @@ func init() {
|
||||||
|
|
||||||
ns := &internal.TemplateFuncsNamespace{
|
ns := &internal.TemplateFuncsNamespace{
|
||||||
Name: name,
|
Name: name,
|
||||||
Context: func(args ...any) (any, error) { return ctx, nil },
|
Context: func(cctx context.Context, args ...any) (any, error) { return ctx, nil },
|
||||||
}
|
}
|
||||||
|
|
||||||
return ns
|
return ns
|
||||||
|
|
|
@ -14,6 +14,8 @@
|
||||||
package encoding
|
package encoding
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
"github.com/gohugoio/hugo/deps"
|
"github.com/gohugoio/hugo/deps"
|
||||||
"github.com/gohugoio/hugo/tpl/internal"
|
"github.com/gohugoio/hugo/tpl/internal"
|
||||||
)
|
)
|
||||||
|
@ -26,7 +28,7 @@ func init() {
|
||||||
|
|
||||||
ns := &internal.TemplateFuncsNamespace{
|
ns := &internal.TemplateFuncsNamespace{
|
||||||
Name: name,
|
Name: name,
|
||||||
Context: func(args ...any) (any, error) { return ctx, nil },
|
Context: func(cctx context.Context, args ...any) (any, error) { return ctx, nil },
|
||||||
}
|
}
|
||||||
|
|
||||||
ns.AddMethodMapping(ctx.Base64Decode,
|
ns.AddMethodMapping(ctx.Base64Decode,
|
||||||
|
|
|
@ -14,6 +14,8 @@
|
||||||
package fmt
|
package fmt
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
"github.com/gohugoio/hugo/deps"
|
"github.com/gohugoio/hugo/deps"
|
||||||
"github.com/gohugoio/hugo/tpl/internal"
|
"github.com/gohugoio/hugo/tpl/internal"
|
||||||
)
|
)
|
||||||
|
@ -26,7 +28,7 @@ func init() {
|
||||||
|
|
||||||
ns := &internal.TemplateFuncsNamespace{
|
ns := &internal.TemplateFuncsNamespace{
|
||||||
Name: name,
|
Name: name,
|
||||||
Context: func(args ...any) (any, error) { return ctx, nil },
|
Context: func(cctx context.Context, args ...any) (any, error) { return ctx, nil },
|
||||||
}
|
}
|
||||||
|
|
||||||
ns.AddMethodMapping(ctx.Print,
|
ns.AddMethodMapping(ctx.Print,
|
||||||
|
|
|
@ -15,6 +15,8 @@
|
||||||
package hugo
|
package hugo
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
"github.com/gohugoio/hugo/deps"
|
"github.com/gohugoio/hugo/deps"
|
||||||
"github.com/gohugoio/hugo/tpl/internal"
|
"github.com/gohugoio/hugo/tpl/internal"
|
||||||
)
|
)
|
||||||
|
@ -27,7 +29,7 @@ func init() {
|
||||||
|
|
||||||
ns := &internal.TemplateFuncsNamespace{
|
ns := &internal.TemplateFuncsNamespace{
|
||||||
Name: name,
|
Name: name,
|
||||||
Context: func(args ...any) (any, error) { return h, nil },
|
Context: func(cctx context.Context, args ...any) (any, error) { return h, nil },
|
||||||
}
|
}
|
||||||
|
|
||||||
// We just add the Hugo struct as the namespace here. No method mappings.
|
// We just add the Hugo struct as the namespace here. No method mappings.
|
||||||
|
|
|
@ -14,6 +14,8 @@
|
||||||
package images
|
package images
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
"github.com/gohugoio/hugo/deps"
|
"github.com/gohugoio/hugo/deps"
|
||||||
"github.com/gohugoio/hugo/tpl/internal"
|
"github.com/gohugoio/hugo/tpl/internal"
|
||||||
)
|
)
|
||||||
|
@ -26,7 +28,7 @@ func init() {
|
||||||
|
|
||||||
ns := &internal.TemplateFuncsNamespace{
|
ns := &internal.TemplateFuncsNamespace{
|
||||||
Name: name,
|
Name: name,
|
||||||
Context: func(args ...any) (any, error) { return ctx, nil },
|
Context: func(cctx context.Context, args ...any) (any, error) { return ctx, nil },
|
||||||
}
|
}
|
||||||
|
|
||||||
ns.AddMethodMapping(ctx.Config,
|
ns.AddMethodMapping(ctx.Config,
|
||||||
|
|
|
@ -14,6 +14,8 @@
|
||||||
package inflect
|
package inflect
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
"github.com/gohugoio/hugo/deps"
|
"github.com/gohugoio/hugo/deps"
|
||||||
"github.com/gohugoio/hugo/tpl/internal"
|
"github.com/gohugoio/hugo/tpl/internal"
|
||||||
)
|
)
|
||||||
|
@ -26,7 +28,7 @@ func init() {
|
||||||
|
|
||||||
ns := &internal.TemplateFuncsNamespace{
|
ns := &internal.TemplateFuncsNamespace{
|
||||||
Name: name,
|
Name: name,
|
||||||
Context: func(args ...any) (any, error) { return ctx, nil },
|
Context: func(cctx context.Context, args ...any) (any, error) { return ctx, nil },
|
||||||
}
|
}
|
||||||
|
|
||||||
ns.AddMethodMapping(ctx.Humanize,
|
ns.AddMethodMapping(ctx.Humanize,
|
||||||
|
|
|
@ -60,29 +60,29 @@ func NewExecuter(helper ExecHelper) Executer {
|
||||||
}
|
}
|
||||||
|
|
||||||
type (
|
type (
|
||||||
dataContextKeyType string
|
pageContextKeyType string
|
||||||
hasLockContextKeyType string
|
hasLockContextKeyType string
|
||||||
stackContextKeyType string
|
stackContextKeyType string
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
// The data object passed to Execute or ExecuteWithContext gets stored with this key if not already set.
|
// The data page passed to ExecuteWithContext gets stored with this key.
|
||||||
DataContextKey = dataContextKeyType("data")
|
PageContextKey = pageContextKeyType("page")
|
||||||
// Used in partialCached to signal to nested templates that a lock is already taken.
|
// Used in partialCached to signal to nested templates that a lock is already taken.
|
||||||
HasLockContextKey = hasLockContextKeyType("hasLock")
|
HasLockContextKey = hasLockContextKeyType("hasLock")
|
||||||
)
|
)
|
||||||
|
|
||||||
// Note: The context is currently not fully implemeted in Hugo. This is a work in progress.
|
// Note: The context is currently not fully implemeted in Hugo. This is a work in progress.
|
||||||
func (t *executer) ExecuteWithContext(ctx context.Context, p Preparer, wr io.Writer, data any) error {
|
func (t *executer) ExecuteWithContext(ctx context.Context, p Preparer, wr io.Writer, data any) error {
|
||||||
|
if ctx == nil {
|
||||||
|
panic("nil context")
|
||||||
|
}
|
||||||
|
|
||||||
tmpl, err := p.Prepare()
|
tmpl, err := p.Prepare()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if v := ctx.Value(DataContextKey); v == nil {
|
|
||||||
ctx = context.WithValue(ctx, DataContextKey, data)
|
|
||||||
}
|
|
||||||
|
|
||||||
value, ok := data.(reflect.Value)
|
value, ok := data.(reflect.Value)
|
||||||
if !ok {
|
if !ok {
|
||||||
value = reflect.ValueOf(data)
|
value = reflect.ValueOf(data)
|
||||||
|
@ -102,28 +102,6 @@ func (t *executer) ExecuteWithContext(ctx context.Context, p Preparer, wr io.Wri
|
||||||
return tmpl.executeWithState(state, value)
|
return tmpl.executeWithState(state, value)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *executer) Execute(p Preparer, wr io.Writer, data any) error {
|
|
||||||
tmpl, err := p.Prepare()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
value, ok := data.(reflect.Value)
|
|
||||||
if !ok {
|
|
||||||
value = reflect.ValueOf(data)
|
|
||||||
}
|
|
||||||
|
|
||||||
state := &state{
|
|
||||||
helper: t.helper,
|
|
||||||
prep: p,
|
|
||||||
tmpl: tmpl,
|
|
||||||
wr: wr,
|
|
||||||
vars: []variable{{"$", value}},
|
|
||||||
}
|
|
||||||
|
|
||||||
return tmpl.executeWithState(state, value)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Prepare returns a template ready for execution.
|
// Prepare returns a template ready for execution.
|
||||||
func (t *Template) Prepare() (*Template, error) {
|
func (t *Template) Prepare() (*Template, error) {
|
||||||
return t, nil
|
return t, nil
|
||||||
|
|
|
@ -17,6 +17,7 @@ package internal
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"go/doc"
|
"go/doc"
|
||||||
|
@ -49,7 +50,7 @@ type TemplateFuncsNamespace struct {
|
||||||
Name string
|
Name string
|
||||||
|
|
||||||
// This is the method receiver.
|
// This is the method receiver.
|
||||||
Context func(v ...any) (any, error)
|
Context func(ctx context.Context, v ...any) (any, error)
|
||||||
|
|
||||||
// Additional info, aliases and examples, per method name.
|
// Additional info, aliases and examples, per method name.
|
||||||
MethodMappings map[string]TemplateFuncMethodMapping
|
MethodMappings map[string]TemplateFuncMethodMapping
|
||||||
|
@ -172,7 +173,7 @@ func (namespaces TemplateFuncsNamespaces) MarshalJSON() ([]byte, error) {
|
||||||
if i != 0 {
|
if i != 0 {
|
||||||
buf.WriteString(",")
|
buf.WriteString(",")
|
||||||
}
|
}
|
||||||
b, err := ns.toJSON()
|
b, err := ns.toJSON(context.TODO())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -188,7 +189,7 @@ var ignoreFuncs = map[string]bool{
|
||||||
"Reset": true,
|
"Reset": true,
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *TemplateFuncsNamespace) toJSON() ([]byte, error) {
|
func (t *TemplateFuncsNamespace) toJSON(ctx context.Context) ([]byte, error) {
|
||||||
var buf bytes.Buffer
|
var buf bytes.Buffer
|
||||||
|
|
||||||
godoc := getGetTplPackagesGoDoc()[t.Name]
|
godoc := getGetTplPackagesGoDoc()[t.Name]
|
||||||
|
@ -197,11 +198,11 @@ func (t *TemplateFuncsNamespace) toJSON() ([]byte, error) {
|
||||||
|
|
||||||
buf.WriteString(fmt.Sprintf(`%q: {`, t.Name))
|
buf.WriteString(fmt.Sprintf(`%q: {`, t.Name))
|
||||||
|
|
||||||
ctx, err := t.Context()
|
tctx, err := t.Context(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
ctxType := reflect.TypeOf(ctx)
|
ctxType := reflect.TypeOf(tctx)
|
||||||
for i := 0; i < ctxType.NumMethod(); i++ {
|
for i := 0; i < ctxType.NumMethod(); i++ {
|
||||||
method := ctxType.Method(i)
|
method := ctxType.Method(i)
|
||||||
if ignoreFuncs[method.Name] {
|
if ignoreFuncs[method.Name] {
|
||||||
|
|
|
@ -14,6 +14,8 @@
|
||||||
package js
|
package js
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
"github.com/gohugoio/hugo/deps"
|
"github.com/gohugoio/hugo/deps"
|
||||||
"github.com/gohugoio/hugo/tpl/internal"
|
"github.com/gohugoio/hugo/tpl/internal"
|
||||||
)
|
)
|
||||||
|
@ -26,7 +28,7 @@ func init() {
|
||||||
|
|
||||||
ns := &internal.TemplateFuncsNamespace{
|
ns := &internal.TemplateFuncsNamespace{
|
||||||
Name: name,
|
Name: name,
|
||||||
Context: func(args ...any) (any, error) { return ctx, nil },
|
Context: func(cctx context.Context, args ...any) (any, error) { return ctx, nil },
|
||||||
}
|
}
|
||||||
|
|
||||||
return ns
|
return ns
|
||||||
|
|
|
@ -14,6 +14,8 @@
|
||||||
package lang
|
package lang
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
"github.com/gohugoio/hugo/deps"
|
"github.com/gohugoio/hugo/deps"
|
||||||
"github.com/gohugoio/hugo/langs"
|
"github.com/gohugoio/hugo/langs"
|
||||||
"github.com/gohugoio/hugo/tpl/internal"
|
"github.com/gohugoio/hugo/tpl/internal"
|
||||||
|
@ -27,7 +29,7 @@ func init() {
|
||||||
|
|
||||||
ns := &internal.TemplateFuncsNamespace{
|
ns := &internal.TemplateFuncsNamespace{
|
||||||
Name: name,
|
Name: name,
|
||||||
Context: func(args ...any) (any, error) { return ctx, nil },
|
Context: func(cctx context.Context, args ...any) (any, error) { return ctx, nil },
|
||||||
}
|
}
|
||||||
|
|
||||||
ns.AddMethodMapping(ctx.Translate,
|
ns.AddMethodMapping(ctx.Translate,
|
||||||
|
|
|
@ -14,6 +14,8 @@
|
||||||
package math
|
package math
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
"github.com/gohugoio/hugo/deps"
|
"github.com/gohugoio/hugo/deps"
|
||||||
"github.com/gohugoio/hugo/tpl/internal"
|
"github.com/gohugoio/hugo/tpl/internal"
|
||||||
)
|
)
|
||||||
|
@ -26,7 +28,7 @@ func init() {
|
||||||
|
|
||||||
ns := &internal.TemplateFuncsNamespace{
|
ns := &internal.TemplateFuncsNamespace{
|
||||||
Name: name,
|
Name: name,
|
||||||
Context: func(args ...any) (any, error) { return ctx, nil },
|
Context: func(cctx context.Context, args ...any) (any, error) { return ctx, nil },
|
||||||
}
|
}
|
||||||
|
|
||||||
ns.AddMethodMapping(ctx.Add,
|
ns.AddMethodMapping(ctx.Add,
|
||||||
|
|
|
@ -14,6 +14,8 @@
|
||||||
package openapi3
|
package openapi3
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
"github.com/gohugoio/hugo/deps"
|
"github.com/gohugoio/hugo/deps"
|
||||||
"github.com/gohugoio/hugo/tpl/internal"
|
"github.com/gohugoio/hugo/tpl/internal"
|
||||||
)
|
)
|
||||||
|
@ -26,7 +28,7 @@ func init() {
|
||||||
|
|
||||||
ns := &internal.TemplateFuncsNamespace{
|
ns := &internal.TemplateFuncsNamespace{
|
||||||
Name: name,
|
Name: name,
|
||||||
Context: func(args ...any) (any, error) { return ctx, nil },
|
Context: func(cctx context.Context, args ...any) (any, error) { return ctx, nil },
|
||||||
}
|
}
|
||||||
|
|
||||||
ns.AddMethodMapping(ctx.Unmarshal,
|
ns.AddMethodMapping(ctx.Unmarshal,
|
||||||
|
|
|
@ -14,6 +14,8 @@
|
||||||
package os
|
package os
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
"github.com/gohugoio/hugo/deps"
|
"github.com/gohugoio/hugo/deps"
|
||||||
"github.com/gohugoio/hugo/tpl/internal"
|
"github.com/gohugoio/hugo/tpl/internal"
|
||||||
)
|
)
|
||||||
|
@ -26,7 +28,7 @@ func init() {
|
||||||
|
|
||||||
ns := &internal.TemplateFuncsNamespace{
|
ns := &internal.TemplateFuncsNamespace{
|
||||||
Name: name,
|
Name: name,
|
||||||
Context: func(args ...any) (any, error) { return ctx, nil },
|
Context: func(cctx context.Context, args ...any) (any, error) { return ctx, nil },
|
||||||
}
|
}
|
||||||
|
|
||||||
ns.AddMethodMapping(ctx.Getenv,
|
ns.AddMethodMapping(ctx.Getenv,
|
||||||
|
|
49
tpl/page/init.go
Normal file
49
tpl/page/init.go
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
// Copyright 2022 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.
|
||||||
|
|
||||||
|
// Package page provides template functions for accessing the current Page object,
|
||||||
|
// the entry level context for the current template.
|
||||||
|
package page
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"github.com/gohugoio/hugo/deps"
|
||||||
|
"github.com/gohugoio/hugo/resources/page"
|
||||||
|
"github.com/gohugoio/hugo/tpl"
|
||||||
|
|
||||||
|
"github.com/gohugoio/hugo/tpl/internal"
|
||||||
|
)
|
||||||
|
|
||||||
|
const name = "page"
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
f := func(d *deps.Deps) *internal.TemplateFuncsNamespace {
|
||||||
|
ns := &internal.TemplateFuncsNamespace{
|
||||||
|
Name: name,
|
||||||
|
Context: func(ctx context.Context, args ...interface{}) (interface{}, error) {
|
||||||
|
v := tpl.GetPageFromContext(ctx)
|
||||||
|
if v == nil {
|
||||||
|
// The multilingual sitemap does not have a page as its context.
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return v.(page.Page), nil
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
return ns
|
||||||
|
}
|
||||||
|
|
||||||
|
internal.AddTemplateFuncsNamespace(f)
|
||||||
|
}
|
179
tpl/page/integration_test.go
Normal file
179
tpl/page/integration_test.go
Normal file
|
@ -0,0 +1,179 @@
|
||||||
|
// Copyright 2023 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.
|
||||||
|
|
||||||
|
package page_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/gohugoio/hugo/hugolib"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestThatPageIsAvailableEverywhere(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
filesTemplate := `
|
||||||
|
-- config.toml --
|
||||||
|
baseURL = 'http://example.com/'
|
||||||
|
disableKinds = ["taxonomy", "term"]
|
||||||
|
enableInlineShortcodes = true
|
||||||
|
paginate = 1
|
||||||
|
enableRobotsTXT = true
|
||||||
|
LANG_CONFIG
|
||||||
|
-- content/_index.md --
|
||||||
|
---
|
||||||
|
title: "Home"
|
||||||
|
aliases: ["/homealias/"]
|
||||||
|
---
|
||||||
|
{{< shortcode "Angled Brackets" >}}
|
||||||
|
{{% shortcode "Percentage" %}}
|
||||||
|
|
||||||
|
{{< outer >}}
|
||||||
|
{{< inner >}}
|
||||||
|
{{< /outer >}}
|
||||||
|
|
||||||
|
{{< foo.inline >}}{{ if page.IsHome }}Shortcode Inline OK.{{ end }}{{< /foo.inline >}}
|
||||||
|
|
||||||
|
## Heading
|
||||||
|
|
||||||
|
[I'm an inline-style link](https://www.google.com)
|
||||||
|
|
||||||
|
![alt text](https://github.com/adam-p/markdown-here/raw/master/src/common/images/icon48.png "Logo Title Text 1")
|
||||||
|
|
||||||
|
$$$bash
|
||||||
|
echo "hello";
|
||||||
|
$$$
|
||||||
|
|
||||||
|
-- content/p1.md --
|
||||||
|
-- content/p2/index.md --
|
||||||
|
-- content/p2/p2_1.md --
|
||||||
|
---
|
||||||
|
title: "P2_1"
|
||||||
|
---
|
||||||
|
{{< foo.inline >}}{{ if page.IsHome }}Shortcode in bundled page OK.{{ else}}Failed.{{ end }}{{< /foo.inline >}}
|
||||||
|
-- content/p3.md --
|
||||||
|
-- layouts/_default/_markup/render-heading.html --
|
||||||
|
{{ if page.IsHome }}
|
||||||
|
Heading OK.
|
||||||
|
{{ end }}
|
||||||
|
-- layouts/_default/_markup/render-image.html --
|
||||||
|
{{ if page.IsHome }}
|
||||||
|
Image OK.
|
||||||
|
{{ end }}
|
||||||
|
-- layouts/_default/_markup/render-link.html --
|
||||||
|
{{ if page.IsHome }}
|
||||||
|
Link OK.
|
||||||
|
{{ end }}
|
||||||
|
-- layouts/_default/myview.html
|
||||||
|
{{ if page.IsHome }}
|
||||||
|
Render OK.
|
||||||
|
{{ end }}
|
||||||
|
-- layouts/_default/_markup/render-codeblock.html --
|
||||||
|
{{ if page.IsHome }}
|
||||||
|
Codeblock OK.
|
||||||
|
{{ end }}
|
||||||
|
-- layouts/_default/single.html --
|
||||||
|
Single.
|
||||||
|
-- layouts/index.html --
|
||||||
|
{{ if eq page . }}Page OK.{{ end }}
|
||||||
|
{{ $r := "{{ if page.IsHome }}ExecuteAsTemplate OK.{{ end }}" | resources.FromString "foo.html" | resources.ExecuteAsTemplate "foo.html" . }}
|
||||||
|
{{ $r.Content }}
|
||||||
|
{{ .RenderString "{{< renderstring.inline >}}{{ if page.IsHome }}RenderString OK.{{ end }}{{< /renderstring.inline >}}}}"}}
|
||||||
|
{{ .Render "myview" }}
|
||||||
|
{{ .Content }}
|
||||||
|
partial: {{ partials.Include "foo.html" . }}
|
||||||
|
{{ $pag := (.Paginate site.RegularPages) }}
|
||||||
|
PageNumber: {{ $pag.PageNumber }}/{{ $pag.TotalPages }}|
|
||||||
|
{{ $p2 := site.GetPage "p2" }}
|
||||||
|
{{ $p2_1 := index $p2.Resources 0 }}
|
||||||
|
Bundled page: {{ $p2_1.Content }}
|
||||||
|
-- layouts/alias.html --
|
||||||
|
{{ if eq page .Page }}Alias OK.{{ else }}Failed.{{ end }}
|
||||||
|
-- layouts/404.html --
|
||||||
|
{{ if eq page . }}404 Page OK.{{ else }}Failed.{{ end }}
|
||||||
|
-- layouts/partials/foo.html --
|
||||||
|
{{ if page.IsHome }}Partial OK.{{ else }}Failed.{{ end }}
|
||||||
|
-- layouts/shortcodes/outer.html --
|
||||||
|
{{ .Inner }}
|
||||||
|
-- layouts/shortcodes/inner.html --
|
||||||
|
{{ if page.IsHome }}Shortcode Inner OK.{{ else }}Failed.{{ end }}
|
||||||
|
-- layouts/shortcodes/shortcode.html --
|
||||||
|
{{ if page.IsHome }}Shortcode {{ .Get 0 }} OK.{{ else }}Failed.{{ end }}
|
||||||
|
-- layouts/sitemap.xml --
|
||||||
|
HRE?{{ if eq page . }}Sitemap OK.{{ else }}Failed.{{ end }}
|
||||||
|
-- layouts/robots.txt --
|
||||||
|
{{ if eq page . }}Robots OK.{{ else }}Failed.{{ end }}
|
||||||
|
-- layouts/sitemapindex.xml --
|
||||||
|
{{ if not page }}SitemapIndex OK.{{ else }}Failed.{{ end }}
|
||||||
|
|
||||||
|
`
|
||||||
|
|
||||||
|
for _, multilingual := range []bool{false, true} {
|
||||||
|
t.Run(fmt.Sprintf("multilingual-%t", multilingual), func(t *testing.T) {
|
||||||
|
// Fenced code blocks.
|
||||||
|
files := strings.ReplaceAll(filesTemplate, "$$$", "```")
|
||||||
|
|
||||||
|
if multilingual {
|
||||||
|
files = strings.ReplaceAll(files, "LANG_CONFIG", `
|
||||||
|
[languages]
|
||||||
|
[languages.en]
|
||||||
|
weight = 1
|
||||||
|
[languages.no]
|
||||||
|
weight = 2
|
||||||
|
`)
|
||||||
|
} else {
|
||||||
|
files = strings.ReplaceAll(files, "LANG_CONFIG", "")
|
||||||
|
}
|
||||||
|
|
||||||
|
b := hugolib.NewIntegrationTestBuilder(
|
||||||
|
hugolib.IntegrationTestConfig{
|
||||||
|
T: t,
|
||||||
|
TxtarString: files,
|
||||||
|
},
|
||||||
|
).Build()
|
||||||
|
|
||||||
|
b.AssertFileContent("public/index.html", `
|
||||||
|
Heading OK.
|
||||||
|
Image OK.
|
||||||
|
Link OK.
|
||||||
|
Codeblock OK.
|
||||||
|
Page OK.
|
||||||
|
Partial OK.
|
||||||
|
Shortcode Angled Brackets OK.
|
||||||
|
Shortcode Percentage OK.
|
||||||
|
Shortcode Inner OK.
|
||||||
|
Shortcode Inline OK.
|
||||||
|
ExecuteAsTemplate OK.
|
||||||
|
RenderString OK.
|
||||||
|
Render OK.
|
||||||
|
Shortcode in bundled page OK.
|
||||||
|
`)
|
||||||
|
|
||||||
|
b.AssertFileContent("public/404.html", `404 Page OK.`)
|
||||||
|
b.AssertFileContent("public/robots.txt", `Robots OK.`)
|
||||||
|
b.AssertFileContent("public/homealias/index.html", `Alias OK.`)
|
||||||
|
b.AssertFileContent("public/page/1/index.html", `Alias OK.`)
|
||||||
|
b.AssertFileContent("public/page/2/index.html", `Page OK.`)
|
||||||
|
if multilingual {
|
||||||
|
b.AssertFileContent("public/sitemap.xml", `SitemapIndex OK.`)
|
||||||
|
} else {
|
||||||
|
b.AssertFileContent("public/sitemap.xml", `Sitemap OK.`)
|
||||||
|
}
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -14,6 +14,8 @@
|
||||||
package partials
|
package partials
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
"github.com/gohugoio/hugo/deps"
|
"github.com/gohugoio/hugo/deps"
|
||||||
"github.com/gohugoio/hugo/tpl/internal"
|
"github.com/gohugoio/hugo/tpl/internal"
|
||||||
)
|
)
|
||||||
|
@ -26,7 +28,7 @@ func init() {
|
||||||
|
|
||||||
ns := &internal.TemplateFuncsNamespace{
|
ns := &internal.TemplateFuncsNamespace{
|
||||||
Name: namespaceName,
|
Name: namespaceName,
|
||||||
Context: func(args ...any) (any, error) { return ctx, nil },
|
Context: func(cctx context.Context, args ...any) (any, error) { return ctx, nil },
|
||||||
}
|
}
|
||||||
|
|
||||||
ns.AddMethodMapping(ctx.Include,
|
ns.AddMethodMapping(ctx.Include,
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
package path
|
package path
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
||||||
|
@ -29,7 +30,7 @@ func init() {
|
||||||
|
|
||||||
ns := &internal.TemplateFuncsNamespace{
|
ns := &internal.TemplateFuncsNamespace{
|
||||||
Name: name,
|
Name: name,
|
||||||
Context: func(args ...any) (any, error) { return ctx, nil },
|
Context: func(cctx context.Context, args ...any) (any, error) { return ctx, nil },
|
||||||
}
|
}
|
||||||
|
|
||||||
ns.AddMethodMapping(ctx.Split,
|
ns.AddMethodMapping(ctx.Split,
|
||||||
|
|
|
@ -15,6 +15,8 @@
|
||||||
package reflect
|
package reflect
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
"github.com/gohugoio/hugo/deps"
|
"github.com/gohugoio/hugo/deps"
|
||||||
"github.com/gohugoio/hugo/tpl/internal"
|
"github.com/gohugoio/hugo/tpl/internal"
|
||||||
)
|
)
|
||||||
|
@ -27,7 +29,7 @@ func init() {
|
||||||
|
|
||||||
ns := &internal.TemplateFuncsNamespace{
|
ns := &internal.TemplateFuncsNamespace{
|
||||||
Name: name,
|
Name: name,
|
||||||
Context: func(args ...any) (any, error) { return ctx, nil },
|
Context: func(cctx context.Context, args ...any) (any, error) { return ctx, nil },
|
||||||
}
|
}
|
||||||
|
|
||||||
ns.AddMethodMapping(ctx.IsMap,
|
ns.AddMethodMapping(ctx.IsMap,
|
||||||
|
|
|
@ -14,6 +14,8 @@
|
||||||
package resources
|
package resources
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
"github.com/gohugoio/hugo/deps"
|
"github.com/gohugoio/hugo/deps"
|
||||||
"github.com/gohugoio/hugo/tpl/internal"
|
"github.com/gohugoio/hugo/tpl/internal"
|
||||||
)
|
)
|
||||||
|
@ -30,7 +32,7 @@ func init() {
|
||||||
|
|
||||||
ns := &internal.TemplateFuncsNamespace{
|
ns := &internal.TemplateFuncsNamespace{
|
||||||
Name: name,
|
Name: name,
|
||||||
Context: func(args ...any) (any, error) { return ctx, nil },
|
Context: func(cctx context.Context, args ...any) (any, error) { return ctx, nil },
|
||||||
}
|
}
|
||||||
|
|
||||||
ns.AddMethodMapping(ctx.Get,
|
ns.AddMethodMapping(ctx.Get,
|
||||||
|
|
|
@ -15,11 +15,10 @@
|
||||||
package resources
|
package resources
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/gohugoio/hugo/common/herrors"
|
|
||||||
|
|
||||||
"errors"
|
"errors"
|
||||||
|
|
||||||
"github.com/gohugoio/hugo/common/maps"
|
"github.com/gohugoio/hugo/common/maps"
|
||||||
|
@ -227,7 +226,6 @@ func (ns *Namespace) ByType(typ any) resource.Resources {
|
||||||
//
|
//
|
||||||
// See Match for a more complete explanation about the rules used.
|
// See Match for a more complete explanation about the rules used.
|
||||||
func (ns *Namespace) Match(pattern any) resource.Resources {
|
func (ns *Namespace) Match(pattern any) resource.Resources {
|
||||||
defer herrors.Recover()
|
|
||||||
patternStr, err := cast.ToStringE(pattern)
|
patternStr, err := cast.ToStringE(pattern)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
|
@ -283,7 +281,7 @@ func (ns *Namespace) FromString(targetPathIn, contentIn any) (resource.Resource,
|
||||||
|
|
||||||
// ExecuteAsTemplate creates a Resource from a Go template, parsed and executed with
|
// ExecuteAsTemplate creates a Resource from a Go template, parsed and executed with
|
||||||
// the given data, and published to the relative target path.
|
// the given data, and published to the relative target path.
|
||||||
func (ns *Namespace) ExecuteAsTemplate(args ...any) (resource.Resource, error) {
|
func (ns *Namespace) ExecuteAsTemplate(ctx context.Context, args ...any) (resource.Resource, error) {
|
||||||
if len(args) != 3 {
|
if len(args) != 3 {
|
||||||
return nil, fmt.Errorf("must provide targetPath, the template data context and a Resource object")
|
return nil, fmt.Errorf("must provide targetPath, the template data context and a Resource object")
|
||||||
}
|
}
|
||||||
|
@ -298,7 +296,7 @@ func (ns *Namespace) ExecuteAsTemplate(args ...any) (resource.Resource, error) {
|
||||||
return nil, fmt.Errorf("type %T not supported in Resource transformations", args[2])
|
return nil, fmt.Errorf("type %T not supported in Resource transformations", args[2])
|
||||||
}
|
}
|
||||||
|
|
||||||
return ns.templatesClient.ExecuteAsTemplate(r, targetPath, data)
|
return ns.templatesClient.ExecuteAsTemplate(ctx, r, targetPath, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fingerprint transforms the given Resource with a MD5 hash of the content in
|
// Fingerprint transforms the given Resource with a MD5 hash of the content in
|
||||||
|
|
|
@ -14,6 +14,8 @@
|
||||||
package safe
|
package safe
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
"github.com/gohugoio/hugo/deps"
|
"github.com/gohugoio/hugo/deps"
|
||||||
"github.com/gohugoio/hugo/tpl/internal"
|
"github.com/gohugoio/hugo/tpl/internal"
|
||||||
)
|
)
|
||||||
|
@ -26,7 +28,7 @@ func init() {
|
||||||
|
|
||||||
ns := &internal.TemplateFuncsNamespace{
|
ns := &internal.TemplateFuncsNamespace{
|
||||||
Name: name,
|
Name: name,
|
||||||
Context: func(args ...any) (any, error) { return ctx, nil },
|
Context: func(cctx context.Context, args ...any) (any, error) { return ctx, nil },
|
||||||
}
|
}
|
||||||
|
|
||||||
ns.AddMethodMapping(ctx.CSS,
|
ns.AddMethodMapping(ctx.CSS,
|
||||||
|
|
|
@ -15,6 +15,8 @@
|
||||||
package site
|
package site
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
"github.com/gohugoio/hugo/deps"
|
"github.com/gohugoio/hugo/deps"
|
||||||
|
|
||||||
"github.com/gohugoio/hugo/tpl/internal"
|
"github.com/gohugoio/hugo/tpl/internal"
|
||||||
|
@ -27,7 +29,7 @@ func init() {
|
||||||
s := d.Site
|
s := d.Site
|
||||||
ns := &internal.TemplateFuncsNamespace{
|
ns := &internal.TemplateFuncsNamespace{
|
||||||
Name: name,
|
Name: name,
|
||||||
Context: func(args ...any) (any, error) { return s, nil },
|
Context: func(cctx context.Context, args ...any) (any, error) { return s, nil },
|
||||||
}
|
}
|
||||||
|
|
||||||
if s == nil {
|
if s == nil {
|
||||||
|
|
|
@ -14,6 +14,8 @@
|
||||||
package strings
|
package strings
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
"github.com/gohugoio/hugo/deps"
|
"github.com/gohugoio/hugo/deps"
|
||||||
"github.com/gohugoio/hugo/tpl/internal"
|
"github.com/gohugoio/hugo/tpl/internal"
|
||||||
)
|
)
|
||||||
|
@ -26,7 +28,7 @@ func init() {
|
||||||
|
|
||||||
ns := &internal.TemplateFuncsNamespace{
|
ns := &internal.TemplateFuncsNamespace{
|
||||||
Name: name,
|
Name: name,
|
||||||
Context: func(args ...any) (any, error) { return ctx, nil },
|
Context: func(cctx context.Context, args ...any) (any, error) { return ctx, nil },
|
||||||
}
|
}
|
||||||
|
|
||||||
ns.AddMethodMapping(ctx.Chomp,
|
ns.AddMethodMapping(ctx.Chomp,
|
||||||
|
|
|
@ -59,7 +59,6 @@ type UnusedTemplatesProvider interface {
|
||||||
// TemplateHandler finds and executes templates.
|
// TemplateHandler finds and executes templates.
|
||||||
type TemplateHandler interface {
|
type TemplateHandler interface {
|
||||||
TemplateFinder
|
TemplateFinder
|
||||||
Execute(t Template, wr io.Writer, data any) error
|
|
||||||
ExecuteWithContext(ctx context.Context, t Template, wr io.Writer, data any) error
|
ExecuteWithContext(ctx context.Context, t Template, wr io.Writer, data any) error
|
||||||
LookupLayout(d output.LayoutDescriptor, f output.Format) (Template, bool, error)
|
LookupLayout(d output.LayoutDescriptor, f output.Format) (Template, bool, error)
|
||||||
HasTemplate(name string) bool
|
HasTemplate(name string) bool
|
||||||
|
@ -153,10 +152,18 @@ type TemplateFuncGetter interface {
|
||||||
GetFunc(name string) (reflect.Value, bool)
|
GetFunc(name string) (reflect.Value, bool)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetDataFromContext returns the template data context (usually .Page) from ctx if set.
|
// GetPageFromContext returns the top level Page.
|
||||||
// NOte: This is not fully implemented yet.
|
func GetPageFromContext(ctx context.Context) any {
|
||||||
func GetDataFromContext(ctx context.Context) any {
|
return ctx.Value(texttemplate.PageContextKey)
|
||||||
return ctx.Value(texttemplate.DataContextKey)
|
}
|
||||||
|
|
||||||
|
// SetPageInContext sets the top level Page.
|
||||||
|
func SetPageInContext(ctx context.Context, p page) context.Context {
|
||||||
|
return context.WithValue(ctx, texttemplate.PageContextKey, p)
|
||||||
|
}
|
||||||
|
|
||||||
|
type page interface {
|
||||||
|
IsNode() bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetHasLockFromContext(ctx context.Context) bool {
|
func GetHasLockFromContext(ctx context.Context) bool {
|
||||||
|
|
|
@ -14,6 +14,8 @@
|
||||||
package templates
|
package templates
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
"github.com/gohugoio/hugo/deps"
|
"github.com/gohugoio/hugo/deps"
|
||||||
"github.com/gohugoio/hugo/tpl/internal"
|
"github.com/gohugoio/hugo/tpl/internal"
|
||||||
)
|
)
|
||||||
|
@ -26,7 +28,7 @@ func init() {
|
||||||
|
|
||||||
ns := &internal.TemplateFuncsNamespace{
|
ns := &internal.TemplateFuncsNamespace{
|
||||||
Name: name,
|
Name: name,
|
||||||
Context: func(args ...any) (any, error) { return ctx, nil },
|
Context: func(cctx context.Context, args ...any) (any, error) { return ctx, nil },
|
||||||
}
|
}
|
||||||
|
|
||||||
ns.AddMethodMapping(ctx.Exists,
|
ns.AddMethodMapping(ctx.Exists,
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
package time
|
package time
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
|
|
||||||
"github.com/gohugoio/hugo/deps"
|
"github.com/gohugoio/hugo/deps"
|
||||||
|
@ -32,7 +33,7 @@ func init() {
|
||||||
|
|
||||||
ns := &internal.TemplateFuncsNamespace{
|
ns := &internal.TemplateFuncsNamespace{
|
||||||
Name: name,
|
Name: name,
|
||||||
Context: func(args ...any) (any, error) {
|
Context: func(cctx context.Context, args ...any) (any, error) {
|
||||||
// Handle overlapping "time" namespace and func.
|
// Handle overlapping "time" namespace and func.
|
||||||
//
|
//
|
||||||
// If no args are passed to `time`, assume namespace usage and
|
// If no args are passed to `time`, assume namespace usage and
|
||||||
|
|
|
@ -232,6 +232,10 @@ func (t templateExec) Clone(d *deps.Deps) *templateExec {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *templateExec) Execute(templ tpl.Template, wr io.Writer, data any) error {
|
func (t *templateExec) Execute(templ tpl.Template, wr io.Writer, data any) error {
|
||||||
|
// TOD1
|
||||||
|
if true {
|
||||||
|
//panic("not implemented")
|
||||||
|
}
|
||||||
return t.ExecuteWithContext(context.Background(), templ, wr, data)
|
return t.ExecuteWithContext(context.Background(), templ, wr, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,8 @@
|
||||||
package transform
|
package transform
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
"github.com/gohugoio/hugo/deps"
|
"github.com/gohugoio/hugo/deps"
|
||||||
"github.com/gohugoio/hugo/tpl/internal"
|
"github.com/gohugoio/hugo/tpl/internal"
|
||||||
)
|
)
|
||||||
|
@ -26,7 +28,7 @@ func init() {
|
||||||
|
|
||||||
ns := &internal.TemplateFuncsNamespace{
|
ns := &internal.TemplateFuncsNamespace{
|
||||||
Name: name,
|
Name: name,
|
||||||
Context: func(args ...any) (any, error) { return ctx, nil },
|
Context: func(cctx context.Context, args ...any) (any, error) { return ctx, nil },
|
||||||
}
|
}
|
||||||
|
|
||||||
ns.AddMethodMapping(ctx.Emojify,
|
ns.AddMethodMapping(ctx.Emojify,
|
||||||
|
|
|
@ -14,6 +14,8 @@
|
||||||
package urls
|
package urls
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
"github.com/gohugoio/hugo/deps"
|
"github.com/gohugoio/hugo/deps"
|
||||||
"github.com/gohugoio/hugo/tpl/internal"
|
"github.com/gohugoio/hugo/tpl/internal"
|
||||||
)
|
)
|
||||||
|
@ -26,7 +28,7 @@ func init() {
|
||||||
|
|
||||||
ns := &internal.TemplateFuncsNamespace{
|
ns := &internal.TemplateFuncsNamespace{
|
||||||
Name: name,
|
Name: name,
|
||||||
Context: func(args ...any) (any, error) { return ctx, nil },
|
Context: func(cctx context.Context, args ...any) (any, error) { return ctx, nil },
|
||||||
}
|
}
|
||||||
|
|
||||||
ns.AddMethodMapping(ctx.AbsURL,
|
ns.AddMethodMapping(ctx.AbsURL,
|
||||||
|
|
Loading…
Reference in a new issue