hugolib: Fix page/section name collision regression

Fixes #15046

When a regular page (e.g. content/s1.md) and a section (content/s1/)
share the same tree key, the assembler must not overwrite the real page
with a synthetic section. Restore the existence guard that was present
in v0.152.2.

The fix checks if a node already exists at the section key before
inserting a synthetic section during root section creation.

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Joe Mooring
2026-06-16 20:37:07 -07:00
committed by Bjørn Erik Pedersen
parent 96e06e1ab8
commit f013346667
2 changed files with 43 additions and 0 deletions
+9
View File
@@ -508,6 +508,15 @@ func (a *allPagesAssembler) doCreatePages(prefix string, depth int) error {
// Try to preserve the original casing if possible.
sectionUnnormalized := p.Unnormalized().Section()
rootSectionPath := a.h.Conf.PathParser().Parse(files.ComponentFolderContent, "/"+sectionUnnormalized+"/_index.md")
// A regular page (e.g. content/s1.md) may share the same tree
// key as its section (both map to /s1). In that case the page
// itself already occupies the section root; creating a synthetic
// section on top of it would overwrite the real content.
if _, exists := treePages.GetRaw(rootSectionPath.Base()); exists {
return true, nil
}
var rootSectionPages contentNode
rootSectionPages, _, err = transformPages(rootSectionPath.Base(), &pageMetaSource{
pathInfo: rootSectionPath,
+34
View File
@@ -14,6 +14,7 @@
package hugolib
import (
"strings"
"testing"
)
@@ -148,3 +149,36 @@ All: {{ .Title }}|{{ .Kind }}|
b.AssertFileExists("public/a/b/index.html", false)
b.AssertFileContent("public/a/b/c/index.html", "All: C|section|")
}
// See issue 15046.
func TestSectionAndSiblingPageURLs(t *testing.T) {
t.Parallel()
files := `
-- hugo.toml --
disableKinds = ['home','rss','sitemap','taxonomy','term']
uglyURLs = false
-- content/s1/p1.md --
---
title: content/s1/p1.md
---
-- content/s1.md --
---
title: content/s1.md
---
-- layouts/all.html --
{{ .Title }}
`
b := Test(t, files)
b.AssertFileContent("public/s1/index.html", "content/s1.md")
b.AssertFileContent("public/s1/p1/index.html", "content/s1/p1.md")
files = strings.ReplaceAll(files, "uglyURLs = false", "uglyURLs = true")
b = Test(t, files)
b.AssertFileContent("public/s1.html", "content/s1.md")
b.AssertFileContent("public/s1/p1.html", "content/s1/p1.md")
}