shithub: hugo

Download patch

ref: d12f6cd7751ba5072dde8a1adda2b773719309fc
parent: c0f54aefe38bc16406a187b3d20b6ffddc70eb04
author: Tatsushi Demachi <[email protected]>
date: Wed Jan 7 16:26:46 EST 2015

Fix `echoParam` template function to accept string key name

This changes `echoParam` template function behavior to accept not only
an array or a slice and its index pair but also a map and its key pair.

This also changes the function that float and uint values are treated as
a valid result type of it.

Fix #771

--- a/tpl/template.go
+++ b/tpl/template.go
@@ -785,20 +785,36 @@
 	return false
 }
 
-func ReturnWhenSet(a interface{}, index int) interface{} {
-	av := reflect.ValueOf(a)
+func ReturnWhenSet(a, k interface{}) interface{} {
+	av, isNil := indirect(reflect.ValueOf(a))
+	if isNil {
+		return ""
+	}
 
+	var avv reflect.Value
 	switch av.Kind() {
 	case reflect.Array, reflect.Slice:
-		if av.Len() > index {
+		index, ok := k.(int)
+		if ok && av.Len() > index {
+			avv = av.Index(index)
+		}
+	case reflect.Map:
+		kv := reflect.ValueOf(k)
+		if kv.Type().AssignableTo(av.Type().Key()) {
+			avv = av.MapIndex(kv)
+		}
+	}
 
-			avv := av.Index(index)
-			switch avv.Kind() {
-			case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
-				return avv.Int()
-			case reflect.String:
-				return avv.String()
-			}
+	if avv.IsValid() {
+		switch avv.Kind() {
+		case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+			return avv.Int()
+		case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
+			return avv.Uint()
+		case reflect.Float32, reflect.Float64:
+			return avv.Float()
+		case reflect.String:
+			return avv.String()
 		}
 	}
 
--- a/tpl/template_test.go
+++ b/tpl/template_test.go
@@ -791,6 +791,31 @@
 	}
 }
 
+func TestReturnWhenSet(t *testing.T) {
+	for i, this := range []struct {
+		data   interface{}
+		key    interface{}
+		expect interface{}
+	}{
+		{[]int{1, 2, 3}, 1, int64(2)},
+		{[]uint{1, 2, 3}, 1, uint64(2)},
+		{[]float64{1.1, 2.2, 3.3}, 1, float64(2.2)},
+		{[]string{"foo", "bar", "baz"}, 1, "bar"},
+		{[]TstX{TstX{A: "a", B: "b"}, TstX{A: "c", B: "d"}, TstX{A: "e", B: "f"}}, 1, ""},
+		{map[string]int{"foo": 1, "bar": 2, "baz": 3}, "bar", int64(2)},
+		{map[string]uint{"foo": 1, "bar": 2, "baz": 3}, "bar", uint64(2)},
+		{map[string]float64{"foo": 1.1, "bar": 2.2, "baz": 3.3}, "bar", float64(2.2)},
+		{map[string]string{"foo": "FOO", "bar": "BAR", "baz": "BAZ"}, "bar", "BAR"},
+		{map[string]TstX{"foo": TstX{A: "a", B: "b"}, "bar": TstX{A: "c", B: "d"}, "baz": TstX{A: "e", B: "f"}}, "bar", ""},
+		{(*[]string)(nil), "bar", ""},
+	} {
+		result := ReturnWhenSet(this.data, this.key)
+		if !reflect.DeepEqual(result, this.expect) {
+			t.Errorf("[%d] ReturnWhenSet got %v (type %v) but expected %v (type %v)", i, result, reflect.TypeOf(result), this.expect, reflect.TypeOf(this.expect))
+		}
+	}
+}
+
 func TestMarkdownify(t *testing.T) {
 
 	result := Markdownify("Hello **World!**")