mirror of
https://github.com/gohugoio/hugo.git
synced 2024-11-07 20:30:36 -05:00
tpl: fix default function
This commit fixes a few things: 1. `given` is now a variadic parameter so that piping works properly 2. add separate template tests to make sure piping works 3. support time values 4. add more tests of the dfault function
This commit is contained in:
parent
0743646f32
commit
09c8c17bf0
3 changed files with 75 additions and 10 deletions
|
@ -37,7 +37,7 @@ non-nil for any other types.
|
|||
e.g.
|
||||
|
||||
{{ index .Params "font" | default "Roboto" }} → default is "Roboto"
|
||||
{{ default "Roboto" .Params.font }} → default is "Roboto"
|
||||
{{ default "Roboto" (index .Params "font") }} → default is "Roboto"
|
||||
|
||||
### delimit
|
||||
Loops through any array, slice or map and returns a string of all the values separated by the delimiter. There is an optional third parameter that lets you choose a different delimiter to go between the last two values.
|
||||
|
|
|
@ -1243,10 +1243,21 @@ func dateFormat(layout string, v interface{}) (string, error) {
|
|||
// is not. "Set" in this context means true for booleans; non-zero for numeric
|
||||
// types; non-zero length for strings, arrays, slices, and maps; any struct
|
||||
// value; or non-nil for any other types.
|
||||
func dfault(dflt, given interface{}) interface{} {
|
||||
g := reflect.ValueOf(given)
|
||||
func dfault(dflt interface{}, given ...interface{}) (interface{}, error) {
|
||||
// given is variadic because the following construct will not pass a piped
|
||||
// argument when the key is missing: {{ index . "key" | default "foo" }}
|
||||
// The Go template will complain that we got 1 argument when we expectd 2.
|
||||
|
||||
if given == nil || len(given) == 0 {
|
||||
return dflt, nil
|
||||
}
|
||||
if len(given) != 1 {
|
||||
return nil, fmt.Errorf("wrong number of args for default: want 2 got %d", len(given)+1)
|
||||
}
|
||||
|
||||
g := reflect.ValueOf(given[0])
|
||||
if !g.IsValid() {
|
||||
return dflt
|
||||
return dflt, nil
|
||||
}
|
||||
|
||||
set := false
|
||||
|
@ -1265,16 +1276,21 @@ func dfault(dflt, given interface{}) interface{} {
|
|||
case reflect.Complex64, reflect.Complex128:
|
||||
set = g.Complex() != 0
|
||||
case reflect.Struct:
|
||||
set = true
|
||||
switch actual := given[0].(type) {
|
||||
case time.Time:
|
||||
set = !actual.IsZero()
|
||||
default:
|
||||
set = true
|
||||
}
|
||||
default:
|
||||
set = !g.IsNil()
|
||||
}
|
||||
|
||||
if set {
|
||||
return given
|
||||
return given[0], nil
|
||||
}
|
||||
|
||||
return dflt
|
||||
return dflt, nil
|
||||
}
|
||||
|
||||
// safeHTMLAttr returns a given string as html/template HTMLAttr content.
|
||||
|
|
|
@ -1844,7 +1844,10 @@ func TestDateFormat(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestDefault(t *testing.T) {
|
||||
func TestDefaultFunc(t *testing.T) {
|
||||
then := time.Now()
|
||||
now := time.Now()
|
||||
|
||||
for i, this := range []struct {
|
||||
dflt interface{}
|
||||
given interface{}
|
||||
|
@ -1854,34 +1857,80 @@ func TestDefault(t *testing.T) {
|
|||
|
||||
{"test1", "set", "set"},
|
||||
{"test2", "", "test2"},
|
||||
{"test3", nil, "test3"},
|
||||
|
||||
{[2]int{10, 20}, [2]int{1, 2}, [2]int{1, 2}},
|
||||
{[2]int{10, 20}, [0]int{}, [2]int{10, 20}},
|
||||
{[2]int{100, 200}, nil, [2]int{100, 200}},
|
||||
|
||||
{[]string{"one"}, []string{"uno"}, []string{"uno"}},
|
||||
{[]string{"one"}, []string{}, []string{"one"}},
|
||||
{[]string{"two"}, []string{}, []string{"two"}},
|
||||
{[]string{"three"}, nil, []string{"three"}},
|
||||
|
||||
{map[string]int{"one": 1}, map[string]int{"uno": 1}, map[string]int{"uno": 1}},
|
||||
{map[string]int{"one": 1}, map[string]int{}, map[string]int{"one": 1}},
|
||||
{map[string]int{"two": 2}, nil, map[string]int{"two": 2}},
|
||||
|
||||
{10, 1, 1},
|
||||
{10, 0, 10},
|
||||
{20, nil, 20},
|
||||
|
||||
{float32(10), float32(1), float32(1)},
|
||||
{float32(10), 0, float32(10)},
|
||||
{float32(20), nil, float32(20)},
|
||||
|
||||
{complex(2, -2), complex(1, -1), complex(1, -1)},
|
||||
{complex(2, -2), complex(0, 0), complex(2, -2)},
|
||||
{complex(3, -3), nil, complex(3, -3)},
|
||||
|
||||
{struct{ f string }{f: "one"}, struct{ f string }{}, struct{ f string }{}},
|
||||
{struct{ f string }{f: "two"}, nil, struct{ f string }{f: "two"}},
|
||||
|
||||
{then, now, now},
|
||||
{then, time.Time{}, then},
|
||||
} {
|
||||
res := dfault(this.dflt, this.given)
|
||||
res, err := dfault(this.dflt, this.given)
|
||||
if err != nil {
|
||||
t.Errorf("[%d] default returned an error: %s", i, err)
|
||||
continue
|
||||
}
|
||||
if !reflect.DeepEqual(this.expected, res) {
|
||||
t.Errorf("[%d] default returned %v, but expected %v", i, res, this.expected)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestDefault(t *testing.T) {
|
||||
for i, this := range []struct {
|
||||
input interface{}
|
||||
tpl string
|
||||
expected string
|
||||
ok bool
|
||||
}{
|
||||
{map[string]string{"foo": "bar"}, `{{ index . "foo" | default "nope" }}`, `bar`, true},
|
||||
{map[string]string{"foo": "pop"}, `{{ index . "bar" | default "nada" }}`, `nada`, true},
|
||||
{map[string]string{"foo": "cat"}, `{{ default "nope" .foo }}`, `cat`, true},
|
||||
{map[string]string{"foo": "dog"}, `{{ default "nope" .foo "extra" }}`, ``, false},
|
||||
} {
|
||||
tmpl, err := New().New("test").Parse(this.tpl)
|
||||
if err != nil {
|
||||
t.Errorf("[%d] unable to create new html template %q: %s", i, this.tpl, err)
|
||||
continue
|
||||
}
|
||||
|
||||
buf := new(bytes.Buffer)
|
||||
err = tmpl.Execute(buf, this.input)
|
||||
if (err == nil) != this.ok {
|
||||
t.Errorf("[%d] execute template returned unexpected error: %s", i, err)
|
||||
continue
|
||||
}
|
||||
|
||||
if buf.String() != this.expected {
|
||||
t.Errorf("[%d] execute template got %v, but expected %v", i, buf.String(), this.expected)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestSafeHTML(t *testing.T) {
|
||||
for i, this := range []struct {
|
||||
str string
|
||||
|
|
Loading…
Reference in a new issue