Fix base template handling with preceding comments

Fixes #6816
This commit is contained in:
Bjørn Erik Pedersen 2020-01-30 20:02:26 +01:00
parent 49ef647203
commit f45cb31728
3 changed files with 66 additions and 9 deletions

View file

@ -398,6 +398,27 @@ title: The Page
} }
// https://github.com/gohugoio/hugo/issues/6816
func TestTemplateBaseWithComment(t *testing.T) {
t.Parallel()
b := newTestSitesBuilder(t).WithSimpleConfigFile()
b.WithTemplatesAdded(
"baseof.html", `Base: {{ block "main" . }}{{ end }}`,
"index.html", `
{{/* A comment */}}
{{ define "main" }}
Bonjour
{{ end }}
`)
b.Build(BuildCfg{})
b.AssertFileContent("public/index.html", `Base:
Bonjour`)
}
func TestTemplateLookupSite(t *testing.T) { func TestTemplateLookupSite(t *testing.T) {
t.Run("basic", func(t *testing.T) { t.Run("basic", func(t *testing.T) {
t.Parallel() t.Parallel()

View file

@ -22,6 +22,8 @@ import (
"strings" "strings"
"sync" "sync"
"time" "time"
"unicode"
"unicode/utf8"
"github.com/gohugoio/hugo/common/types" "github.com/gohugoio/hugo/common/types"
@ -72,13 +74,40 @@ var (
_ tpl.Info = (*templateState)(nil) _ tpl.Info = (*templateState)(nil)
) )
// A template needing a base template is a template with only define sections, var baseTemplateDefineRe = regexp.MustCompile(`^{{-?\s*define`)
// but we check only for the start.
// If a base template does not exist, we will handle that when it's used.
var baseTemplateDefineRe = regexp.MustCompile(`^\s*{{-?\s*define`)
// needsBaseTemplate returns true if the first non-comment template block is a
// define block.
// If a base template does not exist, we will handle that when it's used.
func needsBaseTemplate(templ string) bool { func needsBaseTemplate(templ string) bool {
return baseTemplateDefineRe.MatchString(templ) idx := -1
inComment := false
for i := 0; i < len(templ); {
if !inComment && strings.HasPrefix(templ[i:], "{{/*") {
inComment = true
i += 4
} else if inComment && strings.HasPrefix(templ[i:], "*/}}") {
inComment = false
i += 4
} else {
r, size := utf8.DecodeRuneInString(templ[i:])
if !inComment {
if strings.HasPrefix(templ[i:], "{{") {
idx = i
break
} else if !unicode.IsSpace(r) {
break
}
}
i += size
}
}
if idx == -1 {
return false
}
return baseTemplateDefineRe.MatchString(templ[idx:])
} }
func newIdentity(name string) identity.Manager { func newIdentity(name string) identity.Manager {
@ -549,7 +578,7 @@ func (t *templateHandler) addTemplateFile(name, path string) error {
return nil return nil
} }
needsBaseof := !t.noBaseNeeded(name) && baseTemplateDefineRe.MatchString(tinfo.template) needsBaseof := !t.noBaseNeeded(name) && needsBaseTemplate(tinfo.template)
if needsBaseof { if needsBaseof {
t.needsBaseof[name] = tinfo t.needsBaseof[name] = tinfo
return nil return nil

View file

@ -25,9 +25,16 @@ func TestNeedsBaseTemplate(t *testing.T) {
c.Assert(needsBaseTemplate(`{{define "main" }}`), qt.Equals, true) c.Assert(needsBaseTemplate(`{{define "main" }}`), qt.Equals, true)
c.Assert(needsBaseTemplate(`{{- define "main" }}`), qt.Equals, true) c.Assert(needsBaseTemplate(`{{- define "main" }}`), qt.Equals, true)
c.Assert(needsBaseTemplate(`{{-define "main" }}`), qt.Equals, true) c.Assert(needsBaseTemplate(`{{-define "main" }}`), qt.Equals, true)
c.Assert(needsBaseTemplate(`
{{-define "main" }}
`), qt.Equals, true)
c.Assert(needsBaseTemplate(` {{ define "main" }}`), qt.Equals, true) c.Assert(needsBaseTemplate(` {{ define "main" }}`), qt.Equals, true)
c.Assert(needsBaseTemplate(` c.Assert(needsBaseTemplate(`
{{ define "main" }}`), qt.Equals, true) {{ define "main" }}`), qt.Equals, true)
c.Assert(needsBaseTemplate(` A {{ define "main" }}`), qt.Equals, false) c.Assert(needsBaseTemplate(` A {{ define "main" }}`), qt.Equals, false)
c.Assert(needsBaseTemplate(` {{ printf "foo" }}`), qt.Equals, false)
c.Assert(needsBaseTemplate(`{{/* comment */}} {{ define "main" }}`), qt.Equals, true)
c.Assert(needsBaseTemplate(` {{/* comment */}} A {{ define "main" }}`), qt.Equals, false)
} }