Reimplement and simplify Hugo's template system

See #13541 for details.

Fixes #13545
Fixes #13515
Closes #7964
Closes #13365
Closes #12988
Closes #4891
This commit is contained in:
Bjørn Erik Pedersen
2025-04-06 19:55:35 +02:00
parent 812ea0b325
commit 83cfdd78ca
138 changed files with 5342 additions and 4396 deletions

View File

@@ -51,6 +51,7 @@ My Section Bundle Content Content.
title: "My Section"
---
-- content/mysection/mysectiontext.txt --
Content.
-- content/_index.md --
---
title: "Home"
@@ -99,15 +100,17 @@ My Other Text: {{ $r.Content }}|{{ $r.Permalink }}|
`
func TestRebuildEditLeafBundleHeaderOnly(t *testing.T) {
b := TestRunning(t, rebuildFilesSimple)
b.AssertFileContent("public/mysection/mysectionbundle/index.html",
"My Section Bundle Content Content.")
b.EditFileReplaceAll("content/mysection/mysectionbundle/index.md", "My Section Bundle Content.", "My Section Bundle Content Edited.").Build()
b.AssertFileContent("public/mysection/mysectionbundle/index.html",
"My Section Bundle Content Edited.")
b.AssertRenderCountPage(2) // home (rss) + bundle.
b.AssertRenderCountContent(1)
t.Parallel()
for i := 0; i < 3; i++ {
b := TestRunning(t, rebuildFilesSimple)
b.AssertFileContent("public/mysection/mysectionbundle/index.html",
"My Section Bundle Content Content.")
b.EditFileReplaceAll("content/mysection/mysectionbundle/index.md", "My Section Bundle Content.", "My Section Bundle Content Edited.").Build()
b.AssertFileContent("public/mysection/mysectionbundle/index.html",
"My Section Bundle Content Edited.")
b.AssertRenderCountPage(2) // home (rss) + bundle.
b.AssertRenderCountContent(1)
}
}
func TestRebuildEditTextFileInLeafBundle(t *testing.T) {
@@ -119,7 +122,7 @@ func TestRebuildEditTextFileInLeafBundle(t *testing.T) {
b.AssertFileContent("public/mysection/mysectionbundle/index.html",
"Text 2 Content Edited")
b.AssertRenderCountPage(1)
b.AssertRenderCountContent(1)
b.AssertRenderCountContent(0)
}
func TestRebuildEditTextFileInShortcode(t *testing.T) {
@@ -180,17 +183,17 @@ func TestRebuildEditTextFileInHomeBundle(t *testing.T) {
b.AssertFileContent("public/index.html", "Home Content.")
b.AssertFileContent("public/index.html", "Home Text Content Edited.")
b.AssertRenderCountPage(1)
b.AssertRenderCountContent(1)
b.AssertRenderCountContent(0)
}
func TestRebuildEditTextFileInBranchBundle(t *testing.T) {
b := TestRunning(t, rebuildFilesSimple)
b.AssertFileContent("public/mysection/index.html", "My Section")
b.AssertFileContent("public/mysection/index.html", "My Section", "0:/mysection/mysectiontext.txt|Content.|")
b.EditFileReplaceAll("content/mysection/mysectiontext.txt", "Content.", "Content Edited.").Build()
b.AssertFileContent("public/mysection/index.html", "My Section")
b.AssertFileContent("public/mysection/index.html", "My Section", "0:/mysection/mysectiontext.txt|Content Edited.|")
b.AssertRenderCountPage(1)
b.AssertRenderCountContent(1)
b.AssertRenderCountContent(0)
}
func testRebuildBothWatchingAndRunning(t *testing.T, files string, withB func(b *IntegrationTestBuilder)) {
@@ -484,7 +487,43 @@ Home: {{ .Title }}|{{ .Content }}|
})
}
func TestRebuildSingleWithBaseof(t *testing.T) {
func TestRebuildSingle(t *testing.T) {
t.Parallel()
files := `
-- hugo.toml --
title = "Hugo Site"
baseURL = "https://example.com"
disableKinds = ["term", "taxonomy", "sitemap", "robotstxt", "404"]
disableLiveReload = true
-- content/p1.md --
---
title: "P1"
---
P1 Content.
-- layouts/index.html --
Home.
-- layouts/single.html --
Single: {{ .Title }}|{{ .Content }}|
{{ with (templates.Defer (dict "key" "global")) }}
Defer.
{{ end }}
`
b := Test(t, files, TestOptRunning())
b.AssertFileContent("public/p1/index.html", "Single: P1|", "Defer.")
b.AssertRenderCountPage(3)
b.AssertRenderCountContent(1)
b.EditFileReplaceFunc("layouts/single.html", func(s string) string {
s = strings.Replace(s, "Single", "Single Edited", 1)
s = strings.Replace(s, "Defer.", "Defer Edited.", 1)
return s
}).Build()
b.AssertFileContent("public/p1/index.html", "Single Edited: P1|", "Defer Edited.")
b.AssertRenderCountPage(1)
b.AssertRenderCountContent(0)
}
func TestRebuildSingleWithBaseofEditSingle(t *testing.T) {
t.Parallel()
files := `
@@ -498,9 +537,13 @@ disableLiveReload = true
title: "P1"
---
P1 Content.
[foo](/foo)
-- layouts/_default/baseof.html --
Baseof: {{ .Title }}|
{{ block "main" . }}default{{ end }}
{{ with (templates.Defer (dict "foo" "bar")) }}
Defer.
{{ end }}
-- layouts/index.html --
Home.
-- layouts/_default/single.html --
@@ -509,11 +552,81 @@ Single: {{ .Title }}|{{ .Content }}|
{{ end }}
`
b := Test(t, files, TestOptRunning())
b.AssertFileContent("public/p1/index.html", "Baseof: P1|\n\nSingle: P1|<p>P1 Content.</p>\n|")
b.AssertFileContent("public/p1/index.html", "Single: P1|")
b.EditFileReplaceFunc("layouts/_default/single.html", func(s string) string {
return strings.Replace(s, "Single", "Single Edited", 1)
}).Build()
b.AssertFileContent("public/p1/index.html", "Baseof: P1|\n\nSingle Edited: P1|<p>P1 Content.</p>\n|")
b.AssertFileContent("public/p1/index.html", "Single Edited")
}
func TestRebuildSingleWithBaseofEditBaseof(t *testing.T) {
t.Parallel()
files := `
-- hugo.toml --
title = "Hugo Site"
baseURL = "https://example.com"
disableKinds = ["term", "taxonomy"]
disableLiveReload = true
-- content/p1.md --
---
title: "P1"
---
P1 Content.
[foo](/foo)
-- layouts/_default/baseof.html --
Baseof: {{ .Title }}|
{{ block "main" . }}default{{ end }}
{{ with (templates.Defer (dict "foo" "bar")) }}
Defer.
{{ end }}
-- layouts/index.html --
Home.
-- layouts/_default/single.html --
{{ define "main" }}
Single: {{ .Title }}|{{ .Content }}|
{{ end }}
`
b := Test(t, files, TestOptRunning())
b.AssertFileContent("public/p1/index.html", "Single: P1|")
fmt.Println("===============")
b.EditFileReplaceAll("layouts/_default/baseof.html", "Baseof", "Baseof Edited").Build()
b.AssertFileContent("public/p1/index.html", "Baseof Edited")
}
func TestRebuildWithDeferEditRenderHook(t *testing.T) {
t.Parallel()
files := `
-- hugo.toml --
title = "Hugo Site"
baseURL = "https://example.com"
disableKinds = ["term", "taxonomy"]
disableLiveReload = true
-- content/p1.md --
---
title: "P1"
---
P1 Content.
[foo](/foo)
-- layouts/_default/baseof.html --
Baseof: {{ .Title }}|
{{ block "main" . }}default{{ end }}
{{ with (templates.Defer (dict "foo" "bar")) }}
Defer.
{{ end }}
-- layouts/single.html --
{{ define "main" }}
Single: {{ .Title }}|{{ .Content }}|
{{ end }}
-- layouts/_default/_markup/render-link.html --
Render Link.
`
b := Test(t, files, TestOptRunning())
// Edit render hook.
b.EditFileReplaceAll("layouts/_default/_markup/render-link.html", "Render Link", "Render Link Edited").Build()
b.AssertFileContent("public/p1/index.html", "Render Link Edited")
}
func TestRebuildFromString(t *testing.T) {