mirror of
https://github.com/gohugoio/hugo.git
synced 2024-11-21 20:46:30 -05:00
Allow cascade _target to work with non toml fm
The TOML lib unmarshals slices of string maps to []map[string]interface{} whereas YAML and JSON decode to []interface{} The existing tests only check for TOML working correctly, and _target with cascade did not work at all for frontmatter defined in other formats. Add a function to normalize those slices Fixes #7874
This commit is contained in:
parent
fdfa4a5fe6
commit
3400aff258
4 changed files with 108 additions and 4 deletions
|
@ -14,6 +14,7 @@
|
||||||
package maps
|
package maps
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/gobwas/glob"
|
"github.com/gobwas/glob"
|
||||||
|
@ -64,6 +65,23 @@ func ToStringMap(in interface{}) map[string]interface{} {
|
||||||
return m
|
return m
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func ToSliceStringMap(in interface{}) ([]map[string]interface{}, error) {
|
||||||
|
switch v := in.(type) {
|
||||||
|
case []map[string]interface{}:
|
||||||
|
return v, nil
|
||||||
|
case []interface{}:
|
||||||
|
var s []map[string]interface{}
|
||||||
|
for _, entry := range v {
|
||||||
|
if vv, ok := entry.(map[string]interface{}); ok {
|
||||||
|
s = append(s, vv)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return s, nil
|
||||||
|
default:
|
||||||
|
return nil, fmt.Errorf("unable to cast %#v of type %T to []map[string]interface{}", in, in)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
type keyRename struct {
|
type keyRename struct {
|
||||||
pattern glob.Glob
|
pattern glob.Glob
|
||||||
newKey string
|
newKey string
|
||||||
|
|
|
@ -75,6 +75,39 @@ func TestToLower(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestToSliceStringMap(t *testing.T) {
|
||||||
|
c := qt.New(t)
|
||||||
|
|
||||||
|
tests := []struct {
|
||||||
|
input interface{}
|
||||||
|
expected []map[string]interface{}
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
input: []map[string]interface{}{
|
||||||
|
{"abc": 123},
|
||||||
|
},
|
||||||
|
expected: []map[string]interface{}{
|
||||||
|
{"abc": 123},
|
||||||
|
},
|
||||||
|
}, {
|
||||||
|
input: []interface{}{
|
||||||
|
map[string]interface{}{
|
||||||
|
"def": 456,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expected: []map[string]interface{}{
|
||||||
|
{"def": 456},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range tests {
|
||||||
|
v, err := ToSliceStringMap(test.input)
|
||||||
|
c.Assert(err, qt.IsNil)
|
||||||
|
c.Assert(v, qt.DeepEquals, test.expected)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestRenameKeys(t *testing.T) {
|
func TestRenameKeys(t *testing.T) {
|
||||||
c := qt.New(t)
|
c := qt.New(t)
|
||||||
|
|
||||||
|
|
|
@ -459,4 +459,58 @@ S1|p1:|p2:p2|
|
||||||
|
|
||||||
})
|
})
|
||||||
|
|
||||||
|
c.Run("slice with yaml _target", func(c *qt.C) {
|
||||||
|
b := newBuilder(c)
|
||||||
|
|
||||||
|
b.WithContent("_index.md", `---
|
||||||
|
title: "Home"
|
||||||
|
cascade:
|
||||||
|
- p1: p1
|
||||||
|
_target:
|
||||||
|
path: "**p1**"
|
||||||
|
- p2: p2
|
||||||
|
_target:
|
||||||
|
kind: "section"
|
||||||
|
---
|
||||||
|
`)
|
||||||
|
|
||||||
|
b.Build(BuildCfg{})
|
||||||
|
|
||||||
|
b.AssertFileContent("public/index.html", `
|
||||||
|
P1|p1:p1|p2:|
|
||||||
|
S1|p1:|p2:p2|
|
||||||
|
`)
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
c.Run("slice with json _target", func(c *qt.C) {
|
||||||
|
b := newBuilder(c)
|
||||||
|
|
||||||
|
b.WithContent("_index.md", `{
|
||||||
|
"title": "Home",
|
||||||
|
"cascade": [
|
||||||
|
{
|
||||||
|
"p1": "p1",
|
||||||
|
"_target": {
|
||||||
|
"path": "**p1**"
|
||||||
|
}
|
||||||
|
},{
|
||||||
|
"p2": "p2",
|
||||||
|
"_target": {
|
||||||
|
"kind": "section"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
`)
|
||||||
|
|
||||||
|
b.Build(BuildCfg{})
|
||||||
|
|
||||||
|
b.AssertFileContent("public/index.html", `
|
||||||
|
P1|p1:p1|p2:|
|
||||||
|
S1|p1:|p2:p2|
|
||||||
|
`)
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -342,8 +342,7 @@ func (pm *pageMeta) setMetadata(parentBucket *pagesMapBucket, p *pageState, fron
|
||||||
if p.bucket != nil {
|
if p.bucket != nil {
|
||||||
// Check for any cascade define on itself.
|
// Check for any cascade define on itself.
|
||||||
if cv, found := frontmatter["cascade"]; found {
|
if cv, found := frontmatter["cascade"]; found {
|
||||||
switch v := cv.(type) {
|
if v, err := maps.ToSliceStringMap(cv); err == nil {
|
||||||
case []map[string]interface{}:
|
|
||||||
p.bucket.cascade = make(map[page.PageMatcher]maps.Params)
|
p.bucket.cascade = make(map[page.PageMatcher]maps.Params)
|
||||||
|
|
||||||
for _, vv := range v {
|
for _, vv := range v {
|
||||||
|
@ -367,14 +366,14 @@ func (pm *pageMeta) setMetadata(parentBucket *pagesMapBucket, p *pageState, fron
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
default:
|
} else {
|
||||||
p.bucket.cascade = map[page.PageMatcher]maps.Params{
|
p.bucket.cascade = map[page.PageMatcher]maps.Params{
|
||||||
page.PageMatcher{}: maps.ToStringMap(cv),
|
page.PageMatcher{}: maps.ToStringMap(cv),
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
frontmatter = make(map[string]interface{})
|
frontmatter = make(map[string]interface{})
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue