shithub: hugo

Download patch

ref: 3a27cefec1beb8e2e49ec206264d7d19cde0ffae
parent: ccd83c3040771ea496d41b63fa8cba2cecd46f0f
author: NotZippy <[email protected]>
date: Fri Oct 2 04:30:21 EDT 2015

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.

--- a/docs/content/templates/functions.md
+++ b/docs/content/templates/functions.md
@@ -50,6 +50,29 @@
 
     // 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.
--- a/tpl/template_funcs.go
+++ b/tpl/template_funcs.go
@@ -78,6 +78,21 @@
 	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 @@
 		"ge":           Ge,
 		"lt":           Lt,
 		"le":           Le,
+		"dict":         Dictionary,
 		"in":           In,
 		"slicestr":     Slicestr,
 		"substr":       Substr,
--- a/tpl/template_funcs_test.go
+++ b/tpl/template_funcs_test.go
@@ -324,6 +324,30 @@
 	}
 }
 
+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{}