Skip to content

Commit

Permalink
Cascade
Browse files Browse the repository at this point in the history
  • Loading branch information
bep committed May 13, 2024
1 parent e32dc2d commit f2cd607
Show file tree
Hide file tree
Showing 6 changed files with 87 additions and 28 deletions.
2 changes: 1 addition & 1 deletion hugolib/content_map.go
Original file line number Diff line number Diff line change
Expand Up @@ -315,7 +315,7 @@ func (m *pageMap) addPagesFromGoTmplFi(fi hugofs.FileMetaInfo, buildConfig *Buil
HandlePage: func(pt *pagesfromdata.PagesFromTemplate, pc *pagemeta.PageConfig) error {
s := pt.Site.(*Site)
pc.Path = path.Join(pt.GoTmplFi.Meta().PathInfo.Base(), pc.Path)
if err := pc.Compile(true, "", s.conf.MediaTypes.Config); err != nil {
if err := pc.Compile(true, "", s.Log, s.conf.MediaTypes.Config); err != nil {
return err
}

Expand Down
10 changes: 5 additions & 5 deletions hugolib/content_map_page.go
Original file line number Diff line number Diff line change
Expand Up @@ -1331,7 +1331,7 @@ func (sa *sitePagesAssembler) applyAggregates() error {
// Home page gets it's cascade from the site config.
cascade = sa.conf.Cascade.Config

if pageBundle.m.pageConfig.Cascade == nil {
if pageBundle.m.pageConfig.CascadeCompiled == nil {
// Pass the site cascade downwards.
pw.WalkContext.Data().Insert(keyPage, cascade)
}
Expand Down Expand Up @@ -1371,9 +1371,9 @@ func (sa *sitePagesAssembler) applyAggregates() error {

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

wasZeroDates := pageBundle.m.pageConfig.Dates.IsAllDatesZero()
Expand Down Expand Up @@ -1474,9 +1474,9 @@ func (sa *sitePagesAssembler) applyAggregatesToTaxonomiesAndTerms() error {
p := n.(*pageState)
if p.Kind() != kinds.KindTerm {
// The other kinds were handled in applyAggregates.
if p.m.pageConfig.Cascade != nil {
if p.m.pageConfig.CascadeCompiled != nil {
// Pass it down.
pw.WalkContext.Data().Insert(s, p.m.pageConfig.Cascade)
pw.WalkContext.Data().Insert(s, p.m.pageConfig.CascadeCompiled)
}
}

Expand Down
33 changes: 20 additions & 13 deletions hugolib/page__meta.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ type pageMetaFrontMatter struct {
func (m *pageMetaParams) init(preserveOringal bool) {
if preserveOringal {
m.paramsOriginal = xmaps.Clone[maps.Params](m.pageConfig.Params)
m.cascadeOriginal = xmaps.Clone[map[page.PageMatcher]maps.Params](m.pageConfig.Cascade)
m.cascadeOriginal = xmaps.Clone[map[page.PageMatcher]maps.Params](m.pageConfig.CascadeCompiled)
}
}

Expand Down Expand Up @@ -290,7 +290,7 @@ func (p *pageMeta) setMetaPre(pi *contentParseInfo, logger loggers.Logger, conf
if err != nil {
return err
}
pcfg.Cascade = cascade
pcfg.CascadeCompiled = cascade
}

// Look for path, lang and kind, all of which values we need early on.
Expand Down Expand Up @@ -328,18 +328,18 @@ func (ps *pageState) setMetaPost(cascade map[page.PageMatcher]maps.Params) error
ps.m.setMetaPostCount++
var cascadeHashPre uint64
if ps.m.setMetaPostCount > 1 {
cascadeHashPre = identity.HashUint64(ps.m.pageConfig.Cascade)
ps.m.pageConfig.Cascade = xmaps.Clone[map[page.PageMatcher]maps.Params](ps.m.cascadeOriginal)
cascadeHashPre = identity.HashUint64(ps.m.pageConfig.CascadeCompiled)
ps.m.pageConfig.CascadeCompiled = xmaps.Clone[map[page.PageMatcher]maps.Params](ps.m.cascadeOriginal)

}

// Apply cascades first so they can be overridden later.
if cascade != nil {
if ps.m.pageConfig.Cascade != nil {
if ps.m.pageConfig.CascadeCompiled != nil {
for k, v := range cascade {
vv, found := ps.m.pageConfig.Cascade[k]
vv, found := ps.m.pageConfig.CascadeCompiled[k]
if !found {
ps.m.pageConfig.Cascade[k] = v
ps.m.pageConfig.CascadeCompiled[k] = v
} else {
// Merge
for ck, cv := range v {
Expand All @@ -349,18 +349,18 @@ func (ps *pageState) setMetaPost(cascade map[page.PageMatcher]maps.Params) error
}
}
}
cascade = ps.m.pageConfig.Cascade
cascade = ps.m.pageConfig.CascadeCompiled
} else {
ps.m.pageConfig.Cascade = cascade
ps.m.pageConfig.CascadeCompiled = cascade
}
}

if cascade == nil {
cascade = ps.m.pageConfig.Cascade
cascade = ps.m.pageConfig.CascadeCompiled
}

if ps.m.setMetaPostCount > 1 {
ps.m.setMetaPostCascadeChanged = cascadeHashPre != identity.HashUint64(ps.m.pageConfig.Cascade)
ps.m.setMetaPostCascadeChanged = cascadeHashPre != identity.HashUint64(ps.m.pageConfig.CascadeCompiled)
if !ps.m.setMetaPostCascadeChanged {

// No changes, restore any value that may be changed by aggregation.
Expand Down Expand Up @@ -402,12 +402,14 @@ func (p *pageState) setMetaPostParams() error {
var mtime time.Time
var contentBaseName string
var ext string
var isContentAdapter bool
if p.File() != nil {
isContentAdapter = p.File().IsContentAdapter()
contentBaseName = p.File().ContentBaseName()
if p.File().FileInfo() != nil {
mtime = p.File().FileInfo().ModTime()
}
if !p.File().IsContentAdapter() {
if !isContentAdapter {
ext = p.File().Ext()
}
}
Expand All @@ -433,6 +435,11 @@ func (p *pageState) setMetaPostParams() error {
p.s.Log.Errorf("Failed to handle dates for page %q: %s", p.pathOrTitle(), err)
}

if isContentAdapter {
// Done.
return nil
}

var buildConfig any
var isNewBuildKeyword bool
if v, ok := pm.pageConfig.Params["_build"]; ok {
Expand Down Expand Up @@ -683,7 +690,7 @@ params:
return err
}

return pcfg.Compile(false, ext, p.s.conf.MediaTypes.Config)
return pcfg.Compile(false, ext, p.s.Log, p.s.conf.MediaTypes.Config)
}

// shouldList returns whether this page should be included in the list of pages.
Expand Down
8 changes: 2 additions & 6 deletions hugolib/pagesfromdata/pagesfromgotmpl.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,17 +87,13 @@ func (p *pagesFromDataTemplateContext) AddPage(v any) (string, error) {
return "", nil
}

pd := pagemeta.PageConfig{
IsFromContentAdapter: true,
}
pd := pagemeta.DefaultPageConfig
pd.IsFromContentAdapter = true

if err := mapstructure.WeakDecode(m, &pd); err != nil {
return "", fmt.Errorf("failed to decode page map: %w", err)
}

// TODO1
pd.Build = pagemeta.DefaultBuildConfig

p.p.buildState.NumPagesAdded++

if err := pd.Validate(true); err != nil {
Expand Down
42 changes: 42 additions & 0 deletions hugolib/pagesfromdata/pagesfromgotmpl_integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -423,3 +423,45 @@ baseURL = "https://example.com"

b.AssertFileContent("public/docs/p1/index.html", "RelPermalink: /docs/p1/myresource|Name: myresource|Title: myresource|Params: map[]|MediaType: text/plain|")
}

func TestPagesFromGoTmplCascade(t *testing.T) {
t.Parallel()

files := `
-- hugo.toml --
disableKinds = ["taxonomy", "term", "rss", "sitemap"]
baseURL = "https://example.com"
-- layouts/_default/single.html --
|Content: {{ .Content }}|Title: {{ .Title }}|Path: {{ .Path }}|Params: {{ .Params }}|
-- content/_content.gotmpl --
{{ $cascade := dict "params" (dict "cascadeparam1" "cascadeparam1value" ) }}
{{ $.AddPage (dict "path" "docs" "kind" "section" "cascade" $cascade ) }}
{{ $.AddPage (dict "path" "docs/p1" "content" (dict "value" "**Hello World**" "mediaType" "text/markdown" )) }}
`
b := hugolib.Test(t, files)

b.AssertFileContent("public/docs/p1/index.html", "|Path: /docs/p1|Params: map[cascadeparam1:cascadeparam1value")
}

func TestPagesFromGoBuildOptions(t *testing.T) {
t.Parallel()

files := `
-- hugo.toml --
disableKinds = ["taxonomy", "term", "rss", "sitemap"]
baseURL = "https://example.com"
-- layouts/_default/single.html --
|Content: {{ .Content }}|Title: {{ .Title }}|Path: {{ .Path }}|Params: {{ .Params }}|
-- content/_content.gotmpl --
{{ $.AddPage (dict "path" "docs/p1" "content" (dict "value" "**Hello World**" "mediaType" "text/markdown" )) }}
{{ $never := dict "list" "never" "publishResources" false "render" "never" }}
{{ $.AddPage (dict "path" "docs/p2" "content" (dict "value" "**Hello World**" "mediaType" "text/markdown" ) "build" $never ) }}
`
b := hugolib.Test(t, files)

b.AssertFileExists("public/docs/p1/index.html", true)
b.AssertFileExists("public/docs/p2/index.html", false)
}
20 changes: 17 additions & 3 deletions resources/page/pagemeta/page_frontmatter.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ type PageConfig struct {

FrontMatterOnlyValues `mapstructure:"-" json:"-"`

Cascade map[page.PageMatcher]maps.Params // Only relevant for branch nodes.
Cascade []map[string]any
Sitemap config.SitemapConfig
Build BuildConfig

Expand All @@ -110,10 +110,15 @@ type PageConfig struct {
Content Source

// Compiled values.
CascadeCompiled map[page.PageMatcher]maps.Params
ContentMediaType media.Type `mapstructure:"-" json:"-"`
IsFromContentAdapter bool `mapstructure:"-" json:"-"`
}

var DefaultPageConfig = PageConfig{
Build: DefaultBuildConfig,
}

func (p *PageConfig) Validate(pagesFromData bool) error {
if pagesFromData {
if p.Path == "" {
Expand All @@ -127,7 +132,7 @@ func (p *PageConfig) Validate(pagesFromData bool) error {
}
}

if len(p.Cascade) > 0 {
if p.Cascade != nil {
if !kinds.IsBranch(p.Kind) {
return errors.New("cascade is only supported for branch nodes")
}
Expand All @@ -137,7 +142,7 @@ func (p *PageConfig) Validate(pagesFromData bool) error {
}

// Compile sets up the page configuration after all fields have been set.
func (p *PageConfig) Compile(pagesFromData bool, ext string, mediaTypes media.Types) error {
func (p *PageConfig) Compile(pagesFromData bool, ext string, logger loggers.Logger, mediaTypes media.Types) error {
if p.Content.Markup == "" && p.Content.MediaType == "" {
if ext == "" {
ext = "md"
Expand All @@ -164,6 +169,15 @@ func (p *PageConfig) Compile(pagesFromData bool, ext string, mediaTypes media.Ty
if p.ContentMediaType.IsZero() {
return fmt.Errorf("failed to resolve media type for %q", s)
}

if p.Cascade != nil {
cascade, err := page.DecodeCascade(logger, p.Cascade)
if err != nil {
return fmt.Errorf("failed to decode cascade: %w", err)
}
p.CascadeCompiled = cascade
}

return nil
}

Expand Down

0 comments on commit f2cd607

Please sign in to comment.