mirror of
https://github.com/gohugoio/hugo.git
synced 2024-11-07 20:30:36 -05:00
Add after
template function
Where `first` will return the first N items of a rangeable list, `after` will return all items after the Nth item. This allows the user to do something with the first N items and something different with the remaining items after N.
This commit is contained in:
parent
82cc1ac0f8
commit
c335efdd06
2 changed files with 74 additions and 2 deletions
|
@ -177,7 +177,7 @@ func Substr(a interface{}, nums ...interface{}) (string, error) {
|
|||
}
|
||||
|
||||
var start, length int
|
||||
toInt := func (v interface{}, message string) (int, error) {
|
||||
toInt := func(v interface{}, message string) (int, error) {
|
||||
switch i := v.(type) {
|
||||
case int:
|
||||
return i, nil
|
||||
|
@ -388,6 +388,42 @@ func First(limit interface{}, seq interface{}) (interface{}, error) {
|
|||
return seqv.Slice(0, limitv).Interface(), nil
|
||||
}
|
||||
|
||||
// After is exposed to templates, to iterate over all the items after N in a
|
||||
// rangeable list. It's meant to accompany First
|
||||
func After(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() {
|
||||
return nil, errors.New("no items left")
|
||||
}
|
||||
return seqv.Slice(limitv, seqv.Len()).Interface(), nil
|
||||
}
|
||||
|
||||
var (
|
||||
zero reflect.Value
|
||||
errorType = reflect.TypeOf((*error)(nil)).Elem()
|
||||
|
@ -1252,6 +1288,7 @@ func init() {
|
|||
"relURL": func(a string) template.HTML { return template.HTML(helpers.RelURL(a)) },
|
||||
"markdownify": Markdownify,
|
||||
"first": First,
|
||||
"after": After,
|
||||
"where": Where,
|
||||
"delimit": Delimit,
|
||||
"sort": Sort,
|
||||
|
|
|
@ -4,13 +4,14 @@ import (
|
|||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"html/template"
|
||||
"path"
|
||||
"reflect"
|
||||
"runtime"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
type tstNoStringer struct {
|
||||
|
@ -252,6 +253,40 @@ func TestFirst(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestAfter(t *testing.T) {
|
||||
for i, this := range []struct {
|
||||
count interface{}
|
||||
sequence interface{}
|
||||
expect interface{}
|
||||
}{
|
||||
{int(2), []string{"a", "b", "c", "d"}, []string{"c", "d"}},
|
||||
{int32(3), []string{"a", "b"}, false},
|
||||
{int64(2), []int{100, 200, 300}, []int{300}},
|
||||
{100, []int{100, 200}, false},
|
||||
{"1", []int{100, 200, 300}, []int{200, 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 := After(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 TestIn(t *testing.T) {
|
||||
for i, this := range []struct {
|
||||
v1 interface{}
|
||||
|
|
Loading…
Reference in a new issue