]> git.maquefel.me Git - brevno-suite/hugo/commitdiff
Revise the fix for shortcode vs output format nilpointer
authorBjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>
Wed, 26 Oct 2022 08:09:38 +0000 (10:09 +0200)
committerBjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>
Wed, 26 Oct 2022 11:00:21 +0000 (13:00 +0200)
We do lazy initialization and (potentially) reuse of an output format's rendered content. We do this evaluation when we
start a new rendering a new output format. There are, however, situation where these borders gets crossed (e.g.
accessing content from another output format). We have a check for this in place for most cases, but not the content
rendering of inner markdown blocks inside shortcodes. This patch applies that same logic to the newly introduced
RenderContent method (which is not available from the templates).

Fixes #10391

hugolib/page.go
hugolib/page__output.go
hugolib/page__per_output.go
hugolib/shortcode.go
resources/page/page.go
resources/page/page_lazy_contentprovider.go
resources/page/page_nop.go

index 37bf528c759c395517aed79af03a207b8a4bd817..9f0d08ca3510d7d34837137558f74ff6ddf1d2c9 100644 (file)
@@ -909,6 +909,7 @@ func (p *pageState) shiftToOutputFormat(isRenderingSite bool, idx int) error {
                                }
                                return cp, nil
                        })
+                       p.pageOutput.contentRenderer = lcp
                        p.pageOutput.ContentProvider = lcp
                        p.pageOutput.TableOfContentsProvider = lcp
                        p.pageOutput.PageRenderProvider = lcp
index 4133234779786a654381e74bdc628e9810003526..4ef78b61262d948e99a1bab8524e38f394b257b3 100644 (file)
@@ -81,6 +81,7 @@ type pageOutput struct {
 
        // These interface provides the functionality that is specific for this
        // output format.
+       contentRenderer page.ContentRenderer
        pagePerOutputProviders
        page.ContentProvider
        page.TableOfContentsProvider
@@ -94,10 +95,12 @@ func (p *pageOutput) initContentProvider(cp *pageContentOutput) {
        if cp == nil {
                return
        }
+       p.contentRenderer = cp
        p.ContentProvider = cp
        p.TableOfContentsProvider = cp
        p.PageRenderProvider = cp
        p.cp = cp
+
 }
 
 func (p *pageOutput) enablePlaceholders() {
index de70047c9f789e8e31ab72f2955f5e7f9d442c5e..e8dc695076624290c34024d5daed9a1c5fdcea35 100644 (file)
@@ -123,7 +123,7 @@ func newPageContentOutput(p *pageState, po *pageOutput) (*pageContentOutput, err
                isHTML := cp.p.m.markup == "html"
 
                if !isHTML {
-                       r, err := cp.renderContent(cp.workContent, true)
+                       r, err := po.contentRenderer.RenderContent(cp.workContent, true)
                        if err != nil {
                                return err
                        }
@@ -183,7 +183,7 @@ func newPageContentOutput(p *pageState, po *pageOutput) (*pageContentOutput, err
                                }
                        }
                } else if cp.p.m.summary != "" {
-                       b, err := cp.renderContent([]byte(cp.p.m.summary), false)
+                       b, err := po.contentRenderer.RenderContent([]byte(cp.p.m.summary), false)
                        if err != nil {
                                return err
                        }
@@ -629,7 +629,7 @@ func (p *pageContentOutput) setAutoSummary() error {
        return nil
 }
 
-func (cp *pageContentOutput) renderContent(content []byte, renderTOC bool) (converter.Result, error) {
+func (cp *pageContentOutput) RenderContent(content []byte, renderTOC bool) (converter.Result, error) {
        if err := cp.initRenderHooks(); err != nil {
                return nil, err
        }
index a10afe2bcc95a944208d8832f29c1cf1e72cc6bb..2951a143608c0ae4fb174adc9ca62b8bae0b6cbf 100644 (file)
@@ -381,19 +381,8 @@ func renderShortcode(
                // Pre Hugo 0.55 this was the behaviour even for the outer-most
                // shortcode.
                if sc.doMarkup && (level > 0 || sc.configVersion() == 1) {
-
-                       cp := p.pageOutput.cp
-                       if cp == nil {
-                               var err error
-                               cp, err = newPageContentOutput(p, p.pageOutput)
-                               if err != nil {
-                                       return "", false, err
-                               }
-                               p.pageOutput.initContentProvider(cp)
-                       }
-
                        var err error
-                       b, err := p.pageOutput.cp.renderContent([]byte(inner), false)
+                       b, err := p.pageOutput.contentRenderer.RenderContent([]byte(inner), false)
                        if err != nil {
                                return "", false, err
                        }
index 50459c4655fb4f8ef810ff6b62a486523a390029..f9b8fdcec705a7f6ddd204fbf51595c9a937e436 100644 (file)
@@ -19,6 +19,7 @@ import (
        "html/template"
 
        "github.com/gohugoio/hugo/identity"
+       "github.com/gohugoio/hugo/markup/converter"
 
        "github.com/bep/gitmap"
        "github.com/gohugoio/hugo/config"
@@ -105,6 +106,11 @@ type ContentProvider interface {
        Len() int
 }
 
+// ContentRenderer provides the content rendering methods for some content.
+type ContentRenderer interface {
+       RenderContent(content []byte, renderTOC bool) (converter.Result, error)
+}
+
 // FileProvider provides the source file.
 type FileProvider interface {
        File() source.File
index ba4f8f8ef778adef6550849ec60733b1b78b6daf..2e4ddc3527235eb6a7cb7f4f2130020a130dea23 100644 (file)
@@ -17,6 +17,7 @@ import (
        "html/template"
 
        "github.com/gohugoio/hugo/lazy"
+       "github.com/gohugoio/hugo/markup/converter"
 )
 
 // OutputFormatContentProvider represents the method set that is "outputFormat aware" and that we
@@ -24,6 +25,14 @@ import (
 // Note that this set is currently not complete, but should cover the most common use cases.
 // For the others, the implementation will be from the page.NoopPage.
 type OutputFormatContentProvider interface {
+       OutputFormatPageContentProvider
+
+       // for internal use.
+       ContentRenderer
+}
+
+// OutputFormatPageContentProvider holds the exported methods from Page that are "outputFormat aware".
+type OutputFormatPageContentProvider interface {
        ContentProvider
        TableOfContentsProvider
        PageRenderProvider
@@ -46,7 +55,7 @@ type LazyContentProvider struct {
 func NewLazyContentProvider(f func() (OutputFormatContentProvider, error)) *LazyContentProvider {
        lcp := LazyContentProvider{
                init: lazy.New(),
-               cp:   NopPage,
+               cp:   NopCPageContentRenderer,
        }
        lcp.init.Add(func() (any, error) {
                cp, err := f()
@@ -122,3 +131,8 @@ func (lcp *LazyContentProvider) TableOfContents() template.HTML {
        lcp.init.Do()
        return lcp.cp.TableOfContents()
 }
+
+func (lcp *LazyContentProvider) RenderContent(content []byte, renderTOC bool) (converter.Result, error) {
+       lcp.init.Do()
+       return lcp.cp.RenderContent(content, renderTOC)
+}
index cdc5fd8b160a3d08f1a5ffca6e4ea302e4f69e20..df3227f0a4d9f5059570ce6751d2a7a83295e842 100644 (file)
 package page
 
 import (
+       "bytes"
        "html/template"
        "time"
 
        "github.com/gohugoio/hugo/identity"
+       "github.com/gohugoio/hugo/markup/converter"
 
        "github.com/gohugoio/hugo/hugofs/files"
        "github.com/gohugoio/hugo/tpl"
@@ -41,7 +43,15 @@ import (
 )
 
 var (
-       NopPage Page = new(nopPage)
+       NopPage                 Page            = new(nopPage)
+       NopContentRenderer      ContentRenderer = new(nopContentRenderer)
+       NopCPageContentRenderer                 = struct {
+               OutputFormatPageContentProvider
+               ContentRenderer
+       }{
+               NopPage,
+               NopContentRenderer,
+       }
        NilPage *nopPage
 )
 
@@ -513,3 +523,10 @@ func (p *nopPage) WordCount() int {
 func (p *nopPage) GetIdentity() identity.Identity {
        return identity.NewPathIdentity("content", "foo/bar.md")
 }
+
+type nopContentRenderer int
+
+func (r *nopContentRenderer) RenderContent(content []byte, renderTOC bool) (converter.Result, error) {
+       b := &bytes.Buffer{}
+       return b, nil
+}