mirror of
https://github.com/gohugoio/hugo.git
synced 2024-11-21 20:46:30 -05:00
Add last
template function
`last` allows the user to select the last X items of and array.
This commit is contained in:
parent
627d016cc9
commit
0a2e5424ab
2 changed files with 71 additions and 0 deletions
|
@ -388,6 +388,42 @@ func First(limit interface{}, seq interface{}) (interface{}, error) {
|
||||||
return seqv.Slice(0, limitv).Interface(), nil
|
return seqv.Slice(0, limitv).Interface(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Last is exposed to templates, to iterate over the last N items in a
|
||||||
|
// rangeable list.
|
||||||
|
func Last(limit interface{}, seq interface{}) (interface{}, error) {
|
||||||
|
|
||||||
|
if limit == nil || seq == nil {
|
||||||
|
return nil, errors.New("both limit and seq must be provided")
|
||||||
|
}
|
||||||
|
|
||||||
|
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")
|
||||||
|
}
|
||||||
|
|
||||||
|
seqv := reflect.ValueOf(seq)
|
||||||
|
seqv, isNil := indirect(seqv)
|
||||||
|
if isNil {
|
||||||
|
return nil, errors.New("can't iterate over a nil value")
|
||||||
|
}
|
||||||
|
|
||||||
|
switch seqv.Kind() {
|
||||||
|
case reflect.Array, reflect.Slice, reflect.String:
|
||||||
|
// okay
|
||||||
|
default:
|
||||||
|
return nil, errors.New("can't iterate over " + reflect.ValueOf(seq).Type().String())
|
||||||
|
}
|
||||||
|
if limitv > seqv.Len() {
|
||||||
|
limitv = seqv.Len()
|
||||||
|
}
|
||||||
|
return seqv.Slice(seqv.Len()-limitv, seqv.Len()).Interface(), nil
|
||||||
|
}
|
||||||
|
|
||||||
// After is exposed to templates, to iterate over all the items after N in a
|
// After is exposed to templates, to iterate over all the items after N in a
|
||||||
// rangeable list. It's meant to accompany First
|
// rangeable list. It's meant to accompany First
|
||||||
func After(index interface{}, seq interface{}) (interface{}, error) {
|
func After(index interface{}, seq interface{}) (interface{}, error) {
|
||||||
|
@ -1288,6 +1324,7 @@ func init() {
|
||||||
"relURL": func(a string) template.HTML { return template.HTML(helpers.RelURL(a)) },
|
"relURL": func(a string) template.HTML { return template.HTML(helpers.RelURL(a)) },
|
||||||
"markdownify": Markdownify,
|
"markdownify": Markdownify,
|
||||||
"first": First,
|
"first": First,
|
||||||
|
"last": Last,
|
||||||
"after": After,
|
"after": After,
|
||||||
"where": Where,
|
"where": Where,
|
||||||
"delimit": Delimit,
|
"delimit": Delimit,
|
||||||
|
|
|
@ -253,6 +253,40 @@ func TestFirst(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestLast(t *testing.T) {
|
||||||
|
for i, this := range []struct {
|
||||||
|
count interface{}
|
||||||
|
sequence interface{}
|
||||||
|
expect interface{}
|
||||||
|
}{
|
||||||
|
{int(2), []string{"a", "b", "c"}, []string{"b", "c"}},
|
||||||
|
{int32(3), []string{"a", "b"}, []string{"a", "b"}},
|
||||||
|
{int64(2), []int{100, 200, 300}, []int{200, 300}},
|
||||||
|
{100, []int{100, 200}, []int{100, 200}},
|
||||||
|
{"1", []int{100, 200, 300}, []int{300}},
|
||||||
|
{int64(-1), []int{100, 200, 300}, false},
|
||||||
|
{"noint", []int{100, 200, 300}, false},
|
||||||
|
{1, nil, false},
|
||||||
|
{nil, []int{100}, false},
|
||||||
|
{1, t, false},
|
||||||
|
} {
|
||||||
|
results, err := Last(this.count, this.sequence)
|
||||||
|
if b, ok := this.expect.(bool); ok && !b {
|
||||||
|
if err == nil {
|
||||||
|
t.Errorf("[%d] First didn't return an expected error", i)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestAfter(t *testing.T) {
|
func TestAfter(t *testing.T) {
|
||||||
for i, this := range []struct {
|
for i, this := range []struct {
|
||||||
count interface{}
|
count interface{}
|
||||||
|
|
Loading…
Reference in a new issue