]> git.maquefel.me Git - brevno-suite/hugo/commitdiff
Revert the breaking change from 0.146.0 with dots in content filenames
authorBjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>
Mon, 21 Apr 2025 14:15:21 +0000 (16:15 +0200)
committerBjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>
Tue, 22 Apr 2025 17:23:19 +0000 (19:23 +0200)
Closes #13632

common/paths/pathparser.go
common/paths/pathparser_test.go
common/paths/paths_integration_test.go
hugolib/collections_test.go
hugolib/content_render_hooks_test.go
hugolib/site_test.go
tpl/tplimpl/templatestore.go
tpl/tplimpl/templatestore_integration_test.go

index c04f2022e4f165504dd5fef20c1f709bc9722582..b0a2f9fc4d0abc3b21b12648388b4fcd9213b84a 100644 (file)
@@ -124,14 +124,15 @@ func (pp *PathParser) parseIdentifier(component, s string, p *Path, i, lastDot i
        if p.posContainerHigh != -1 {
                return
        }
-       mayHaveLang := pp.LanguageIndex != nil
+       mayHaveLang := p.posIdentifierLanguage == -1 && pp.LanguageIndex != nil
        mayHaveLang = mayHaveLang && (component == files.ComponentFolderContent || component == files.ComponentFolderLayouts)
        mayHaveOutputFormat := component == files.ComponentFolderLayouts
-       mayHaveKind := mayHaveOutputFormat
+       mayHaveKind := p.posIdentifierKind == -1 && mayHaveOutputFormat
+       mayHaveLayout := component == files.ComponentFolderLayouts
 
        var found bool
        var high int
-       if len(p.identifiers) > 0 {
+       if len(p.identifiersKnown) > 0 {
                high = lastDot
        } else {
                high = len(p.s)
@@ -139,9 +140,9 @@ func (pp *PathParser) parseIdentifier(component, s string, p *Path, i, lastDot i
        id := types.LowHigh[string]{Low: i + 1, High: high}
        sid := p.s[id.Low:id.High]
 
-       if len(p.identifiers) == 0 {
+       if len(p.identifiersKnown) == 0 {
                // The first is always the extension.
-               p.identifiers = append(p.identifiers, id)
+               p.identifiersKnown = append(p.identifiersKnown, id)
                found = true
 
                // May also be the output format.
@@ -164,8 +165,8 @@ func (pp *PathParser) parseIdentifier(component, s string, p *Path, i, lastDot i
                        }
                        found = langFound
                        if langFound {
-                               p.identifiers = append(p.identifiers, id)
-                               p.posIdentifierLanguage = len(p.identifiers) - 1
+                               p.identifiersKnown = append(p.identifiersKnown, id)
+                               p.posIdentifierLanguage = len(p.identifiersKnown) - 1
 
                        }
                }
@@ -177,28 +178,33 @@ func (pp *PathParser) parseIdentifier(component, s string, p *Path, i, lastDot i
                        // false positives on the form css.html.
                        if pp.IsOutputFormat(sid, p.Ext()) {
                                found = true
-                               p.identifiers = append(p.identifiers, id)
-                               p.posIdentifierOutputFormat = len(p.identifiers) - 1
+                               p.identifiersKnown = append(p.identifiersKnown, id)
+                               p.posIdentifierOutputFormat = len(p.identifiersKnown) - 1
                        }
                }
 
                if !found && mayHaveKind {
                        if kinds.GetKindMain(sid) != "" {
                                found = true
-                               p.identifiers = append(p.identifiers, id)
-                               p.posIdentifierKind = len(p.identifiers) - 1
+                               p.identifiersKnown = append(p.identifiersKnown, id)
+                               p.posIdentifierKind = len(p.identifiersKnown) - 1
                        }
                }
 
                if !found && sid == identifierBaseof {
                        found = true
-                       p.identifiers = append(p.identifiers, id)
-                       p.posIdentifierBaseof = len(p.identifiers) - 1
+                       p.identifiersKnown = append(p.identifiersKnown, id)
+                       p.posIdentifierBaseof = len(p.identifiersKnown) - 1
+               }
+
+               if !found && mayHaveLayout {
+                       p.identifiersKnown = append(p.identifiersKnown, id)
+                       p.posIdentifierLayout = len(p.identifiersKnown) - 1
+                       found = true
                }
 
                if !found {
-                       p.identifiers = append(p.identifiers, id)
-                       p.identifiersUnknown = append(p.identifiersUnknown, len(p.identifiers)-1)
+                       p.identifiersUnknown = append(p.identifiersUnknown, id)
                }
 
        }
@@ -252,13 +258,13 @@ func (pp *PathParser) doParse(component, s string, p *Path) (*Path, error) {
                }
        }
 
-       if len(p.identifiers) > 0 {
+       if len(p.identifiersKnown) > 0 {
                isContentComponent := p.component == files.ComponentFolderContent || p.component == files.ComponentFolderArchetypes
                isContent := isContentComponent && pp.IsContentExt(p.Ext())
-               id := p.identifiers[len(p.identifiers)-1]
+               id := p.identifiersKnown[len(p.identifiersKnown)-1]
 
-               if id.High > p.posContainerHigh {
-                       b := p.s[p.posContainerHigh:id.High]
+               if id.Low > p.posContainerHigh {
+                       b := p.s[p.posContainerHigh : id.Low-1]
                        if isContent {
                                switch b {
                                case "index":
@@ -294,6 +300,16 @@ func (pp *PathParser) doParse(component, s string, p *Path) (*Path, error) {
                }
        }
 
+       if p.pathType == TypeShortcode && p.posIdentifierLayout != -1 {
+               // myshortcode or myshortcode.html, no layout.
+               if len(p.identifiersKnown) <= 2 {
+                       p.posIdentifierLayout = -1
+               } else {
+                       // First is always the name.
+                       p.posIdentifierLayout--
+               }
+       }
+
        return p, nil
 }
 
@@ -350,13 +366,14 @@ type Path struct {
        component string
        pathType  Type
 
-       identifiers []types.LowHigh[string]
+       identifiersKnown   []types.LowHigh[string]
+       identifiersUnknown []types.LowHigh[string]
 
        posIdentifierLanguage     int
        posIdentifierOutputFormat int
        posIdentifierKind         int
+       posIdentifierLayout       int
        posIdentifierBaseof       int
-       identifiersUnknown        []int
        disabled                  bool
 
        trimLeadingSlash bool
@@ -388,10 +405,11 @@ func (p *Path) reset() {
        p.posSectionHigh = -1
        p.component = ""
        p.pathType = 0
-       p.identifiers = p.identifiers[:0]
+       p.identifiersKnown = p.identifiersKnown[:0]
        p.posIdentifierLanguage = -1
        p.posIdentifierOutputFormat = -1
        p.posIdentifierKind = -1
+       p.posIdentifierLayout = -1
        p.posIdentifierBaseof = -1
        p.disabled = false
        p.trimLeadingSlash = false
@@ -479,7 +497,7 @@ func (p *Path) Name() string {
 // Name returns the last element of path without any extension.
 func (p *Path) NameNoExt() string {
        if i := p.identifierIndex(0); i != -1 {
-               return p.s[p.posContainerHigh : p.identifiers[i].Low-1]
+               return p.s[p.posContainerHigh : p.identifiersKnown[i].Low-1]
        }
        return p.s[p.posContainerHigh:]
 }
@@ -491,7 +509,7 @@ func (p *Path) NameNoLang() string {
                return p.Name()
        }
 
-       return p.s[p.posContainerHigh:p.identifiers[i].Low-1] + p.s[p.identifiers[i].High:]
+       return p.s[p.posContainerHigh:p.identifiersKnown[i].Low-1] + p.s[p.identifiersKnown[i].High:]
 }
 
 // BaseNameNoIdentifier returns the logical base name for a resource without any identifier (e.g. no extension).
@@ -510,15 +528,15 @@ func (p *Path) NameNoIdentifier() string {
 }
 
 func (p *Path) nameLowHigh() types.LowHigh[string] {
-       if len(p.identifiers) > 0 {
-               lastID := p.identifiers[len(p.identifiers)-1]
+       if len(p.identifiersKnown) > 0 {
+               lastID := p.identifiersKnown[len(p.identifiersKnown)-1]
                if p.posContainerHigh == lastID.Low {
                        // The last identifier is the name.
                        return lastID
                }
                return types.LowHigh[string]{
                        Low:  p.posContainerHigh,
-                       High: p.identifiers[len(p.identifiers)-1].Low - 1,
+                       High: p.identifiersKnown[len(p.identifiersKnown)-1].Low - 1,
                }
        }
        return types.LowHigh[string]{
@@ -566,7 +584,7 @@ func (p *Path) PathNoIdentifier() string {
 
 // PathBeforeLangAndOutputFormatAndExt returns the path up to the first identifier that is not a language or output format.
 func (p *Path) PathBeforeLangAndOutputFormatAndExt() string {
-       if len(p.identifiers) == 0 {
+       if len(p.identifiersKnown) == 0 {
                return p.norm(p.s)
        }
        i := p.identifierIndex(0)
@@ -582,7 +600,7 @@ func (p *Path) PathBeforeLangAndOutputFormatAndExt() string {
                return p.norm(p.s)
        }
 
-       id := p.identifiers[i]
+       id := p.identifiersKnown[i]
        return p.norm(p.s[:id.Low-1])
 }
 
@@ -633,11 +651,11 @@ func (p *Path) BaseNoLeadingSlash() string {
 }
 
 func (p *Path) base(preserveExt, isBundle bool) string {
-       if len(p.identifiers) == 0 {
+       if len(p.identifiersKnown) == 0 {
                return p.norm(p.s)
        }
 
-       if preserveExt && len(p.identifiers) == 1 {
+       if preserveExt && len(p.identifiersKnown) == 1 {
                // Preserve extension.
                return p.norm(p.s)
        }
@@ -659,7 +677,7 @@ func (p *Path) base(preserveExt, isBundle bool) string {
        }
 
        // For txt files etc. we want to preserve the extension.
-       id := p.identifiers[0]
+       id := p.identifiersKnown[0]
 
        return p.norm(p.s[:high] + p.s[id.Low-1:id.High])
 }
@@ -676,6 +694,10 @@ func (p *Path) Kind() string {
        return p.identifierAsString(p.posIdentifierKind)
 }
 
+func (p *Path) Layout() string {
+       return p.identifierAsString(p.posIdentifierLayout)
+}
+
 func (p *Path) Lang() string {
        return p.identifierAsString(p.posIdentifierLanguage)
 }
@@ -689,8 +711,8 @@ func (p *Path) Disabled() bool {
 }
 
 func (p *Path) Identifiers() []string {
-       ids := make([]string, len(p.identifiers))
-       for i, id := range p.identifiers {
+       ids := make([]string, len(p.identifiersKnown))
+       for i, id := range p.identifiersKnown {
                ids[i] = p.s[id.Low:id.High]
        }
        return ids
@@ -699,7 +721,7 @@ func (p *Path) Identifiers() []string {
 func (p *Path) IdentifiersUnknown() []string {
        ids := make([]string, len(p.identifiersUnknown))
        for i, id := range p.identifiersUnknown {
-               ids[i] = p.s[p.identifiers[id].Low:p.identifiers[id].High]
+               ids[i] = p.s[id.Low:id.High]
        }
        return ids
 }
@@ -735,12 +757,12 @@ func (p *Path) identifierAsString(i int) string {
                return ""
        }
 
-       id := p.identifiers[i]
+       id := p.identifiersKnown[i]
        return p.s[id.Low:id.High]
 }
 
 func (p *Path) identifierIndex(i int) int {
-       if i < 0 || i >= len(p.identifiers) {
+       if i < 0 || i >= len(p.identifiersKnown) {
                return -1
        }
        return i
index fd1590c73e0903d96e10a9e6ca00d8802a715057..a6194e756d2e30f5cf836bd56e18bb6606f60b24 100644 (file)
@@ -171,22 +171,25 @@ func TestParse(t *testing.T) {
                        "/a/b.a.b.no.txt",
                        func(c *qt.C, p *Path) {
                                c.Assert(p.Name(), qt.Equals, "b.a.b.no.txt")
-                               c.Assert(p.NameNoIdentifier(), qt.Equals, "b")
+                               c.Assert(p.NameNoIdentifier(), qt.Equals, "b.a.b")
                                c.Assert(p.NameNoLang(), qt.Equals, "b.a.b.txt")
-                               c.Assert(p.Identifiers(), qt.DeepEquals, []string{"txt", "no", "b", "a", "b"})
+                               c.Assert(p.Identifiers(), qt.DeepEquals, []string{"txt", "no"})
                                c.Assert(p.IdentifiersUnknown(), qt.DeepEquals, []string{"b", "a", "b"})
-                               c.Assert(p.Base(), qt.Equals, "/a/b.txt")
-                               c.Assert(p.BaseNoLeadingSlash(), qt.Equals, "a/b.txt")
+                               c.Assert(p.Base(), qt.Equals, "/a/b.a.b.txt")
+                               c.Assert(p.BaseNoLeadingSlash(), qt.Equals, "a/b.a.b.txt")
                                c.Assert(p.Path(), qt.Equals, "/a/b.a.b.no.txt")
-                               c.Assert(p.PathNoLang(), qt.Equals, "/a/b.txt")
+                               c.Assert(p.PathNoLang(), qt.Equals, "/a/b.a.b.txt")
                                c.Assert(p.Ext(), qt.Equals, "txt")
-                               c.Assert(p.PathNoIdentifier(), qt.Equals, "/a/b")
+                               c.Assert(p.PathNoIdentifier(), qt.Equals, "/a/b.a.b")
                        },
                },
                {
                        "Home branch cundle",
                        "/_index.md",
                        func(c *qt.C, p *Path) {
+                               c.Assert(p.Identifiers(), qt.DeepEquals, []string{"md"})
+                               c.Assert(p.IsBranchBundle(), qt.IsTrue)
+                               c.Assert(p.IsBundle(), qt.IsTrue)
                                c.Assert(p.Base(), qt.Equals, "/")
                                c.Assert(p.BaseReTyped("foo"), qt.Equals, "/foo")
                                c.Assert(p.Path(), qt.Equals, "/_index.md")
@@ -206,7 +209,8 @@ func TestParse(t *testing.T) {
                                c.Assert(p.ContainerDir(), qt.Equals, "")
                                c.Assert(p.Dir(), qt.Equals, "/a")
                                c.Assert(p.Ext(), qt.Equals, "md")
-                               c.Assert(p.Identifiers(), qt.DeepEquals, []string{"md", "index"})
+                               c.Assert(p.IdentifiersUnknown(), qt.DeepEquals, []string{"index"})
+                               c.Assert(p.Identifiers(), qt.DeepEquals, []string{"md"})
                                c.Assert(p.IsBranchBundle(), qt.IsFalse)
                                c.Assert(p.IsBundle(), qt.IsTrue)
                                c.Assert(p.IsLeafBundle(), qt.IsTrue)
@@ -228,7 +232,7 @@ func TestParse(t *testing.T) {
                                c.Assert(p.ContainerDir(), qt.Equals, "/a")
                                c.Assert(p.Dir(), qt.Equals, "/a/b")
                                c.Assert(p.Ext(), qt.Equals, "md")
-                               c.Assert(p.Identifiers(), qt.DeepEquals, []string{"md", "no", "index"})
+                               c.Assert(p.Identifiers(), qt.DeepEquals, []string{"md", "no"})
                                c.Assert(p.IsBranchBundle(), qt.IsFalse)
                                c.Assert(p.IsBundle(), qt.IsTrue)
                                c.Assert(p.IsLeafBundle(), qt.IsTrue)
@@ -250,7 +254,7 @@ func TestParse(t *testing.T) {
                                c.Assert(p.Container(), qt.Equals, "b")
                                c.Assert(p.ContainerDir(), qt.Equals, "/a")
                                c.Assert(p.Ext(), qt.Equals, "md")
-                               c.Assert(p.Identifiers(), qt.DeepEquals, []string{"md", "no", "_index"})
+                               c.Assert(p.Identifiers(), qt.DeepEquals, []string{"md", "no"})
                                c.Assert(p.IsBranchBundle(), qt.IsTrue)
                                c.Assert(p.IsBundle(), qt.IsTrue)
                                c.Assert(p.IsLeafBundle(), qt.IsFalse)
@@ -289,7 +293,7 @@ func TestParse(t *testing.T) {
                        func(c *qt.C, p *Path) {
                                c.Assert(p.Base(), qt.Equals, "/a/b/index.txt")
                                c.Assert(p.Ext(), qt.Equals, "txt")
-                               c.Assert(p.Identifiers(), qt.DeepEquals, []string{"txt", "no", "index"})
+                               c.Assert(p.Identifiers(), qt.DeepEquals, []string{"txt", "no"})
                                c.Assert(p.IsLeafBundle(), qt.IsFalse)
                                c.Assert(p.PathNoIdentifier(), qt.Equals, "/a/b/index")
                        },
@@ -372,7 +376,7 @@ func TestParse(t *testing.T) {
        }
        for _, test := range tests {
                c.Run(test.name, func(c *qt.C) {
-                       if test.name != "Basic Markdown file" {
+                       if test.name != "Home branch cundle" {
                                // return
                        }
                        test.assert(c, testParser.Parse(files.ComponentFolderContent, test.path))
@@ -401,10 +405,58 @@ func TestParseLayouts(t *testing.T) {
                        "/list.no.html",
                        func(c *qt.C, p *Path) {
                                c.Assert(p.Identifiers(), qt.DeepEquals, []string{"html", "no", "list"})
+                               c.Assert(p.IdentifiersUnknown(), qt.DeepEquals, []string{})
                                c.Assert(p.Base(), qt.Equals, "/list.html")
                                c.Assert(p.Lang(), qt.Equals, "no")
                        },
                },
+               {
+                       "Kind",
+                       "/section.no.html",
+                       func(c *qt.C, p *Path) {
+                               c.Assert(p.Kind(), qt.Equals, kinds.KindSection)
+                               c.Assert(p.Identifiers(), qt.DeepEquals, []string{"html", "no", "section"})
+                               c.Assert(p.IdentifiersUnknown(), qt.DeepEquals, []string{})
+                               c.Assert(p.Base(), qt.Equals, "/section.html")
+                               c.Assert(p.Lang(), qt.Equals, "no")
+                       },
+               },
+               {
+                       "Layout",
+                       "/list.section.no.html",
+                       func(c *qt.C, p *Path) {
+                               c.Assert(p.Layout(), qt.Equals, "list")
+                               c.Assert(p.Identifiers(), qt.DeepEquals, []string{"html", "no", "section", "list"})
+                               c.Assert(p.IdentifiersUnknown(), qt.DeepEquals, []string{})
+                               c.Assert(p.Base(), qt.Equals, "/list.html")
+                               c.Assert(p.Lang(), qt.Equals, "no")
+                       },
+               },
+               {
+                       "Layout multiple",
+                       "/maylayout.list.section.no.html",
+                       func(c *qt.C, p *Path) {
+                               c.Assert(p.Layout(), qt.Equals, "maylayout")
+                               c.Assert(p.Identifiers(), qt.DeepEquals, []string{"html", "no", "section", "list", "maylayout"})
+                               c.Assert(p.IdentifiersUnknown(), qt.DeepEquals, []string{})
+                               c.Assert(p.Base(), qt.Equals, "/maylayout.html")
+                               c.Assert(p.Lang(), qt.Equals, "no")
+                       },
+               },
+               {
+                       "Layout shortcode",
+                       "/_shortcodes/myshort.list.no.html",
+                       func(c *qt.C, p *Path) {
+                               c.Assert(p.Layout(), qt.Equals, "list")
+                       },
+               },
+               {
+                       "Layout baseof",
+                       "/baseof.list.no.html",
+                       func(c *qt.C, p *Path) {
+                               c.Assert(p.Layout(), qt.Equals, "list")
+                       },
+               },
                {
                        "Lang and output format",
                        "/list.no.amp.not.html",
@@ -429,6 +481,20 @@ func TestParseLayouts(t *testing.T) {
                                c.Assert(p.OutputFormat(), qt.Equals, "html")
                        },
                },
+               {
+                       "Shortcode with layout",
+                       "/_shortcodes/myshortcode.list.html",
+                       func(c *qt.C, p *Path) {
+                               c.Assert(p.Base(), qt.Equals, "/_shortcodes/myshortcode.html")
+                               c.Assert(p.Type(), qt.Equals, TypeShortcode)
+                               c.Assert(p.Identifiers(), qt.DeepEquals, []string{"html", "list", "myshortcode"})
+                               c.Assert(p.PathNoIdentifier(), qt.Equals, "/_shortcodes/myshortcode")
+                               c.Assert(p.PathBeforeLangAndOutputFormatAndExt(), qt.Equals, "/_shortcodes/myshortcode.list")
+                               c.Assert(p.Lang(), qt.Equals, "")
+                               c.Assert(p.Kind(), qt.Equals, "")
+                               c.Assert(p.OutputFormat(), qt.Equals, "html")
+                       },
+               },
                {
                        "Sub dir",
                        "/pages/home.html",
@@ -445,7 +511,7 @@ func TestParseLayouts(t *testing.T) {
                        "/pages/baseof.list.section.fr.amp.html",
                        func(c *qt.C, p *Path) {
                                c.Assert(p.Identifiers(), qt.DeepEquals, []string{"html", "amp", "fr", "section", "list", "baseof"})
-                               c.Assert(p.IdentifiersUnknown(), qt.DeepEquals, []string{"list"})
+                               c.Assert(p.IdentifiersUnknown(), qt.DeepEquals, []string{})
                                c.Assert(p.Kind(), qt.Equals, kinds.KindSection)
                                c.Assert(p.Lang(), qt.Equals, "fr")
                                c.Assert(p.OutputFormat(), qt.Equals, "amp")
@@ -501,6 +567,9 @@ func TestParseLayouts(t *testing.T) {
 
        for _, test := range tests {
                c.Run(test.name, func(c *qt.C) {
+                       if test.name != "Baseof" {
+                               // return
+                       }
                        test.assert(c, testParser.Parse(files.ComponentFolderLayouts, test.path))
                })
        }
index 62d40f5270266a53286517b63036ef6535e3455e..f5ea3066ac99c908300211b1742b113a90122fc8 100644 (file)
@@ -78,3 +78,26 @@ disablePathToLower = true
        b.AssertFileContent("public/en/mysection/mybundle/index.html", "en|Single")
        b.AssertFileContent("public/fr/MySection/MyBundle/index.html", "fr|Single")
 }
+
+func TestIssue13596(t *testing.T) {
+       t.Parallel()
+
+       files := `
+-- hugo.toml --
+disableKinds = ['home','rss','section','sitemap','taxonomy','term']
+-- content/p1/index.md --
+---
+title: p1
+---
+-- content/p1/a.1.txt --
+-- content/p1/a.2.txt --
+-- layouts/all.html --
+{{ range .Resources.Match "*" }}{{ .Name }}|{{ end }}
+`
+
+       b := hugolib.Test(t, files)
+
+       b.AssertFileContent("public/p1/index.html", "a.1.txt|a.2.txt|")
+       b.AssertFileExists("public/p1/a.1.txt", true)
+       b.AssertFileExists("public/p1/a.2.txt", true) // fails
+}
index a8c817becac25a4158542eb52d37f7fca7600945..f62d4c60455677f7f858be806be449a4e1453cfc 100644 (file)
@@ -39,6 +39,8 @@ title: "Page"
 `)
        b.CreateSites().Build(BuildCfg{})
 
+       // b.H.TemplateStore.PrintDebug("", tplimpl.CategoryLayout, os.Stdout)
+
        c.Assert(len(b.H.Sites), qt.Equals, 1)
        c.Assert(len(b.H.Sites[0].RegularPages()), qt.Equals, 2)
 
index 56ae0a052abce57bd35f7d3d4cc3005e8c8991f3..c4e15a5c674298eba83840b848b60d232dece489 100644 (file)
@@ -464,8 +464,6 @@ title: "Home"
 `
        b := Test(t, files)
 
-       // b.DebugPrint("", tplimpl.CategoryShortcode)
-
        b.AssertFileContentExact("public/index.xml", "My shortcode XML.")
        b.AssertFileContentExact("public/index.html", "My shortcode HTML.")
        s := b.H.Sites[0]
index a9fe977cf5edabb0ca2da518f5928054f627255a..4d68602e51ccd4ab023fadf1c549d1b6ca8a64a4 100644 (file)
@@ -978,7 +978,7 @@ func TestRefLinking(t *testing.T) {
                {".", "", true, "/level2/level3/"},
                {"./", "", true, "/level2/level3/"},
 
-               {"embedded.dot.md", "", true, "/level2/level3/embedded/"},
+               {"embedded.dot.md", "", true, "/level2/level3/embedded.dot/"},
 
                // test empty link, as well as fragment only link
                {"", "", true, ""},
index 5be65f874f2ee3449de19fd13c5f02ce73172e85..dba89760895c6f19b48a8f34e621e988e23e81e2 100644 (file)
@@ -654,7 +654,7 @@ func (s *TemplateStore) PrintDebug(prefix string, category Category, w io.Writer
                        return
                }
                s := strings.ReplaceAll(strings.TrimSpace(vv.content), "\n", " ")
-               ts := fmt.Sprintf("kind: %q layout: %q content: %.30s", vv.D.Kind, vv.D.LayoutFromTemplate, s)
+               ts := fmt.Sprintf("kind: %q layout: %q lang: %q content: %.30s", vv.D.Kind, vv.D.LayoutFromTemplate, vv.D.Lang, s)
                fmt.Fprintf(w, "%s%s %s\n", strings.Repeat(" ", level), key, ts)
        }
        s.treeMain.WalkPrefix(prefix, func(key string, v map[nodeKey]*TemplInfo) (bool, error) {
@@ -1126,7 +1126,7 @@ func (s *TemplateStore) insertTemplate2(
 
        if !replace {
                if v, found := m[nk]; found {
-                       if len(pi.IdentifiersUnknown()) >= len(v.PathInfo.IdentifiersUnknown()) {
+                       if len(pi.Identifiers()) >= len(v.PathInfo.Identifiers()) {
                                // e.g. /pages/home.foo.html and  /pages/home.html where foo may be a valid language name in another site.
                                return nil, nil
                        }
@@ -1261,7 +1261,10 @@ func (s *TemplateStore) insertTemplates(include func(fi hugofs.FileMetaInfo) boo
                        )
 
                        base := piOrig.PathBeforeLangAndOutputFormatAndExt()
-                       identifiers := pi.IdentifiersUnknown()
+                       identifiers := []string{}
+                       if pi.Layout() != "" {
+                               identifiers = append(identifiers, pi.Layout())
+                       }
                        if pi.Kind() != "" {
                                identifiers = append(identifiers, pi.Kind())
                        }
@@ -1576,24 +1579,12 @@ func (s *TemplateStore) toKeyCategoryAndDescriptor(p *paths.Path) (string, strin
        outputFormat, mediaType := s.resolveOutputFormatAndOrMediaType(p.OutputFormat(), p.Ext())
        nameNoIdentifier := p.NameNoIdentifier()
 
-       var layout string
-       unknownids := p.IdentifiersUnknown()
-       if p.Type() == paths.TypeShortcode {
-               if len(unknownids) > 1 {
-                       // The name is the last identifier.
-                       layout = unknownids[len(unknownids)-2]
-               }
-       } else if len(unknownids) > 0 {
-               // Pick the last, closest to the base name.
-               layout = unknownids[len(unknownids)-1]
-       }
-
        d := TemplateDescriptor{
                Lang:               p.Lang(),
                OutputFormat:       p.OutputFormat(),
                MediaType:          mediaType.Type,
                Kind:               p.Kind(),
-               LayoutFromTemplate: layout,
+               LayoutFromTemplate: p.Layout(),
                IsPlainText:        outputFormat.IsPlainText,
        }
 
@@ -1633,6 +1624,7 @@ func (s *TemplateStore) toKeyCategoryAndDescriptor(p *paths.Path) (string, strin
 
        if category == CategoryShortcode {
                k1 = p.PathNoIdentifier()
+
                parts := strings.Split(k1, "/"+containerShortcodes+"/")
                k1 = parts[0]
                if len(parts) > 1 {
index 06cb00212b131b3a8713471229dbe089ac2940f3..bd00f82b7b2d303b2b8c2b106b984da4a575704b 100644 (file)
@@ -1056,7 +1056,7 @@ All.
 
        b := hugolib.Test(t, files, hugolib.TestOptWarn())
 
-       b.AssertLogContains("Duplicate content path")
+       b.AssertLogContains("Duplicate content path")
 }
 
 // Issue #13577.