diff options
author | Bjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com> | 2020-10-05 20:01:52 +0200 |
---|---|---|
committer | Bjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com> | 2020-10-06 14:06:10 +0200 |
commit | c63db7f1f6774a2d661af1d8197c6fe377e3ad25 (patch) | |
tree | bbeccc7dd4f41acdcc1cfd584ea351e6284869d5 /hugolib | |
parent | 5e2a547cb594b31ecb0f089b08db2e15c6dc381a (diff) |
Allow cascade to be a slice with a _target discriminator
Fixes #7782
Diffstat (limited to 'hugolib')
-rw-r--r-- | hugolib/cascade_test.go | 70 | ||||
-rw-r--r-- | hugolib/content_map_page.go | 2 | ||||
-rw-r--r-- | hugolib/page__meta.go | 61 | ||||
-rw-r--r-- | hugolib/page_test.go | 21 | ||||
-rw-r--r-- | hugolib/pages_capture.go | 9 |
5 files changed, 152 insertions, 11 deletions
diff --git a/hugolib/cascade_test.go b/hugolib/cascade_test.go index 33fc7ceec..336acdcf3 100644 --- a/hugolib/cascade_test.go +++ b/hugolib/cascade_test.go @@ -229,7 +229,7 @@ Banner: post.jpg`, counters := &testCounters{} b.Build(BuildCfg{testCounters: counters}) - // As we only changed the content, not the cascade front matter, make + // As we only changed the content, not the cascade front matter, // only the home page is re-rendered. b.Assert(int(counters.contentRenderCounter), qt.Equals, 1) @@ -392,3 +392,71 @@ defaultContentLanguageInSubDir = false return b } + +func TestCascadeTarget(t *testing.T) { + t.Parallel() + + c := qt.New(t) + + newBuilder := func(c *qt.C) *sitesBuilder { + b := newTestSitesBuilder(c) + + b.WithTemplates("index.html", ` +{{ $p1 := site.GetPage "s1/p1" }} +{{ $s1 := site.GetPage "s1" }} + +P1|p1:{{ $p1.Params.p1 }}|p2:{{ $p1.Params.p2 }}| +S1|p1:{{ $s1.Params.p1 }}|p2:{{ $s1.Params.p2 }}| +`) + b.WithContent("s1/_index.md", "---\ntitle: s1 section\n---") + b.WithContent("s1/p1/index.md", "---\ntitle: p1\n---") + b.WithContent("s1/p2/index.md", "---\ntitle: p2\n---") + b.WithContent("s2/p1/index.md", "---\ntitle: p1_2\n---") + + return b + + } + + c.Run("slice", func(c *qt.C) { + b := newBuilder(c) + b.WithContent("_index.md", `+++ +title = "Home" +[[cascade]] +p1 = "p1" +[[cascade]] +p2 = "p2" ++++ +`) + + b.Build(BuildCfg{}) + + b.AssertFileContent("public/index.html", "P1|p1:p1|p2:p2") + + }) + + c.Run("slice with _target", func(c *qt.C) { + b := newBuilder(c) + + b.WithContent("_index.md", `+++ +title = "Home" +[[cascade]] +p1 = "p1" +[cascade._target] +path="**p1**" +[[cascade]] +p2 = "p2" +[cascade._target] +kind="section" ++++ +`) + + b.Build(BuildCfg{}) + + b.AssertFileContent("public/index.html", ` +P1|p1:p1|p2:| +S1|p1:|p2:p2| +`) + + }) + +} diff --git a/hugolib/content_map_page.go b/hugolib/content_map_page.go index b32f808c9..b2a8fda7e 100644 --- a/hugolib/content_map_page.go +++ b/hugolib/content_map_page.go @@ -789,7 +789,7 @@ func (m *pageMaps) withMaps(fn func(pm *pageMap) error) error { type pagesMapBucket struct { // Cascading front matter. - cascade maps.Params + cascade map[page.PageMatcher]maps.Params owner *pageState // The branch node diff --git a/hugolib/page__meta.go b/hugolib/page__meta.go index 0e16292f0..c7a8db3d5 100644 --- a/hugolib/page__meta.go +++ b/hugolib/page__meta.go @@ -308,12 +308,22 @@ func (p *pageMeta) Weight() int { func (pm *pageMeta) mergeBucketCascades(b1, b2 *pagesMapBucket) { if b1.cascade == nil { - b1.cascade = make(map[string]interface{}) + b1.cascade = make(map[page.PageMatcher]maps.Params) } + if b2 != nil && b2.cascade != nil { for k, v := range b2.cascade { - if _, found := b1.cascade[k]; !found { + + vv, found := b1.cascade[k] + if !found { b1.cascade[k] = v + } else { + // Merge + for ck, cv := range v { + if _, found := vv[ck]; !found { + vv[ck] = cv + } + } } } } @@ -332,14 +342,44 @@ func (pm *pageMeta) setMetadata(parentBucket *pagesMapBucket, p *pageState, fron if p.bucket != nil { // Check for any cascade define on itself. if cv, found := frontmatter["cascade"]; found { - p.bucket.cascade = maps.ToStringMap(cv) + switch v := cv.(type) { + case []map[string]interface{}: + p.bucket.cascade = make(map[page.PageMatcher]maps.Params) + + for _, vv := range v { + var m page.PageMatcher + if mv, found := vv["_target"]; found { + err := page.DecodePageMatcher(mv, &m) + if err != nil { + return err + } + } + c, found := p.bucket.cascade[m] + if found { + // Merge + for k, v := range vv { + if _, found := c[k]; !found { + c[k] = v + } + } + } else { + p.bucket.cascade[m] = vv + } + + } + default: + p.bucket.cascade = map[page.PageMatcher]maps.Params{ + page.PageMatcher{}: maps.ToStringMap(cv), + } + } + } } } else { frontmatter = make(map[string]interface{}) } - var cascade map[string]interface{} + var cascade map[page.PageMatcher]maps.Params if p.bucket != nil { if parentBucket != nil { @@ -351,9 +391,14 @@ func (pm *pageMeta) setMetadata(parentBucket *pagesMapBucket, p *pageState, fron cascade = parentBucket.cascade } - for k, v := range cascade { - if _, found := frontmatter[k]; !found { - frontmatter[k] = v + for m, v := range cascade { + if !m.Matches(p) { + continue + } + for kk, vv := range v { + if _, found := frontmatter[kk]; !found { + frontmatter[kk] = vv + } } } @@ -466,7 +511,7 @@ func (pm *pageMeta) setMetadata(parentBucket *pagesMapBucket, p *pageState, fron case "outputs": o := cast.ToStringSlice(v) if len(o) > 0 { - // Output formats are exlicitly set in front matter, use those. + // Output formats are explicitly set in front matter, use those. outFormats, err := p.s.outputFormatsConfig.GetByNames(o...) if err != nil { diff --git a/hugolib/page_test.go b/hugolib/page_test.go index 2df679a74..3a30216ed 100644 --- a/hugolib/page_test.go +++ b/hugolib/page_test.go @@ -1757,3 +1757,24 @@ $$$ `<pre><code class="language-bash {hl_lines=[1]}" data-lang="bash {hl_lines=[1]}">SHORT`, ) } + +func TestPageCaseIssues(t *testing.T) { + t.Parallel() + + b := newTestSitesBuilder(t) + b.WithConfigFile("toml", `defaultContentLanguage = "no" +[languages] +[languages.NO] +title = "Norsk" +`) + b.WithContent("a/B/C/Page1.md", "---\ntitle: Page1\n---") + b.WithTemplates("index.html", ` +{{ $p1 := site.GetPage "a/B/C/Page1" }} +Lang: {{ .Lang }} +Page1: {{ $p1.Path }} +`) + + b.Build(BuildCfg{}) + + b.AssertFileContent("public/index.html", "Lang: no", filepath.FromSlash("Page1: a/B/C/Page1.md")) +} diff --git a/hugolib/pages_capture.go b/hugolib/pages_capture.go index ddb4bc495..4ee33992d 100644 --- a/hugolib/pages_capture.go +++ b/hugolib/pages_capture.go @@ -137,6 +137,7 @@ func (c *pagesCollector) isCascadingEdit(dir contentDirKey) (bool, string) { hasCascade := n.p.bucket.cascade != nil && len(n.p.bucket.cascade) > 0 if !ok { isCascade = hasCascade + return true } @@ -145,7 +146,12 @@ func (c *pagesCollector) isCascadingEdit(dir contentDirKey) (bool, string) { return true } - isCascade = !reflect.DeepEqual(cascade1, n.p.bucket.cascade) + for _, v := range n.p.bucket.cascade { + isCascade = !reflect.DeepEqual(cascade1, v) + if isCascade { + break + } + } return true @@ -187,6 +193,7 @@ func (c *pagesCollector) Collect() (collectErr error) { collectErr = c.collectDir(dir.dirname, true, nil) case bundleBranch: isCascading, section := c.isCascadingEdit(dir) + if isCascading { c.contentMap.deleteSection(section) } |