diff --git a/docs/content/extras/scratch.md b/docs/content/extras/scratch.md index 4788a75f0..187339863 100644 --- a/docs/content/extras/scratch.md +++ b/docs/content/extras/scratch.md @@ -21,7 +21,9 @@ weight: 80 * `SetInMap` takes a `key`, `mapKey` and `value` * `GetSortedMapValues` returns array of values from `key` sorted by `mapKey` -`Set` and `SetInMap` can store values of any type. `Add` accepts values that support Go's `+` operator. +`Set` and `SetInMap` can store values of any type. + +For single values, `Add` accepts values that support Go's `+` operator. If the first `Add` for a key is an array or slice, the follwing adds will be appended to that list. The scope of the backing data is global for the given `Node` or `Page`, and spans partial and shortcode includes. diff --git a/hugolib/scratch.go b/hugolib/scratch.go index a3b73e402..29dfd492f 100644 --- a/hugolib/scratch.go +++ b/hugolib/scratch.go @@ -15,6 +15,7 @@ package hugolib import ( "github.com/spf13/hugo/helpers" + "reflect" "sort" ) @@ -23,16 +24,30 @@ type Scratch struct { values map[string]interface{} } -// Add will add (using the + operator) the addend to the existing addend (if found). +// For single values, Add will add (using the + operator) the addend to the existing addend (if found). // Supports numeric values and strings. +// +// If the first add for a key is an array or slice, then the next value(s) will be appended. func (c *Scratch) Add(key string, newAddend interface{}) (string, error) { var newVal interface{} existingAddend, found := c.values[key] if found { var err error - newVal, err = helpers.DoArithmetic(existingAddend, newAddend, '+') - if err != nil { - return "", err + + addendV := reflect.ValueOf(existingAddend) + + if addendV.Kind() == reflect.Slice || addendV.Kind() == reflect.Array { + nav := reflect.ValueOf(newAddend) + if nav.Kind() == reflect.Slice || nav.Kind() == reflect.Array { + newVal = reflect.AppendSlice(addendV, nav).Interface() + } else { + newVal = reflect.Append(addendV, nav).Interface() + } + } else { + newVal, err = helpers.DoArithmetic(existingAddend, newAddend, '+') + if err != nil { + return "", err + } } } else { newVal = newAddend diff --git a/hugolib/scratch_test.go b/hugolib/scratch_test.go index 1ab0e1a23..c90ef733d 100644 --- a/hugolib/scratch_test.go +++ b/hugolib/scratch_test.go @@ -15,6 +15,7 @@ package hugolib import ( "github.com/stretchr/testify/assert" + "reflect" "testing" ) @@ -47,6 +48,32 @@ func TestScratchAdd(t *testing.T) { } +func TestScratchAddSlice(t *testing.T) { + scratch := newScratch() + + _, err := scratch.Add("intSlice", []int{1, 2}) + assert.Nil(t, err) + _, err = scratch.Add("intSlice", 3) + assert.Nil(t, err) + + sl := scratch.Get("intSlice") + expected := []int{1, 2, 3} + + if !reflect.DeepEqual(expected, sl) { + t.Errorf("Slice difference, go %q expected %q", sl, expected) + } + + _, err = scratch.Add("intSlice", []int{4, 5}) + + sl = scratch.Get("intSlice") + expected = []int{1, 2, 3, 4, 5} + + if !reflect.DeepEqual(expected, sl) { + t.Errorf("Slice difference, go %q expected %q", sl, expected) + } + +} + func TestScratchSet(t *testing.T) { scratch := newScratch() scratch.Set("key", "val")