diff options
author | John Feminella <jxf+github@jxf.me> | 2017-02-19 02:50:08 -0500 |
---|---|---|
committer | Bjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com> | 2017-02-19 08:50:08 +0100 |
commit | b2e3748a4e148a9624b9906bd8f34a238a54429c (patch) | |
tree | f29cb748dab294a8a1880495f0dffed5bcf229bc /hugolib | |
parent | 6d2281c8ead70ac07122027c989807c0aa1a7722 (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.go | 51 | ||||
-rw-r--r-- | hugolib/pageSort.go | 3 | ||||
-rw-r--r-- | hugolib/pageSort_test.go | 11 | ||||
-rw-r--r-- | hugolib/page_test.go | 31 |
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) |