From 3a27cefec1beb8e2e49ec206264d7d19cde0ffae Mon Sep 17 00:00:00 2001 From: NotZippy Date: Fri, 2 Oct 2015 08:30:21 -0700 Subject: [PATCH] Add dictionary function to be passed into a template Allows templates to dynamically build maps. Example usage: Creating and passing a map to a subtemplate while in a range on the parent. --- docs/content/templates/functions.md | 23 +++++++++++++++++++++++ tpl/template_funcs.go | 16 ++++++++++++++++ tpl/template_funcs_test.go | 24 ++++++++++++++++++++++++ 3 files changed, 63 insertions(+) diff --git a/docs/content/templates/functions.md b/docs/content/templates/functions.md index d27e45035..88129aa1f 100644 --- a/docs/content/templates/functions.md +++ b/docs/content/templates/functions.md @@ -50,6 +50,29 @@ e.g. // Outputs Tags: tag1, tag2 and tag3 +### dict +Creates a dictionary (map[string, interface{}), expects parameters added in value:object fasion. +Invalid combinations like keys that are not strings or uneven number of parameters, will result in an exception thrown +Useful for passing maps to partials when adding to a template. + +e.g. Pass into "foo.html" a map with the keys "important, content" + + {{$important := .Site.Params.SomethingImportant }} + {{range .Site.Params.Bar}} + {{partial "foo" (dict "content" . "important" $important)}} + {{end}} + +"foo.html" + + Important {{.important}} + {{.content}} + + +or Create a map on the fly to pass into + + {{partial "foo" (dict "important" "Smiles" "content" "You should do more")}} + + ### echoParam Prints a parameter if it is set. diff --git a/tpl/template_funcs.go b/tpl/template_funcs.go index 7af70b474..b1ac341f6 100644 --- a/tpl/template_funcs.go +++ b/tpl/template_funcs.go @@ -78,6 +78,21 @@ func Lt(a, b interface{}) bool { return left < right } +func Dictionary(values ...interface{}) (map[string]interface{}, error) { + if len(values)%2 != 0 { + return nil, errors.New("invalid dict call") + } + dict := make(map[string]interface{}, len(values)/2) + for i := 0; i < len(values); i+=2 { + key, ok := values[i].(string) + if !ok { + return nil, errors.New("dict keys must be strings") + } + dict[key] = values[i+1] + } + return dict, nil +} + func compareGetFloat(a interface{}, b interface{}) (float64, float64) { var left, right float64 var leftStr, rightStr *string @@ -1356,6 +1371,7 @@ func init() { "ge": Ge, "lt": Lt, "le": Le, + "dict": Dictionary, "in": In, "slicestr": Slicestr, "substr": Substr, diff --git a/tpl/template_funcs_test.go b/tpl/template_funcs_test.go index e8b91efa3..bc2515a4a 100644 --- a/tpl/template_funcs_test.go +++ b/tpl/template_funcs_test.go @@ -324,6 +324,30 @@ func TestAfter(t *testing.T) { } } +func TestDictionary(t *testing.T) { + for i, this := range []struct { + v1 []interface{} + expecterr bool + expectedValue map[string] interface{} + }{ + {[]interface{}{"a", "b"}, false, map[string]interface{}{"a":"b"}}, + {[]interface{}{5, "b"}, true,nil}, + {[]interface{}{"a", 12,"b",[]int{4}}, false,map[string]interface{}{"a":12,"b":[]int{4}}}, + {[]interface{}{"a", "b", "c"}, true,nil}, + } { + r,e := Dictionary(this.v1...) + + if (this.expecterr && e==nil) || (!this.expecterr && e!=nil) { + t.Errorf("[%d] got an unexpected error", i, e, this.expecterr) + } else if !this.expecterr { + if !reflect.DeepEqual(r, this.expectedValue) { + t.Errorf("[%d] got %v but expected %v", i, r, this.expectedValue) + } + } + } +} + + func TestIn(t *testing.T) { for i, this := range []struct { v1 interface{}