Revert the breaking change from 0.146.0 with dots in content filenames - hugo - [fork] hugo port for 9front
HTML git clone git@git.drkhsh.at/hugo.git
DIR Log
DIR Files
DIR Refs
DIR Submodules
DIR README
DIR LICENSE
---
DIR commit 496730840e388d7187149503f6e6e4648a8f65c1
DIR parent 6d69dc88a46a002eda3f5b56ac73d29c6b9d0bc3
HTML Author: Bjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>
Date: Mon, 21 Apr 2025 16:15:21 +0200
Revert the breaking change from 0.146.0 with dots in content filenames
Closes #13632
Diffstat:
M common/paths/pathparser.go | 96 +++++++++++++++++++------------
M common/paths/pathparser_test.go | 93 +++++++++++++++++++++++++++----
M common/paths/paths_integration_tes… | 23 +++++++++++++++++++++++
M hugolib/collections_test.go | 2 ++
M hugolib/content_render_hooks_test.… | 2 --
M hugolib/site_test.go | 2 +-
M tpl/tplimpl/templatestore.go | 24 ++++++++----------------
M tpl/tplimpl/templatestore_integrat… | 2 +-
8 files changed, 175 insertions(+), 69 deletions(-)
---
DIR diff --git a/common/paths/pathparser.go b/common/paths/pathparser.go
@@ -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
DIR diff --git a/common/paths/pathparser_test.go b/common/paths/pathparser_test.go
@@ -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,11 +405,59 @@ 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",
func(c *qt.C, p *Path) {
@@ -430,6 +482,20 @@ func TestParseLayouts(t *testing.T) {
},
},
{
+ "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",
func(c *qt.C, p *Path) {
@@ -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))
})
}
DIR diff --git a/common/paths/paths_integration_test.go b/common/paths/paths_integration_test.go
@@ -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
+}
DIR diff --git a/hugolib/collections_test.go b/hugolib/collections_test.go
@@ -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)
DIR diff --git a/hugolib/content_render_hooks_test.go b/hugolib/content_render_hooks_test.go
@@ -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]
DIR diff --git a/hugolib/site_test.go b/hugolib/site_test.go
@@ -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, ""},
DIR diff --git a/tpl/tplimpl/templatestore.go b/tpl/tplimpl/templatestore.go
@@ -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 {
DIR diff --git a/tpl/tplimpl/templatestore_integration_test.go b/tpl/tplimpl/templatestore_integration_test.go
@@ -1056,7 +1056,7 @@ All.
b := hugolib.Test(t, files, hugolib.TestOptWarn())
- b.AssertLogContains("Duplicate content path")
+ b.AssertLogContains("! Duplicate content path")
}
// Issue #13577.