mirror of
https://github.com/gohugoio/hugo.git
synced 2024-11-21 20:46:30 -05:00
tpl/collections: Fix append when appending a slice to a slice of slices
Fixes #11093
This commit is contained in:
parent
732dcb848f
commit
d178fe94fe
3 changed files with 101 additions and 4 deletions
|
@ -22,6 +22,9 @@ import (
|
|||
// If length of from is one and the only element is a slice of same type as to,
|
||||
// it will be appended.
|
||||
func Append(to any, from ...any) (any, error) {
|
||||
if len(from) == 0 {
|
||||
return to, nil
|
||||
}
|
||||
tov, toIsNil := indirect(reflect.ValueOf(to))
|
||||
|
||||
toIsNil = toIsNil || to == nil
|
||||
|
@ -33,18 +36,39 @@ func Append(to any, from ...any) (any, error) {
|
|||
}
|
||||
|
||||
tot = tov.Type().Elem()
|
||||
if tot.Kind() == reflect.Slice {
|
||||
totvt := tot.Elem()
|
||||
fromvs := make([]reflect.Value, len(from))
|
||||
for i, f := range from {
|
||||
fromv := reflect.ValueOf(f)
|
||||
fromt := fromv.Type()
|
||||
if fromt.Kind() == reflect.Slice {
|
||||
fromt = fromt.Elem()
|
||||
}
|
||||
if totvt != fromt {
|
||||
return nil, fmt.Errorf("cannot append slice of %s to slice of %s", fromt, totvt)
|
||||
} else {
|
||||
fromvs[i] = fromv
|
||||
}
|
||||
}
|
||||
return reflect.Append(tov, fromvs...).Interface(), nil
|
||||
|
||||
}
|
||||
|
||||
toIsNil = tov.Len() == 0
|
||||
|
||||
if len(from) == 1 {
|
||||
fromv := reflect.ValueOf(from[0])
|
||||
fromt := fromv.Type()
|
||||
if fromt.Kind() == reflect.Slice {
|
||||
fromt = fromt.Elem()
|
||||
}
|
||||
if fromv.Kind() == reflect.Slice {
|
||||
if toIsNil {
|
||||
// If we get nil []string, we just return the []string
|
||||
return from[0], nil
|
||||
}
|
||||
|
||||
fromt := reflect.TypeOf(from[0]).Elem()
|
||||
|
||||
// If we get []string []string, we append the from slice to to
|
||||
if tot == fromt {
|
||||
return reflect.AppendSlice(tov, fromv).Interface(), nil
|
||||
|
@ -52,6 +76,7 @@ func Append(to any, from ...any) (any, error) {
|
|||
// Fall back to a []interface{} slice.
|
||||
return appendToInterfaceSliceFromValues(tov, fromv)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,7 +24,7 @@ func TestAppend(t *testing.T) {
|
|||
t.Parallel()
|
||||
c := qt.New(t)
|
||||
|
||||
for _, test := range []struct {
|
||||
for i, test := range []struct {
|
||||
start any
|
||||
addend []any
|
||||
expected any
|
||||
|
@ -85,6 +85,47 @@ func TestAppend(t *testing.T) {
|
|||
}
|
||||
|
||||
c.Assert(err, qt.IsNil)
|
||||
c.Assert(result, qt.DeepEquals, test.expected)
|
||||
c.Assert(result, qt.DeepEquals, test.expected, qt.Commentf("test: [%d] %v", i, test))
|
||||
}
|
||||
}
|
||||
|
||||
// #11093
|
||||
func TestAppendToMultiDimensionalSlice(t *testing.T) {
|
||||
t.Parallel()
|
||||
c := qt.New(t)
|
||||
|
||||
for _, test := range []struct {
|
||||
to any
|
||||
from []any
|
||||
expected any
|
||||
}{
|
||||
{[][]string{{"a", "b"}},
|
||||
[]any{[]string{"c", "d"}},
|
||||
[][]string{
|
||||
{"a", "b"},
|
||||
{"c", "d"},
|
||||
},
|
||||
},
|
||||
{[][]string{{"a", "b"}},
|
||||
[]any{[]string{"c", "d"}, []string{"e", "f"}},
|
||||
[][]string{
|
||||
{"a", "b"},
|
||||
{"c", "d"},
|
||||
{"e", "f"},
|
||||
},
|
||||
},
|
||||
{[][]string{{"a", "b"}},
|
||||
[]any{[]int{1, 2}},
|
||||
false,
|
||||
},
|
||||
} {
|
||||
result, err := Append(test.to, test.from...)
|
||||
if b, ok := test.expected.(bool); ok && !b {
|
||||
c.Assert(err, qt.Not(qt.IsNil))
|
||||
} else {
|
||||
c.Assert(err, qt.IsNil)
|
||||
c.Assert(result, qt.DeepEquals, test.expected)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -73,3 +73,34 @@ Desc: [map[a:3 b:3] map[a:3 b:1] map[a:3 b:1] map[a:3 b:1] map[a:3 b:0] map[a:3
|
|||
|
||||
}
|
||||
}
|
||||
|
||||
// Issue #11004.
|
||||
func TestAppendSliceToASliceOfSlices(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
files := `
|
||||
-- hugo.toml --
|
||||
-- layouts/index.html --
|
||||
{{ $obj := slice (slice "a") }}
|
||||
{{ $obj = $obj | append (slice "b") }}
|
||||
{{ $obj = $obj | append (slice "c") }}
|
||||
|
||||
{{ $obj }}
|
||||
|
||||
|
||||
`
|
||||
|
||||
for i := 0; i < 4; i++ {
|
||||
|
||||
b := hugolib.NewIntegrationTestBuilder(
|
||||
hugolib.IntegrationTestConfig{
|
||||
T: t,
|
||||
TxtarString: files,
|
||||
},
|
||||
).Build()
|
||||
|
||||
b.AssertFileContent("public/index.html", "[[a] [b] [c]]")
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue