]> git.maquefel.me Git - brevno-suite/hugo/commitdiff
paths: Fix handling of _ as a path name
authorkhayyam <khayyam.saleem@gmail.com>
Mon, 16 Feb 2026 16:32:45 +0000 (11:32 -0500)
committerGitHub <noreply@github.com>
Mon, 16 Feb 2026 16:32:45 +0000 (17:32 +0100)
Fixes #14344

common/paths/pathparser.go
hugolib/site_test.go

index fbba141b86645c5057c30c6d399ac6da7ade3599..5d828df142545cc4b4742bfe7eae8f670a38adcc 100644 (file)
@@ -30,10 +30,18 @@ import (
 )
 
 const (
-       identifierBaseof         = "baseof"
-       identifierCurstomWrapper = "_"
+       identifierBaseof        = "baseof"
+       identifierCustomWrapper = "_"
 )
 
+// isCustomWrapperIdentifier tells whether a supplied path is of the form _xyz_.
+// must have non-empty content between the identifierCustomWrapper's to pass.
+func isCustomWrapperIdentifier(s string) bool {
+       return len(s) > 2*len(identifierCustomWrapper) &&
+               strings.HasPrefix(s, identifierCustomWrapper) &&
+               strings.HasSuffix(s, identifierCustomWrapper)
+}
+
 // PathParser parses and manages paths.
 type PathParser struct {
        // Maps the language code to its index in the languages/sites slice.
@@ -188,7 +196,7 @@ func (pp *PathParser) parseIdentifier(component, s string, p *Path, i, lastDot,
        id := types.LowHigh[string]{Low: i + 1, High: high}
        sid := p.s[id.Low:id.High]
 
-       if strings.HasPrefix(sid, identifierCurstomWrapper) && strings.HasSuffix(sid, identifierCurstomWrapper) {
+       if isCustomWrapperIdentifier(sid) {
                p.identifiersKnown = append(p.identifiersKnown, id)
                p.posIdentifierCustom = len(p.identifiersKnown) - 1
                found = true
@@ -775,7 +783,7 @@ func (p *Path) Lang() string {
 }
 
 func (p *Path) Custom() string {
-       return strings.TrimSuffix(strings.TrimPrefix(p.identifierAsString(p.posIdentifierCustom), identifierCurstomWrapper), identifierCurstomWrapper)
+       return strings.TrimSuffix(strings.TrimPrefix(p.identifierAsString(p.posIdentifierCustom), identifierCustomWrapper), identifierCustomWrapper)
 }
 
 func (p *Path) Identifier(i int) string {
index 01da9d6b87aafc4dc807c59533955ce323d540e9..dc9f141488eba03555c08eb786e5b22faa6b4062 100644 (file)
@@ -458,6 +458,33 @@ Content: {{ .Content }}
        b.AssertFileContent("public/post/nested-a/content-a/index.html", `Content: http://example.com/post/nested-b/content-b/`)
 }
 
+// Issue 14344
+func TestRefUnderscoreSection(t *testing.T) {
+       t.Parallel()
+
+       files := `
+-- hugo.toml --
+baseURL = 'https://example.org/'
+-- layouts/home.html --
+{{ .Content }}
+-- content/_index.md --
+---
+title: home
+---
+{{% ref "definitions/_" %}}
+-- content/definitions/_/_index.md --
+---
+title: underscore
+---
+`
+
+       b := Test(t, files)
+
+       b.AssertFileContent("public/index.html",
+               `https://example.org/definitions/_/`,
+       )
+}
+
 func TestClassCollector(t *testing.T) {
        for _, minify := range []bool{false, true} {
                t.Run(fmt.Sprintf("minify-%t", minify), func(t *testing.T) {