mirror of
https://github.com/harttle/liquidjs.git
synced 2026-09-16 12:50:38 -07:00
feat: jsonify, inspect, to_integer, normalize_whitespace filters
This commit is contained in:
@@ -47,14 +47,17 @@ filters:
|
|||||||
floor: floor.html
|
floor: floor.html
|
||||||
group_by: group_by.html
|
group_by: group_by.html
|
||||||
group_by_exp: group_by_exp.html
|
group_by_exp: group_by_exp.html
|
||||||
|
inspect: inspect.html
|
||||||
join: join.html
|
join: join.html
|
||||||
json: json.html
|
json: json.html
|
||||||
|
jsonify: jsonify.html
|
||||||
last: last.html
|
last: last.html
|
||||||
lstrip: lstrip.html
|
lstrip: lstrip.html
|
||||||
map: map.html
|
map: map.html
|
||||||
minus: minus.html
|
minus: minus.html
|
||||||
modulo: modulo.html
|
modulo: modulo.html
|
||||||
newline_to_br: newline_to_br.html
|
newline_to_br: newline_to_br.html
|
||||||
|
normalize_whitespace: normalize_whitespace.html
|
||||||
plus: plus.html
|
plus: plus.html
|
||||||
pop: pop.html
|
pop: pop.html
|
||||||
push: push.html
|
push: push.html
|
||||||
@@ -80,6 +83,7 @@ filters:
|
|||||||
strip_newlines: strip_newlines.html
|
strip_newlines: strip_newlines.html
|
||||||
sum: sum.html
|
sum: sum.html
|
||||||
times: times.html
|
times: times.html
|
||||||
|
to_integer: to_integer.html
|
||||||
truncate: truncate.html
|
truncate: truncate.html
|
||||||
truncatewords: truncatewords.html
|
truncatewords: truncatewords.html
|
||||||
uniq: uniq.html
|
uniq: uniq.html
|
||||||
|
|||||||
@@ -0,0 +1,42 @@
|
|||||||
|
---
|
||||||
|
title: inspect
|
||||||
|
---
|
||||||
|
|
||||||
|
{% since %}v10.13.0{% endsince %}
|
||||||
|
|
||||||
|
Similar with `json`, but `inspect` allows cyclic structure. For the scope below:
|
||||||
|
|
||||||
|
```
|
||||||
|
const foo = {
|
||||||
|
bar: 'BAR'
|
||||||
|
}
|
||||||
|
foo.foo = foo
|
||||||
|
const scope = { foo }
|
||||||
|
```
|
||||||
|
|
||||||
|
Input
|
||||||
|
```liquid
|
||||||
|
{% foo | inspect %}
|
||||||
|
```
|
||||||
|
|
||||||
|
Output
|
||||||
|
```text
|
||||||
|
{"bar":"BAR","foo":"[Circular]"}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Formatting
|
||||||
|
|
||||||
|
An additional `space` argument can be specified for the indent width.
|
||||||
|
|
||||||
|
Input
|
||||||
|
```liquid
|
||||||
|
{{ foo | inspect: 4 }}
|
||||||
|
```
|
||||||
|
|
||||||
|
Output
|
||||||
|
```text
|
||||||
|
{
|
||||||
|
"bar": "BAR",
|
||||||
|
"foo": "[Circular]"
|
||||||
|
}
|
||||||
|
```
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
---
|
||||||
|
title: jsonify
|
||||||
|
---
|
||||||
|
|
||||||
|
{% since %}v10.13.0{% endsince %}
|
||||||
|
|
||||||
|
See [json][json].
|
||||||
|
|
||||||
|
[json]: /filters/json.html
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
---
|
||||||
|
title: normalize_whitespace
|
||||||
|
---
|
||||||
|
|
||||||
|
{% since %}v10.13.0{% endsince %}
|
||||||
|
|
||||||
|
Replace any occurrence of whitespace with a single space.
|
||||||
|
|
||||||
|
Input
|
||||||
|
```liquid
|
||||||
|
{{ "a \n b" | normalize_whitespace }}
|
||||||
|
```
|
||||||
|
|
||||||
|
Output
|
||||||
|
```html
|
||||||
|
a b
|
||||||
|
```
|
||||||
@@ -10,10 +10,10 @@ There's 40+ filters supported by LiquidJS. These filters can be categorized into
|
|||||||
Categories | Filters
|
Categories | Filters
|
||||||
--- | ---
|
--- | ---
|
||||||
Math | plus, minus, modulo, times, floor, ceil, round, divided_by, abs, at_least, at_most
|
Math | plus, minus, modulo, times, floor, ceil, round, divided_by, abs, at_least, at_most
|
||||||
String | append, prepend, capitalize, upcase, downcase, strip, lstrip, rstrip, strip_newlines, split, replace, replace_first, replace_last,remove, remove_first, remove_last, truncate, truncatewords
|
String | append, prepend, capitalize, upcase, downcase, strip, lstrip, rstrip, strip_newlines, split, replace, replace_first, replace_last,remove, remove_first, remove_last, truncate, truncatewords, normalize_whitespace
|
||||||
HTML/URI | escape, escape_once, url_encode, url_decode, strip_html, newline_to_br
|
HTML/URI | escape, escape_once, url_encode, url_decode, strip_html, newline_to_br
|
||||||
Array | slice, map, sort, sort_natural, uniq, where, where_exp, group_by, group_by_exp, find, find_exp, first, last, join, reverse, concat, compact, size, push, pop, shift, unshift
|
Array | slice, map, sort, sort_natural, uniq, where, where_exp, group_by, group_by_exp, find, find_exp, first, last, join, reverse, concat, compact, size, push, pop, shift, unshift
|
||||||
Date | date
|
Date | date
|
||||||
Misc | default, json, raw
|
Misc | default, json, jsonify, inspect, raw, to_integer
|
||||||
|
|
||||||
[shopify/liquid]: https://github.com/Shopify/liquid
|
[shopify/liquid]: https://github.com/Shopify/liquid
|
||||||
|
|||||||
@@ -0,0 +1,17 @@
|
|||||||
|
---
|
||||||
|
title: to_integer
|
||||||
|
---
|
||||||
|
|
||||||
|
{% since %}v10.13.0{% endsince %}
|
||||||
|
|
||||||
|
Convert values to number.
|
||||||
|
|
||||||
|
Input
|
||||||
|
```liquid
|
||||||
|
{{ "123" | to_integer | json }}
|
||||||
|
```
|
||||||
|
|
||||||
|
Output
|
||||||
|
```text
|
||||||
|
123
|
||||||
|
```
|
||||||
@@ -16,7 +16,7 @@ In the meantime, it's now implemented in JavaScript, that means it has to be mor
|
|||||||
* **Async as first-class citizen**. Filters and tags can be implemented asynchronously by return a `Promise`.
|
* **Async as first-class citizen**. Filters and tags can be implemented asynchronously by return a `Promise`.
|
||||||
* **Also can be sync**. For scenarios that are not I/O intensive, render synchronously can be much faster. You can call synchronous APIs like `.renderSync()` as long as all the filters and tags in template support to be rendered synchronously. All builtin filters/tags support both sync and async render.
|
* **Also can be sync**. For scenarios that are not I/O intensive, render synchronously can be much faster. You can call synchronous APIs like `.renderSync()` as long as all the filters and tags in template support to be rendered synchronously. All builtin filters/tags support both sync and async render.
|
||||||
* **[Abstract file system][afs]**. Along with async feature, LiquidJS can be used to serve templates stored in Databases [#414][#414], on remote HTTP server [#485][#485], and so on.
|
* **[Abstract file system][afs]**. Along with async feature, LiquidJS can be used to serve templates stored in Databases [#414][#414], on remote HTTP server [#485][#485], and so on.
|
||||||
* **Additional tags and filters** like `layout` and `json`, see below for details.
|
* **Additional tags and filters** like `layout` and `json`, `inspect`, `where_exp`, `group_by`, etc., see below for details.
|
||||||
|
|
||||||
## Differences
|
## Differences
|
||||||
|
|
||||||
@@ -31,7 +31,7 @@ Though we're trying to be compatible with the Ruby version, there are still some
|
|||||||
* Trailing unmatched characters inside filters are allowed in shopify/liquid but not in LiquidJS. It means filter arguments without a colon like `{%raw%}{{ "a b" | split " "}}{%endraw%}` will throw an error in LiquidJS. This is intended to improve Liquid usability, see [#208][#208] and [#212][#212].
|
* Trailing unmatched characters inside filters are allowed in shopify/liquid but not in LiquidJS. It means filter arguments without a colon like `{%raw%}{{ "a b" | split " "}}{%endraw%}` will throw an error in LiquidJS. This is intended to improve Liquid usability, see [#208][#208] and [#212][#212].
|
||||||
* LiquidJS has more tags/filters than [the Liquid language][liquid]:
|
* LiquidJS has more tags/filters than [the Liquid language][liquid]:
|
||||||
* LiquidJS-defined tags: [layout][layout], [render][render] and corresponding `block` tag.
|
* LiquidJS-defined tags: [layout][layout], [render][render] and corresponding `block` tag.
|
||||||
* LiquidJS-defined filters: [json][json].
|
* LiquidJS-defined filters: [json][json], group_by, group_by_exp, where_exp, jsonify, inspect, etc.
|
||||||
* Tags/filters that don't depend on Shopify platform are borrowed from [Shopify][shopify-tags].
|
* Tags/filters that don't depend on Shopify platform are borrowed from [Shopify][shopify-tags].
|
||||||
* Tags/filters that don't depend on Jekyll framework are borrowed from [Jekyll][jekyll-filters].
|
* Tags/filters that don't depend on Jekyll framework are borrowed from [Jekyll][jekyll-filters].
|
||||||
* Some tags/filters behave differently: [date][date] filter.
|
* Some tags/filters behave differently: [date][date] filter.
|
||||||
|
|||||||
@@ -0,0 +1,42 @@
|
|||||||
|
---
|
||||||
|
title: inspect
|
||||||
|
---
|
||||||
|
|
||||||
|
{% since %}v10.13.0{% endsince %}
|
||||||
|
|
||||||
|
类似于 `json`,但可以处理循环引用的情况。例如对于上下文:
|
||||||
|
|
||||||
|
```
|
||||||
|
const foo = {
|
||||||
|
bar: 'BAR'
|
||||||
|
}
|
||||||
|
foo.foo = foo
|
||||||
|
const scope = { foo }
|
||||||
|
```
|
||||||
|
|
||||||
|
输入
|
||||||
|
```liquid
|
||||||
|
{% foo | inspect %}
|
||||||
|
```
|
||||||
|
|
||||||
|
输出
|
||||||
|
```text
|
||||||
|
{"bar":"BAR","foo":"[Circular]"}
|
||||||
|
```
|
||||||
|
|
||||||
|
## 格式化
|
||||||
|
|
||||||
|
可以指定一个 `space` 参数来缩进长度。
|
||||||
|
|
||||||
|
输入
|
||||||
|
```liquid
|
||||||
|
{{ foo | inspect: 4 }}
|
||||||
|
```
|
||||||
|
|
||||||
|
输出
|
||||||
|
```text
|
||||||
|
{
|
||||||
|
"bar": "BAR",
|
||||||
|
"foo": "[Circular]"
|
||||||
|
}
|
||||||
|
```
|
||||||
@@ -23,13 +23,13 @@ title: json
|
|||||||
|
|
||||||
可以指定一个 `space` 参数来格式化 JSON。
|
可以指定一个 `space` 参数来格式化 JSON。
|
||||||
|
|
||||||
Input
|
输入
|
||||||
```liquid
|
```liquid
|
||||||
{% assign arr = "foo bar coo" | split: " " %}
|
{% assign arr = "foo bar coo" | split: " " %}
|
||||||
{{ arr | json: 4 }}
|
{{ arr | json: 4 }}
|
||||||
```
|
```
|
||||||
|
|
||||||
Output
|
输出
|
||||||
```text
|
```text
|
||||||
[
|
[
|
||||||
"foo",
|
"foo",
|
||||||
|
|||||||
@@ -0,0 +1,9 @@
|
|||||||
|
---
|
||||||
|
title: jsonify
|
||||||
|
---
|
||||||
|
|
||||||
|
{% since %}v10.13.0{% endsince %}
|
||||||
|
|
||||||
|
见 [json][json]。
|
||||||
|
|
||||||
|
[json]: ./json.html
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
---
|
||||||
|
title: normalize_whitespace
|
||||||
|
---
|
||||||
|
|
||||||
|
{% since %}v10.13.0{% endsince %}
|
||||||
|
|
||||||
|
把连续的空白字符替换为单个空格。
|
||||||
|
|
||||||
|
输入
|
||||||
|
```liquid
|
||||||
|
{{ "a \n b" | normalize_whitespace }}
|
||||||
|
```
|
||||||
|
|
||||||
|
输出
|
||||||
|
```html
|
||||||
|
a b
|
||||||
|
```
|
||||||
@@ -10,10 +10,10 @@ LiquidJS 共支持 40+ 个过滤器,可以分为如下几类:
|
|||||||
类别 | 过滤器
|
类别 | 过滤器
|
||||||
--- | ---
|
--- | ---
|
||||||
数学 | plus, minus, modulo, times, floor, ceil, round, divided_by, abs, at_least, at_most
|
数学 | plus, minus, modulo, times, floor, ceil, round, divided_by, abs, at_least, at_most
|
||||||
字符串 | append, prepend, capitalize, upcase, downcase, strip, lstrip, rstrip, strip_newlines, split, replace, replace_first, replace_last, remove, remove_first, remove_last, truncate, truncatewords
|
字符串 | append, prepend, capitalize, upcase, downcase, strip, lstrip, rstrip, strip_newlines, split, replace, replace_first, replace_last, remove, remove_first, remove_last, truncate, truncatewords, normalize_whitespace
|
||||||
HTML/URI | escape, escape_once, url_encode, url_decode, strip_html, newline_to_br
|
HTML/URI | escape, escape_once, url_encode, url_decode, strip_html, newline_to_br
|
||||||
数组 | slice, map, sort, sort_natural, uniq, where, where_exp, group_by, group_by_exp, find, find_exp, first, last, join, reverse, concat, compact, size, push, pop, shift, unshift
|
数组 | slice, map, sort, sort_natural, uniq, where, where_exp, group_by, group_by_exp, find, find_exp, first, last, join, reverse, concat, compact, size, push, pop, shift, unshift
|
||||||
日期 | date
|
日期 | date
|
||||||
其他 | default, json
|
其他 | default, json, jsonify, inspect, raw, to_integer
|
||||||
|
|
||||||
[shopify/liquid]: https://github.com/Shopify/liquid
|
[shopify/liquid]: https://github.com/Shopify/liquid
|
||||||
|
|||||||
@@ -0,0 +1,17 @@
|
|||||||
|
---
|
||||||
|
title: to_integer
|
||||||
|
---
|
||||||
|
|
||||||
|
{% since %}v10.13.0{% endsince %}
|
||||||
|
|
||||||
|
转换为数字类型。
|
||||||
|
|
||||||
|
输入
|
||||||
|
```liquid
|
||||||
|
{{ "123" | to_integer | json }}
|
||||||
|
```
|
||||||
|
|
||||||
|
输出
|
||||||
|
```text
|
||||||
|
123
|
||||||
|
```
|
||||||
@@ -4,7 +4,7 @@ import * as urlFilters from './url'
|
|||||||
import * as arrayFilters from './array'
|
import * as arrayFilters from './array'
|
||||||
import * as dateFilters from './date'
|
import * as dateFilters from './date'
|
||||||
import * as stringFilters from './string'
|
import * as stringFilters from './string'
|
||||||
import { Default, json, raw } from './misc'
|
import misc from './misc'
|
||||||
import { FilterImplOptions } from '../template'
|
import { FilterImplOptions } from '../template'
|
||||||
|
|
||||||
export const filters: Record<string, FilterImplOptions> = {
|
export const filters: Record<string, FilterImplOptions> = {
|
||||||
@@ -14,7 +14,5 @@ export const filters: Record<string, FilterImplOptions> = {
|
|||||||
...arrayFilters,
|
...arrayFilters,
|
||||||
...dateFilters,
|
...dateFilters,
|
||||||
...stringFilters,
|
...stringFilters,
|
||||||
json,
|
...misc
|
||||||
raw,
|
|
||||||
default: Default
|
|
||||||
}
|
}
|
||||||
|
|||||||
+28
-3
@@ -2,18 +2,43 @@ import { isFalsy } from '../render/boolean'
|
|||||||
import { identify, isArray, isString, toValue } from '../util/underscore'
|
import { identify, isArray, isString, toValue } from '../util/underscore'
|
||||||
import { FilterImpl } from '../template'
|
import { FilterImpl } from '../template'
|
||||||
|
|
||||||
export function Default<T1 extends boolean, T2> (this: FilterImpl, value: T1, defaultValue: T2, ...args: Array<[string, any]>): T1 | T2 {
|
function defaultFilter<T1 extends boolean, T2> (this: FilterImpl, value: T1, defaultValue: T2, ...args: Array<[string, any]>): T1 | T2 {
|
||||||
value = toValue(value)
|
value = toValue(value)
|
||||||
if (isArray(value) || isString(value)) return value.length ? value : defaultValue
|
if (isArray(value) || isString(value)) return value.length ? value : defaultValue
|
||||||
if (value === false && (new Map(args)).get('allow_false')) return false as T1
|
if (value === false && (new Map(args)).get('allow_false')) return false as T1
|
||||||
return isFalsy(value, this.context) ? defaultValue : value
|
return isFalsy(value, this.context) ? defaultValue : value
|
||||||
}
|
}
|
||||||
|
|
||||||
export function json (value: any, space = 0) {
|
function json (value: any, space = 0) {
|
||||||
return JSON.stringify(value, null, space)
|
return JSON.stringify(value, null, space)
|
||||||
}
|
}
|
||||||
|
|
||||||
export const raw = {
|
function inspect (value: any, space = 0) {
|
||||||
|
const ancestors: object[] = []
|
||||||
|
return JSON.stringify(value, function (this: unknown, _key: unknown, value: any) {
|
||||||
|
if (typeof value !== 'object' || value === null) return value
|
||||||
|
// `this` is the object that value is contained in, i.e., its direct parent.
|
||||||
|
while (ancestors.length > 0 && ancestors[ancestors.length - 1] !== this) ancestors.pop()
|
||||||
|
if (ancestors.includes(value)) return '[Circular]'
|
||||||
|
ancestors.push(value)
|
||||||
|
return value
|
||||||
|
}, space)
|
||||||
|
}
|
||||||
|
|
||||||
|
function to_integer (value: any) {
|
||||||
|
return Number(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
const raw = {
|
||||||
raw: true,
|
raw: true,
|
||||||
handler: identify
|
handler: identify
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export default {
|
||||||
|
default: defaultFilter,
|
||||||
|
raw,
|
||||||
|
jsonify: json,
|
||||||
|
to_integer,
|
||||||
|
json,
|
||||||
|
inspect
|
||||||
|
}
|
||||||
|
|||||||
@@ -112,3 +112,8 @@ export function truncatewords (v: string, words = 15, o = '...') {
|
|||||||
if (arr.length >= words) ret += o
|
if (arr.length >= words) ret += o
|
||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function normalize_whitespace (v: string) {
|
||||||
|
v = stringify(v)
|
||||||
|
return v.replace(/\s+/g, ' ')
|
||||||
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import { LRU, LiquidCache } from './cache'
|
|||||||
import { FS, LookupType } from './fs'
|
import { FS, LookupType } from './fs'
|
||||||
import * as fs from './fs/fs-impl'
|
import * as fs from './fs/fs-impl'
|
||||||
import { defaultOperators, Operators } from './render'
|
import { defaultOperators, Operators } from './render'
|
||||||
import { json } from './filters/misc'
|
import misc from './filters/misc'
|
||||||
import { escape } from './filters/html'
|
import { escape } from './filters/html'
|
||||||
|
|
||||||
type OutputEscape = (value: any) => string
|
type OutputEscape = (value: any) => string
|
||||||
@@ -193,7 +193,7 @@ export function normalize (options: LiquidOptions): NormalizedFullOptions {
|
|||||||
|
|
||||||
function getOutputEscapeFunction (nameOrFunction: OutputEscapeOption): OutputEscape {
|
function getOutputEscapeFunction (nameOrFunction: OutputEscapeOption): OutputEscape {
|
||||||
if (nameOrFunction === 'escape') return escape
|
if (nameOrFunction === 'escape') return escape
|
||||||
if (nameOrFunction === 'json') return json
|
if (nameOrFunction === 'json') return misc.json
|
||||||
assert(isFunction(nameOrFunction), '`outputEscape` need to be of type string or function')
|
assert(isFunction(nameOrFunction), '`outputEscape` need to be of type string or function')
|
||||||
return nameOrFunction
|
return nameOrFunction
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,4 +30,33 @@ describe('filters/object', function () {
|
|||||||
expect(liquid.parseAndRenderSync('{{obj | json: 4}}', scope)).toBe(result)
|
expect(liquid.parseAndRenderSync('{{obj | json: 4}}', scope)).toBe(result)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
describe('jsonify', function () {
|
||||||
|
it('should stringify string', async () => expect(await liquid.parseAndRender('{{"foo" | jsonify}}')).toBe('"foo"'))
|
||||||
|
})
|
||||||
|
describe('inspect', function () {
|
||||||
|
it('should inspect string', async () => expect(await liquid.parseAndRender('{{"foo" | inspect}}')).toBe('"foo"'))
|
||||||
|
it('should inspect object', () => {
|
||||||
|
const text = '{{foo | inspect}}'
|
||||||
|
const foo = { bar: 'bar' }
|
||||||
|
const expected = '{"bar":"bar"}'
|
||||||
|
return expect(liquid.parseAndRenderSync(text, { foo })).toBe(expected)
|
||||||
|
})
|
||||||
|
it('should inspect cyclic object', () => {
|
||||||
|
const text = '{{foo | inspect}}'
|
||||||
|
const foo: any = { bar: 'bar' }
|
||||||
|
foo.foo = foo
|
||||||
|
const expected = '{"bar":"bar","foo":"[Circular]"}'
|
||||||
|
return expect(liquid.parseAndRenderSync(text, { foo })).toBe(expected)
|
||||||
|
})
|
||||||
|
it('should support space argument', () => {
|
||||||
|
const text = '{{foo | inspect: 4}}'
|
||||||
|
const foo: any = { bar: 'bar' }
|
||||||
|
foo.foo = foo
|
||||||
|
const expected = '{\n "bar": "bar",\n "foo": "[Circular]"\n}'
|
||||||
|
return expect(liquid.parseAndRenderSync(text, { foo })).toBe(expected)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
describe('to_integer', function () {
|
||||||
|
it('should stringify string', () => expect(liquid.parseAndRenderSync('{{ "123" | to_integer | json }}')).toBe('123'))
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
import { test } from '../../stub/render'
|
import { test } from '../../stub/render'
|
||||||
|
import { Liquid } from '../../../src/liquid'
|
||||||
|
|
||||||
describe('filters/string', function () {
|
describe('filters/string', function () {
|
||||||
|
const liquid = new Liquid()
|
||||||
describe('append', function () {
|
describe('append', function () {
|
||||||
it('should return "-3abc" for -3, "abc"',
|
it('should return "-3abc" for -3, "abc"',
|
||||||
() => test('{{ -3 | append: "abc" }}', '-3abc'))
|
() => test('{{ -3 | append: "abc" }}', '-3abc'))
|
||||||
@@ -228,4 +230,12 @@ describe('filters/string', function () {
|
|||||||
'Take my protein pills and put my helmet on')
|
'Take my protein pills and put my helmet on')
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
describe('normalize_whitespace', () => {
|
||||||
|
it('should replace " \n " with " "', () => {
|
||||||
|
expect(liquid.parseAndRenderSync('{{ "a \n b" | normalize_whitespace }}')).toEqual('a b')
|
||||||
|
})
|
||||||
|
it('should replace multiple occurrences', () => {
|
||||||
|
expect(liquid.parseAndRenderSync('{{ "a \n b c" | normalize_whitespace }}')).toEqual('a b c')
|
||||||
|
})
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
Reference in New Issue
Block a user