ref: 298ebc37c2d485ab34735f81541a5deaf079b03e
parent: 2618cfbeaa06bd2a4d26b3e3999e3c9ca9a49854
author: John Feminella <jxf+github@jxf.me>
date: Fri Feb 10 03:01:25 EST 2017
hugolib: Add ability to sort by frontmatter parameters
--- a/docs/content/templates/list.md
+++ b/docs/content/templates/list.md
@@ -237,6 +237,18 @@
</li>
{{ end }}
+### Order by Parameter
+Order based on the specified frontmatter parameter. Pages without that
+parameter will use the site's `.Site.Params` default. If the parameter is not
+found at all in some entries, those entries will appear together at the end
+of the ordering.
+
+The below example sorts a list of posts by their rating.
+
+ {{ range (.Data.Pages.ByParam "rating") }}
+ <!-- ... -->
+ {{ end }}
+
### Reverse Order
Can be applied to any of the above. Using Date for an example.
--- a/hugolib/pageSort.go
+++ b/hugolib/pageSort.go
@@ -15,6 +15,8 @@
import (
"sort"
+
+ "github.com/spf13/cast"
)
var spc = newPageCache()
@@ -272,6 +274,31 @@
}
pages, _ := spc.get(key, p, reverseFunc)
+
+ return pages
+}
+
+func (p Pages) ByParam(paramsKey interface{}) Pages {
+ paramsKeyStr := cast.ToString(paramsKey)
+ key := "pageSort.ByParam." + paramsKeyStr
+
+ paramsKeyComparator := func(p1, p2 *Page) bool {
+ v1, _ := p1.Param(paramsKeyStr)
+ v2, _ := p2.Param(paramsKeyStr)
+ s1 := cast.ToString(v1)
+ s2 := cast.ToString(v2)
+
+ // Sort nils last.
+ if s1 == "" {
+ return false
+ } else if s2 == "" {
+ return true
+ }
+
+ return s1 < s2
+ }
+
+ pages, _ := spc.get(key, p, pageBy(paramsKeyComparator).Sort)
return pages
}
--- a/hugolib/pageSort_test.go
+++ b/hugolib/pageSort_test.go
@@ -20,6 +20,7 @@
"testing"
"time"
+ "github.com/spf13/cast"
"github.com/spf13/hugo/helpers"
"github.com/spf13/hugo/source"
"github.com/stretchr/testify/assert"
@@ -113,6 +114,34 @@
assert.True(t, probablyEqualPages(p2, p1.Reverse()))
}
+func TestPageSortByParam(t *testing.T) {
+ var k interface{} = "arbitrary"
+
+ unsorted := createSortTestPages(10)
+ delete(unsorted[9].Params, cast.ToString(k))
+
+ firstSetValue, _ := unsorted[0].Param(k)
+ secondSetValue, _ := unsorted[1].Param(k)
+ lastSetValue, _ := unsorted[8].Param(k)
+ unsetValue, _ := unsorted[9].Param(k)
+
+ assert.Equal(t, "xyz100", firstSetValue)
+ assert.Equal(t, "xyz99", secondSetValue)
+ assert.Equal(t, "xyz92", lastSetValue)
+ assert.Equal(t, nil, unsetValue)
+
+ sorted := unsorted.ByParam("arbitrary")
+ firstSetSortedValue, _ := sorted[0].Param(k)
+ secondSetSortedValue, _ := sorted[1].Param(k)
+ lastSetSortedValue, _ := sorted[8].Param(k)
+ unsetSortedValue, _ := sorted[9].Param(k)
+
+ assert.Equal(t, firstSetValue, firstSetSortedValue)
+ assert.Equal(t, secondSetValue, lastSetSortedValue)
+ assert.Equal(t, lastSetValue, secondSetSortedValue)
+ assert.Equal(t, unsetValue, unsetSortedValue)
+}
+
func BenchmarkSortByWeightAndReverse(b *testing.B) {
p := createSortTestPages(300)
@@ -154,6 +183,9 @@
},
Site: &info,
Source: Source{File: *source.NewFile(filepath.FromSlash(fmt.Sprintf("/x/y/p%d.md", i)))},
+ Params: map[string]interface{}{
+ "arbitrary": "xyz" + fmt.Sprintf("%v", 100-i),
+ },
}
w := 5
--
⑨