mirror of
https://github.com/gohugoio/hugo.git
synced 2025-08-30 22:39:58 +02:00
tpl/collections: Add Pages support to Intersect and Union
This enables `AND` (`intersect`) and `OR` (`union`) filters when combined with `where`. Example: ```go {{ $pages := where .Site.RegularPages "Type" "not in" (slice "page" "about") }} {{ $pages := $pages | union (where .Site.RegularPages "Params.pinned" true) }} {{ $pages := $pages | intersect (where .Site.RegularPages "Params.images" "!=" nil) }} ``` The above fetches regular pages not of `page` or `about` type unless they are pinned. And finally, we exclude all pages with no `images` set in Page params. Fixes #3174
This commit is contained in:
@@ -258,11 +258,34 @@ func TestIn(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
type page struct {
|
||||
Title string
|
||||
}
|
||||
|
||||
func (p page) String() string {
|
||||
return "p-" + p.Title
|
||||
}
|
||||
|
||||
type pagesPtr []*page
|
||||
type pagesVals []page
|
||||
|
||||
func TestIntersect(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
ns := New(&deps.Deps{})
|
||||
|
||||
var (
|
||||
p1 = &page{"A"}
|
||||
p2 = &page{"B"}
|
||||
p3 = &page{"C"}
|
||||
p4 = &page{"D"}
|
||||
|
||||
p1v = page{"A"}
|
||||
p2v = page{"B"}
|
||||
p3v = page{"C"}
|
||||
p4v = page{"D"}
|
||||
)
|
||||
|
||||
for i, test := range []struct {
|
||||
l1, l2 interface{}
|
||||
expect interface{}
|
||||
@@ -280,6 +303,7 @@ func TestIntersect(t *testing.T) {
|
||||
{[]int{2, 4}, []int{1, 2, 4}, []int{2, 4}},
|
||||
{[]int{1, 2, 4}, []int{3, 6}, []int{}},
|
||||
{[]float64{2.2, 4.4}, []float64{1.1, 2.2, 4.4}, []float64{2.2, 4.4}},
|
||||
|
||||
// errors
|
||||
{"not array or slice", []string{"a"}, false},
|
||||
{[]string{"a"}, "not array or slice", false},
|
||||
@@ -314,8 +338,15 @@ func TestIntersect(t *testing.T) {
|
||||
{[]int64{1, 2, 3}, []interface{}{int64(1), int64(2), int64(2)}, []int64{1, 2}},
|
||||
{[]float32{1, 2, 3}, []interface{}{float32(1), float32(2), float32(2)}, []float32{1, 2}},
|
||||
{[]float64{1, 2, 3}, []interface{}{float64(1), float64(2), float64(2)}, []float64{1, 2}},
|
||||
|
||||
// Structs
|
||||
{pagesPtr{p1, p4, p2, p3}, pagesPtr{p4, p2, p2}, pagesPtr{p4, p2}},
|
||||
{pagesVals{p1v, p4v, p2v, p3v}, pagesVals{p1v, p3v, p3v}, pagesVals{p1v, p3v}},
|
||||
{[]interface{}{p1, p4, p2, p3}, []interface{}{p4, p2, p2}, []interface{}{p4, p2}},
|
||||
{[]interface{}{p1v, p4v, p2v, p3v}, []interface{}{p1v, p3v, p3v}, []interface{}{p1v, p3v}},
|
||||
} {
|
||||
errMsg := fmt.Sprintf("[%d] %v", i, test)
|
||||
|
||||
errMsg := fmt.Sprintf("[%d]", test)
|
||||
|
||||
result, err := ns.Intersect(test.l1, test.l2)
|
||||
|
||||
@@ -325,7 +356,9 @@ func TestIntersect(t *testing.T) {
|
||||
}
|
||||
|
||||
assert.NoError(t, err, errMsg)
|
||||
assert.Equal(t, test.expect, result, errMsg)
|
||||
if !reflect.DeepEqual(result, test.expect) {
|
||||
t.Fatalf("[%d] Got\n%v expected\n%v", i, result, test.expect)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -569,6 +602,18 @@ func TestUnion(t *testing.T) {
|
||||
|
||||
ns := New(&deps.Deps{})
|
||||
|
||||
var (
|
||||
p1 = &page{"A"}
|
||||
p2 = &page{"B"}
|
||||
// p3 = &page{"C"}
|
||||
p4 = &page{"D"}
|
||||
|
||||
p1v = page{"A"}
|
||||
//p2v = page{"B"}
|
||||
p3v = page{"C"}
|
||||
//p4v = page{"D"}
|
||||
)
|
||||
|
||||
for i, test := range []struct {
|
||||
l1 interface{}
|
||||
l2 interface{}
|
||||
@@ -604,6 +649,7 @@ func TestUnion(t *testing.T) {
|
||||
{[]int16{2, 4}, []interface{}{1, 2, 4}, []int16{2, 4, 1}, false},
|
||||
{[]int32{2, 4}, []interface{}{1, 2, 4}, []int32{2, 4, 1}, false},
|
||||
{[]int64{2, 4}, []interface{}{1, 2, 4}, []int64{2, 4, 1}, false},
|
||||
|
||||
{[]float64{2.2, 4.4}, []interface{}{1.1, 2.2, 4.4}, []float64{2.2, 4.4, 1.1}, false},
|
||||
{[]float32{2.2, 4.4}, []interface{}{1.1, 2.2, 4.4}, []float32{2.2, 4.4, 1.1}, false},
|
||||
|
||||
@@ -611,14 +657,21 @@ func TestUnion(t *testing.T) {
|
||||
{[]interface{}{"a", "b", "c", "c"}, []string{"a", "b", "d"}, []interface{}{"a", "b", "c", "d"}, false},
|
||||
{[]interface{}{}, []string{}, []interface{}{}, false},
|
||||
{[]interface{}{1, 2}, []int{2, 3}, []interface{}{1, 2, 3}, false},
|
||||
{[]interface{}{1, 2}, []int8{2, 3}, []interface{}{1, 2, int8(3)}, false},
|
||||
{[]interface{}{1, 2}, []int8{2, 3}, []interface{}{1, 2, 3}, false}, // 28
|
||||
{[]interface{}{uint(1), uint(2)}, []uint{2, 3}, []interface{}{uint(1), uint(2), uint(3)}, false},
|
||||
{[]interface{}{1.1, 2.2}, []float64{2.2, 3.3}, []interface{}{1.1, 2.2, 3.3}, false},
|
||||
|
||||
// Structs
|
||||
{pagesPtr{p1, p4}, pagesPtr{p4, p2, p2}, pagesPtr{p1, p4, p2}, false},
|
||||
{pagesVals{p1v}, pagesVals{p3v, p3v}, pagesVals{p1v, p3v}, false},
|
||||
{[]interface{}{p1, p4}, []interface{}{p4, p2, p2}, []interface{}{p1, p4, p2}, false},
|
||||
{[]interface{}{p1v}, []interface{}{p3v, p3v}, []interface{}{p1v, p3v}, false},
|
||||
|
||||
// errors
|
||||
{"not array or slice", []string{"a"}, false, true},
|
||||
{[]string{"a"}, "not array or slice", false, true},
|
||||
} {
|
||||
|
||||
errMsg := fmt.Sprintf("[%d] %v", i, test)
|
||||
|
||||
result, err := ns.Union(test.l1, test.l2)
|
||||
@@ -628,7 +681,9 @@ func TestUnion(t *testing.T) {
|
||||
}
|
||||
|
||||
assert.NoError(t, err, errMsg)
|
||||
assert.Equal(t, test.expect, result, errMsg)
|
||||
if !reflect.DeepEqual(result, test.expect) {
|
||||
t.Fatalf("[%d] Got\n%v expected\n%v", i, result, test.expect)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user