mirror of
https://github.com/gohugoio/hugo.git
synced 2024-11-07 20:30:36 -05:00
tpl: Add intersect operator to where function
Returns true if a given field value that is a slice / array of strings, integers or floats contains elements in common with the matching value. It follows the same rules as the intersect function. Closes #1945
This commit is contained in:
parent
ffbd2b6c67
commit
09038865c2
3 changed files with 112 additions and 11 deletions
|
@ -67,7 +67,7 @@ Creates a dictionary `(map[string, interface{})`, expects parameters added in va
|
|||
Invalid combinations like keys that are not strings or uneven number of parameters, will result in an exception thrown.
|
||||
Useful for passing maps to partials when adding to a template.
|
||||
|
||||
e.g. Pass into "foo.html" a map with the keys "important, content"
|
||||
e.g. Pass into "foo.html" a map with the keys "important, content"
|
||||
|
||||
{{$important := .Site.Params.SomethingImportant }}
|
||||
{{range .Site.Params.Bar}}
|
||||
|
@ -78,9 +78,8 @@ e.g. Pass into "foo.html" a map with the keys "important, content"
|
|||
|
||||
Important {{.important}}
|
||||
{{.content}}
|
||||
|
||||
|
||||
or create a map on the fly to pass into
|
||||
or create a map on the fly to pass into
|
||||
|
||||
{{partial "foo" (dict "important" "Smiles" "content" "You should do more")}}
|
||||
|
||||
|
@ -313,6 +312,15 @@ Following operators are now available
|
|||
- `<`, `lt`: True if a given field value is lesser than a matching value
|
||||
- `in`: True if a given field value is included in a matching value. A matching value must be an array or a slice
|
||||
- `not in`: True if a given field value isn't included in a matching value. A matching value must be an array or a slice
|
||||
- `intersect`: True if a given field value that is a slice / array of strings or integers contains elements in common with the matching value. It follows the same rules as the intersect function.
|
||||
|
||||
*`intersect` operator, e.g.:*
|
||||
|
||||
{{ range where .Site.Pages ".Params.tags" "intersect" .Params.tags }}
|
||||
{{ if ne .Permalink $.Permalink }}
|
||||
{{ .Render "summary" }}
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
|
||||
*`where` and `first` can be stacked, e.g.:*
|
||||
|
||||
|
@ -340,7 +348,7 @@ e.g.
|
|||
|
||||
### readDir
|
||||
|
||||
Gets a directory listing from a directory relative to the current project working dir.
|
||||
Gets a directory listing from a directory relative to the current project working dir.
|
||||
|
||||
So, If the project working dir has a single file named `README.txt`:
|
||||
|
||||
|
@ -349,7 +357,7 @@ So, If the project working dir has a single file named `README.txt`:
|
|||
### readFile
|
||||
Reads a file from disk and converts it into a string. Note that the filename must be relative to the current project working dir.
|
||||
So, if you have a file with the name `README.txt` in the root of your project with the content `Hugo Rocks!`:
|
||||
|
||||
|
||||
`{{readFile "README.txt"}}` → `"Hugo Rocks!"`
|
||||
|
||||
## Math
|
||||
|
|
|
@ -646,6 +646,7 @@ func checkCondition(v, mv reflect.Value, op string) (bool, error) {
|
|||
|
||||
var ivp, imvp *int64
|
||||
var svp, smvp *string
|
||||
var slv, slmv interface{}
|
||||
var ima []int64
|
||||
var sma []string
|
||||
if mv.Type() == v.Type() {
|
||||
|
@ -668,6 +669,9 @@ func checkCondition(v, mv reflect.Value, op string) (bool, error) {
|
|||
imv := toTimeUnix(mv)
|
||||
imvp = &imv
|
||||
}
|
||||
case reflect.Array, reflect.Slice:
|
||||
slv = v.Interface()
|
||||
slmv = mv.Interface()
|
||||
}
|
||||
} else {
|
||||
if mv.Kind() != reflect.Array && mv.Kind() != reflect.Slice {
|
||||
|
@ -765,8 +769,24 @@ func checkCondition(v, mv reflect.Value, op string) (bool, error) {
|
|||
return !r, nil
|
||||
}
|
||||
return r, nil
|
||||
case "intersect":
|
||||
r, err := intersect(slv, slmv)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
if reflect.TypeOf(r).Kind() == reflect.Slice {
|
||||
s := reflect.ValueOf(r)
|
||||
|
||||
if s.Len() > 0 {
|
||||
return true, nil
|
||||
}
|
||||
return false, nil
|
||||
} else {
|
||||
return false, errors.New("invalid intersect values")
|
||||
}
|
||||
default:
|
||||
return false, errors.New("no such an operator")
|
||||
return false, errors.New("no such operator")
|
||||
}
|
||||
return false, nil
|
||||
}
|
||||
|
|
|
@ -18,11 +18,6 @@ import (
|
|||
"encoding/base64"
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/spf13/afero"
|
||||
"github.com/spf13/cast"
|
||||
"github.com/spf13/hugo/hugofs"
|
||||
"github.com/spf13/viper"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"html/template"
|
||||
"math/rand"
|
||||
"path"
|
||||
|
@ -32,6 +27,12 @@ import (
|
|||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/spf13/afero"
|
||||
"github.com/spf13/cast"
|
||||
"github.com/spf13/hugo/hugofs"
|
||||
"github.com/spf13/viper"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
type tstNoStringer struct {
|
||||
|
@ -1202,6 +1203,78 @@ func TestWhere(t *testing.T) {
|
|||
{"a": 3, "b": 4},
|
||||
},
|
||||
},
|
||||
{
|
||||
sequence: []map[string][]string{
|
||||
{"a": []string{"A", "B", "C"}, "b": []string{"D", "E", "F"}}, {"a": []string{"G", "H", "I"}, "b": []string{"J", "K", "L"}}, {"a": []string{"M", "N", "O"}, "b": []string{"P", "Q", "R"}},
|
||||
},
|
||||
key: "b", op: "intersect", match: []string{"D", "P", "Q"},
|
||||
expect: []map[string][]string{
|
||||
{"a": []string{"A", "B", "C"}, "b": []string{"D", "E", "F"}}, {"a": []string{"M", "N", "O"}, "b": []string{"P", "Q", "R"}},
|
||||
},
|
||||
},
|
||||
{
|
||||
sequence: []map[string][]int{
|
||||
{"a": []int{1, 2, 3}, "b": []int{4, 5, 6}}, {"a": []int{7, 8, 9}, "b": []int{10, 11, 12}}, {"a": []int{13, 14, 15}, "b": []int{16, 17, 18}},
|
||||
},
|
||||
key: "b", op: "intersect", match: []int{4, 10, 12},
|
||||
expect: []map[string][]int{
|
||||
{"a": []int{1, 2, 3}, "b": []int{4, 5, 6}}, {"a": []int{7, 8, 9}, "b": []int{10, 11, 12}},
|
||||
},
|
||||
},
|
||||
{
|
||||
sequence: []map[string][]int8{
|
||||
{"a": []int8{1, 2, 3}, "b": []int8{4, 5, 6}}, {"a": []int8{7, 8, 9}, "b": []int8{10, 11, 12}}, {"a": []int8{13, 14, 15}, "b": []int8{16, 17, 18}},
|
||||
},
|
||||
key: "b", op: "intersect", match: []int8{4, 10, 12},
|
||||
expect: []map[string][]int8{
|
||||
{"a": []int8{1, 2, 3}, "b": []int8{4, 5, 6}}, {"a": []int8{7, 8, 9}, "b": []int8{10, 11, 12}},
|
||||
},
|
||||
},
|
||||
{
|
||||
sequence: []map[string][]int16{
|
||||
{"a": []int16{1, 2, 3}, "b": []int16{4, 5, 6}}, {"a": []int16{7, 8, 9}, "b": []int16{10, 11, 12}}, {"a": []int16{13, 14, 15}, "b": []int16{16, 17, 18}},
|
||||
},
|
||||
key: "b", op: "intersect", match: []int16{4, 10, 12},
|
||||
expect: []map[string][]int16{
|
||||
{"a": []int16{1, 2, 3}, "b": []int16{4, 5, 6}}, {"a": []int16{7, 8, 9}, "b": []int16{10, 11, 12}},
|
||||
},
|
||||
},
|
||||
{
|
||||
sequence: []map[string][]int32{
|
||||
{"a": []int32{1, 2, 3}, "b": []int32{4, 5, 6}}, {"a": []int32{7, 8, 9}, "b": []int32{10, 11, 12}}, {"a": []int32{13, 14, 15}, "b": []int32{16, 17, 18}},
|
||||
},
|
||||
key: "b", op: "intersect", match: []int32{4, 10, 12},
|
||||
expect: []map[string][]int32{
|
||||
{"a": []int32{1, 2, 3}, "b": []int32{4, 5, 6}}, {"a": []int32{7, 8, 9}, "b": []int32{10, 11, 12}},
|
||||
},
|
||||
},
|
||||
{
|
||||
sequence: []map[string][]int64{
|
||||
{"a": []int64{1, 2, 3}, "b": []int64{4, 5, 6}}, {"a": []int64{7, 8, 9}, "b": []int64{10, 11, 12}}, {"a": []int64{13, 14, 15}, "b": []int64{16, 17, 18}},
|
||||
},
|
||||
key: "b", op: "intersect", match: []int64{4, 10, 12},
|
||||
expect: []map[string][]int64{
|
||||
{"a": []int64{1, 2, 3}, "b": []int64{4, 5, 6}}, {"a": []int64{7, 8, 9}, "b": []int64{10, 11, 12}},
|
||||
},
|
||||
},
|
||||
{
|
||||
sequence: []map[string][]float32{
|
||||
{"a": []float32{1.0, 2.0, 3.0}, "b": []float32{4.0, 5.0, 6.0}}, {"a": []float32{7.0, 8.0, 9.0}, "b": []float32{10.0, 11.0, 12.0}}, {"a": []float32{13.0, 14.0, 15.0}, "b": []float32{16.0, 17.0, 18.0}},
|
||||
},
|
||||
key: "b", op: "intersect", match: []float32{4, 10, 12},
|
||||
expect: []map[string][]float32{
|
||||
{"a": []float32{1.0, 2.0, 3.0}, "b": []float32{4.0, 5.0, 6.0}}, {"a": []float32{7.0, 8.0, 9.0}, "b": []float32{10.0, 11.0, 12.0}},
|
||||
},
|
||||
},
|
||||
{
|
||||
sequence: []map[string][]float64{
|
||||
{"a": []float64{1.0, 2.0, 3.0}, "b": []float64{4.0, 5.0, 6.0}}, {"a": []float64{7.0, 8.0, 9.0}, "b": []float64{10.0, 11.0, 12.0}}, {"a": []float64{13.0, 14.0, 15.0}, "b": []float64{16.0, 17.0, 18.0}},
|
||||
},
|
||||
key: "b", op: "intersect", match: []float64{4, 10, 12},
|
||||
expect: []map[string][]float64{
|
||||
{"a": []float64{1.0, 2.0, 3.0}, "b": []float64{4.0, 5.0, 6.0}}, {"a": []float64{7.0, 8.0, 9.0}, "b": []float64{10.0, 11.0, 12.0}},
|
||||
},
|
||||
},
|
||||
{
|
||||
sequence: []map[string]int{
|
||||
{"a": 1, "b": 2}, {"a": 3, "b": 4}, {"a": 5, "b": 6},
|
||||
|
|
Loading…
Reference in a new issue