mirror of
https://github.com/gohugoio/hugo.git
synced 2024-12-26 00:32:07 +00:00
Revise the fix for shortcode vs output format nilpointer
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
This commit is contained in:
parent
e5d2a8f6a3
commit
631d768be9
7 changed files with 47 additions and 17 deletions
|
@ -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
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -16,10 +16,12 @@
|
|||
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
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue