Fix intersect and similar for term entry page collections

Fixes #12254
This commit is contained in:
Bjørn Erik Pedersen 2024-03-15 13:12:25 +01:00
parent 57206e7274
commit b40f3c7df6
5 changed files with 69 additions and 5 deletions

View file

@ -99,6 +99,14 @@ type Unwrapper interface {
Unwrapv() any 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. // LowHigh is typically used to represent a slice boundary.
type LowHigh struct { type LowHigh struct {
Low int Low int

View file

@ -36,6 +36,7 @@ import (
"github.com/gohugoio/hugo/common/herrors" "github.com/gohugoio/hugo/common/herrors"
"github.com/gohugoio/hugo/common/maps" "github.com/gohugoio/hugo/common/maps"
"github.com/gohugoio/hugo/common/types"
"github.com/gohugoio/hugo/source" "github.com/gohugoio/hugo/source"
@ -731,3 +732,9 @@ func (p pageWithWeight0) Weight0() int {
func (p pageWithWeight0) page() page.Page { func (p pageWithWeight0) page() page.Page {
return p.pageState return p.pageState
} }
var _ types.Unwrapper = (*pageWithWeight0)(nil)
func (p pageWithWeight0) Unwrapv() any {
return p.pageState
}

View file

@ -617,10 +617,10 @@ type intersector struct {
} }
func (i *intersector) appendIfNotSeen(v reflect.Value) { func (i *intersector) appendIfNotSeen(v reflect.Value) {
vi := v.Interface() k := normalize(v)
if !i.seen[vi] { if !i.seen[k] {
i.r = reflect.Append(i.r, v) 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) i.appendIfNotSeen(l1vv)
} }
case kind == reflect.Ptr, kind == reflect.Struct: case kind == reflect.Ptr, kind == reflect.Struct:
if l1vv.Interface() == l2vv.Interface() { if types.Unwrapv(l1vv.Interface()) == types.Unwrapv(l2vv.Interface()) {
i.appendIfNotSeen(l1vv) i.appendIfNotSeen(l1vv)
} }
case kind == reflect.Interface: case kind == reflect.Interface:

View file

@ -230,3 +230,51 @@ boolf = false
"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|",
)
}

View file

@ -18,6 +18,7 @@ import (
"fmt" "fmt"
"reflect" "reflect"
"github.com/gohugoio/hugo/common/types"
"github.com/mitchellh/hashstructure" "github.com/mitchellh/hashstructure"
) )
@ -60,7 +61,7 @@ func normalize(v reflect.Value) any {
return f return f
} }
} }
return v.Interface() return types.Unwrapv(v.Interface())
} }
// collects identities from the slices in seqs into a set. Numeric values are normalized, // collects identities from the slices in seqs into a set. Numeric values are normalized,