mirror of
https://github.com/gohugoio/hugo.git
synced 2024-12-29 01:14:06 +00:00
ee359df172
The template packages are based on go1.20.5 with the patch in befec5ddbbfbd81ec84e74e15a38044d67f8785b added. This also includes a security fix that now disallows Go template actions in JS literals (inside backticks). This will throw an error saying "... appears in a JS template literal". If you're really sure this isn't a security risk in your case, you can revert to the old behaviour: ```toml [security] [security.gotemplates] allowActionJSTmpl = true ``` See https://github.com/golang/go/issues/59234 Fixes #11112
230 lines
5.2 KiB
Go
230 lines
5.2 KiB
Go
package tplimpl_test
|
|
|
|
import (
|
|
"path/filepath"
|
|
"strings"
|
|
"testing"
|
|
|
|
qt "github.com/frankban/quicktest"
|
|
"github.com/gohugoio/hugo/hugolib"
|
|
"github.com/gohugoio/hugo/tpl"
|
|
)
|
|
|
|
func TestPrintUnusedTemplates(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
files := `
|
|
-- config.toml --
|
|
baseURL = 'http://example.com/'
|
|
printUnusedTemplates=true
|
|
-- content/p1.md --
|
|
---
|
|
title: "P1"
|
|
---
|
|
{{< usedshortcode >}}
|
|
-- layouts/baseof.html --
|
|
{{ block "main" . }}{{ end }}
|
|
-- layouts/baseof.json --
|
|
{{ block "main" . }}{{ end }}
|
|
-- layouts/index.html --
|
|
{{ define "main" }}FOO{{ end }}
|
|
-- layouts/_default/single.json --
|
|
-- layouts/_default/single.html --
|
|
{{ define "main" }}MAIN{{ end }}
|
|
-- layouts/post/single.html --
|
|
{{ define "main" }}MAIN{{ end }}
|
|
-- layouts/partials/usedpartial.html --
|
|
-- layouts/partials/unusedpartial.html --
|
|
-- layouts/shortcodes/usedshortcode.html --
|
|
{{ partial "usedpartial.html" }}
|
|
-- layouts/shortcodes/unusedshortcode.html --
|
|
|
|
`
|
|
|
|
b := hugolib.NewIntegrationTestBuilder(
|
|
hugolib.IntegrationTestConfig{
|
|
T: t,
|
|
TxtarString: files,
|
|
NeedsOsFS: true,
|
|
},
|
|
)
|
|
b.Build()
|
|
|
|
unused := b.H.Tmpl().(tpl.UnusedTemplatesProvider).UnusedTemplates()
|
|
|
|
var names []string
|
|
for _, tmpl := range unused {
|
|
names = append(names, tmpl.Name())
|
|
}
|
|
|
|
b.Assert(names, qt.DeepEquals, []string{"_default/single.json", "baseof.json", "partials/unusedpartial.html", "post/single.html", "shortcodes/unusedshortcode.html"})
|
|
b.Assert(unused[0].Filename(), qt.Equals, filepath.Join(b.Cfg.WorkingDir, "layouts/_default/single.json"))
|
|
}
|
|
|
|
// Verify that the new keywords in Go 1.18 is available.
|
|
func TestGo18Constructs(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
files := `
|
|
-- config.toml --
|
|
baseURL = 'http://example.com/'
|
|
disableKinds = ["section", "home", "rss", "taxonomy", "term", "rss"]
|
|
-- content/p1.md --
|
|
---
|
|
title: "P1"
|
|
---
|
|
-- layouts/partials/counter.html --
|
|
{{ if .Scratch.Get "counter" }}{{ .Scratch.Add "counter" 1 }}{{ else }}{{ .Scratch.Set "counter" 1 }}{{ end }}{{ return true }}
|
|
-- layouts/_default/single.html --
|
|
continue:{{ range seq 5 }}{{ if eq . 2 }}{{continue}}{{ end }}{{ . }}{{ end }}:END:
|
|
break:{{ range seq 5 }}{{ if eq . 2 }}{{break}}{{ end }}{{ . }}{{ end }}:END:
|
|
continue2:{{ range seq 5 }}{{ if eq . 2 }}{{ continue }}{{ end }}{{ . }}{{ end }}:END:
|
|
break2:{{ range seq 5 }}{{ if eq . 2 }}{{ break }}{{ end }}{{ . }}{{ end }}:END:
|
|
|
|
counter1: {{ partial "counter.html" . }}/{{ .Scratch.Get "counter" }}
|
|
and1: {{ if (and false (partial "counter.html" .)) }}true{{ else }}false{{ end }}
|
|
or1: {{ if (or true (partial "counter.html" .)) }}true{{ else }}false{{ end }}
|
|
and2: {{ if (and true (partial "counter.html" .)) }}true{{ else }}false{{ end }}
|
|
or2: {{ if (or false (partial "counter.html" .)) }}true{{ else }}false{{ end }}
|
|
|
|
|
|
counter2: {{ .Scratch.Get "counter" }}
|
|
|
|
|
|
`
|
|
|
|
b := hugolib.NewIntegrationTestBuilder(
|
|
hugolib.IntegrationTestConfig{
|
|
T: t,
|
|
TxtarString: files,
|
|
NeedsOsFS: true,
|
|
},
|
|
)
|
|
b.Build()
|
|
|
|
b.AssertFileContent("public/p1/index.html", `
|
|
continue:1345:END:
|
|
break:1:END:
|
|
continue2:1345:END:
|
|
break2:1:END:
|
|
counter1: true/1
|
|
and1: false
|
|
or1: true
|
|
and2: true
|
|
or2: true
|
|
counter2: 3
|
|
`)
|
|
|
|
}
|
|
|
|
// Issue 10495
|
|
func TestCommentsBeforeBlockDefinition(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
files := `
|
|
-- config.toml --
|
|
baseURL = 'http://example.com/'
|
|
-- content/s1/p1.md --
|
|
---
|
|
title: "S1P1"
|
|
---
|
|
-- content/s2/p1.md --
|
|
---
|
|
title: "S2P1"
|
|
---
|
|
-- content/s3/p1.md --
|
|
---
|
|
title: "S3P1"
|
|
---
|
|
-- layouts/_default/baseof.html --
|
|
{{ block "main" . }}{{ end }}
|
|
-- layouts/s1/single.html --
|
|
{{/* foo */}}
|
|
{{ define "main" }}{{ .Title }}{{ end }}
|
|
-- layouts/s2/single.html --
|
|
{{- /* foo */}}
|
|
{{ define "main" }}{{ .Title }}{{ end }}
|
|
-- layouts/s3/single.html --
|
|
{{- /* foo */ -}}
|
|
{{ define "main" }}{{ .Title }}{{ end }}
|
|
`
|
|
|
|
b := hugolib.NewIntegrationTestBuilder(
|
|
hugolib.IntegrationTestConfig{
|
|
T: t,
|
|
TxtarString: files,
|
|
},
|
|
)
|
|
b.Build()
|
|
|
|
b.AssertFileContent("public/s1/p1/index.html", `S1P1`)
|
|
b.AssertFileContent("public/s2/p1/index.html", `S2P1`)
|
|
b.AssertFileContent("public/s3/p1/index.html", `S3P1`)
|
|
}
|
|
|
|
func TestGoTemplateBugs(t *testing.T) {
|
|
|
|
t.Run("Issue 11112", func(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
files := `
|
|
-- config.toml --
|
|
-- layouts/index.html --
|
|
{{ $m := dict "key" "value" }}
|
|
{{ $k := "" }}
|
|
{{ $v := "" }}
|
|
{{ range $k, $v = $m }}
|
|
{{ $k }} = {{ $v }}
|
|
{{ end }}
|
|
`
|
|
|
|
b := hugolib.NewIntegrationTestBuilder(
|
|
hugolib.IntegrationTestConfig{
|
|
T: t,
|
|
TxtarString: files,
|
|
},
|
|
)
|
|
b.Build()
|
|
|
|
b.AssertFileContent("public/index.html", `key = value`)
|
|
})
|
|
|
|
}
|
|
|
|
func TestSecurityAllowActionJSTmpl(t *testing.T) {
|
|
|
|
filesTemplate := `
|
|
-- config.toml --
|
|
SECURITYCONFIG
|
|
-- layouts/index.html --
|
|
<script>
|
|
var a = §§{{.Title }}§§;
|
|
</script>
|
|
`
|
|
|
|
files := strings.ReplaceAll(filesTemplate, "SECURITYCONFIG", "")
|
|
|
|
b, err := hugolib.NewIntegrationTestBuilder(
|
|
hugolib.IntegrationTestConfig{
|
|
T: t,
|
|
TxtarString: files,
|
|
},
|
|
).BuildE()
|
|
|
|
b.Assert(err, qt.Not(qt.IsNil))
|
|
b.Assert(err.Error(), qt.Contains, "{{.Title}} appears in a JS template literal")
|
|
|
|
files = strings.ReplaceAll(filesTemplate, "SECURITYCONFIG", `
|
|
[security]
|
|
[security.gotemplates]
|
|
allowActionJSTmpl = true
|
|
`)
|
|
|
|
b = hugolib.NewIntegrationTestBuilder(
|
|
hugolib.IntegrationTestConfig{
|
|
T: t,
|
|
TxtarString: files,
|
|
},
|
|
).Build()
|
|
|
|
}
|