diff --git a/hugofs/component_fs.go b/hugofs/component_fs.go index ec7f06a07..e59b595c7 100644 --- a/hugofs/component_fs.go +++ b/hugofs/component_fs.go @@ -320,8 +320,9 @@ func (fs *componentFs) applyMeta(fi FileNameIsDir, name string) (FileMetaInfo, b meta.PathInfo = pi if !fim.IsDir() { + pp := fs.opts.Cfg.PathParser() if fileLang := meta.PathInfo.Lang(); fileLang != "" { - if idx, ok := fs.opts.Cfg.PathParser().LanguageIndex[fileLang]; ok { + if idx, ok := pp.LanguageIndex[fileLang]; ok { // A valid lang set in filename. // Give priority to myfile.sv.txt inside the sv filesystem. meta.Weight++ @@ -330,7 +331,29 @@ func (fs *componentFs) applyMeta(fi FileNameIsDir, name string) (FileMetaInfo, b // Not the default language, add some weight. meta.SitesMatrix = sitesmatrix.NewWeightedVectorStore(meta.SitesMatrix, 10) } - + } + } + // Filename identifiers for roles/versions replace any mount configuration for that dimension. + if roles := pi.Roles(); len(roles) > 0 { + var indices []int + for _, role := range roles { + if idx := pp.ConfiguredDimensions.ConfiguredRoles.ResolveIndex(role); idx >= 0 { + indices = append(indices, idx) + } + } + if len(indices) > 0 { + meta.SitesMatrix = meta.SitesMatrix.WithRoleIndices(indices...) + } + } + if versions := pi.Versions(); len(versions) > 0 { + var indices []int + for _, version := range versions { + if idx := pp.ConfiguredDimensions.ConfiguredVersions.ResolveIndex(version); idx >= 0 { + indices = append(indices, idx) + } + } + if len(indices) > 0 { + meta.SitesMatrix = meta.SitesMatrix.WithVersionIndices(indices...) } } switch meta.Component { @@ -341,7 +364,6 @@ func (fs *componentFs) applyMeta(fi FileNameIsDir, name string) (FileMetaInfo, b meta.Weight-- } } - } if fi.IsDir() { diff --git a/hugolib/sitesmatrix/dimensions.go b/hugolib/sitesmatrix/dimensions.go index d7a96a038..aefa6f5e0 100644 --- a/hugolib/sitesmatrix/dimensions.go +++ b/hugolib/sitesmatrix/dimensions.go @@ -214,7 +214,9 @@ type VectorProvider interface { type VectorStore interface { VectorProvider Complement(...VectorProvider) VectorStore - WithLanguageIndices(i int) VectorStore + WithLanguageIndices(i ...int) VectorStore + WithVersionIndices(i ...int) VectorStore + WithRoleIndices(i ...int) VectorStore HasLanguage(lang int) bool HasVersion(version int) bool HasRole(role int) bool diff --git a/hugolib/sitesmatrix/sitematrix_integration_test.go b/hugolib/sitesmatrix/sitematrix_integration_test.go index 84908a190..e76e2b7aa 100644 --- a/hugolib/sitesmatrix/sitematrix_integration_test.go +++ b/hugolib/sitesmatrix/sitematrix_integration_test.go @@ -1901,3 +1901,55 @@ title: p1 de `) } + +// Issue 14756. +func TestFilenameIdentifierShouldReplaceMountDimension(t *testing.T) { + t.Parallel() + files := ` +-- hugo.toml -- +baseURL = "https://example.org/" +disableKinds = ["taxonomy", "term", "rss", "sitemap"] +defaultContentLanguage = "en" +defaultContentRole = "guest" +defaultContentRoleInSubdir = true +[roles] +[roles.guest] +weight = 100 +[roles.member] +weight = 200 +[module] +[[module.mounts]] +source = 'content/member' +target = 'content' +[module.mounts.sites.matrix] +roles = "member" +[[module.mounts]] +source = 'content/guest' +target = 'content' +[module.mounts.sites.matrix] +roles = "*" +-- content/member/bundle/index.md -- +--- +title: "Bundle" +--- +-- content/guest/bundle/index.md -- +--- +title: "Bundle" +--- +-- content/guest/bundle/img._role_member_.txt -- +memberimg +-- content/guest/bundle/guestimg.txt -- +guestimg +-- layouts/page.html -- +Role: {{ .Site.Role.Name }}|{{ range .Resources }}{{ .Name }}|{{ end }}$ +-- layouts/list.html -- +List. +` + + b := hugolib.Test(t, files) + + // The guest role should only see guestimg.txt (not img._role_member_.txt). + b.AssertFileContent("public/guest/bundle/index.html", "Role: guest|guestimg.txt|$") + // The member role should see both. + b.AssertFileContent("public/member/bundle/index.html", "Role: member|guestimg.txt|img._role_member_.txt|$") +} diff --git a/hugolib/sitesmatrix/vectorstores.go b/hugolib/sitesmatrix/vectorstores.go index 174dd6ea9..b865bea65 100644 --- a/hugolib/sitesmatrix/vectorstores.go +++ b/hugolib/sitesmatrix/vectorstores.go @@ -209,17 +209,46 @@ func (s *vectorStoreMap) Vectors() []Vector { return vectors } -func (s *vectorStoreMap) WithLanguageIndices(i int) VectorStore { +func (s *vectorStoreMap) WithLanguageIndices(i ...int) VectorStore { c := s.clone() for v := range c.sets { - v[Language] = i - c.sets[v] = struct{}{} + for _, i := range i { + nv := v + nv[Language] = i + c.sets[nv] = struct{}{} + } } return c } +func (s *vectorStoreMap) WithVersionIndices(indices ...int) VectorStore { + old := s.clone() + c := newVectorStoreMap(len(old.sets) * len(indices)) + for v := range old.sets { + for _, i := range indices { + nv := v + nv[Version] = i + c.sets[nv] = struct{}{} + } + } + return c +} + +func (s *vectorStoreMap) WithRoleIndices(indices ...int) VectorStore { + old := s.clone() + c := newVectorStoreMap(len(old.sets) * len(indices)) + for v := range old.sets { + for _, i := range indices { + nv := v + nv[Role] = i + c.sets[nv] = struct{}{} + } + } + return c +} + func (s *vectorStoreMap) HasLanguage(i int) bool { for v := range s.sets { if v.Language() == i { @@ -589,10 +618,24 @@ func (s IntSets) shallowClone() *IntSets { return &s } -// WithLanguageIndices replaces the current language set with a single language index. -func (s *IntSets) WithLanguageIndices(i int) VectorStore { +// WithLanguageIndices replaces the current language set with the given language indices. +func (s *IntSets) WithLanguageIndices(indices ...int) VectorStore { c := s.shallowClone() - c.languages = hmaps.NewOrderedIntSet(i) + c.languages = hmaps.NewOrderedIntSet(indices...) + return c.init() +} + +// WithVersionIndices replaces the current version set with the given version indices. +func (s *IntSets) WithVersionIndices(indices ...int) VectorStore { + c := s.shallowClone() + c.versions = hmaps.NewOrderedIntSet(indices...) + return c.init() +} + +// WithRoleIndices replaces the current role set with the given role indices. +func (s *IntSets) WithRoleIndices(indices ...int) VectorStore { + c := s.shallowClone() + c.roles = hmaps.NewOrderedIntSet(indices...) return c.init() }