summaryrefslogtreecommitdiffstats
path: root/hugolib
diff options
context:
space:
mode:
authorJohn Feminella <jxf+github@jxf.me>2017-02-19 02:50:08 -0500
committerBjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>2017-02-19 08:50:08 +0100
commitb2e3748a4e148a9624b9906bd8f34a238a54429c (patch)
treef29cb748dab294a8a1880495f0dffed5bcf229bc /hugolib
parent6d2281c8ead70ac07122027c989807c0aa1a7722 (diff)
hugolib: Enhance `.Param` to permit arbitrarily nested parameter references
The Param method currently assumes that its argument is a single, distinct, top-level key to look up in the Params map. This enhances the Param method; it will now also attempt to see if the key can be interpreted as a nested chain of keys to look up in Params. Fixes #2598
Diffstat (limited to 'hugolib')
-rw-r--r--hugolib/page.go51
-rw-r--r--hugolib/pageSort.go3
-rw-r--r--hugolib/pageSort_test.go11
-rw-r--r--hugolib/page_test.go31
4 files changed, 87 insertions, 9 deletions
diff --git a/hugolib/page.go b/hugolib/page.go
index e92767da0..042f1378e 100644
--- a/hugolib/page.go
+++ b/hugolib/page.go
@@ -314,13 +314,64 @@ func (p *Page) Param(key interface{}) (interface{}, error) {
if err != nil {
return nil, err
}
+
keyStr = strings.ToLower(keyStr)
+ result, _ := p.traverseDirect(keyStr)
+ if result != nil {
+ return result, nil
+ }
+
+ keySegments := strings.Split(keyStr, ".")
+ if len(keySegments) == 1 {
+ return nil, nil
+ }
+
+ return p.traverseNested(keySegments)
+}
+
+func (p *Page) traverseDirect(key string) (interface{}, error) {
+ keyStr := strings.ToLower(key)
if val, ok := p.Params[keyStr]; ok {
return val, nil
}
+
return p.Site.Params[keyStr], nil
}
+func (p *Page) traverseNested(keySegments []string) (interface{}, error) {
+ result := traverse(keySegments, p.Params)
+ if result != nil {
+ return result, nil
+ }
+
+ result = traverse(keySegments, p.Site.Params)
+ if result != nil {
+ return result, nil
+ }
+
+ // Didn't find anything, but also no problems.
+ return nil, nil
+}
+
+func traverse(keys []string, m map[string]interface{}) interface{} {
+ // Shift first element off.
+ firstKey, rest := keys[0], keys[1:]
+ result := m[firstKey]
+
+ // No point in continuing here.
+ if result == nil {
+ return result
+ }
+
+ if len(rest) == 0 {
+ // That was the last key.
+ return result
+ } else {
+ // That was not the last key.
+ return traverse(rest, cast.ToStringMap(result))
+ }
+}
+
func (p *Page) Author() Author {
authors := p.Authors()
diff --git a/hugolib/pageSort.go b/hugolib/pageSort.go
index e1ea786b6..6d2431cec 100644
--- a/hugolib/pageSort.go
+++ b/hugolib/pageSort.go
@@ -14,9 +14,8 @@
package hugolib
import (
- "sort"
-
"github.com/spf13/cast"
+ "sort"
)
var spc = newPageCache()
diff --git a/hugolib/pageSort_test.go b/hugolib/pageSort_test.go
index f5f28f1d7..a17f53dc6 100644
--- a/hugolib/pageSort_test.go
+++ b/hugolib/pageSort_test.go
@@ -20,7 +20,6 @@ import (
"testing"
"time"
- "github.com/spf13/cast"
"github.com/stretchr/testify/assert"
)
@@ -121,11 +120,11 @@ func TestPageSortReverse(t *testing.T) {
func TestPageSortByParam(t *testing.T) {
t.Parallel()
- var k interface{} = "arbitrary"
+ var k interface{} = "arbitrarily.nested"
s := newTestSite(t)
unsorted := createSortTestPages(s, 10)
- delete(unsorted[9].Params, cast.ToString(k))
+ delete(unsorted[9].Params, "arbitrarily")
firstSetValue, _ := unsorted[0].Param(k)
secondSetValue, _ := unsorted[1].Param(k)
@@ -137,7 +136,7 @@ func TestPageSortByParam(t *testing.T) {
assert.Equal(t, "xyz92", lastSetValue)
assert.Equal(t, nil, unsetValue)
- sorted := unsorted.ByParam("arbitrary")
+ sorted := unsorted.ByParam("arbitrarily.nested")
firstSetSortedValue, _ := sorted[0].Param(k)
secondSetSortedValue, _ := sorted[1].Param(k)
lastSetSortedValue, _ := sorted[8].Param(k)
@@ -182,7 +181,9 @@ func createSortTestPages(s *Site, num int) Pages {
for i := 0; i < num; i++ {
p := s.newPage(filepath.FromSlash(fmt.Sprintf("/x/y/p%d.md", i)))
p.Params = map[string]interface{}{
- "arbitrary": "xyz" + fmt.Sprintf("%v", 100-i),
+ "arbitrarily": map[string]interface{}{
+ "nested": ("xyz" + fmt.Sprintf("%v", 100-i)),
+ },
}
w := 5
diff --git a/hugolib/page_test.go b/hugolib/page_test.go
index 90a4d1245..0fa622e33 100644
--- a/hugolib/page_test.go
+++ b/hugolib/page_test.go
@@ -1336,7 +1336,7 @@ some content
func TestPageParams(t *testing.T) {
t.Parallel()
s := newTestSite(t)
- want := map[string]interface{}{
+ wantedMap := map[string]interface{}{
"tags": []string{"hugo", "web"},
// Issue #2752
"social": []interface{}{
@@ -1348,10 +1348,37 @@ func TestPageParams(t *testing.T) {
for i, c := range pagesParamsTemplate {
p, err := s.NewPageFrom(strings.NewReader(c), "content/post/params.md")
require.NoError(t, err, "err during parse", "#%d", i)
- assert.Equal(t, want, p.Params, "#%d", i)
+ for key, _ := range wantedMap {
+ assert.Equal(t, wantedMap[key], p.Params[key], "#%d", key)
+ }
}
}
+func TestTraverse(t *testing.T) {
+ exampleParams := `---
+rating: "5 stars"
+tags:
+ - hugo
+ - web
+social:
+ twitter: "@jxxf"
+ facebook: "https://example.com"
+---`
+ t.Parallel()
+ s := newTestSite(t)
+ p, _ := s.NewPageFrom(strings.NewReader(exampleParams), "content/post/params.md")
+ fmt.Println("%v", p.Params)
+
+ topLevelKeyValue, _ := p.Param("rating")
+ assert.Equal(t, "5 stars", topLevelKeyValue)
+
+ nestedStringKeyValue, _ := p.Param("social.twitter")
+ assert.Equal(t, "@jxxf", nestedStringKeyValue)
+
+ nonexistentKeyValue, _ := p.Param("doesn't.exist")
+ assert.Nil(t, nonexistentKeyValue)
+}
+
func TestPageSimpleMethods(t *testing.T) {
t.Parallel()
s := newTestSite(t)