mirror of
https://github.com/gohugoio/hugo.git
synced 2024-11-07 20:30:36 -05:00
tpl: Improve template funcs GoDoc
This commit is contained in:
parent
aa2c724195
commit
cd1ed563a8
17 changed files with 170 additions and 163 deletions
|
@ -19,12 +19,15 @@ import (
|
|||
"github.com/gohugoio/hugo/common/collections"
|
||||
)
|
||||
|
||||
// Append appends the arguments up to the last one to the slice in the last argument.
|
||||
// Append appends args up to the last one to the slice in the last argument.
|
||||
// This construct allows template constructs like this:
|
||||
// {{ $pages = $pages | append $p2 $p1 }}
|
||||
//
|
||||
// {{ $pages = $pages | append $p2 $p1 }}
|
||||
//
|
||||
// Note that with 2 arguments where both are slices of the same type,
|
||||
// the first slice will be appended to the second:
|
||||
// {{ $pages = $pages | append .Site.RegularPages }}
|
||||
//
|
||||
// {{ $pages = $pages | append .Site.RegularPages }}
|
||||
func (ns *Namespace) Append(args ...any) (any, error) {
|
||||
if len(args) < 2 {
|
||||
return nil, errors.New("need at least 2 arguments to append")
|
||||
|
|
|
@ -24,9 +24,9 @@ import (
|
|||
"github.com/gohugoio/hugo/tpl"
|
||||
)
|
||||
|
||||
// Apply takes a map, array, or slice and returns a new slice with the function fname applied over it.
|
||||
func (ns *Namespace) Apply(ctx context.Context, seq any, fname string, args ...any) (any, error) {
|
||||
if seq == nil {
|
||||
// Apply takes a map, array, or slice c and returns a new slice with the function fname applied over it.
|
||||
func (ns *Namespace) Apply(ctx context.Context, c any, fname string, args ...any) (any, error) {
|
||||
if c == nil {
|
||||
return make([]any, 0), nil
|
||||
}
|
||||
|
||||
|
@ -34,7 +34,7 @@ func (ns *Namespace) Apply(ctx context.Context, seq any, fname string, args ...a
|
|||
return nil, errors.New("can't apply myself (no turtles allowed)")
|
||||
}
|
||||
|
||||
seqv := reflect.ValueOf(seq)
|
||||
seqv := reflect.ValueOf(c)
|
||||
seqv, isNil := indirect(seqv)
|
||||
if isNil {
|
||||
return nil, errors.New("can't iterate over a nil value")
|
||||
|
@ -61,7 +61,7 @@ func (ns *Namespace) Apply(ctx context.Context, seq any, fname string, args ...a
|
|||
|
||||
return r, nil
|
||||
default:
|
||||
return nil, fmt.Errorf("can't apply over %v", seq)
|
||||
return nil, fmt.Errorf("can't apply over %v", c)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -63,45 +63,45 @@ type Namespace struct {
|
|||
deps *deps.Deps
|
||||
}
|
||||
|
||||
// After returns all the items after the first N in a rangeable list.
|
||||
func (ns *Namespace) After(index any, seq any) (any, error) {
|
||||
if index == nil || seq == nil {
|
||||
// After returns all the items after the first n items in list l.
|
||||
func (ns *Namespace) After(n any, l any) (any, error) {
|
||||
if n == nil || l == nil {
|
||||
return nil, errors.New("both limit and seq must be provided")
|
||||
}
|
||||
|
||||
indexv, err := cast.ToIntE(index)
|
||||
nv, err := cast.ToIntE(n)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if indexv < 0 {
|
||||
return nil, errors.New("sequence bounds out of range [" + cast.ToString(indexv) + ":]")
|
||||
if nv < 0 {
|
||||
return nil, errors.New("sequence bounds out of range [" + cast.ToString(nv) + ":]")
|
||||
}
|
||||
|
||||
seqv := reflect.ValueOf(seq)
|
||||
seqv, isNil := indirect(seqv)
|
||||
lv := reflect.ValueOf(l)
|
||||
lv, isNil := indirect(lv)
|
||||
if isNil {
|
||||
return nil, errors.New("can't iterate over a nil value")
|
||||
}
|
||||
|
||||
switch seqv.Kind() {
|
||||
switch lv.Kind() {
|
||||
case reflect.Array, reflect.Slice, reflect.String:
|
||||
// okay
|
||||
default:
|
||||
return nil, errors.New("can't iterate over " + reflect.ValueOf(seq).Type().String())
|
||||
return nil, errors.New("can't iterate over " + reflect.ValueOf(l).Type().String())
|
||||
}
|
||||
|
||||
if indexv >= seqv.Len() {
|
||||
return seqv.Slice(0, 0).Interface(), nil
|
||||
if nv >= lv.Len() {
|
||||
return lv.Slice(0, 0).Interface(), nil
|
||||
}
|
||||
|
||||
return seqv.Slice(indexv, seqv.Len()).Interface(), nil
|
||||
return lv.Slice(nv, lv.Len()).Interface(), nil
|
||||
}
|
||||
|
||||
// Delimit takes a given sequence and returns a delimited HTML string.
|
||||
// Delimit takes a given list l and returns a string delimited by sep.
|
||||
// If last is passed to the function, it will be used as the final delimiter.
|
||||
func (ns *Namespace) Delimit(seq, delimiter any, last ...any) (template.HTML, error) {
|
||||
d, err := cast.ToStringE(delimiter)
|
||||
func (ns *Namespace) Delimit(l, sep any, last ...any) (template.HTML, error) {
|
||||
d, err := cast.ToStringE(sep)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
@ -117,32 +117,32 @@ func (ns *Namespace) Delimit(seq, delimiter any, last ...any) (template.HTML, er
|
|||
}
|
||||
}
|
||||
|
||||
seqv := reflect.ValueOf(seq)
|
||||
seqv, isNil := indirect(seqv)
|
||||
lv := reflect.ValueOf(l)
|
||||
lv, isNil := indirect(lv)
|
||||
if isNil {
|
||||
return "", errors.New("can't iterate over a nil value")
|
||||
}
|
||||
|
||||
var str string
|
||||
switch seqv.Kind() {
|
||||
switch lv.Kind() {
|
||||
case reflect.Map:
|
||||
sortSeq, err := ns.Sort(seq)
|
||||
sortSeq, err := ns.Sort(l)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
seqv = reflect.ValueOf(sortSeq)
|
||||
lv = reflect.ValueOf(sortSeq)
|
||||
fallthrough
|
||||
case reflect.Array, reflect.Slice, reflect.String:
|
||||
for i := 0; i < seqv.Len(); i++ {
|
||||
val := seqv.Index(i).Interface()
|
||||
for i := 0; i < lv.Len(); i++ {
|
||||
val := lv.Index(i).Interface()
|
||||
valStr, err := cast.ToStringE(val)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
switch {
|
||||
case i == seqv.Len()-2 && dLast != nil:
|
||||
case i == lv.Len()-2 && dLast != nil:
|
||||
str += valStr + *dLast
|
||||
case i == seqv.Len()-1:
|
||||
case i == lv.Len()-1:
|
||||
str += valStr
|
||||
default:
|
||||
str += valStr + d
|
||||
|
@ -150,15 +150,14 @@ func (ns *Namespace) Delimit(seq, delimiter any, last ...any) (template.HTML, er
|
|||
}
|
||||
|
||||
default:
|
||||
return "", fmt.Errorf("can't iterate over %v", seq)
|
||||
return "", fmt.Errorf("can't iterate over %v", l)
|
||||
}
|
||||
|
||||
return template.HTML(str), nil
|
||||
}
|
||||
|
||||
// Dictionary creates a map[string]interface{} from the given parameters by
|
||||
// walking the parameters and treating them as key-value pairs. The number
|
||||
// of parameters must be even.
|
||||
// Dictionary creates a new map from the given parameters by
|
||||
// treating values as key-value pairs. The number of values must be even.
|
||||
// The keys can be string slices, which will create the needed nested structure.
|
||||
func (ns *Namespace) Dictionary(values ...any) (map[string]any, error) {
|
||||
if len(values)%2 != 0 {
|
||||
|
@ -196,10 +195,10 @@ func (ns *Namespace) Dictionary(values ...any) (map[string]any, error) {
|
|||
return root, nil
|
||||
}
|
||||
|
||||
// EchoParam returns a given value if it is set; otherwise, it returns an
|
||||
// EchoParam returns a the value in the collection c with key k if is set; otherwise, it returns an
|
||||
// empty string.
|
||||
func (ns *Namespace) EchoParam(a, key any) any {
|
||||
av, isNil := indirect(reflect.ValueOf(a))
|
||||
func (ns *Namespace) EchoParam(c, k any) any {
|
||||
av, isNil := indirect(reflect.ValueOf(c))
|
||||
if isNil {
|
||||
return ""
|
||||
}
|
||||
|
@ -207,12 +206,12 @@ func (ns *Namespace) EchoParam(a, key any) any {
|
|||
var avv reflect.Value
|
||||
switch av.Kind() {
|
||||
case reflect.Array, reflect.Slice:
|
||||
index, ok := key.(int)
|
||||
index, ok := k.(int)
|
||||
if ok && av.Len() > index {
|
||||
avv = av.Index(index)
|
||||
}
|
||||
case reflect.Map:
|
||||
kv := reflect.ValueOf(key)
|
||||
kv := reflect.ValueOf(k)
|
||||
if kv.Type().AssignableTo(av.Type().Key()) {
|
||||
avv = av.MapIndex(kv)
|
||||
}
|
||||
|
@ -240,9 +239,9 @@ func (ns *Namespace) EchoParam(a, key any) any {
|
|||
return ""
|
||||
}
|
||||
|
||||
// First returns the first N items in a rangeable list.
|
||||
func (ns *Namespace) First(limit any, seq any) (any, error) {
|
||||
if limit == nil || seq == nil {
|
||||
// First returns the first limit items in list l.
|
||||
func (ns *Namespace) First(limit any, l any) (any, error) {
|
||||
if limit == nil || l == nil {
|
||||
return nil, errors.New("both limit and seq must be provided")
|
||||
}
|
||||
|
||||
|
@ -255,27 +254,27 @@ func (ns *Namespace) First(limit any, seq any) (any, error) {
|
|||
return nil, errors.New("sequence length must be non-negative")
|
||||
}
|
||||
|
||||
seqv := reflect.ValueOf(seq)
|
||||
seqv, isNil := indirect(seqv)
|
||||
lv := reflect.ValueOf(l)
|
||||
lv, isNil := indirect(lv)
|
||||
if isNil {
|
||||
return nil, errors.New("can't iterate over a nil value")
|
||||
}
|
||||
|
||||
switch seqv.Kind() {
|
||||
switch lv.Kind() {
|
||||
case reflect.Array, reflect.Slice, reflect.String:
|
||||
// okay
|
||||
default:
|
||||
return nil, errors.New("can't iterate over " + reflect.ValueOf(seq).Type().String())
|
||||
return nil, errors.New("can't iterate over " + reflect.ValueOf(l).Type().String())
|
||||
}
|
||||
|
||||
if limitv > seqv.Len() {
|
||||
limitv = seqv.Len()
|
||||
if limitv > lv.Len() {
|
||||
limitv = lv.Len()
|
||||
}
|
||||
|
||||
return seqv.Slice(0, limitv).Interface(), nil
|
||||
return lv.Slice(0, limitv).Interface(), nil
|
||||
}
|
||||
|
||||
// In returns whether v is in the set l. l may be an array or slice.
|
||||
// In returns whether v is in the list l. l may be an array or slice.
|
||||
func (ns *Namespace) In(l any, v any) (bool, error) {
|
||||
if l == nil || v == nil {
|
||||
return false, nil
|
||||
|
@ -354,7 +353,7 @@ func (ns *Namespace) Intersect(l1, l2 any) (any, error) {
|
|||
}
|
||||
}
|
||||
|
||||
// Group groups a set of elements by the given key.
|
||||
// Group groups a set of items by the given key.
|
||||
// This is currently only supported for Pages.
|
||||
func (ns *Namespace) Group(key any, items any) (any, error) {
|
||||
if key == nil {
|
||||
|
@ -374,10 +373,10 @@ func (ns *Namespace) Group(key any, items any) (any, error) {
|
|||
return nil, fmt.Errorf("grouping not supported for type %T %T", items, in)
|
||||
}
|
||||
|
||||
// IsSet returns whether a given array, channel, slice, or map has a key
|
||||
// IsSet returns whether a given array, channel, slice, or map in c has the given key
|
||||
// defined.
|
||||
func (ns *Namespace) IsSet(a any, key any) (bool, error) {
|
||||
av := reflect.ValueOf(a)
|
||||
func (ns *Namespace) IsSet(c any, key any) (bool, error) {
|
||||
av := reflect.ValueOf(c)
|
||||
kv := reflect.ValueOf(key)
|
||||
|
||||
switch av.Kind() {
|
||||
|
@ -394,15 +393,15 @@ func (ns *Namespace) IsSet(a any, key any) (bool, error) {
|
|||
return av.MapIndex(kv).IsValid(), nil
|
||||
}
|
||||
default:
|
||||
helpers.DistinctErrorLog.Printf("WARNING: calling IsSet with unsupported type %q (%T) will always return false.\n", av.Kind(), a)
|
||||
helpers.DistinctErrorLog.Printf("WARNING: calling IsSet with unsupported type %q (%T) will always return false.\n", av.Kind(), c)
|
||||
}
|
||||
|
||||
return false, nil
|
||||
}
|
||||
|
||||
// Last returns the last N items in a rangeable list.
|
||||
func (ns *Namespace) Last(limit any, seq any) (any, error) {
|
||||
if limit == nil || seq == nil {
|
||||
// Last returns the last limit items in the list l.
|
||||
func (ns *Namespace) Last(limit any, l any) (any, error) {
|
||||
if limit == nil || l == nil {
|
||||
return nil, errors.New("both limit and seq must be provided")
|
||||
}
|
||||
|
||||
|
@ -415,7 +414,7 @@ func (ns *Namespace) Last(limit any, seq any) (any, error) {
|
|||
return nil, errors.New("sequence length must be non-negative")
|
||||
}
|
||||
|
||||
seqv := reflect.ValueOf(seq)
|
||||
seqv := reflect.ValueOf(l)
|
||||
seqv, isNil := indirect(seqv)
|
||||
if isNil {
|
||||
return nil, errors.New("can't iterate over a nil value")
|
||||
|
@ -425,7 +424,7 @@ func (ns *Namespace) Last(limit any, seq any) (any, error) {
|
|||
case reflect.Array, reflect.Slice, reflect.String:
|
||||
// okay
|
||||
default:
|
||||
return nil, errors.New("can't iterate over " + reflect.ValueOf(seq).Type().String())
|
||||
return nil, errors.New("can't iterate over " + reflect.ValueOf(l).Type().String())
|
||||
}
|
||||
|
||||
if limitv > seqv.Len() {
|
||||
|
@ -435,7 +434,7 @@ func (ns *Namespace) Last(limit any, seq any) (any, error) {
|
|||
return seqv.Slice(seqv.Len()-limitv, seqv.Len()).Interface(), nil
|
||||
}
|
||||
|
||||
// Querify encodes the given parameters in URL-encoded form ("bar=baz&foo=quux") sorted by key.
|
||||
// Querify encodes the given params in URL-encoded form ("bar=baz&foo=quux") sorted by key.
|
||||
func (ns *Namespace) Querify(params ...any) (string, error) {
|
||||
qs := url.Values{}
|
||||
|
||||
|
@ -476,12 +475,12 @@ func (ns *Namespace) Querify(params ...any) (string, error) {
|
|||
return qs.Encode(), nil
|
||||
}
|
||||
|
||||
// Reverse creates a copy of slice and reverses it.
|
||||
func (ns *Namespace) Reverse(slice any) (any, error) {
|
||||
if slice == nil {
|
||||
// Reverse creates a copy of the list l and reverses it.
|
||||
func (ns *Namespace) Reverse(l any) (any, error) {
|
||||
if l == nil {
|
||||
return nil, nil
|
||||
}
|
||||
v := reflect.ValueOf(slice)
|
||||
v := reflect.ValueOf(l)
|
||||
|
||||
switch v.Kind() {
|
||||
case reflect.Slice:
|
||||
|
@ -499,14 +498,15 @@ func (ns *Namespace) Reverse(slice any) (any, error) {
|
|||
return sliceCopy.Interface(), nil
|
||||
}
|
||||
|
||||
// Seq creates a sequence of integers. It's named and used as GNU's seq.
|
||||
// Seq creates a sequence of integers from args. It's named and used as GNU's seq.
|
||||
//
|
||||
// Examples:
|
||||
// 3 => 1, 2, 3
|
||||
// 1 2 4 => 1, 3
|
||||
// -3 => -1, -2, -3
|
||||
// 1 4 => 1, 2, 3, 4
|
||||
// 1 -2 => 1, 0, -1, -2
|
||||
//
|
||||
// 3 => 1, 2, 3
|
||||
// 1 2 4 => 1, 3
|
||||
// -3 => -1, -2, -3
|
||||
// 1 4 => 1, 2, 3, 4
|
||||
// 1 -2 => 1, 0, -1, -2
|
||||
func (ns *Namespace) Seq(args ...any) ([]int, error) {
|
||||
if len(args) < 1 || len(args) > 3 {
|
||||
return nil, errors.New("invalid number of arguments to Seq")
|
||||
|
@ -574,31 +574,31 @@ func (ns *Namespace) Seq(args ...any) ([]int, error) {
|
|||
return seq, nil
|
||||
}
|
||||
|
||||
// Shuffle returns the given rangeable list in a randomised order.
|
||||
func (ns *Namespace) Shuffle(seq any) (any, error) {
|
||||
if seq == nil {
|
||||
// Shuffle returns list l in a randomised order.
|
||||
func (ns *Namespace) Shuffle(l any) (any, error) {
|
||||
if l == nil {
|
||||
return nil, errors.New("both count and seq must be provided")
|
||||
}
|
||||
|
||||
seqv := reflect.ValueOf(seq)
|
||||
seqv, isNil := indirect(seqv)
|
||||
lv := reflect.ValueOf(l)
|
||||
lv, isNil := indirect(lv)
|
||||
if isNil {
|
||||
return nil, errors.New("can't iterate over a nil value")
|
||||
}
|
||||
|
||||
switch seqv.Kind() {
|
||||
switch lv.Kind() {
|
||||
case reflect.Array, reflect.Slice, reflect.String:
|
||||
// okay
|
||||
default:
|
||||
return nil, errors.New("can't iterate over " + reflect.ValueOf(seq).Type().String())
|
||||
return nil, errors.New("can't iterate over " + reflect.ValueOf(l).Type().String())
|
||||
}
|
||||
|
||||
shuffled := reflect.MakeSlice(reflect.TypeOf(seq), seqv.Len(), seqv.Len())
|
||||
shuffled := reflect.MakeSlice(reflect.TypeOf(l), lv.Len(), lv.Len())
|
||||
|
||||
randomIndices := rand.Perm(seqv.Len())
|
||||
randomIndices := rand.Perm(lv.Len())
|
||||
|
||||
for index, value := range randomIndices {
|
||||
shuffled.Index(value).Set(seqv.Index(index))
|
||||
shuffled.Index(value).Set(lv.Index(index))
|
||||
}
|
||||
|
||||
return shuffled.Interface(), nil
|
||||
|
@ -733,14 +733,14 @@ func (ns *Namespace) Union(l1, l2 any) (any, error) {
|
|||
}
|
||||
}
|
||||
|
||||
// Uniq takes in a slice or array and returns a slice with subsequent
|
||||
// Uniq takes returns a new list with all duplicate elements in the list l removed.
|
||||
// duplicate elements removed.
|
||||
func (ns *Namespace) Uniq(seq any) (any, error) {
|
||||
if seq == nil {
|
||||
func (ns *Namespace) Uniq(l any) (any, error) {
|
||||
if l == nil {
|
||||
return make([]any, 0), nil
|
||||
}
|
||||
|
||||
v := reflect.ValueOf(seq)
|
||||
v := reflect.ValueOf(l)
|
||||
var slice reflect.Value
|
||||
|
||||
switch v.Kind() {
|
||||
|
@ -750,7 +750,7 @@ func (ns *Namespace) Uniq(seq any) (any, error) {
|
|||
case reflect.Array:
|
||||
slice = reflect.MakeSlice(reflect.SliceOf(v.Type().Elem()), 0, 0)
|
||||
default:
|
||||
return nil, fmt.Errorf("type %T not supported", seq)
|
||||
return nil, fmt.Errorf("type %T not supported", l)
|
||||
}
|
||||
|
||||
seen := make(map[any]bool)
|
||||
|
@ -770,8 +770,8 @@ func (ns *Namespace) Uniq(seq any) (any, error) {
|
|||
}
|
||||
|
||||
// KeyVals creates a key and values wrapper.
|
||||
func (ns *Namespace) KeyVals(key any, vals ...any) (types.KeyValues, error) {
|
||||
return types.KeyValues{Key: key, Values: vals}, nil
|
||||
func (ns *Namespace) KeyVals(key any, values ...any) (types.KeyValues, error) {
|
||||
return types.KeyValues{Key: key, Values: values}, nil
|
||||
}
|
||||
|
||||
// NewScratch creates a new Scratch which can be used to store values in a
|
||||
|
|
|
@ -19,19 +19,21 @@ import (
|
|||
"reflect"
|
||||
)
|
||||
|
||||
// Complement gives the elements in the last element of seqs that are not in
|
||||
// Complement gives the elements in the last element of ls that are not in
|
||||
// any of the others.
|
||||
// All elements of seqs must be slices or arrays of comparable types.
|
||||
//
|
||||
// All elements of ls must be slices or arrays of comparable types.
|
||||
//
|
||||
// The reasoning behind this rather clumsy API is so we can do this in the templates:
|
||||
// {{ $c := .Pages | complement $last4 }}
|
||||
func (ns *Namespace) Complement(seqs ...any) (any, error) {
|
||||
if len(seqs) < 2 {
|
||||
//
|
||||
// {{ $c := .Pages | complement $last4 }}
|
||||
func (ns *Namespace) Complement(ls ...any) (any, error) {
|
||||
if len(ls) < 2 {
|
||||
return nil, errors.New("complement needs at least two arguments")
|
||||
}
|
||||
|
||||
universe := seqs[len(seqs)-1]
|
||||
as := seqs[:len(seqs)-1]
|
||||
universe := ls[len(ls)-1]
|
||||
as := ls[:len(ls)-1]
|
||||
|
||||
aset, err := collectIdentities(as...)
|
||||
if err != nil {
|
||||
|
|
|
@ -27,12 +27,11 @@ import (
|
|||
// arguments. Thus "index x 1 2 3" is, in Go syntax, x[1][2][3]. Each
|
||||
// indexed item must be a map, slice, or array.
|
||||
//
|
||||
// Copied from Go stdlib src/text/template/funcs.go.
|
||||
// Adapted from Go stdlib src/text/template/funcs.go.
|
||||
//
|
||||
// We deviate from the stdlib due to https://github.com/golang/go/issues/14751.
|
||||
//
|
||||
// TODO(moorereason): merge upstream changes.
|
||||
// We deviate from the stdlib mostly because of https://github.com/golang/go/issues/14751.
|
||||
func (ns *Namespace) Index(item any, args ...any) (any, error) {
|
||||
// TODO(moorereason): merge upstream changes.
|
||||
v := reflect.ValueOf(item)
|
||||
if !v.IsValid() {
|
||||
// See issue 10489
|
||||
|
|
|
@ -24,8 +24,9 @@ import (
|
|||
"errors"
|
||||
)
|
||||
|
||||
// Merge creates a copy of the final parameter and merges the preceding
|
||||
// Merge creates a copy of the final parameter in params and merges the preceding
|
||||
// parameters into it in reverse order.
|
||||
//
|
||||
// Currently only maps are supported. Key handling is case insensitive.
|
||||
func (ns *Namespace) Merge(params ...any) (any, error) {
|
||||
if len(params) < 2 {
|
||||
|
|
|
@ -141,6 +141,7 @@ func TestMerge(t *testing.T) {
|
|||
} {
|
||||
|
||||
test := test
|
||||
i := i
|
||||
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
|
|
@ -25,13 +25,13 @@ import (
|
|||
"github.com/spf13/cast"
|
||||
)
|
||||
|
||||
// Sort returns a sorted sequence.
|
||||
func (ns *Namespace) Sort(seq any, args ...any) (any, error) {
|
||||
if seq == nil {
|
||||
// Sort returns a sorted copy of the list l.
|
||||
func (ns *Namespace) Sort(l any, args ...any) (any, error) {
|
||||
if l == nil {
|
||||
return nil, errors.New("sequence must be provided")
|
||||
}
|
||||
|
||||
seqv, isNil := indirect(reflect.ValueOf(seq))
|
||||
seqv, isNil := indirect(reflect.ValueOf(l))
|
||||
if isNil {
|
||||
return nil, errors.New("can't iterate over a nil value")
|
||||
}
|
||||
|
@ -43,7 +43,7 @@ func (ns *Namespace) Sort(seq any, args ...any) (any, error) {
|
|||
case reflect.Map:
|
||||
sliceType = reflect.SliceOf(seqv.Type().Elem())
|
||||
default:
|
||||
return nil, errors.New("can't sort " + reflect.ValueOf(seq).Type().String())
|
||||
return nil, errors.New("can't sort " + reflect.ValueOf(l).Type().String())
|
||||
}
|
||||
|
||||
collator := langs.GetCollator(ns.deps.Language)
|
||||
|
|
|
@ -23,11 +23,11 @@ import (
|
|||
"github.com/gohugoio/hugo/common/maps"
|
||||
)
|
||||
|
||||
// Where returns a filtered subset of a given data type.
|
||||
func (ns *Namespace) Where(seq, key any, args ...any) (any, error) {
|
||||
seqv, isNil := indirect(reflect.ValueOf(seq))
|
||||
// Where returns a filtered subset of collection c.
|
||||
func (ns *Namespace) Where(c, key any, args ...any) (any, error) {
|
||||
seqv, isNil := indirect(reflect.ValueOf(c))
|
||||
if isNil {
|
||||
return nil, errors.New("can't iterate over a nil value of type " + reflect.ValueOf(seq).Type().String())
|
||||
return nil, errors.New("can't iterate over a nil value of type " + reflect.ValueOf(c).Type().String())
|
||||
}
|
||||
|
||||
mv, op, err := parseWhereArgs(args...)
|
||||
|
@ -47,7 +47,7 @@ func (ns *Namespace) Where(seq, key any, args ...any) (any, error) {
|
|||
case reflect.Map:
|
||||
return ns.checkWhereMap(seqv, kv, mv, path, op)
|
||||
default:
|
||||
return nil, fmt.Errorf("can't iterate over %v", seq)
|
||||
return nil, fmt.Errorf("can't iterate over %v", c)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -40,25 +40,25 @@ type Namespace struct {
|
|||
caseInsensitive bool
|
||||
}
|
||||
|
||||
// Default checks whether a given value is set and returns a default value if it
|
||||
// Default checks whether a givenv is set and returns the default value defaultv if it
|
||||
// is not. "Set" in this context means non-zero for numeric types and times;
|
||||
// non-zero length for strings, arrays, slices, and maps;
|
||||
// any boolean or struct value; or non-nil for any other types.
|
||||
func (*Namespace) Default(dflt any, given ...any) (any, error) {
|
||||
func (*Namespace) Default(defaultv any, givenv ...any) (any, 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 expected 2.
|
||||
|
||||
if len(given) == 0 {
|
||||
return dflt, nil
|
||||
if len(givenv) == 0 {
|
||||
return defaultv, nil
|
||||
}
|
||||
if len(given) != 1 {
|
||||
return nil, fmt.Errorf("wrong number of args for default: want 2 got %d", len(given)+1)
|
||||
if len(givenv) != 1 {
|
||||
return nil, fmt.Errorf("wrong number of args for default: want 2 got %d", len(givenv)+1)
|
||||
}
|
||||
|
||||
g := reflect.ValueOf(given[0])
|
||||
g := reflect.ValueOf(givenv[0])
|
||||
if !g.IsValid() {
|
||||
return dflt, nil
|
||||
return defaultv, nil
|
||||
}
|
||||
|
||||
set := false
|
||||
|
@ -77,7 +77,7 @@ func (*Namespace) Default(dflt any, given ...any) (any, error) {
|
|||
case reflect.Complex64, reflect.Complex128:
|
||||
set = g.Complex() != 0
|
||||
case reflect.Struct:
|
||||
switch actual := given[0].(type) {
|
||||
switch actual := givenv[0].(type) {
|
||||
case time.Time:
|
||||
set = !actual.IsZero()
|
||||
default:
|
||||
|
@ -88,10 +88,10 @@ func (*Namespace) Default(dflt any, given ...any) (any, error) {
|
|||
}
|
||||
|
||||
if set {
|
||||
return given[0], nil
|
||||
return givenv[0], nil
|
||||
}
|
||||
|
||||
return dflt, nil
|
||||
return defaultv, nil
|
||||
}
|
||||
|
||||
// Eq returns the boolean truth of arg1 == arg2 || arg1 == arg3 || arg1 == arg4.
|
||||
|
@ -223,12 +223,13 @@ func (n *Namespace) checkComparisonArgCount(min int, others ...any) bool {
|
|||
}
|
||||
|
||||
// Conditional can be used as a ternary operator.
|
||||
// It returns a if condition, else b.
|
||||
func (n *Namespace) Conditional(condition bool, a, b any) any {
|
||||
if condition {
|
||||
return a
|
||||
//
|
||||
// It returns v1 if cond is true, else v2.
|
||||
func (n *Namespace) Conditional(cond bool, v1, v2 any) any {
|
||||
if cond {
|
||||
return v1
|
||||
}
|
||||
return b
|
||||
return v2
|
||||
}
|
||||
|
||||
func (ns *Namespace) compareGet(a any, b any) (float64, float64) {
|
||||
|
|
|
@ -36,9 +36,9 @@ func New() *Namespace {
|
|||
// Namespace provides template functions for the "crypto" namespace.
|
||||
type Namespace struct{}
|
||||
|
||||
// MD5 hashes the given input and returns its MD5 checksum.
|
||||
func (ns *Namespace) MD5(in any) (string, error) {
|
||||
conv, err := cast.ToStringE(in)
|
||||
// MD5 hashes the v and returns its MD5 checksum.
|
||||
func (ns *Namespace) MD5(v any) (string, error) {
|
||||
conv, err := cast.ToStringE(v)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
@ -47,9 +47,9 @@ func (ns *Namespace) MD5(in any) (string, error) {
|
|||
return hex.EncodeToString(hash[:]), nil
|
||||
}
|
||||
|
||||
// SHA1 hashes the given input and returns its SHA1 checksum.
|
||||
func (ns *Namespace) SHA1(in any) (string, error) {
|
||||
conv, err := cast.ToStringE(in)
|
||||
// SHA1 hashes v and returns its SHA1 checksum.
|
||||
func (ns *Namespace) SHA1(v any) (string, error) {
|
||||
conv, err := cast.ToStringE(v)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
@ -58,9 +58,9 @@ func (ns *Namespace) SHA1(in any) (string, error) {
|
|||
return hex.EncodeToString(hash[:]), nil
|
||||
}
|
||||
|
||||
// SHA256 hashes the given input and returns its SHA256 checksum.
|
||||
func (ns *Namespace) SHA256(in any) (string, error) {
|
||||
conv, err := cast.ToStringE(in)
|
||||
// SHA256 hashes v and returns its SHA256 checksum.
|
||||
func (ns *Namespace) SHA256(v any) (string, error) {
|
||||
conv, err := cast.ToStringE(v)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
@ -69,9 +69,9 @@ func (ns *Namespace) SHA256(in any) (string, error) {
|
|||
return hex.EncodeToString(hash[:]), nil
|
||||
}
|
||||
|
||||
// FNV32a hashes using fnv32a algorithm
|
||||
func (ns *Namespace) FNV32a(in any) (int, error) {
|
||||
conv, err := cast.ToStringE(in)
|
||||
// FNV32a hashes v using fnv32a algorithm.
|
||||
func (ns *Namespace) FNV32a(v any) (int, error) {
|
||||
conv, err := cast.ToStringE(v)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
|
|
@ -58,7 +58,7 @@ type Namespace struct {
|
|||
client *http.Client
|
||||
}
|
||||
|
||||
// GetCSV expects a data separator and one or n-parts of a URL to a resource which
|
||||
// GetCSV expects the separator sep and one or n-parts of a URL to a resource which
|
||||
// can either be a local or a remote one.
|
||||
// The data separator can be a comma, semi-colon, pipe, etc, but only one character.
|
||||
// If you provide multiple parts for the URL they will be joined together to the final URL.
|
||||
|
@ -99,7 +99,7 @@ func (ns *Namespace) GetCSV(sep string, args ...any) (d [][]string, err error) {
|
|||
return
|
||||
}
|
||||
|
||||
// GetJSON expects one or n-parts of a URL to a resource which can either be a local or a remote one.
|
||||
// GetJSON expects one or n-parts of a URL in args to a resource which can either be a local or a remote one.
|
||||
// If you provide multiple parts they will be joined together to the final URL.
|
||||
// GetJSON returns nil or parsed JSON to use in a short code.
|
||||
func (ns *Namespace) GetJSON(args ...any) (any, error) {
|
||||
|
|
|
@ -31,8 +31,11 @@ type Namespace struct {
|
|||
|
||||
// Dump returns a object dump of val as a string.
|
||||
// Note that not every value passed to Dump will print so nicely, but
|
||||
// we'll improve on that. We recommend using the "go" Chroma lexer to format the output
|
||||
// we'll improve on that.
|
||||
//
|
||||
// We recommend using the "go" Chroma lexer to format the output
|
||||
// nicely.
|
||||
//
|
||||
// Also note that the output from Dump may change from Hugo version to the next,
|
||||
// so don't depend on a specific output.
|
||||
func (ns *Namespace) Dump(val any) string {
|
||||
|
|
|
@ -64,6 +64,7 @@ type Namespace struct {
|
|||
d *deps.Deps
|
||||
}
|
||||
|
||||
// Goat creates a new SVG diagram from input v.
|
||||
func (d *Namespace) Goat(v any) SVGDiagram {
|
||||
var r io.Reader
|
||||
|
||||
|
|
|
@ -57,7 +57,7 @@ func (ns *Namespace) Base64Encode(content any) (string, error) {
|
|||
}
|
||||
|
||||
// Jsonify encodes a given object to JSON. To pretty print the JSON, pass a map
|
||||
// or dictionary of options as the first argument. Supported options are
|
||||
// or dictionary of options as the first value in args. Supported options are
|
||||
// "prefix" and "indent". Each JSON element in the output will begin on a new
|
||||
// line beginning with prefix followed by one or more copies of indent according
|
||||
// to the indentation nesting.
|
||||
|
|
|
@ -47,12 +47,12 @@ type Namespace struct {
|
|||
distinctLogger loggers.IgnorableLogger
|
||||
}
|
||||
|
||||
// Print returns a string representation args.
|
||||
// Print returns a string representation of args.
|
||||
func (ns *Namespace) Print(args ...any) string {
|
||||
return _fmt.Sprint(args...)
|
||||
}
|
||||
|
||||
// Printf returns a formatted string representation of args.
|
||||
// Printf returns string representation of args formatted with the layouut in format.
|
||||
func (ns *Namespace) Printf(format string, args ...any) string {
|
||||
return _fmt.Sprintf(format, args...)
|
||||
}
|
||||
|
@ -70,7 +70,7 @@ func (ns *Namespace) Errorf(format string, args ...any) string {
|
|||
}
|
||||
|
||||
// Erroridf formats args according to a format specifier and logs an ERROR and
|
||||
// an information text that the error with the given ID can be suppressed in config.
|
||||
// an information text that the error with the given id can be suppressed in config.
|
||||
// It returns an empty string.
|
||||
func (ns *Namespace) Erroridf(id, format string, args ...any) string {
|
||||
ns.distinctLogger.Errorsf(id, format, args...)
|
||||
|
|
|
@ -30,16 +30,12 @@ func New() *Namespace {
|
|||
// Namespace provides template functions for the "inflect" namespace.
|
||||
type Namespace struct{}
|
||||
|
||||
// Humanize returns the humanized form of a single parameter.
|
||||
// Humanize returns the humanized form of v.
|
||||
//
|
||||
// If the parameter is either an integer or a string containing an integer
|
||||
// If v is either an integer or a string containing an integer
|
||||
// value, the behavior is to add the appropriate ordinal.
|
||||
//
|
||||
// Example: "my-first-post" -> "My first post"
|
||||
// Example: "103" -> "103rd"
|
||||
// Example: 52 -> "52nd"
|
||||
func (ns *Namespace) Humanize(in any) (string, error) {
|
||||
word, err := cast.ToStringE(in)
|
||||
func (ns *Namespace) Humanize(v any) (string, error) {
|
||||
word, err := cast.ToStringE(v)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
@ -48,7 +44,7 @@ func (ns *Namespace) Humanize(in any) (string, error) {
|
|||
return "", nil
|
||||
}
|
||||
|
||||
_, ok := in.(int) // original param was literal int value
|
||||
_, ok := v.(int) // original param was literal int value
|
||||
_, err = strconv.Atoi(word) // original param was string containing an int value
|
||||
if ok || err == nil {
|
||||
return _inflect.Ordinalize(word), nil
|
||||
|
@ -58,9 +54,9 @@ func (ns *Namespace) Humanize(in any) (string, error) {
|
|||
return _inflect.Humanize(strings.ToLower(str)), nil
|
||||
}
|
||||
|
||||
// Pluralize returns the plural form of a single word.
|
||||
func (ns *Namespace) Pluralize(in any) (string, error) {
|
||||
word, err := cast.ToStringE(in)
|
||||
// Pluralize returns the plural form of the single word in v.
|
||||
func (ns *Namespace) Pluralize(v any) (string, error) {
|
||||
word, err := cast.ToStringE(v)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
@ -68,9 +64,9 @@ func (ns *Namespace) Pluralize(in any) (string, error) {
|
|||
return _inflect.Pluralize(word), nil
|
||||
}
|
||||
|
||||
// Singularize returns the singular form of a single word.
|
||||
func (ns *Namespace) Singularize(in any) (string, error) {
|
||||
word, err := cast.ToStringE(in)
|
||||
// Singularize returns the singular form of a single word in v.
|
||||
func (ns *Namespace) Singularize(v any) (string, error) {
|
||||
word, err := cast.ToStringE(v)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue