Fix server rebuild issue with partials referenced from render hooks

Fixes #7990
This commit is contained in:
Bjørn Erik Pedersen 2020-11-26 08:32:49 +01:00
parent 7e223b3baa
commit e442cf30a2
6 changed files with 57 additions and 12 deletions

View file

@ -20,6 +20,43 @@ import (
qt "github.com/frankban/quicktest" qt "github.com/frankban/quicktest"
) )
func TestRenderHookEditNestedPartial(t *testing.T) {
config := `
baseURL="https://example.org"
workingDir="/mywork"
`
b := newTestSitesBuilder(t).WithWorkingDir("/mywork").WithConfigFile("toml", config).Running()
b.WithTemplates("_default/single.html", "{{ .Content }}")
b.WithTemplates("partials/mypartial1.html", `PARTIAL1 {{ partial "mypartial2.html" }}`)
b.WithTemplates("partials/mypartial2.html", `PARTIAL2`)
b.WithTemplates("_default/_markup/render-link.html", `Link {{ .Text | safeHTML }}|{{ partial "mypartial1.html" . }}END`)
b.WithContent("p1.md", `---
title: P1
---
[First Link](https://www.google.com "Google's Homepage")
`)
b.Build(BuildCfg{})
b.AssertFileContent("public/p1/index.html", `Link First Link|PARTIAL1 PARTIAL2END`)
b.EditFiles("layouts/partials/mypartial1.html", `PARTIAL1_EDITED {{ partial "mypartial2.html" }}`)
b.Build(BuildCfg{})
b.AssertFileContent("public/p1/index.html", `Link First Link|PARTIAL1_EDITED PARTIAL2END`)
b.EditFiles("layouts/partials/mypartial2.html", `PARTIAL2_EDITED`)
b.Build(BuildCfg{})
b.AssertFileContent("public/p1/index.html", `Link First Link|PARTIAL1_EDITED PARTIAL2_EDITEDEND`)
}
func TestRenderHooks(t *testing.T) { func TestRenderHooks(t *testing.T) {
config := ` config := `
baseURL="https://example.org" baseURL="https://example.org"

View file

@ -409,7 +409,7 @@ func (p *pageState) createRenderHooks(f output.Format) (*hooks.Renderers, error)
if templFound { if templFound {
renderers.LinkRenderer = hookRenderer{ renderers.LinkRenderer = hookRenderer{
templateHandler: p.s.Tmpl(), templateHandler: p.s.Tmpl(),
Provider: templ.(tpl.Info), SearchProvider: templ.(identity.SearchProvider),
templ: templ, templ: templ,
} }
} }
@ -422,7 +422,7 @@ func (p *pageState) createRenderHooks(f output.Format) (*hooks.Renderers, error)
if templFound { if templFound {
renderers.ImageRenderer = hookRenderer{ renderers.ImageRenderer = hookRenderer{
templateHandler: p.s.Tmpl(), templateHandler: p.s.Tmpl(),
Provider: templ.(tpl.Info), SearchProvider: templ.(identity.SearchProvider),
templ: templ, templ: templ,
} }
} }
@ -435,7 +435,7 @@ func (p *pageState) createRenderHooks(f output.Format) (*hooks.Renderers, error)
if templFound { if templFound {
renderers.HeadingRenderer = hookRenderer{ renderers.HeadingRenderer = hookRenderer{
templateHandler: p.s.Tmpl(), templateHandler: p.s.Tmpl(),
Provider: templ.(tpl.Info), SearchProvider: templ.(identity.SearchProvider),
templ: templ, templ: templ,
} }
} }

View file

@ -1738,7 +1738,7 @@ var infoOnMissingLayout = map[string]bool{
// where ITEM is the thing being hooked. // where ITEM is the thing being hooked.
type hookRenderer struct { type hookRenderer struct {
templateHandler tpl.TemplateHandler templateHandler tpl.TemplateHandler
identity.Provider identity.SearchProvider
templ tpl.Template templ tpl.Template
} }

View file

@ -64,13 +64,18 @@ type Identity interface {
// Manager manages identities, and is itself a Provider of Identity. // Manager manages identities, and is itself a Provider of Identity.
type Manager interface { type Manager interface {
IdentitiesProvider SearchProvider
Provider
Add(ids ...Provider) Add(ids ...Provider)
Search(id Identity) Provider
Reset() Reset()
} }
// SearchProvider provides access to the chained set of identities.
type SearchProvider interface {
Provider
IdentitiesProvider
Search(id Identity) Provider
}
// A PathIdentity is a common identity identified by a type and a path, e.g. "layouts" and "_default/single.html". // A PathIdentity is a common identity identified by a type and a path, e.g. "layouts" and "_default/single.html".
type PathIdentity struct { type PathIdentity struct {
Type string Type string

View file

@ -202,7 +202,7 @@ type renderContext struct {
type renderContextData interface { type renderContextData interface {
RenderContext() converter.RenderContext RenderContext() converter.RenderContext
DocumentContext() converter.DocumentContext DocumentContext() converter.DocumentContext
AddIdentity(id identity.Identity) AddIdentity(id identity.Provider)
} }
type renderContextDataHolder struct { type renderContextDataHolder struct {
@ -219,7 +219,7 @@ func (ctx *renderContextDataHolder) DocumentContext() converter.DocumentContext
return ctx.dctx return ctx.dctx
} }
func (ctx *renderContextDataHolder) AddIdentity(id identity.Identity) { func (ctx *renderContextDataHolder) AddIdentity(id identity.Provider) {
ctx.ids.Add(id) ctx.ids.Add(id)
} }

View file

@ -186,7 +186,7 @@ func (r *hookedRenderer) renderImage(w util.BufWriter, source []byte, node ast.N
}, },
) )
ctx.AddIdentity(h.ImageRenderer.GetIdentity()) ctx.AddIdentity(h.ImageRenderer)
return ast.WalkContinue, err return ast.WalkContinue, err
@ -248,7 +248,10 @@ func (r *hookedRenderer) renderLink(w util.BufWriter, source []byte, node ast.No
}, },
) )
ctx.AddIdentity(h.LinkRenderer.GetIdentity()) // TODO(bep) I have a working branch that fixes these rather confusing identity types,
// but for now it's important that it's not .GetIdentity() that's added here,
// to make sure we search the entire chain on changes.
ctx.AddIdentity(h.LinkRenderer)
return ast.WalkContinue, err return ast.WalkContinue, err
} }
@ -308,7 +311,7 @@ func (r *hookedRenderer) renderHeading(w util.BufWriter, source []byte, node ast
}, },
) )
ctx.AddIdentity(h.HeadingRenderer.GetIdentity()) ctx.AddIdentity(h.HeadingRenderer)
return ast.WalkContinue, err return ast.WalkContinue, err
} }