aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--common/types/types.go8
-rw-r--r--hugolib/page.go7
-rw-r--r--tpl/collections/collections.go8
-rw-r--r--tpl/collections/collections_integration_test.go48
-rw-r--r--tpl/collections/reflect_helpers.go3
5 files changed, 69 insertions, 5 deletions
diff --git a/common/types/types.go b/common/types/types.go
index 801c511a0..e3850ddac 100644
--- a/common/types/types.go
+++ b/common/types/types.go
@@ -99,6 +99,14 @@ type Unwrapper interface {
Unwrapv() any
}
+// Unwrap returns the underlying value of v if it implements Unwrapper, otherwise v is returned.
+func Unwrapv(v any) any {
+ if u, ok := v.(Unwrapper); ok {
+ return u.Unwrapv()
+ }
+ return v
+}
+
// LowHigh is typically used to represent a slice boundary.
type LowHigh struct {
Low int
diff --git a/hugolib/page.go b/hugolib/page.go
index c743d4282..0622a15fe 100644
--- a/hugolib/page.go
+++ b/hugolib/page.go
@@ -36,6 +36,7 @@ import (
"github.com/gohugoio/hugo/common/herrors"
"github.com/gohugoio/hugo/common/maps"
+ "github.com/gohugoio/hugo/common/types"
"github.com/gohugoio/hugo/source"
@@ -731,3 +732,9 @@ func (p pageWithWeight0) Weight0() int {
func (p pageWithWeight0) page() page.Page {
return p.pageState
}
+
+var _ types.Unwrapper = (*pageWithWeight0)(nil)
+
+func (p pageWithWeight0) Unwrapv() any {
+ return p.pageState
+}
diff --git a/tpl/collections/collections.go b/tpl/collections/collections.go
index 2107cf5a0..edec536ef 100644
--- a/tpl/collections/collections.go
+++ b/tpl/collections/collections.go
@@ -617,10 +617,10 @@ type intersector struct {
}
func (i *intersector) appendIfNotSeen(v reflect.Value) {
- vi := v.Interface()
- if !i.seen[vi] {
+ k := normalize(v)
+ if !i.seen[k] {
i.r = reflect.Append(i.r, v)
- i.seen[vi] = true
+ i.seen[k] = true
}
}
@@ -638,7 +638,7 @@ func (i *intersector) handleValuePair(l1vv, l2vv reflect.Value) {
i.appendIfNotSeen(l1vv)
}
case kind == reflect.Ptr, kind == reflect.Struct:
- if l1vv.Interface() == l2vv.Interface() {
+ if types.Unwrapv(l1vv.Interface()) == types.Unwrapv(l2vv.Interface()) {
i.appendIfNotSeen(l1vv)
}
case kind == reflect.Interface:
diff --git a/tpl/collections/collections_integration_test.go b/tpl/collections/collections_integration_test.go
index 1bcabb447..3bcd4effb 100644
--- a/tpl/collections/collections_integration_test.go
+++ b/tpl/collections/collections_integration_test.go
@@ -230,3 +230,51 @@ boolf = false
"false",
)
}
+
+func TestTermEntriesCollectionsIssue12254(t *testing.T) {
+ t.Parallel()
+
+ files := `
+-- hugo.toml --
+capitalizeListTitles = false
+disableKinds = ['rss','sitemap']
+-- content/p1.md --
+---
+title: p1
+categories: [cat-a]
+tags: ['tag-b','tag-a','tag-c']
+---
+-- content/p2.md --
+---
+title: p2
+categories: [cat-a]
+tags: ['tag-b','tag-a']
+---
+-- content/p3.md --
+---
+title: p3
+categories: [cat-a]
+tags: ['tag-b']
+---
+-- layouts/_default/term.html --
+{{ $list1 := .Pages }}
+{{ range $i, $e := site.Taxonomies.tags.ByCount }}
+{{ $list2 := .Pages }}
+{{ $i }}: List1: {{ len $list1 }}|
+{{ $i }}: List2: {{ len $list2 }}|
+{{ $i }}: Intersect: {{ intersect $.Pages .Pages | len }}|
+{{ $i }}: Union: {{ union $.Pages .Pages | len }}|
+{{ $i }}: SymDiff: {{ symdiff $.Pages .Pages | len }}|
+{{ $i }}: Uniq: {{ append $.Pages .Pages | uniq | len }}|
+{{ end }}
+
+
+`
+ b := hugolib.Test(t, files)
+
+ b.AssertFileContent("public/categories/cat-a/index.html",
+ "0: List1: 3|\n0: List2: 3|\n0: Intersect: 3|\n0: Union: 3|\n0: SymDiff: 0|\n0: Uniq: 3|\n\n\n1: List1: 3|",
+ "1: List2: 2|\n1: Intersect: 2|\n1: Union: 3|\n1: SymDiff: 1|\n1: Uniq: 3|\n\n\n2: List1: 3|\n2: List2: 1|",
+ "2: Intersect: 1|\n2: Union: 3|\n2: SymDiff: 2|\n2: Uniq: 3|",
+ )
+}
diff --git a/tpl/collections/reflect_helpers.go b/tpl/collections/reflect_helpers.go
index 56909d30e..4687acdde 100644
--- a/tpl/collections/reflect_helpers.go
+++ b/tpl/collections/reflect_helpers.go
@@ -18,6 +18,7 @@ import (
"fmt"
"reflect"
+ "github.com/gohugoio/hugo/common/types"
"github.com/mitchellh/hashstructure"
)
@@ -60,7 +61,7 @@ func normalize(v reflect.Value) any {
return f
}
}
- return v.Interface()
+ return types.Unwrapv(v.Interface())
}
// collects identities from the slices in seqs into a set. Numeric values are normalized,