Skip to content

Commit

Permalink
Fix baseof block regression
Browse files Browse the repository at this point in the history
From Hugo 0.74.0.

Fixes #7478
  • Loading branch information
bep committed Jul 13, 2020
1 parent 6e0452e commit c91dbe4
Show file tree
Hide file tree
Showing 3 changed files with 94 additions and 65 deletions.
5 changes: 3 additions & 2 deletions hugolib/hugo_sites_build_errors_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,8 @@ func TestSiteBuildErrors(t *testing.T) {
fileFixer: func(content string) string {
return strings.Replace(content, ".Title }}", ".Title }", 1)
},
assertCreateError: func(a testSiteBuildErrorAsserter, err error) {
// Base templates gets parsed at build time.
assertBuildError: func(a testSiteBuildErrorAsserter, err error) {
a.assertLineNumber(4, err)
},
},
Expand All @@ -90,7 +91,7 @@ func TestSiteBuildErrors(t *testing.T) {
a.c.Assert(fe.Position().LineNumber, qt.Equals, 5)
a.c.Assert(fe.Position().ColumnNumber, qt.Equals, 1)
a.c.Assert(fe.ChromaLexer, qt.Equals, "go-html-template")
a.assertErrorMessage("\"layouts/_default/single.html:5:1\": parse failed: template: _default/single.html.___b:5: unexpected \"}\" in operand", fe.Error())
a.assertErrorMessage("\"layouts/foo/single.html:5:1\": parse failed: template: foo/single.html:5: unexpected \"}\" in operand", fe.Error())

},
},
Expand Down
43 changes: 43 additions & 0 deletions hugolib/template_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -677,3 +677,46 @@ P3: Inline: p3
)

}

// https://github.com/gohugoio/hugo/issues/7478
func TestBaseWithAndWithoutDefine(t *testing.T) {

b := newTestSitesBuilder(t)

b.WithContent("p1.md", "---\ntitle: P\n---\nContent")

b.WithTemplates(
"_default/baseof.html", `
::Header Start:{{ block "header" . }}{{ end }}:Header End:
::{{ block "main" . }}Main{{ end }}::
`, "index.html", `
{{ define "header" }}
Home Header
{{ end }}
{{ define "main" }}
This is home main
{{ end }}
`,

"_default/single.html", `
{{ define "main" }}
This is single main
{{ end }}
`,
)

b.CreateSites().Build(BuildCfg{})

b.AssertFileContent("public/index.html", `
Home Header
This is home main
`,
)

b.AssertFileContent("public/p1/index.html", `
::Header Start::Header End:
This is single main
`,
)

}
111 changes: 48 additions & 63 deletions tpl/tplimpl/template.go
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ func newTemplateExec(d *deps.Deps) (*templateExec, error) {
baseof: make(map[string]templateInfo),
needsBaseof: make(map[string]templateInfo),

main: newTemplateNamespace(funcMap, false),
main: newTemplateNamespace(funcMap),

Deps: d,
layoutHandler: output.NewLayoutHandler(),
Expand Down Expand Up @@ -174,17 +174,11 @@ func newTemplateExec(d *deps.Deps) (*templateExec, error) {
return e, nil
}

func newTemplateNamespace(funcs map[string]interface{}, lock bool) *templateNamespace {
var mu *sync.RWMutex
if lock {
mu = &sync.RWMutex{}
}

func newTemplateNamespace(funcs map[string]interface{}) *templateNamespace {
return &templateNamespace{
prototypeHTML: htmltemplate.New("").Funcs(funcs),
prototypeText: texttemplate.New("").Funcs(funcs),
templateStateMap: &templateStateMap{
mu: mu,
templates: make(map[string]*templateState),
},
}
Expand Down Expand Up @@ -426,6 +420,10 @@ func (t *templateHandler) findLayout(d output.LayoutDescriptor, f output.Format)

t.applyTemplateTransformers(t.main, ts)

if err := t.extractPartials(ts.Template); err != nil {
return nil, false, err
}

return ts, true, nil

}
Expand Down Expand Up @@ -570,24 +568,12 @@ func (t *templateHandler) addTemplateFile(name, path string) error {
if isBaseTemplatePath(name) {
// Store it for later.
t.baseof[name] = tinfo
// Also parse and add it on its own to make sure we reach the inline partials.
tinfo.name = name + ".___b"
_, err := t.addTemplateTo(tinfo, t.main)
if err != nil {
return tinfo.errWithFileContext("parse failed", err)
}
return nil
}

needsBaseof := !t.noBaseNeeded(name) && needsBaseTemplate(tinfo.template)
if needsBaseof {
t.needsBaseof[name] = tinfo
// Also parse and add it on its own to make sure we reach the inline partials.
tinfo.name = name + ".___b"
_, err := t.addTemplateTo(tinfo, t.main)
if err != nil {
return tinfo.errWithFileContext("parse failed", err)
}
return nil
}

Expand Down Expand Up @@ -748,6 +734,38 @@ func (t *templateHandler) noBaseNeeded(name string) bool {
return strings.Contains(name, "_markup/")
}

func (t *templateHandler) extractPartials(templ tpl.Template) error {
templs := templates(templ)
for _, templ := range templs {
if templ.Name() == "" || !strings.HasPrefix(templ.Name(), "partials/") {
continue
}

ts := newTemplateState(templ, templateInfo{name: templ.Name()})
ts.typ = templatePartial

t.main.mu.RLock()
_, found := t.main.templates[templ.Name()]
t.main.mu.RUnlock()

if !found {
t.main.mu.Lock()
// This is a template defined inline.
_, err := applyTemplateTransformers(ts, t.main.newTemplateLookup(ts))
if err != nil {
t.main.mu.Unlock()
return err
}
t.main.templates[templ.Name()] = ts
t.main.mu.Unlock()

}
}

return nil

}

func (t *templateHandler) postTransform() error {
defineCheckedHTML := false
defineCheckedText := false
Expand All @@ -774,25 +792,8 @@ func (t *templateHandler) postTransform() error {
defineCheckedHTML = true
}

templs := templates(v.Template)
for _, templ := range templs {
if templ.Name() == "" || !strings.HasPrefix(templ.Name(), "partials/") {
continue
}

ts := newTemplateState(templ, templateInfo{name: templ.Name()})
ts.typ = templatePartial

if _, found := t.main.templates[templ.Name()]; !found {
// This is a template defined inline.

_, err := applyTemplateTransformers(ts, t.main.newTemplateLookup(ts))
if err != nil {
return err
}
t.main.templates[templ.Name()] = ts

}
if err := t.extractPartials(v.Template); err != nil {
return err
}
}

Expand Down Expand Up @@ -828,20 +829,12 @@ type templateNamespace struct {
*templateStateMap
}

func (t templateNamespace) Clone(lock bool) *templateNamespace {
if t.mu != nil {
t.mu.Lock()
defer t.mu.Unlock()
}

var mu *sync.RWMutex
if lock {
mu = &sync.RWMutex{}
}
func (t templateNamespace) Clone() *templateNamespace {
t.mu.Lock()
defer t.mu.Unlock()

t.templateStateMap = &templateStateMap{
templates: make(map[string]*templateState),
mu: mu,
}

t.prototypeText = texttemplate.Must(t.prototypeText.Clone())
Expand All @@ -851,20 +844,14 @@ func (t templateNamespace) Clone(lock bool) *templateNamespace {
}

func (t *templateNamespace) Lookup(name string) (tpl.Template, bool) {
if t.mu != nil {
t.mu.RLock()
defer t.mu.RUnlock()
}
t.mu.RLock()
defer t.mu.RUnlock()

templ, found := t.templates[name]
if !found {
return nil, false
}

if t.mu != nil {
return &templateWrapperWithLock{RWMutex: t.mu, Template: templ}, true
}

return templ, found
}

Expand Down Expand Up @@ -892,10 +879,8 @@ func (t *templateNamespace) newTemplateLookup(in *templateState) func(name strin
}

func (t *templateNamespace) parse(info templateInfo) (*templateState, error) {
if t.mu != nil {
t.mu.Lock()
defer t.mu.Unlock()
}
t.mu.Lock()
defer t.mu.Unlock()

if info.isText {
prototype := t.prototypeText
Expand Down Expand Up @@ -952,7 +937,7 @@ func isText(templ tpl.Template) bool {
}

type templateStateMap struct {
mu *sync.RWMutex // May be nil
mu sync.RWMutex
templates map[string]*templateState
}

Expand Down

0 comments on commit c91dbe4

Please sign in to comment.