Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a page template func #10755

Merged
merged 1 commit into from
Feb 25, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion commands/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -577,7 +577,7 @@ func (c *commandeer) serve(s *serverCmd) error {
// to cached values if nil.
templ, handler := getErrorTemplateAndHandler(c.hugoTry())
b := &bytes.Buffer{}
err := handler.Execute(templ, b, ctx)
err := handler.ExecuteWithContext(context.Background(), templ, b, ctx)
return b, err
},
}
Expand Down
17 changes: 17 additions & 0 deletions common/hreflect/helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,23 @@ func AsTime(v reflect.Value, loc *time.Location) (time.Time, bool) {
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
func indirectInterface(v reflect.Value) reflect.Value {
if v.Kind() != reflect.Interface {
Expand Down
5 changes: 4 additions & 1 deletion hugolib/alias.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ package hugolib

import (
"bytes"
"context"
"errors"
"fmt"
"io"
Expand Down Expand Up @@ -64,8 +65,10 @@ func (a aliasHandler) renderAlias(permalink string, p page.Page) (io.Reader, err
p,
}

ctx := tpl.SetPageInContext(context.Background(), p)

buffer := new(bytes.Buffer)
err := a.t.Execute(templ, buffer, data)
err := a.t.ExecuteWithContext(ctx, templ, buffer, data)
if err != nil {
return nil, err
}
Expand Down
5 changes: 3 additions & 2 deletions hugolib/hugo_sites.go
Original file line number Diff line number Diff line change
Expand Up @@ -767,10 +767,11 @@ func (h *HugoSites) renderCrossSitesSitemap() error {
}

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")

return s.renderAndWriteXML(&s.PathSpec.ProcessingStats.Sitemaps, "sitemapindex",
return s.renderAndWriteXML(ctx, &s.PathSpec.ProcessingStats.Sitemaps, "sitemapindex",
s.siteCfg.sitemap.Filename, h.toSiteInfos(), templ)
}

Expand Down
3 changes: 3 additions & 0 deletions hugolib/page__per_output.go
Original file line number Diff line number Diff line change
Expand Up @@ -740,6 +740,7 @@ func (cp *pageContentOutput) ParseContent(ctx context.Context, content []byte) (
return nil, ok, nil
}
rctx := converter.RenderContext{
Ctx: ctx,
Src: content,
RenderTOC: true,
GetRenderer: cp.renderHooks.getRenderer,
Expand All @@ -758,6 +759,7 @@ func (cp *pageContentOutput) RenderContent(ctx context.Context, content []byte,
return nil, ok, nil
}
rctx := converter.RenderContext{
Ctx: ctx,
Src: content,
RenderTOC: true,
GetRenderer: cp.renderHooks.getRenderer,
Expand All @@ -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) {
r, err := c.Convert(
converter.RenderContext{
Ctx: ctx,
Src: content,
RenderTOC: renderTOC,
GetRenderer: cp.renderHooks.getRenderer,
Expand Down
25 changes: 14 additions & 11 deletions hugolib/site.go
Original file line number Diff line number Diff line change
Expand Up @@ -1710,12 +1710,12 @@ func (s *Site) lookupLayouts(layouts ...string) tpl.Template {
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)
renderBuffer := bp.GetBuffer()
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
}

Expand All @@ -1739,8 +1739,9 @@ func (s *Site) renderAndWritePage(statCounter *uint64, name string, targetPath s
defer bp.PutBuffer(renderBuffer)

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
}

Expand Down Expand Up @@ -1797,16 +1798,16 @@ type hookRendererTemplate struct {
resolvePosition func(ctx any) text.Position
}

func (hr hookRendererTemplate) RenderLink(w io.Writer, ctx hooks.LinkContext) error {
return hr.templateHandler.Execute(hr.templ, w, ctx)
func (hr hookRendererTemplate) RenderLink(cctx context.Context, w io.Writer, ctx hooks.LinkContext) error {
return hr.templateHandler.ExecuteWithContext(cctx, hr.templ, w, ctx)
}

func (hr hookRendererTemplate) RenderHeading(w io.Writer, ctx hooks.HeadingContext) error {
return hr.templateHandler.Execute(hr.templ, w, ctx)
func (hr hookRendererTemplate) RenderHeading(cctx context.Context, w io.Writer, ctx hooks.HeadingContext) error {
return hr.templateHandler.ExecuteWithContext(cctx, hr.templ, w, ctx)
}

func (hr hookRendererTemplate) RenderCodeblock(w hugio.FlexiWriter, ctx hooks.CodeblockContext) error {
return hr.templateHandler.Execute(hr.templ, w, ctx)
func (hr hookRendererTemplate) RenderCodeblock(cctx context.Context, w hugio.FlexiWriter, ctx hooks.CodeblockContext) error {
return hr.templateHandler.ExecuteWithContext(cctx, hr.templ, w, ctx)
}

func (hr hookRendererTemplate) ResolvePosition(ctx any) text.Position {
Expand All @@ -1817,13 +1818,15 @@ func (hr hookRendererTemplate) IsDefaultCodeBlockRenderer() bool {
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 {
s.logMissingLayout(name, "", "", outputFormat)
return nil
}

ctx := context.Background()
if ctx == nil {
panic("nil context")
}

if err = s.Tmpl().ExecuteWithContext(ctx, templ, w, d); err != nil {
return fmt.Errorf("render of %q failed: %w", name, err)
Expand Down
6 changes: 4 additions & 2 deletions hugolib/site_render.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
package hugolib

import (
"context"
"fmt"
"path"
"strings"
Expand Down Expand Up @@ -197,7 +198,7 @@ func (s *Site) renderPaginator(p *pageState, templ tpl.Template) error {
d.Addends = fmt.Sprintf("/%s/%d", paginatePath, 1)
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
}
}
Expand Down Expand Up @@ -278,14 +279,15 @@ func (s *Site) renderSitemap() error {
}

targetPath := p.targetPaths().TargetFilename
ctx := tpl.SetPageInContext(context.Background(), p)

if targetPath == "" {
return errors.New("failed to create targetPath for sitemap")
}

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 {
Expand Down
4 changes: 4 additions & 0 deletions markup/converter/converter.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ package converter

import (
"bytes"
"context"

"github.com/gohugoio/hugo/common/hexec"
"github.com/gohugoio/hugo/common/loggers"
Expand Down Expand Up @@ -141,6 +142,9 @@ type DocumentContext struct {

// RenderContext holds contextual information about the content to render.
type RenderContext struct {
// Ctx is the context.Context for the current Page render.
Ctx context.Context

// Src is the content to render.
Src []byte

Expand Down
7 changes: 4 additions & 3 deletions markup/converter/hooks/hooks.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
package hooks

import (
"context"
"io"

"github.com/gohugoio/hugo/common/hugio"
Expand Down Expand Up @@ -85,12 +86,12 @@ type AttributesOptionsSliceProvider interface {
}

type LinkRenderer interface {
RenderLink(w io.Writer, ctx LinkContext) error
RenderLink(cctx context.Context, w io.Writer, ctx LinkContext) error
identity.Provider
}

type CodeBlockRenderer interface {
RenderCodeblock(w hugio.FlexiWriter, ctx CodeblockContext) error
RenderCodeblock(cctx context.Context, w hugio.FlexiWriter, ctx CodeblockContext) error
identity.Provider
}

Expand Down Expand Up @@ -119,7 +120,7 @@ type HeadingContext interface {
// HeadingRenderer describes a uniquely identifiable rendering hook.
type HeadingRenderer interface {
// 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
}

Expand Down
1 change: 1 addition & 0 deletions markup/goldmark/codeblocks/render.go
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ func (r *htmlRenderer) renderCodeBlock(w util.BufWriter, src []byte, node ast.No
cr := renderer.(hooks.CodeBlockRenderer)

err := cr.RenderCodeblock(
ctx.RenderContext().Ctx,
w,
cbctx,
)
Expand Down
4 changes: 4 additions & 0 deletions markup/goldmark/render_hooks.go
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,7 @@ func (r *hookedRenderer) renderImage(w util.BufWriter, source []byte, node ast.N
attrs := r.filterInternalAttributes(n.Attributes())

err := lr.RenderLink(
ctx.RenderContext().Ctx,
w,
imageLinkContext{
linkContext: linkContext{
Expand Down Expand Up @@ -271,6 +272,7 @@ func (r *hookedRenderer) renderLink(w util.BufWriter, source []byte, node ast.No
ctx.Buffer.Truncate(pos)

err := lr.RenderLink(
ctx.RenderContext().Ctx,
w,
linkContext{
page: ctx.DocumentContext().Document,
Expand Down Expand Up @@ -340,6 +342,7 @@ func (r *hookedRenderer) renderAutoLink(w util.BufWriter, source []byte, node as
}

err := lr.RenderLink(
ctx.RenderContext().Ctx,
w,
linkContext{
page: ctx.DocumentContext().Document,
Expand Down Expand Up @@ -428,6 +431,7 @@ func (r *hookedRenderer) renderHeading(w util.BufWriter, source []byte, node ast
anchor := anchori.([]byte)

err := hr.RenderHeading(
ctx.RenderContext().Ctx,
w,
headingContext{
page: ctx.DocumentContext().Document,
Expand Down
3 changes: 2 additions & 1 deletion markup/highlight/highlight.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
package highlight

import (
"context"
"fmt"
gohtml "html"
"html/template"
Expand Down Expand Up @@ -122,7 +123,7 @@ func (h chromaHighlighter) HighlightCodeBlock(ctx hooks.CodeblockContext, opts a
}, 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

attributes := ctx.(hooks.AttributesOptionsSliceProvider).AttributesSlice()
Expand Down
4 changes: 4 additions & 0 deletions resources/errorResource.go
Original file line number Diff line number Diff line change
Expand Up @@ -135,3 +135,7 @@ func (e *errorResource) DecodeImage() (image.Image, error) {
func (e *errorResource) Transform(...ResourceTransformation) (ResourceTransformer, error) {
panic(e.ResourceError)
}

func (e *errorResource) TransformWithContext(context.Context, ...ResourceTransformation) (ResourceTransformer, error) {
panic(e.ResourceError)
}
7 changes: 1 addition & 6 deletions resources/page/pagegroup.go
Original file line number Diff line number Diff line change
Expand Up @@ -159,12 +159,7 @@ func (p Pages) GroupBy(ctx context.Context, key string, order ...string) (PagesG
case reflect.StructField:
fv = ppv.Elem().FieldByName(key)
case reflect.Method:
var args []reflect.Value
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]
fv = hreflect.CallMethodByName(ctx, key, ppv)[0]
}
if !fv.IsValid() {
continue
Expand Down
1 change: 1 addition & 0 deletions resources/resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ type ResourceTransformer interface {

type Transformer interface {
Transform(...ResourceTransformation) (ResourceTransformer, error)
TransformWithContext(context.Context, ...ResourceTransformation) (ResourceTransformer, error)
}

func NewFeatureNotAvailableTransformer(key string, elements ...any) ResourceTransformation {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
package templates

import (
"context"
"fmt"

"github.com/gohugoio/hugo/helpers"
Expand Down Expand Up @@ -61,11 +62,11 @@ func (t *executeAsTemplateTransform) Transform(ctx *resources.ResourceTransforma

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) {
return res.Transform(&executeAsTemplateTransform{
func (c *Client) ExecuteAsTemplate(ctx context.Context, res resources.ResourceTransformer, targetPath string, data any) (resource.Resource, error) {
return res.TransformWithContext(ctx, &executeAsTemplateTransform{
rs: c.rs,
targetPath: helpers.ToSlashTrimLeading(targetPath),
t: c.t,
Expand Down
Loading