From 298ebc37c2d485ab34735f81541a5deaf079b03e Mon Sep 17 00:00:00 2001 From: John Feminella Date: Fri, 10 Feb 2017 08:01:25 -0500 Subject: [PATCH] hugolib: Add ability to sort by frontmatter parameters --- docs/content/templates/list.md | 12 ++++++++++++ hugolib/pageSort.go | 27 +++++++++++++++++++++++++++ hugolib/pageSort_test.go | 32 ++++++++++++++++++++++++++++++++ 3 files changed, 71 insertions(+) diff --git a/docs/content/templates/list.md b/docs/content/templates/list.md index 36ababff6..c4f20d986 100644 --- a/docs/content/templates/list.md +++ b/docs/content/templates/list.md @@ -237,6 +237,18 @@ your list templates: {{ 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. diff --git a/hugolib/pageSort.go b/hugolib/pageSort.go index f0c2db33d..e12cf68e4 100644 --- a/hugolib/pageSort.go +++ b/hugolib/pageSort.go @@ -15,6 +15,8 @@ package hugolib import ( "sort" + + "github.com/spf13/cast" ) var spc = newPageCache() @@ -275,3 +277,28 @@ func (p Pages) Reverse() Pages { 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 +} diff --git a/hugolib/pageSort_test.go b/hugolib/pageSort_test.go index 126c1b4ad..c0dedbe2d 100644 --- a/hugolib/pageSort_test.go +++ b/hugolib/pageSort_test.go @@ -20,6 +20,7 @@ import ( "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 @@ func TestPageSortReverse(t *testing.T) { 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 @@ func createSortTestPages(num int) Pages { }, 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