diff options
author | Bjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com> | 2018-09-10 09:48:10 +0200 |
---|---|---|
committer | Bjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com> | 2018-09-14 10:12:08 +0200 |
commit | e27fd4c1b80b7acb43290ac50e9f140d690cf042 (patch) | |
tree | 34b0f36bde4598781f9b331b5956fae3b4b33866 /hugolib | |
parent | b7ca3e1b3a83ef27bef841c319edb5b377cc4102 (diff) |
tpl/collections: Add collections.Append
Before this commit you would typically use `.Scratch.Add` to manually create slices in a loop.
With variable overwrite in Go 1.11, we can do better. This commit adds the `append` template func.
A made-up example:
```bash
{{ $p1 := index .Site.RegularPages 0 }}{{ $p2 := index .Site.RegularPages 1 }}
{{ $pages := slice }}
{{ if true }}
{{ $pages = $pages | append $p2 $p1 }}
{{ end }}
```
Note that with 2 slices as arguments, the two examples below will give the same result:
```bash
{{ $s1 := slice "a" "b" | append (slice "c" "d") }}
{{ $s2 := slice "a" "b" | append "c" "d" }}
```
Both of the above will give `[]string{a, b, c, d}`.
This commit also improves the type handling in the `slice` template function. Now `slice "a" "b"` will give a `[]string` slice. The old behaviour was to return a `[]interface{}`.
Fixes #5190
Diffstat (limited to 'hugolib')
-rw-r--r-- | hugolib/collections.go | 68 | ||||
-rw-r--r-- | hugolib/collections_test.go | 54 |
2 files changed, 101 insertions, 21 deletions
diff --git a/hugolib/collections.go b/hugolib/collections.go index 56830d8e6..b9992c425 100644 --- a/hugolib/collections.go +++ b/hugolib/collections.go @@ -16,14 +16,17 @@ package hugolib import ( "fmt" + "github.com/gohugoio/hugo/resource" + "github.com/gohugoio/hugo/common/collections" ) var ( - _ collections.Grouper = (*Page)(nil) - _ collections.Slicer = (*Page)(nil) - _ collections.Slicer = PageGroup{} - _ collections.Slicer = WeightedPage{} + _ collections.Grouper = (*Page)(nil) + _ collections.Slicer = (*Page)(nil) + _ collections.Slicer = PageGroup{} + _ collections.Slicer = WeightedPage{} + _ resource.ResourcesConverter = Pages{} ) // collections.Slicer implementations below. We keep these bridge implementations @@ -32,36 +35,50 @@ var ( // Slice is not meant to be used externally. It's a bridge function // for the template functions. See collections.Slice. -func (p *Page) Slice(items []interface{}) (interface{}, error) { +func (p *Page) Slice(items interface{}) (interface{}, error) { return toPages(items) } // Slice is not meant to be used externally. It's a bridge function // for the template functions. See collections.Slice. -func (p PageGroup) Slice(items []interface{}) (interface{}, error) { - groups := make(PagesGroup, len(items)) - for i, v := range items { - g, ok := v.(PageGroup) - if !ok { - return nil, fmt.Errorf("type %T is not a PageGroup", v) +func (p PageGroup) Slice(in interface{}) (interface{}, error) { + switch items := in.(type) { + case PageGroup: + return items, nil + case []interface{}: + groups := make(PagesGroup, len(items)) + for i, v := range items { + g, ok := v.(PageGroup) + if !ok { + return nil, fmt.Errorf("type %T is not a PageGroup", v) + } + groups[i] = g } - groups[i] = g + return groups, nil + default: + return nil, fmt.Errorf("invalid slice type %T", items) } - return groups, nil } // Slice is not meant to be used externally. It's a bridge function // for the template functions. See collections.Slice. -func (p WeightedPage) Slice(items []interface{}) (interface{}, error) { - weighted := make(WeightedPages, len(items)) - for i, v := range items { - g, ok := v.(WeightedPage) - if !ok { - return nil, fmt.Errorf("type %T is not a WeightedPage", v) +func (p WeightedPage) Slice(in interface{}) (interface{}, error) { + switch items := in.(type) { + case WeightedPages: + return items, nil + case []interface{}: + weighted := make(WeightedPages, len(items)) + for i, v := range items { + g, ok := v.(WeightedPage) + if !ok { + return nil, fmt.Errorf("type %T is not a WeightedPage", v) + } + weighted[i] = g } - weighted[i] = g + return weighted, nil + default: + return nil, fmt.Errorf("invalid slice type %T", items) } - return weighted, nil } // collections.Grouper implementations below @@ -76,3 +93,12 @@ func (p *Page) Group(key interface{}, in interface{}) (interface{}, error) { } return PageGroup{Key: key, Pages: pages}, nil } + +// ToResources wraps resource.ResourcesConverter +func (pages Pages) ToResources() resource.Resources { + r := make(resource.Resources, len(pages)) + for i, p := range pages { + r[i] = p + } + return r +} diff --git a/hugolib/collections_test.go b/hugolib/collections_test.go index 124a6ede7..9cf328a05 100644 --- a/hugolib/collections_test.go +++ b/hugolib/collections_test.go @@ -86,3 +86,57 @@ tags_weight: %d "pageGroups:2:hugolib.PagesGroup:Page(/page1.md)/Page(/page2.md)", `weightedPages:2::hugolib.WeightedPages:[WeightedPage(10,"Page") WeightedPage(20,"Page")]`) } + +func TestAppendFunc(t *testing.T) { + assert := require.New(t) + + pageContent := ` +--- +title: "Page" +tags: ["blue", "green"] +tags_weight: %d +--- + +` + b := newTestSitesBuilder(t) + b.WithSimpleConfigFile(). + WithContent("page1.md", fmt.Sprintf(pageContent, 10), "page2.md", fmt.Sprintf(pageContent, 20)). + WithTemplatesAdded("index.html", ` + +{{ $p1 := index .Site.RegularPages 0 }}{{ $p2 := index .Site.RegularPages 1 }} + +{{ $pages := slice }} + +{{ if true }} + {{ $pages = $pages | append $p2 $p1 }} +{{ end }} +{{ $appendPages := .Site.Pages | append .Site.RegularPages }} +{{ $appendStrings := slice "a" "b" | append "c" "d" "e" }} +{{ $appendStringsSlice := slice "a" "b" "c" | append (slice "c" "d") }} + +{{ printf "pages:%d:%T:%v/%v" (len $pages) $pages (index $pages 0) (index $pages 1) }} +{{ printf "appendPages:%d:%T:%v/%v" (len $appendPages) $appendPages (index $appendPages 0).Kind (index $appendPages 8).Kind }} +{{ printf "appendStrings:%T:%v" $appendStrings $appendStrings }} +{{ printf "appendStringsSlice:%T:%v" $appendStringsSlice $appendStringsSlice }} + +{{/* add some slightly related funcs to check what types we get */}} +{{ $u := $appendStrings | union $appendStringsSlice }} +{{ $i := $appendStrings | intersect $appendStringsSlice }} +{{ printf "union:%T:%v" $u $u }} +{{ printf "intersect:%T:%v" $i $i }} + +`) + b.CreateSites().Build(BuildCfg{}) + + assert.Equal(1, len(b.H.Sites)) + require.Len(t, b.H.Sites[0].RegularPages, 2) + + b.AssertFileContent("public/index.html", + "pages:2:hugolib.Pages:Page(/page2.md)/Page(/page1.md)", + "appendPages:9:hugolib.Pages:home/page", + "appendStrings:[]string:[a b c d e]", + "appendStringsSlice:[]string:[a b c c d]", + "union:[]string:[a b c d e]", + "intersect:[]string:[a b c d]", + ) +} |