Skip to content

Commit 629d958

Browse files
feat: Array sum filter (#661)
* feat(filters): add array sum filter * docs(filters): array sum filter * docs: update versoin number in source/filters/sum.md --------- Co-authored-by: Jun Yang <[email protected]>
1 parent fe978c8 commit 629d958

File tree

4 files changed

+70
-0
lines changed

4 files changed

+70
-0
lines changed

docs/source/_data/sidebar.yml

+1
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ filters:
7070
strip: strip.html
7171
strip_html: strip_html.html
7272
strip_newlines: strip_newlines.html
73+
sum: sum.html
7374
times: times.html
7475
truncate: truncate.html
7576
truncatewords: truncatewords.html

docs/source/filters/sum.md

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
---
2+
title: sum
3+
---
4+
5+
{% since %}v10.10.0{% endsince %}
6+
7+
Computes the sum of all the numbers in an array.
8+
An optional argument specifies which property of the array's items to sum up.
9+
10+
In this example, assume the object `cart.products` contains an array of all products in the cart of a website.
11+
Assume each cart product has a `qty` property that gives the count of that product instance in the cart.
12+
Using the `sum` filter we can calculate the total number of products in the cart.
13+
14+
Input
15+
```liquid
16+
The cart has {{ order.products | sum: "qty" }} products.
17+
```
18+
19+
Output
20+
```text
21+
The cart has 7 products.
22+
```

src/filters/array.ts

+9
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,15 @@ export function * map (this: FilterImpl, arr: Scope[], property: string): Iterab
4343
return results
4444
}
4545

46+
export function * sum (this: FilterImpl, arr: Scope[], property?: string): IterableIterator<unknown> {
47+
let sum = 0
48+
for (const item of toArray(toValue(arr))) {
49+
const data = Number(property ? yield this.context._getFromScope(item, stringify(property), false) : item)
50+
sum += Number.isNaN(data) ? 0 : data
51+
}
52+
return sum
53+
}
54+
4655
export function compact<T> (this: FilterImpl, arr: T[]) {
4756
arr = toValue(arr)
4857
return toArray(arr).filter(x => !isNil(toValue(x)))

test/integration/filters/array.spec.ts

+38
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,44 @@ describe('filters/array', function () {
7474
return test(tpl, { arr: [a, b, c] }, 'Alice Bob Carol')
7575
})
7676
})
77+
describe('sum', () => {
78+
it('should support sum with no args', function () {
79+
const ages = [21, null, -4, '4.5', 13.25, undefined, 0]
80+
return test('{{ages | sum}}', { ages }, '34.75')
81+
})
82+
it('should support sum with property', function () {
83+
const ages = [21, null, -4, '4.5', 13.25, undefined, 0].map(x => ({ age: x }))
84+
return test('{{ages | sum: "age"}}', { ages }, '34.75')
85+
})
86+
it('should support sum with nested property', function () {
87+
const ages = [21, null, -4, '4.5', 13.25, undefined, 0].map(x => ({ age: { first: x } }))
88+
return test('{{ages | sum: "age.first"}}', { ages }, '34.75')
89+
})
90+
it('should support non-array input', function () {
91+
const age = 21.5
92+
return test('{{age | sum}}', { age }, '21.5')
93+
})
94+
it('should coerce missing property to zero', function () {
95+
const ages = [{ qty: 1 }, { qty: 2, cnt: 3 }, { cnt: 4 }]
96+
return test('{{ages | sum}} {{ages | sum: "cnt"}} {{ages | sum: "other"}}', { ages }, '0 7 0')
97+
})
98+
it('should coerce indexable non-map values to zero', function () {
99+
const input = [1, 'foo', { quantity: 3 }]
100+
return test('{{input | sum}}', { input }, '1')
101+
})
102+
it('should coerce unindexable values to zero', function () {
103+
const input = [1, null, { quantity: 2 }]
104+
return test('{{input | sum}}', { input }, '1')
105+
})
106+
it('should coerce true to 1', function () {
107+
const input = [1, true, null, { quantity: 2 }]
108+
return test('{{input | sum}}', { input }, '2')
109+
})
110+
it('should not support nested arrays', function () {
111+
const ages = [1, [2, [3, 4]]]
112+
return test('{{ages | sum}}', { ages }, '1')
113+
})
114+
})
77115
describe('compact', () => {
78116
it('should compact array', function () {
79117
const posts = [{ category: 'foo' }, { category: 'bar' }, { foo: 'bar' }]

0 commit comments

Comments
 (0)