tpl/tplimpl: Prefer early suffixes when media type matches

Fixes #13877
Close #14601

Co-Authored-By: Joe Mooring <joe.mooring@veriphor.com>
This commit is contained in:
Bjørn Erik Pedersen
2026-03-08 13:38:38 +01:00
parent 13a95b9c01
commit 4eafd9eb7b
2 changed files with 52 additions and 2 deletions
+32
View File
@@ -644,3 +644,35 @@ Overridden.
b.AssertFileContent("public/index.html", "Overridden.")
}
// Issue 13877
func TestTemplateSelectionFirstMediaTypeSuffix(t *testing.T) {
t.Parallel()
files := `
-- hugo.toml --
disableKinds = ['home','rss','section','sitemap','taxonomy','term']
[mediaTypes.'text/html']
suffixes = ['b','a','d','c']
[outputFormats.html]
mediaType = 'text/html'
-- content/p1.md --
---
title: p1
---
-- layouts/page.html.a --
page.html.a
-- layouts/page.html.b --
page.html.b
-- layouts/page.html.c --
page.html.c
-- layouts/page.html.d --
page.html.d
`
b := Test(t, files)
b.AssertFileContent("public/p1/index.b", "page.html.b")
}
+20 -2
View File
@@ -29,6 +29,7 @@ import (
"path/filepath"
"reflect"
"regexp"
"slices"
"sort"
"strings"
"sync"
@@ -1271,8 +1272,25 @@ func (s *TemplateStore) insertTemplate2(
if !replace && existingFound {
if len(pi.Identifiers()) >= len(nkExisting.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
if d.MediaType != "" && pi.Ext() != nkExisting.PathInfo.Ext() {
// Issue #13877: when multiple templates differ only in their file extension
// and both extensions are valid suffixes for the same media type,
// prefer the one whose extension matches an earlier suffix.
if mt, ok := s.opts.MediaTypes.GetByType(d.MediaType); ok {
suffixes := mt.Suffixes()
newIdx := slices.Index(suffixes, pi.Ext())
if newIdx != -1 {
existingIdx := slices.Index(suffixes, nkExisting.PathInfo.Ext())
if existingIdx == -1 || newIdx < existingIdx {
replace = true
}
}
}
}
if !replace {
// e.g. /pages/home.foo.html and /pages/home.html where foo may be a valid language name in another site.
return nil, nil
}
}
}