Make First accept any int

TOML and YAML handles integers differently, creating issues when using integer values from configuration or front matter in the First template function.

This currently works in YAML (parses into int), but not in TOML (parses into int64).

This commit modifies First so it accepts any int.

Fixes #551
This commit is contained in:
bep 2014-10-10 00:57:57 +02:00 committed by spf13
parent d064139cee
commit da5d98e958
2 changed files with 33 additions and 15 deletions

View file

@ -14,6 +14,7 @@ import (
"strings" "strings"
"github.com/eknkc/amber" "github.com/eknkc/amber"
"github.com/spf13/cast"
"github.com/spf13/hugo/helpers" "github.com/spf13/hugo/helpers"
jww "github.com/spf13/jwalterweatherman" jww "github.com/spf13/jwalterweatherman"
) )
@ -167,8 +168,15 @@ func In(l interface{}, v interface{}) bool {
// First is exposed to templates, to iterate over the first N items in a // First is exposed to templates, to iterate over the first N items in a
// rangeable list. // rangeable list.
func First(limit int, seq interface{}) (interface{}, error) { func First(limit interface{}, seq interface{}) (interface{}, error) {
if limit < 1 {
limitv, err := cast.ToIntE(limit)
if err != nil {
return nil, err
}
if limitv < 1 {
return nil, errors.New("can't return negative/empty count of items from sequence") return nil, errors.New("can't return negative/empty count of items from sequence")
} }
@ -189,10 +197,10 @@ func First(limit int, seq interface{}) (interface{}, error) {
default: default:
return nil, errors.New("can't iterate over " + reflect.ValueOf(seq).Type().String()) return nil, errors.New("can't iterate over " + reflect.ValueOf(seq).Type().String())
} }
if limit > seqv.Len() { if limitv > seqv.Len() {
limit = seqv.Len() limitv = seqv.Len()
} }
return seqv.Slice(0, limit).Interface(), nil return seqv.Slice(0, limitv).Interface(), nil
} }
func Where(seq, key, match interface{}) (interface{}, error) { func Where(seq, key, match interface{}) (interface{}, error) {

View file

@ -125,21 +125,31 @@ func TestDoArithmetic(t *testing.T) {
func TestFirst(t *testing.T) { func TestFirst(t *testing.T) {
for i, this := range []struct { for i, this := range []struct {
count int count interface{}
sequence interface{} sequence interface{}
expect interface{} expect interface{}
}{ }{
{2, []string{"a", "b", "c"}, []string{"a", "b"}}, {int(2), []string{"a", "b", "c"}, []string{"a", "b"}},
{3, []string{"a", "b"}, []string{"a", "b"}}, {int32(3), []string{"a", "b"}, []string{"a", "b"}},
{2, []int{100, 200, 300}, []int{100, 200}}, {int64(2), []int{100, 200, 300}, []int{100, 200}},
{100, []int{100, 200}, []int{100, 200}},
{"1", []int{100, 200, 300}, []int{100}},
{int64(-1), []int{100, 200, 300}, false},
{"noint", []int{100, 200, 300}, false},
} { } {
results, err := First(this.count, this.sequence) results, err := First(this.count, this.sequence)
if err != nil { if b, ok := this.expect.(bool); ok && !b {
t.Errorf("[%d] failed: %s", i, err) if err == nil {
continue t.Errorf("[%d] First didn't return an expected error")
} }
if !reflect.DeepEqual(results, this.expect) { } else {
t.Errorf("[%d] First %d items, got %v but expected %v", i, this.count, results, this.expect) if err != nil {
t.Errorf("[%d] failed: %s", i, err)
continue
}
if !reflect.DeepEqual(results, this.expect) {
t.Errorf("[%d] First %d items, got %v but expected %v", i, this.count, results, this.expect)
}
} }
} }
} }