hugo

Unnamed repository; edit this file 'description' to name the repository.

git clone git://git.shimmy1996.com/hugo.git
commit 18074d0c2375cc4bf4d7933dd4206cb878a23d1c
parent 35bfb662229226d5f3cc3077ca74323f0aa88b7d
Author: Bjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>
Date:   Tue,  9 Mar 2021 10:26:44 +0100

Fix output format handling for render hooks

Fixes #8176

Diffstat:
Mhugolib/content_render_hooks_test.go | 13++++++++++++-
Mhugolib/page.go | 10+++++-----
Mhugolib/page__output.go | 33++++++++++++++++++++++++++++++---
Mhugolib/page__per_output.go | 2+-
Mmarkup/converter/converter.go | 2+-
Mmarkup/converter/hooks/hooks.go | 54+++++++++++++++++++++++++++++++++++++++++++++++-------
Mmarkup/goldmark/render_hooks.go | 12++++++------
7 files changed, 102 insertions(+), 24 deletions(-)
diff --git a/hugolib/content_render_hooks_test.go b/hugolib/content_render_hooks_test.go
@@ -315,8 +315,10 @@ func TestRenderHooksRSS(t *testing.T) {
 
 	b.WithTemplates("index.html", `
 {{ $p := site.GetPage "p1.md" }}
+{{ $p2 := site.GetPage "p2.md" }}
 
 P1: {{ $p.Content }}
+P2: {{ $p2.Content }}
 	
 	`, "index.xml", `
 
@@ -330,6 +332,8 @@ P3: {{ $p3.Content }}
 	`,
 		"_default/_markup/render-link.html", `html-link: {{ .Destination | safeURL }}|`,
 		"_default/_markup/render-link.rss.xml", `xml-link: {{ .Destination | safeURL }}|`,
+		"_default/_markup/render-heading.html", `html-heading: {{ .Text }}|`,
+		"_default/_markup/render-heading.rss.xml", `xml-heading: {{ .Text }}|`,
 	)
 
 	b.WithContent("p1.md", `---
@@ -337,12 +341,14 @@ title: "p1"
 ---
 P1. [I'm an inline-style link](https://www.gohugo.io)
 
+# Heading in p1
 
 `, "p2.md", `---
 title: "p2"
 ---
 P1. [I'm an inline-style link](https://www.bep.is)
 
+# Heading in p2
 
 `,
 		"p3.md", `---
@@ -356,10 +362,15 @@ P3. [I'm an inline-style link](https://www.example.org)
 
 	b.Build(BuildCfg{})
 
-	b.AssertFileContent("public/index.html", "P1: <p>P1. html-link: https://www.gohugo.io|</p>")
+	b.AssertFileContent("public/index.html", `
+P1: <p>P1. html-link: https://www.gohugo.io|</p>
+html-heading: Heading in p1|
+html-heading: Heading in p2|
+`)
 	b.AssertFileContent("public/index.xml", `
 P2: <p>P1. xml-link: https://www.bep.is|</p>
 P3: <p>P3. xml-link: https://www.example.org|</p>
+xml-heading: Heading in p2|
 `)
 }
 
diff --git a/hugolib/page.go b/hugolib/page.go
@@ -390,7 +390,7 @@ func (ps *pageState) initCommonProviders(pp pagePaths) error {
 	return nil
 }
 
-func (p *pageState) createRenderHooks(f output.Format) (*hooks.Renderers, error) {
+func (p *pageState) createRenderHooks(f output.Format) (hooks.Renderers, error) {
 	layoutDescriptor := p.getLayoutDescriptor()
 	layoutDescriptor.RenderingHook = true
 	layoutDescriptor.LayoutOverride = false
@@ -401,7 +401,7 @@ func (p *pageState) createRenderHooks(f output.Format) (*hooks.Renderers, error)
 	layoutDescriptor.Kind = "render-link"
 	templ, templFound, err := p.s.Tmpl().LookupLayout(layoutDescriptor, f)
 	if err != nil {
-		return nil, err
+		return renderers, err
 	}
 	if templFound {
 		renderers.LinkRenderer = hookRenderer{
@@ -414,7 +414,7 @@ func (p *pageState) createRenderHooks(f output.Format) (*hooks.Renderers, error)
 	layoutDescriptor.Kind = "render-image"
 	templ, templFound, err = p.s.Tmpl().LookupLayout(layoutDescriptor, f)
 	if err != nil {
-		return nil, err
+		return renderers, err
 	}
 	if templFound {
 		renderers.ImageRenderer = hookRenderer{
@@ -427,7 +427,7 @@ func (p *pageState) createRenderHooks(f output.Format) (*hooks.Renderers, error)
 	layoutDescriptor.Kind = "render-heading"
 	templ, templFound, err = p.s.Tmpl().LookupLayout(layoutDescriptor, f)
 	if err != nil {
-		return nil, err
+		return renderers, err
 	}
 	if templFound {
 		renderers.HeadingRenderer = hookRenderer{
@@ -437,7 +437,7 @@ func (p *pageState) createRenderHooks(f output.Format) (*hooks.Renderers, error)
 		}
 	}
 
-	return &renderers, nil
+	return renderers, nil
 }
 
 func (p *pageState) getLayoutDescriptor() output.LayoutDescriptor {
diff --git a/hugolib/page__output.go b/hugolib/page__output.go
@@ -107,12 +107,39 @@ func (o *pageOutput) initRenderHooks() error {
 		h, err := ps.createRenderHooks(o.f)
 		if err != nil {
 			initErr = err
-		}
-		if h == nil {
 			return
 		}
-
 		o.cp.renderHooks.hooks = h
+
+		if !o.cp.renderHooksHaveVariants || h.IsZero() {
+			// Check if there is a different render hooks template
+			// for any of the other page output formats.
+			// If not, we can reuse this.
+			for _, po := range ps.pageOutputs {
+				if po.f.Name != o.f.Name {
+					h2, err := ps.createRenderHooks(po.f)
+					if err != nil {
+						initErr = err
+						return
+					}
+
+					if h2.IsZero() {
+						continue
+					}
+
+					if o.cp.renderHooks.hooks.IsZero() {
+						o.cp.renderHooks.hooks = h2
+					}
+
+					o.cp.renderHooksHaveVariants = !h2.Eq(o.cp.renderHooks.hooks)
+
+					if o.cp.renderHooksHaveVariants {
+						break
+					}
+
+				}
+			}
+		}
 	})
 
 	return initErr
diff --git a/hugolib/page__per_output.go b/hugolib/page__per_output.go
@@ -226,7 +226,7 @@ func newPageContentOutput(p *pageState, po *pageOutput) (*pageContentOutput, err
 }
 
 type renderHooks struct {
-	hooks *hooks.Renderers
+	hooks hooks.Renderers
 	init  sync.Once
 }
 
diff --git a/markup/converter/converter.go b/markup/converter/converter.go
@@ -127,7 +127,7 @@ type DocumentContext struct {
 type RenderContext struct {
 	Src         []byte
 	RenderTOC   bool
-	RenderHooks *hooks.Renderers
+	RenderHooks hooks.Renderers
 }
 
 var FeatureRenderHooks = identity.NewPathIdentity("markup", "renderingHooks")
diff --git a/markup/converter/hooks/hooks.go b/markup/converter/hooks/hooks.go
@@ -14,7 +14,9 @@
 package hooks
 
 import (
+	"fmt"
 	"io"
+	"strings"
 
 	"github.com/gohugoio/hugo/identity"
 )
@@ -67,26 +69,64 @@ type Renderers struct {
 	HeadingRenderer HeadingRenderer
 }
 
-func (r *Renderers) Eq(other interface{}) bool {
-	ro, ok := other.(*Renderers)
+func (r Renderers) Eq(other interface{}) bool {
+	ro, ok := other.(Renderers)
 	if !ok {
 		return false
 	}
-	if r == nil || ro == nil {
-		return r == nil
+
+	if r.IsZero() || ro.IsZero() {
+		return r.IsZero() && ro.IsZero()
 	}
 
-	if r.ImageRenderer.GetIdentity() != ro.ImageRenderer.GetIdentity() {
+	var b1, b2 bool
+	b1, b2 = r.ImageRenderer == nil, ro.ImageRenderer == nil
+	if (b1 || b2) && (b1 != b2) {
+		return false
+	}
+	if !b1 && r.ImageRenderer.GetIdentity() != ro.ImageRenderer.GetIdentity() {
 		return false
 	}
 
-	if r.LinkRenderer.GetIdentity() != ro.LinkRenderer.GetIdentity() {
+	b1, b2 = r.LinkRenderer == nil, ro.LinkRenderer == nil
+	if (b1 || b2) && (b1 != b2) {
+		return false
+	}
+	if !b1 && r.LinkRenderer.GetIdentity() != ro.LinkRenderer.GetIdentity() {
 		return false
 	}
 
-	if r.HeadingRenderer.GetIdentity() != ro.HeadingRenderer.GetIdentity() {
+	b1, b2 = r.HeadingRenderer == nil, ro.HeadingRenderer == nil
+	if (b1 || b2) && (b1 != b2) {
+		return false
+	}
+	if !b1 && r.HeadingRenderer.GetIdentity() != ro.HeadingRenderer.GetIdentity() {
 		return false
 	}
 
 	return true
 }
+
+func (r Renderers) IsZero() bool {
+	return r.HeadingRenderer == nil && r.LinkRenderer == nil && r.ImageRenderer == nil
+}
+
+func (r Renderers) String() string {
+	if r.IsZero() {
+		return "<zero>"
+	}
+
+	var sb strings.Builder
+
+	if r.LinkRenderer != nil {
+		sb.WriteString(fmt.Sprintf("LinkRenderer<%s>|", r.LinkRenderer.GetIdentity()))
+	}
+	if r.HeadingRenderer != nil {
+		sb.WriteString(fmt.Sprintf("HeadingRenderer<%s>|", r.HeadingRenderer.GetIdentity()))
+	}
+	if r.ImageRenderer != nil {
+		sb.WriteString(fmt.Sprintf("ImageRenderer<%s>|", r.ImageRenderer.GetIdentity()))
+	}
+
+	return sb.String()
+}
diff --git a/markup/goldmark/render_hooks.go b/markup/goldmark/render_hooks.go
@@ -206,12 +206,12 @@ func (r *hookedRenderer) renderDefaultImage(w util.BufWriter, source []byte, nod
 
 func (r *hookedRenderer) renderImage(w util.BufWriter, source []byte, node ast.Node, entering bool) (ast.WalkStatus, error) {
 	n := node.(*ast.Image)
-	var h *hooks.Renderers
+	var h hooks.Renderers
 
 	ctx, ok := w.(*renderContext)
 	if ok {
 		h = ctx.RenderContext().RenderHooks
-		ok = h != nil && h.ImageRenderer != nil
+		ok = h.ImageRenderer != nil
 	}
 
 	if !ok {
@@ -267,12 +267,12 @@ func (r *hookedRenderer) renderDefaultLink(w util.BufWriter, source []byte, node
 
 func (r *hookedRenderer) renderLink(w util.BufWriter, source []byte, node ast.Node, entering bool) (ast.WalkStatus, error) {
 	n := node.(*ast.Link)
-	var h *hooks.Renderers
+	var h hooks.Renderers
 
 	ctx, ok := w.(*renderContext)
 	if ok {
 		h = ctx.RenderContext().RenderHooks
-		ok = h != nil && h.LinkRenderer != nil
+		ok = h.LinkRenderer != nil
 	}
 
 	if !ok {
@@ -326,12 +326,12 @@ func (r *hookedRenderer) renderDefaultHeading(w util.BufWriter, source []byte, n
 
 func (r *hookedRenderer) renderHeading(w util.BufWriter, source []byte, node ast.Node, entering bool) (ast.WalkStatus, error) {
 	n := node.(*ast.Heading)
-	var h *hooks.Renderers
+	var h hooks.Renderers
 
 	ctx, ok := w.(*renderContext)
 	if ok {
 		h = ctx.RenderContext().RenderHooks
-		ok = h != nil && h.HeadingRenderer != nil
+		ok = h.HeadingRenderer != nil
 	}
 
 	if !ok {