From f45cb3172862140883cfa08bd401c17e1ada5b39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Pedersen?= Date: Thu, 30 Jan 2020 20:02:26 +0100 Subject: Fix base template handling with preceding comments Fixes #6816 --- tpl/tplimpl/template.go | 41 +++++++++++++++++++++++++++++++++++------ tpl/tplimpl/template_test.go | 13 ++++++++++--- 2 files changed, 45 insertions(+), 9 deletions(-) (limited to 'tpl') diff --git a/tpl/tplimpl/template.go b/tpl/tplimpl/template.go index a87cdde34..457a5cb92 100644 --- a/tpl/tplimpl/template.go +++ b/tpl/tplimpl/template.go @@ -22,6 +22,8 @@ import ( "strings" "sync" "time" + "unicode" + "unicode/utf8" "github.com/gohugoio/hugo/common/types" @@ -72,13 +74,40 @@ var ( _ tpl.Info = (*templateState)(nil) ) -// A template needing a base template is a template with only define sections, -// 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`) +var baseTemplateDefineRe = regexp.MustCompile(`^{{-?\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 { - 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 { @@ -549,7 +578,7 @@ func (t *templateHandler) addTemplateFile(name, path string) error { return nil } - needsBaseof := !t.noBaseNeeded(name) && baseTemplateDefineRe.MatchString(tinfo.template) + needsBaseof := !t.noBaseNeeded(name) && needsBaseTemplate(tinfo.template) if needsBaseof { t.needsBaseof[name] = tinfo return nil diff --git a/tpl/tplimpl/template_test.go b/tpl/tplimpl/template_test.go index 05be5bbb7..5e372d986 100644 --- a/tpl/tplimpl/template_test.go +++ b/tpl/tplimpl/template_test.go @@ -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(` 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) } -- cgit v1.2.3