shithub: hugo

Download patch

ref: e8a716b23a1ca78cf29460daacd4ba49bbc05ad1
parent: 3e6cb2cb77e16be5b6ddd4ae55d5fc6bfba2d226
author: Bjørn Erik Pedersen <[email protected]>
date: Sun Jun 9 08:50:53 EDT 2019

tpl/collections: Fix slice type handling in sort

The `sort` template func was producing a `[]page.Page` which did not work in `.Paginate`.

Fixes #6023

--- a/go.sum
+++ b/go.sum
@@ -220,6 +220,8 @@
 github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646/go.mod h1:jpp1/29i3P1S/RLdc7JQKbRpFeM1dOBd8T9ki5s+AY8=
 github.com/nicksnyder/go-i18n v1.10.0 h1:5AzlPKvXBH4qBzmZ09Ua9Gipyruv6uApMcrNZdo96+Q=
 github.com/nicksnyder/go-i18n v1.10.0/go.mod h1:HrK7VCrbOvQoUAQ7Vpy7i87N7JZZZ7R2xBGjv0j365Q=
+github.com/niklasfasching/go-org v0.0.0-20190112190817-da99094e202f h1:XQqYaaEslPrQl81puWcHVAlt1l16dIQaWXYeEDbw9uI=
+github.com/niklasfasching/go-org v0.0.0-20190112190817-da99094e202f/go.mod h1:AsLD6X7djzRIz4/RFZu8vwRL0VGjUvGZCCH1Nz0VdrU=
 github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
 github.com/olekukonko/tablewriter v0.0.0-20180506121414-d4647c9c7a84 h1:fiKJgB4JDUd43CApkmCeTSQlWjtTtABrU2qsgbuP0BI=
 github.com/olekukonko/tablewriter v0.0.0-20180506121414-d4647c9c7a84/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo=
--- a/hugolib/paginator_test.go
+++ b/hugolib/paginator_test.go
@@ -15,6 +15,7 @@
 
 import (
 	"fmt"
+	"path/filepath"
 	"testing"
 )
 
@@ -95,4 +96,12 @@
 		"Page Number: 1",
 		"0: 1/1  true")
 
+}
+
+// Issue 6023
+func TestPaginateWithSort(t *testing.T) {
+	b := newTestSitesBuilder(t).WithSimpleConfigFile()
+	b.WithTemplatesAdded("index.html", `{{ range (.Paginate (sort .Site.RegularPages ".File.Filename" "desc")).Pages }}|{{ .File.Filename }}{{ end }}`)
+	b.Build(BuildCfg{}).AssertFileContent("public/index.html",
+		filepath.FromSlash("|content/sect/doc1.nn.md|content/sect/doc1.nb.md|content/sect/doc1.fr.md|content/sect/doc1.en.md"))
 }
--- a/resources/page/pages.go
+++ b/resources/page/pages.go
@@ -66,6 +66,12 @@
 		return v.Pages(), nil
 	case PageGroup:
 		return v.Pages, nil
+	case []Page:
+		pages := make(Pages, len(v))
+		for i, vv := range v {
+			pages[i] = vv
+		}
+		return pages, nil
 	case []interface{}:
 		pages := make(Pages, len(v))
 		success := true
--- a/resources/page/pages_test.go
+++ b/resources/page/pages_test.go
@@ -53,3 +53,24 @@
 	})
 
 }
+
+func TestToPages(t *testing.T) {
+	assert := require.New(t)
+
+	p1, p2 := &testPage{title: "p1"}, &testPage{title: "p2"}
+	pages12 := Pages{p1, p2}
+
+	mustToPages := func(in interface{}) Pages {
+		p, err := ToPages(in)
+		assert.NoError(err)
+		return p
+	}
+
+	assert.Equal(Pages{}, mustToPages(nil))
+	assert.Equal(pages12, mustToPages(pages12))
+	assert.Equal(pages12, mustToPages([]Page{p1, p2}))
+	assert.Equal(pages12, mustToPages([]interface{}{p1, p2}))
+
+	_, err := ToPages("not a page")
+	assert.Error(err)
+}
--- a/tpl/collections/sort.go
+++ b/tpl/collections/sort.go
@@ -31,21 +31,23 @@
 		return nil, errors.New("sequence must be provided")
 	}
 
-	seqv := reflect.ValueOf(seq)
-	seqv, isNil := indirect(seqv)
+	seqv, isNil := indirect(reflect.ValueOf(seq))
 	if isNil {
 		return nil, errors.New("can't iterate over a nil value")
 	}
 
+	var sliceType reflect.Type
 	switch seqv.Kind() {
-	case reflect.Array, reflect.Slice, reflect.Map:
-		// ok
+	case reflect.Array, reflect.Slice:
+		sliceType = seqv.Type()
+	case reflect.Map:
+		sliceType = reflect.SliceOf(seqv.Type().Elem())
 	default:
 		return nil, errors.New("can't sort " + reflect.ValueOf(seq).Type().String())
 	}
 
 	// Create a list of pairs that will be used to do the sort
-	p := pairList{SortAsc: true, SliceType: reflect.SliceOf(seqv.Type().Elem())}
+	p := pairList{SortAsc: true, SliceType: sliceType}
 	p.Pairs = make([]pair, seqv.Len())
 
 	var sortByField string
--- a/tpl/collections/sort_test.go
+++ b/tpl/collections/sort_test.go
@@ -14,6 +14,7 @@
 package collections
 
 import (
+	"fmt"
 	"reflect"
 	"testing"
 
@@ -20,6 +21,8 @@
 	"github.com/gohugoio/hugo/deps"
 )
 
+type stringsSlice []string
+
 func TestSort(t *testing.T) {
 	t.Parallel()
 
@@ -42,6 +45,9 @@
 	}{
 		{[]string{"class1", "class2", "class3"}, nil, "asc", []string{"class1", "class2", "class3"}},
 		{[]string{"class3", "class1", "class2"}, nil, "asc", []string{"class1", "class2", "class3"}},
+		// Issue 6023
+		{stringsSlice{"class3", "class1", "class2"}, nil, "asc", stringsSlice{"class1", "class2", "class3"}},
+
 		{[]int{1, 2, 3, 4, 5}, nil, "asc", []int{1, 2, 3, 4, 5}},
 		{[]int{5, 4, 3, 1, 2}, nil, "asc", []int{1, 2, 3, 4, 5}},
 		// test sort key parameter is focibly set empty
@@ -212,26 +218,29 @@
 		},
 		{nil, nil, "asc", false},
 	} {
-		var result interface{}
-		var err error
-		if test.sortByField == nil {
-			result, err = ns.Sort(test.seq)
-		} else {
-			result, err = ns.Sort(test.seq, test.sortByField, test.sortAsc)
-		}
 
-		if b, ok := test.expect.(bool); ok && !b {
-			if err == nil {
-				t.Errorf("[%d] Sort didn't return an expected error", i)
+		t.Run(fmt.Sprintf("test%d", i), func(t *testing.T) {
+			var result interface{}
+			var err error
+			if test.sortByField == nil {
+				result, err = ns.Sort(test.seq)
+			} else {
+				result, err = ns.Sort(test.seq, test.sortByField, test.sortAsc)
 			}
-		} else {
-			if err != nil {
-				t.Errorf("[%d] failed: %s", i, err)
-				continue
+
+			if b, ok := test.expect.(bool); ok && !b {
+				if err == nil {
+					t.Fatal("Sort didn't return an expected error")
+				}
+			} else {
+				if err != nil {
+					t.Fatalf("failed: %s", err)
+				}
+				if !reflect.DeepEqual(result, test.expect) {
+					t.Fatalf("Sort called on sequence: %#v | sortByField: `%v` | got\n%#v but expected\n%#v", test.seq, test.sortByField, result, test.expect)
+				}
 			}
-			if !reflect.DeepEqual(result, test.expect) {
-				t.Errorf("[%d] Sort called on sequence: %v | sortByField: `%v` | got %v but expected %v", i, test.seq, test.sortByField, result, test.expect)
-			}
-		}
+		})
+
 	}
 }