Skip to content

Commit 0deb93e

Browse files
feat: add find_index, has, and reject filters (#799)
* feat: add find_index, has, and reject filters * Minor tweaks * Change semantics of jekyllStyle, add more tests * Some docs improvements
1 parent b0facc7 commit 0deb93e

File tree

10 files changed

+595
-23
lines changed

10 files changed

+595
-23
lines changed

Diff for: docs/source/_data/sidebar.yml

+6
Original file line numberDiff line numberDiff line change
@@ -51,10 +51,14 @@ filters:
5151
escape_once: escape_once.html
5252
find: find.html
5353
find_exp: find_exp.html
54+
find_index: find_index.html
55+
find_index_exp: find_index_exp.html
5456
first: first.html
5557
floor: floor.html
5658
group_by: group_by.html
5759
group_by_exp: group_by_exp.html
60+
has: has.html
61+
has_exp: has_exp.html
5862
inspect: inspect.html
5963
join: join.html
6064
json: json.html
@@ -72,6 +76,8 @@ filters:
7276
push: push.html
7377
prepend: prepend.html
7478
raw: raw.html
79+
reject: reject.html
80+
reject_exp: reject_exp.html
7581
remove: remove.html
7682
remove_first: remove_first.html
7783
remove_last: remove_last.html

Diff for: docs/source/filters/find_index.md

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
---
2+
title: find_index
3+
---
4+
5+
{% since %}v10.21.0{% endsince %}
6+
7+
Return the 0-based index of the first object in an array for which the queried attribute has the given value or return `nil` if no item in the array satisfies the given criteria. For the following `members` array:
8+
9+
```javascript
10+
const members = [
11+
{ graduation_year: 2013, name: 'Jay' },
12+
{ graduation_year: 2014, name: 'John' },
13+
{ graduation_year: 2014, name: 'Jack' }
14+
]
15+
```
16+
17+
Input
18+
```liquid
19+
{{ members | find_index: "graduation_year", 2014 | json }}
20+
```
21+
22+
Output
23+
```text
24+
1
25+
```

Diff for: docs/source/filters/find_index_exp.md

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
---
2+
title: find_index_exp
3+
---
4+
5+
{% since %}v10.21.0{% endsince %}
6+
7+
Return the 0-based index of the first object in an array for which the given expression evaluates to true or return `nil` if no item in the array satisfies the evaluated expression.
8+
9+
```javascript
10+
const members = [
11+
{ graduation_year: 2013, name: 'Jay' },
12+
{ graduation_year: 2014, name: 'John' },
13+
{ graduation_year: 2014, name: 'Jack' }
14+
]
15+
```
16+
17+
Input
18+
```liquid
19+
{{ members | find_index_exp: "item", "item.graduation_year == 2014" | json }}
20+
```
21+
22+
Output
23+
```text
24+
1
25+
```

Diff for: docs/source/filters/has.md

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
---
2+
title: has
3+
---
4+
5+
{% since %}v10.21.0{% endsince %}
6+
7+
Return `true` if the array includes an item for which the queried attribute has the given value or return `false` if no item in the array satisfies the given criteria. For the following `members` array:
8+
9+
```javascript
10+
const members = [
11+
{ graduation_year: 2013, name: 'Jay' },
12+
{ graduation_year: 2014, name: 'John' },
13+
{ graduation_year: 2014, name: 'Jack' }
14+
]
15+
```
16+
17+
Input
18+
```liquid
19+
{{ members | has: "graduation_year", 2014 | json }}
20+
```
21+
22+
Output
23+
```text
24+
true
25+
```

Diff for: docs/source/filters/has_exp.md

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
---
2+
title: has_exp
3+
---
4+
5+
{% since %}v10.21.0{% endsince %}
6+
7+
Return `true` if an item exists in an array for which the given expression evaluates to true or return `false` if no item in the array satisfies the evaluated expression.
8+
9+
```javascript
10+
const members = [
11+
{ graduation_year: 2013, name: 'Jay' },
12+
{ graduation_year: 2014, name: 'John' },
13+
{ graduation_year: 2014, name: 'Jack' }
14+
]
15+
```
16+
17+
Input
18+
```liquid
19+
{{ members | has_exp: "item", "item.graduation_year == 2014" | json }}
20+
```
21+
22+
Output
23+
```text
24+
true
25+
```

Diff for: docs/source/filters/reject.md

+118
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
---
2+
title: reject
3+
---
4+
5+
{% since %}v10.21.0{% endsince %}
6+
7+
Creates an array excluding the objects with a given property value, or excluding [truthy][truthy] values by default when a property is not given.
8+
9+
In this example, assume you have a list of products and you want to filter out kitchen products. Using `reject`, you can create an array excluding only the products that have a `"type"` of `"kitchen"`.
10+
11+
Input
12+
```liquid
13+
All products:
14+
{% for product in products %}
15+
- {{ product.title }}
16+
{% endfor %}
17+
18+
{% assign non_kitchen_products = products | reject: "type", "kitchen" %}
19+
20+
Kitchen products:
21+
{% for product in non_kitchen_products %}
22+
- {{ product.title }}
23+
{% endfor %}
24+
```
25+
26+
Output
27+
```text
28+
All products:
29+
- Vacuum
30+
- Spatula
31+
- Television
32+
- Garlic press
33+
34+
Kitchen products:
35+
- Vacuum
36+
- Television
37+
```
38+
39+
Say instead you have a list of products and you want to exclude taxable products. You can `reject` with a property name but no target value to reject all products with a [truthy][truthy] `"taxable"` value.
40+
41+
Input
42+
```liquid
43+
All products:
44+
{% for product in products %}
45+
- {{ product.title }}
46+
{% endfor %}
47+
48+
{% assign not_taxed_products = products | reject: "taxable" %}
49+
50+
Available products:
51+
{% for product in not_taxed_products %}
52+
- {{ product.title }}
53+
{% endfor %}
54+
```
55+
56+
Output
57+
```text
58+
All products:
59+
- Vacuum
60+
- Spatula
61+
- Television
62+
- Garlic press
63+
64+
Available products:
65+
- Spatula
66+
- Television
67+
```
68+
69+
Additionally, `property` can be any valid Liquid variable expression as used in output syntax, except that the scope of this expression is within each item. For the following `products` array:
70+
71+
```javascript
72+
const products = [
73+
{ meta: { details: { class: 'A' } }, order: 1 },
74+
{ meta: { details: { class: 'B' } }, order: 2 },
75+
{ meta: { details: { class: 'B' } }, order: 3 }
76+
]
77+
```
78+
79+
Input
80+
```liquid
81+
{% assign selected = products | reject: 'meta.details["class"]', "B" %}
82+
{% for item in selected -%}
83+
- {{ item.order }}
84+
{% endfor %}
85+
```
86+
87+
Output
88+
```text
89+
- 1
90+
```
91+
92+
## Jekyll style
93+
94+
{% since %}v10.21.0{% endsince %}
95+
96+
For Liquid users migrating from Jekyll, there's a `jekyllWhere` option to mimic the behavior of Jekyll's `where` filter. This option is set to `false` by default. When enabled, if `property` is an array, the target value is matched using `Array.includes` instead of `==`, which is particularly useful for excluding tags.
97+
98+
```javascript
99+
const pages = [
100+
{ tags: ["cat", "food"], title: 'Cat Food' },
101+
{ tags: ["dog", "food"], title: 'Dog Food' },
102+
]
103+
```
104+
105+
Input
106+
```liquid
107+
{% assign selected = pages | reject: 'tags', "cat" %}
108+
{% for item in selected -%}
109+
- {{ item.title }}
110+
{% endfor %}
111+
```
112+
113+
Output
114+
```text
115+
Dog Food
116+
```
117+
118+
[truthy]: ../tutorials/truthy-and-falsy.html

Diff for: docs/source/filters/reject_exp.md

+37
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
---
2+
title: reject_exp
3+
---
4+
5+
{% since %}v10.21.0{% endsince %}
6+
7+
Select all the objects in an array where the expression is false. In this example, assume you have a list of products and you want to hide your kitchen products. Using `reject_exp`, you can create an array that omits only the products that have a `"type"` of `"kitchen"`.
8+
9+
Input
10+
```liquid
11+
All products:
12+
{% for product in products %}
13+
- {{ product.title }}
14+
{% endfor %}
15+
16+
{% assign non_kitchen_products = products | reject_exp: "item", "item.type == 'kitchen'" %}
17+
18+
Kitchen products:
19+
{% for product in non_kitchen_products %}
20+
- {{ product.title }}
21+
{% endfor %}
22+
```
23+
24+
Output
25+
```text
26+
All products:
27+
- Vacuum
28+
- Spatula
29+
- Television
30+
- Garlic press
31+
32+
Kitchen products:
33+
- Vacuum
34+
- Television
35+
```
36+
37+
[truthy]: ../tutorials/truthy-and-falsy.html

Diff for: docs/source/filters/where.md

+5-3
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ Kitchen products:
3737
```
3838

3939
Say instead you have a list of products and you only want to show those that are available to buy. You can `where` with a property name but no target value to include all products with a [truthy][truthy] `"available"` value.
40+
As a special case, the same will happen if the target value is given but evaluates to `undefined`.
4041

4142
Input
4243
```liquid
@@ -70,7 +71,6 @@ The `where` filter can also be used to find a single object in an array when com
7071
Input
7172
```liquid
7273
{% assign new_shirt = products | where: "type", "shirt" | first %}
73-
7474
Featured product: {{ new_shirt.title }}
7575
```
7676

@@ -105,9 +105,11 @@ Output
105105

106106
## Jekyll style
107107

108-
{% since %}v10.19.0{% endsince %}
108+
{% since %}v10.21.0{% endsince %}
109+
110+
For Liquid users migrating from Jekyll, there's a `jekyllWhere` option to mimic the behavior of Jekyll's `where` filter. This option is set to `false` by default. When enabled, if `property` is an array, the target value is matched using `Array.includes` instead of `==`, which is particularly useful for filtering tags. Additionally, a target value of `undefined` is treated normally, entries matched are exactly those which are themselves `undefined`.
109111

110-
For Liquid users migrating from Jekyll, there's a `jekyllWhere` option to mimic the behavior of Jekyll's `where` filter. This option is set to `false` by default. When enabled, if `property` is an array, the target value is matched using `Array.includes` instead of `==`, which is particularly useful for filtering tags.
112+
This option affects other array selection filters as well, such as `reject` and `find`.
111113

112114
```javascript
113115
const pages = [

0 commit comments

Comments
 (0)