Skip to content

Commit

Permalink
Add path, kind and lang to content front matter
Browse files Browse the repository at this point in the history
Note that none of these can be set via cascade (you will get an error)

Fixes #11544
  • Loading branch information
bep committed Jan 30, 2024
1 parent ec22bb3 commit f31a6db
Show file tree
Hide file tree
Showing 22 changed files with 707 additions and 429 deletions.
2 changes: 1 addition & 1 deletion go.mod
Expand Up @@ -48,7 +48,7 @@ require (
github.com/marekm4/color-extractor v1.2.1
github.com/mattn/go-isatty v0.0.20
github.com/mitchellh/hashstructure v1.1.0
github.com/mitchellh/mapstructure v1.5.0
github.com/mitchellh/mapstructure v1.5.1-0.20231216201459-8508981c8b6c
github.com/muesli/smartcrop v0.3.0
github.com/niklasfasching/go-org v1.7.0
github.com/olekukonko/tablewriter v0.0.5
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Expand Up @@ -359,6 +359,8 @@ github.com/mitchellh/hashstructure v1.1.0 h1:P6P1hdjqAAknpY/M1CGipelZgp+4y9ja9km
github.com/mitchellh/hashstructure v1.1.0/go.mod h1:xUDAozZz0Wmdiufv0uyhnHkUTN6/6d8ulp4AwfLKrmA=
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/mitchellh/mapstructure v1.5.1-0.20231216201459-8508981c8b6c h1:cqn374mizHuIWj+OSJCajGr/phAmuMug9qIX3l9CflE=
github.com/mitchellh/mapstructure v1.5.1-0.20231216201459-8508981c8b6c/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 h1:RWengNIwukTxcDr9M+97sNutRR1RKhG96O6jWumTTnw=
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8=
github.com/montanaflynn/stats v0.6.3/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc=
Expand Down
6 changes: 4 additions & 2 deletions hugolib/content_map.go
Expand Up @@ -187,7 +187,7 @@ func (m *pageMap) AddFi(fi hugofs.FileMetaInfo) error {
if pi.IsContent() {
// Create the page now as we need it at assemembly time.
// The other resources are created if needed.
pageResource, err := m.s.h.newPage(
pageResource, pi, err := m.s.h.newPage(
&pageMeta{
f: source.NewFileInfo(fim),
pathInfo: pi,
Expand All @@ -197,6 +197,8 @@ func (m *pageMap) AddFi(fi hugofs.FileMetaInfo) error {
if err != nil {
return err
}
key = pi.Base()

rs = &resourceSource{r: pageResource}
} else {
rs = &resourceSource{path: pi, opener: r, fi: fim}
Expand Down Expand Up @@ -226,7 +228,7 @@ func (m *pageMap) AddFi(fi hugofs.FileMetaInfo) error {
},
))
// A content file.
p, err := m.s.h.newPage(
p, pi, err := m.s.h.newPage(
&pageMeta{
f: source.NewFileInfo(fi),
pathInfo: pi,
Expand Down
89 changes: 52 additions & 37 deletions hugolib/content_map_page.go
Expand Up @@ -43,6 +43,7 @@ import (

"github.com/gohugoio/hugo/resources/kinds"
"github.com/gohugoio/hugo/resources/page"
"github.com/gohugoio/hugo/resources/page/pagemeta"
"github.com/gohugoio/hugo/resources/resource"
)

Expand Down Expand Up @@ -97,7 +98,6 @@ type pageMap struct {
cacheContentRendered *dynacache.Partition[string, *resources.StaleValue[contentSummary]]
cacheContentPlain *dynacache.Partition[string, *resources.StaleValue[contentPlainPlainWords]]
contentTableOfContents *dynacache.Partition[string, *resources.StaleValue[contentTableOfContents]]
cacheContentSource *dynacache.Partition[string, *resources.StaleValue[[]byte]]

cfg contentMapConfig
}
Expand Down Expand Up @@ -147,7 +147,6 @@ func (t *pageTrees) collectIdentities(key string) []identity.Identity {

// collectIdentitiesSurrounding collects all identities surrounding the given key.
func (t *pageTrees) collectIdentitiesSurrounding(key string, maxSamplesPerTree int) []identity.Identity {
// TODO1 test language coverage from this.
ids := t.collectIdentitiesSurroundingIn(key, maxSamplesPerTree, t.treePages)
ids = append(ids, t.collectIdentitiesSurroundingIn(key, maxSamplesPerTree, t.treeResources)...)
return ids
Expand Down Expand Up @@ -483,7 +482,7 @@ func (m *pageMap) getOrCreateResourcesForPage(ps *pageState) resource.Resources
return nil, err
}

if translationKey := ps.m.translationKey; translationKey != "" {
if translationKey := ps.m.pageConfig.TranslationKey; translationKey != "" {
// This this should not be a very common case.
// Merge in resources from the other languages.
translatedPages, _ := m.s.h.translationKeyPages.Get(translationKey)
Expand Down Expand Up @@ -539,9 +538,9 @@ func (m *pageMap) getOrCreateResourcesForPage(ps *pageState) resource.Resources

sort.SliceStable(res, lessFunc)

if len(ps.m.resourcesMetadata) > 0 {
if len(ps.m.pageConfig.Resources) > 0 {
for i, r := range res {
res[i] = resources.CloneWithMetadataIfNeeded(ps.m.resourcesMetadata, r)
res[i] = resources.CloneWithMetadataIfNeeded(ps.m.pageConfig.Resources, r)
}
sort.SliceStable(res, lessFunc)
}
Expand Down Expand Up @@ -819,7 +818,6 @@ func newPageMap(i int, s *Site, mcache *dynacache.Cache, pageTrees *pageTrees) *
cacheContentRendered: dynacache.GetOrCreatePartition[string, *resources.StaleValue[contentSummary]](mcache, fmt.Sprintf("/cont/ren/%d", i), dynacache.OptionsPartition{Weight: 70, ClearWhen: dynacache.ClearOnChange}),
cacheContentPlain: dynacache.GetOrCreatePartition[string, *resources.StaleValue[contentPlainPlainWords]](mcache, fmt.Sprintf("/cont/pla/%d", i), dynacache.OptionsPartition{Weight: 70, ClearWhen: dynacache.ClearOnChange}),
contentTableOfContents: dynacache.GetOrCreatePartition[string, *resources.StaleValue[contentTableOfContents]](mcache, fmt.Sprintf("/cont/toc/%d", i), dynacache.OptionsPartition{Weight: 70, ClearWhen: dynacache.ClearOnChange}),
cacheContentSource: dynacache.GetOrCreatePartition[string, *resources.StaleValue[[]byte]](mcache, fmt.Sprintf("/cont/src/%d", i), dynacache.OptionsPartition{Weight: 70, ClearWhen: dynacache.ClearOnChange}),

cfg: contentMapConfig{
lang: s.Lang(),
Expand Down Expand Up @@ -1215,7 +1213,7 @@ func (sa *sitePagesAssembler) applyAggregates() error {
// Home page gets it's cascade from the site config.
cascade = sa.conf.Cascade.Config

if pageBundle.m.cascade == nil {
if pageBundle.m.pageConfig.Cascade == nil {
// Pass the site cascade downwards.
pw.WalkContext.Data().Insert(keyPage, cascade)
}
Expand All @@ -1227,12 +1225,12 @@ func (sa *sitePagesAssembler) applyAggregates() error {
}

if (pageBundle.IsHome() || pageBundle.IsSection()) && pageBundle.m.setMetaPostCount > 0 {
oldDates := pageBundle.m.dates
oldDates := pageBundle.m.pageConfig.Dates

// We need to wait until after the walk to determine if any of the dates have changed.
pw.WalkContext.AddPostHook(
func() error {
if oldDates != pageBundle.m.dates {
if oldDates != pageBundle.m.pageConfig.Dates {
sa.assembleChanges.Add(pageBundle)
}
return nil
Expand All @@ -1251,11 +1249,12 @@ func (sa *sitePagesAssembler) applyAggregates() error {

const eventName = "dates"
if n.isContentNodeBranch() {
if pageBundle.m.cascade != nil {
if pageBundle.m.pageConfig.Cascade != nil {
// Pass it down.
pw.WalkContext.Data().Insert(keyPage, pageBundle.m.cascade)
pw.WalkContext.Data().Insert(keyPage, pageBundle.m.pageConfig.Cascade)
}
wasZeroDates := resource.IsZeroDates(pageBundle.m.dates)

wasZeroDates := pageBundle.m.pageConfig.Dates.IsAllDatesZero()
if wasZeroDates || pageBundle.IsHome() {
pw.WalkContext.AddEventListener(eventName, keyPage, func(e *doctree.Event[contentNodeI]) {
sp, ok := e.Source.(*pageState)
Expand All @@ -1264,15 +1263,15 @@ func (sa *sitePagesAssembler) applyAggregates() error {
}

if wasZeroDates {
pageBundle.m.dates.UpdateDateAndLastmodIfAfter(sp.m.dates)
pageBundle.m.pageConfig.Dates.UpdateDateAndLastmodIfAfter(sp.m.pageConfig.Dates)
}

if pageBundle.IsHome() {
if pageBundle.m.dates.Lastmod().After(pageBundle.s.lastmod) {
pageBundle.s.lastmod = pageBundle.m.dates.Lastmod()
if pageBundle.m.pageConfig.Dates.Lastmod.After(pageBundle.s.lastmod) {
pageBundle.s.lastmod = pageBundle.m.pageConfig.Dates.Lastmod
}
if sp.m.dates.Lastmod().After(pageBundle.s.lastmod) {
pageBundle.s.lastmod = sp.m.dates.Lastmod()
if sp.m.pageConfig.Dates.Lastmod.After(pageBundle.s.lastmod) {
pageBundle.s.lastmod = sp.m.pageConfig.Dates.Lastmod
}
}
})
Expand Down Expand Up @@ -1351,9 +1350,9 @@ func (sa *sitePagesAssembler) applyAggregatesToTaxonomiesAndTerms() error {
p := n.(*pageState)
if p.Kind() != kinds.KindTerm {
// The other kinds were handled in applyAggregates.
if p.m.cascade != nil {
if p.m.pageConfig.Cascade != nil {
// Pass it down.
pw.WalkContext.Data().Insert(s, p.m.cascade)
pw.WalkContext.Data().Insert(s, p.m.pageConfig.Cascade)
}
}

Expand Down Expand Up @@ -1388,14 +1387,14 @@ func (sa *sitePagesAssembler) applyAggregatesToTaxonomiesAndTerms() error {
// Send the date info up the tree.
pw.WalkContext.SendEvent(&doctree.Event[contentNodeI]{Source: n, Path: s, Name: eventName})

if resource.IsZeroDates(p.m.dates) {
if p.m.pageConfig.Dates.IsAllDatesZero() {
pw.WalkContext.AddEventListener(eventName, s, func(e *doctree.Event[contentNodeI]) {
sp, ok := e.Source.(*pageState)
if !ok {
return
}

p.m.dates.UpdateDateAndLastmodIfAfter(sp.m.dates)
p.m.pageConfig.Dates.UpdateDateAndLastmodIfAfter(sp.m.pageConfig.Dates)
})
}

Expand Down Expand Up @@ -1443,8 +1442,8 @@ func (sa *sitePagesAssembler) assembleTermsAndTranslations() error {
// This is a little out of place, but is conveniently put here.
// Check if translationKey is set by user.
// This is to support the manual way of setting the translationKey in front matter.
if ps.m.translationKey != "" {
sa.s.h.translationKeyPages.Append(ps.m.translationKey, ps)
if ps.m.pageConfig.TranslationKey != "" {
sa.s.h.translationKeyPages.Append(ps.m.pageConfig.TranslationKey, ps)
}

if sa.pageMap.cfg.taxonomyTermDisabled {
Expand Down Expand Up @@ -1477,9 +1476,13 @@ func (sa *sitePagesAssembler) assembleTermsAndTranslations() error {
singular: viewName.singular,
s: sa.Site,
pathInfo: pi,
kind: kinds.KindTerm,
pageMetaParams: pageMetaParams{
pageConfig: &pagemeta.PageConfig{
Kind: kinds.KindTerm,
},
},
}
n, err := sa.h.newPage(m)
n, pi, err := sa.h.newPage(m)
if err != nil {
return false, err
}
Expand Down Expand Up @@ -1524,7 +1527,7 @@ func (sa *sitePagesAssembler) assembleResources() error {
targetPaths := ps.targetPaths()
baseTarget := targetPaths.SubResourceBaseTarget
duplicateResourceFiles := true
if ps.s.ContentSpec.Converters.IsGoldmark(ps.m.markup) {
if ps.s.ContentSpec.Converters.IsGoldmark(ps.m.pageConfig.Markup) {
duplicateResourceFiles = ps.s.ContentSpec.Converters.GetMarkupConfig().Goldmark.DuplicateResourceFiles
}

Expand Down Expand Up @@ -1566,7 +1569,7 @@ func (sa *sitePagesAssembler) assembleResources() error {
BasePathTargetPath: baseTarget,
Name: relPath,
NameOriginal: relPathOriginal,
LazyPublish: !ps.m.buildConfig.PublishResources,
LazyPublish: !ps.m.pageConfig.Build.PublishResources,
}
r, err := ps.m.s.ResourceSpec.NewResource(rd)
if err != nil {
Expand Down Expand Up @@ -1631,7 +1634,7 @@ func (sa *sitePagesAssembler) removeShouldNotBuild() error {
case kinds.KindHome, kinds.KindSection, kinds.KindTaxonomy:
// We need to keep these for the structure, but disable
// them so they don't get listed/rendered.
(&p.m.buildConfig).Disable()
(&p.m.pageConfig.Build).Disable()
default:
keys = append(keys, key)
}
Expand Down Expand Up @@ -1673,13 +1676,17 @@ func (sa *sitePagesAssembler) addStandalonePages() error {
}

m := &pageMeta{
s: s,
pathInfo: s.Conf.PathParser().Parse(files.ComponentFolderContent, key+f.MediaType.FirstSuffix.FullSuffix),
kind: kind,
s: s,
pathInfo: s.Conf.PathParser().Parse(files.ComponentFolderContent, key+f.MediaType.FirstSuffix.FullSuffix),
pageMetaParams: pageMetaParams{
pageConfig: &pagemeta.PageConfig{
Kind: kind,
},
},
standaloneOutputFormat: f,
}

p, _ := s.h.newPage(m)
p, _, _ := s.h.newPage(m)

tree.InsertIntoValuesDimension(key, p)
}
Expand Down Expand Up @@ -1756,7 +1763,7 @@ func (sa *sitePagesAssembler) addMissingRootSections() error {
pathInfo: pth,
}

ps, err := sa.h.newPage(m)
ps, pth, err := sa.h.newPage(m)
if err != nil {
return false, err
}
Expand All @@ -1781,9 +1788,13 @@ func (sa *sitePagesAssembler) addMissingRootSections() error {
m := &pageMeta{
s: sa.Site,
pathInfo: p,
kind: kinds.KindHome,
pageMetaParams: pageMetaParams{
pageConfig: &pagemeta.PageConfig{
Kind: kinds.KindHome,
},
},
}
n, err := sa.h.newPage(m)
n, p, err := sa.h.newPage(m)
if err != nil {
return err
}
Expand All @@ -1810,10 +1821,14 @@ func (sa *sitePagesAssembler) addMissingTaxonomies() error {
m := &pageMeta{
s: sa.Site,
pathInfo: sa.Conf.PathParser().Parse(files.ComponentFolderContent, key+"/_index.md"),
kind: kinds.KindTaxonomy,
pageMetaParams: pageMetaParams{
pageConfig: &pagemeta.PageConfig{
Kind: kinds.KindTaxonomy,
},
},
singular: viewName.singular,
}
p, _ := sa.h.newPage(m)
p, _, _ := sa.h.newPage(m)
tree.InsertIntoValuesDimension(key, p)
}
}
Expand Down
3 changes: 3 additions & 0 deletions hugolib/hugo_sites.go
Expand Up @@ -26,6 +26,7 @@ import (
"github.com/gohugoio/hugo/config/allconfig"
"github.com/gohugoio/hugo/hugofs/glob"
"github.com/gohugoio/hugo/hugolib/doctree"
"github.com/gohugoio/hugo/resources"

"github.com/fsnotify/fsnotify"

Expand Down Expand Up @@ -72,6 +73,8 @@ type HugoSites struct {

// Cache for page listings.
cachePages *dynacache.Partition[string, page.Pages]
// Cache for content sources.
cacheContentSource *dynacache.Partition[string, *resources.StaleValue[[]byte]]

// Before Hugo 0.122.0 we managed all translations in a map using a translationKey
// that could be overridden in front matter.
Expand Down
9 changes: 9 additions & 0 deletions hugolib/integrationtest_builder.go
Expand Up @@ -80,6 +80,15 @@ func Test(t testing.TB, files string, opts ...TestOpt) *IntegrationTestBuilder {
return NewIntegrationTestBuilder(cfg).Build()
}

// TestE is the same as Test, but returns an error instead of failing the test.
func TestE(t testing.TB, files string, opts ...TestOpt) (*IntegrationTestBuilder, error) {
cfg := IntegrationTestConfig{T: t, TxtarString: files}
for _, o := range opts {
o(&cfg)
}
return NewIntegrationTestBuilder(cfg).BuildE()
}

// TestRunning is a convenience method to create a new IntegrationTestBuilder from some files with Running set to true and run a build.
// Deprecated: Use Test with TestOptRunning instead.
func TestRunning(t testing.TB, files string, opts ...TestOpt) *IntegrationTestBuilder {
Expand Down

0 comments on commit f31a6db

Please sign in to comment.