Skip to content

Commit 08f48b9

Browse files
committed
compare, hugolib, tpl: Add Eqer interface
And use it in `eq` and `ne` so `Page` values can be compared directly in the templates without thinking about it being a `Page` or a `PageOutput` wrapper. Fixes #3807
1 parent 2fc121c commit 08f48b9

File tree

4 files changed

+59
-0
lines changed

4 files changed

+59
-0
lines changed

‎compare/eq.go‎

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// Copyright 2017-present The Hugo Authors. All rights reserved.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
// http://www.apache.org/licenses/LICENSE-2.0
7+
//
8+
// Unless required by applicable law or agreed to in writing, software
9+
// distributed under the License is distributed on an "AS IS" BASIS,
10+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11+
// See the License for the specific language governing permissions and
12+
// limitations under the License.
13+
14+
package compare
15+
16+
// Eqer can be used to determine if this value is equal to the other.
17+
// The semantics of equals is that the two value are interchangeable
18+
// in the Hugo templates.
19+
type Eqer interface {
20+
Eq(other interface{}) bool
21+
}

‎hugolib/page.go‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ import (
3838
"unicode/utf8"
3939

4040
bp "github.com/gohugoio/hugo/bufferpool"
41+
"github.com/gohugoio/hugo/compare"
4142
"github.com/gohugoio/hugo/source"
4243
"github.com/spf13/cast"
4344
)
@@ -49,6 +50,10 @@ var (
4950
allKindsInPages = []string{KindPage, KindHome, KindSection, KindTaxonomy, KindTaxonomyTerm}
5051

5152
allKinds = append(allKindsInPages, []string{kindRSS, kindSitemap, kindRobotsTXT, kind404}...)
53+
54+
// Assert that it implements the Eqer interface.
55+
_ compare.Eqer = (*Page)(nil)
56+
_ compare.Eqer = (*PageOutput)(nil)
5257
)
5358

5459
const (

‎tpl/compare/compare.go‎

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ import (
1818
"reflect"
1919
"strconv"
2020
"time"
21+
22+
"github.com/gohugoio/hugo/compare"
2123
)
2224

2325
// New returns a new instance of the compare-namespaced template functions.
@@ -85,6 +87,14 @@ func (*Namespace) Default(dflt interface{}, given ...interface{}) (interface{},
8587

8688
// Eq returns the boolean truth of arg1 == arg2.
8789
func (*Namespace) Eq(x, y interface{}) bool {
90+
91+
// hugolib.Page implements compare.Eqer to make Page and PageOutput comparable.
92+
if e1, ok := x.(compare.Eqer); ok {
93+
if e2, ok := y.(compare.Eqer); ok {
94+
return e1.Eq(e2)
95+
}
96+
}
97+
8898
normalize := func(v interface{}) interface{} {
8999
vv := reflect.ValueOf(v)
90100
switch vv.Kind() {

‎tpl/compare/compare_test.go‎

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,25 @@ import (
2626
"github.com/stretchr/testify/require"
2727
)
2828

29+
type tstEqerType1 string
30+
type tstEqerType2 string
31+
32+
func (t tstEqerType2) Eq(other interface{}) bool {
33+
return cast.ToString(t) == cast.ToString(other)
34+
}
35+
36+
func (t tstEqerType2) String() string {
37+
return string(t)
38+
}
39+
40+
func (t tstEqerType1) Eq(other interface{}) bool {
41+
return cast.ToString(t) == cast.ToString(other)
42+
}
43+
44+
func (t tstEqerType1) String() string {
45+
return string(t)
46+
}
47+
2948
type tstCompareType int
3049

3150
const (
@@ -148,6 +167,10 @@ func doTestCompare(t *testing.T, tp tstCompareType, funcUnderTest func(a, b inte
148167
{"a", "a", 0},
149168
{"a", "b", -1},
150169
{"b", "a", 1},
170+
{tstEqerType1("a"), tstEqerType1("a"), 0},
171+
{tstEqerType1("a"), tstEqerType2("a"), 0},
172+
{tstEqerType2("a"), tstEqerType1("a"), 0},
173+
{tstEqerType2("a"), tstEqerType1("b"), -1},
151174
} {
152175
result := funcUnderTest(test.left, test.right)
153176
success := false

0 commit comments

Comments
 (0)