mirror of
https://github.com/harttle/liquidjs.git
synced 2026-09-18 14:00:39 -07:00
refactor: remove /dist from repo
This commit is contained in:
@@ -0,0 +1,66 @@
|
||||
import { test } from 'test/stub/render'
|
||||
|
||||
describe('filters/array', function () {
|
||||
describe('join', function () {
|
||||
it('should support join', function () {
|
||||
const src = '{% assign beatles = "John, Paul, George, Ringo" | split: ", " %}' +
|
||||
'{{ beatles | join: " and " }}'
|
||||
return test(src, 'John and Paul and George and Ringo')
|
||||
})
|
||||
it('should default separator to space', function () {
|
||||
const src = '{% assign beatles = "John, Paul, George, Ringo" | split: ", " %}' +
|
||||
'{{ beatles | join }}'
|
||||
return test(src, 'John Paul George Ringo')
|
||||
})
|
||||
})
|
||||
it('should support split/last', function () {
|
||||
const src = '{% assign my_array = "zebra, octopus, giraffe, tiger" | split: ", " %}' +
|
||||
'{{ my_array|last }}'
|
||||
return test(src, 'tiger')
|
||||
})
|
||||
it('should support map', function () {
|
||||
return test('{{posts | map: "category"}}', '["foo","bar"]')
|
||||
})
|
||||
it('should support reverse', function () {
|
||||
return test('{{ "Ground control to Major Tom." | split: "" | reverse | join: "" }}',
|
||||
'.moT rojaM ot lortnoc dnuorG')
|
||||
})
|
||||
describe('size', function () {
|
||||
it('should return string length',
|
||||
() => test('{{ "Ground control to Major Tom." | size }}', '28'))
|
||||
it('should return array size', function () {
|
||||
return test('{% assign my_array = "apples, oranges, peaches, plums"' +
|
||||
' | split: ", " %}{{ my_array | size }}',
|
||||
'4')
|
||||
})
|
||||
it('should also be used with dot notation - string',
|
||||
() => test('{% assign my_string = "Ground control to Major Tom." %}{{ my_string.size }}', '28'))
|
||||
it('should also be used with dot notation - array',
|
||||
() => test('{% assign my_array = "apples, oranges, peaches, plums" | split: ", " %}{{ my_array.size }}', '4'))
|
||||
})
|
||||
describe('slice', function () {
|
||||
it('should slice first char by 0', () => test('{{ "Liquid" | slice: 0 }}', 'L'))
|
||||
it('should slice third char by 2', () => test('{{ "Liquid" | slice: 2 }}', 'q'))
|
||||
it('should slice substr by 2,5', () => test('{{ "Liquid" | slice: 2, 5 }}', 'quid'))
|
||||
it('should slice substr by -3,2', () => test('{{ "Liquid" | slice: -3, 2 }}', 'ui'))
|
||||
it('should support array', () => test('{{ "1,2,3,4" | split: "," | slice: 1,2 | join }}', '2 3'))
|
||||
})
|
||||
it('should support sort', function () {
|
||||
return test('{% assign my_array = "zebra, octopus, giraffe, Sally Snake"' +
|
||||
' | split: ", " %}' +
|
||||
'{{ my_array | sort | join: ", " }}',
|
||||
'Sally Snake, giraffe, octopus, zebra')
|
||||
})
|
||||
describe('uniq', function () {
|
||||
it('should uniq string list', function () {
|
||||
return test(
|
||||
'{% assign my_array = "ants, bugs, bees, bugs, ants" | split: ", " %}' +
|
||||
'{{ my_array | uniq | join: ", " }}',
|
||||
'ants, bugs, bees'
|
||||
)
|
||||
})
|
||||
it('should uniq falsy value', function () {
|
||||
return test('{{"" | uniq | join: ","}}', '')
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,20 @@
|
||||
import { test, ctx } from 'test/stub/render'
|
||||
|
||||
describe('filters/date', function () {
|
||||
it('should support date: %a %b %d %Y', function () {
|
||||
const str = ctx.date.toDateString()
|
||||
return test('{{ date | date:"%a %b %d %Y"}}', str)
|
||||
})
|
||||
it('should create a new Date when given "now"', function () {
|
||||
return test('{{ "now" | date: "%Y"}}', (new Date()).getFullYear().toString())
|
||||
})
|
||||
it('should parse as Date when given UTC string', function () {
|
||||
return test('{{ "1991-02-22T00:00:00" | date: "%Y"}}', '1991')
|
||||
})
|
||||
it('should render string as string if not valid', function () {
|
||||
return test('{{ "foo" | date: "%Y"}}', 'foo')
|
||||
})
|
||||
it('should render object as string if not valid', function () {
|
||||
return test('{{ obj | date: "%Y"}}', '{"foo":"bar"}')
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,43 @@
|
||||
import { test } from 'test/stub/render'
|
||||
|
||||
describe('filters/html', function () {
|
||||
describe('escape', function () {
|
||||
it('should escape \' and &', function () {
|
||||
return test('{{ "Have you read \'James & the Giant Peach\'?" | escape }}',
|
||||
'Have you read 'James & the Giant Peach'?')
|
||||
})
|
||||
it('should escape normal string', function () {
|
||||
return test('{{ "Tetsuro Takara" | escape }}', 'Tetsuro Takara')
|
||||
})
|
||||
it('should escape function', function () {
|
||||
return test('{{ func | escape }}', 'function () { }')
|
||||
})
|
||||
})
|
||||
describe('escape_once', function () {
|
||||
it('should do escape', () =>
|
||||
test('{{ "1 < 2 & 3" | escape_once }}', '1 < 2 & 3'))
|
||||
it('should not escape twice',
|
||||
() => test('{{ "1 < 2 & 3" | escape_once }}', '1 < 2 & 3'))
|
||||
})
|
||||
describe('strip_html', function () {
|
||||
it('should strip all tags', function () {
|
||||
return test('{{ "Have <em>you</em> read <cite><a href="https://en.wikipedia.org/wiki/Ulysses_(novel)">Ulysses</a></cite>?" | strip_html }}',
|
||||
'Have you read Ulysses?')
|
||||
})
|
||||
it('should strip all comment tags', function () {
|
||||
return test('{{ "<!--Have you read-->Ulysses?" | strip_html }}',
|
||||
'Ulysses?')
|
||||
})
|
||||
it('should strip all style tags and their contents', function () {
|
||||
return test('{{ "<style>cite { font-style: italic; }</style><cite>Ulysses<cite>?" | strip_html }}',
|
||||
'Ulysses?')
|
||||
})
|
||||
it('should strip all scripts tags and their contents', function () {
|
||||
return test('{{ "<script async>console.log(\'hello world\')</script><cite>Ulysses<cite>?" | strip_html }}',
|
||||
'Ulysses?')
|
||||
})
|
||||
it('should strip until empty', function () {
|
||||
return test('{{"<br/><br />< p ></p></ p >" | strip_html }}', '')
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,64 @@
|
||||
import { test } from 'test/stub/render'
|
||||
|
||||
describe('filters/math', function () {
|
||||
describe('abs', function () {
|
||||
it('should return 3 for -3', () => test('{{ -3 | abs }}', '3'))
|
||||
it('should return 2 for arr[0]', () => test('{{ arr[0] | abs }}', '2'))
|
||||
it('should return convert string', () => test('{{ "-3" | abs }}', '3'))
|
||||
})
|
||||
describe('ceil', function () {
|
||||
it('should return "2" for 1.2', () => test('{{ 1.2 | ceil }}', '2'))
|
||||
it('should return "2" for 2.0', () => test('{{ 2.0 | ceil }}', '2'))
|
||||
it('should return "4" for 3.5', () => test('{{ "3.5" | ceil }}', '4'))
|
||||
it('should return "184" for 183.357', () => test('{{ 183.357 | ceil }}', '184'))
|
||||
})
|
||||
describe('divided_by', function () {
|
||||
it('should return 2 for 4,2', () => test('{{4 | divided_by: 2}}', '2'))
|
||||
it('should return 4 for 16,4', () => test('{{16 | divided_by: 4}}', '4'))
|
||||
it('should return 1 for 5,3', () => test('{{5 | divided_by: 3}}', (5 / 3).toString()))
|
||||
it('should convert string to number', () => test('{{"6" | divided_by: "3"}}', '2'))
|
||||
})
|
||||
describe('floor', function () {
|
||||
it('should return "1" for 1.2', () => test('{{ 1.2 | floor }}', '1'))
|
||||
it('should return "2" for 2.0', () => test('{{ 2.0 | floor }}', '2'))
|
||||
it('should return "183" for 183.357', () => test('{{ 183.357 | floor }}', '183'))
|
||||
it('should return "3" for 3.5', () => test('{{ "3.5" | floor }}', '3'))
|
||||
})
|
||||
describe('minus', function () {
|
||||
it('should return "2" for 4,2', () => test('{{ 4 | minus: 2 }}', '2'))
|
||||
it('should return "12" for 16,4', () => test('{{ 16 | minus: 4 }}', '12'))
|
||||
it('should return "171.357" for 183.357,12',
|
||||
() => test('{{ 183.357 | minus: 12 }}', '171.357'))
|
||||
it('should convert first arg as number', () => test('{{ "4" | minus: 1 }}', '3'))
|
||||
it('should convert both args as number', () => test('{{ "4" | minus: "1" }}', '3'))
|
||||
})
|
||||
describe('modulo', function () {
|
||||
it('should return "1" for 3,2', () => test('{{ 3 | modulo: 2 }}', '1'))
|
||||
it('should return "3" for 24,7', () => test('{{ 24 | modulo: 7 }}', '3'))
|
||||
it('should return "3.357" for 183.357,12',
|
||||
() => test('{{ 183.357 | modulo: 12 }}', '3.357'))
|
||||
it('should convert string', () => test('{{ "24" | modulo: "7" }}', '3'))
|
||||
})
|
||||
describe('plus', function () {
|
||||
it('should return "6" for 4,2', () => test('{{ 4 | plus: 2 }}', '6'))
|
||||
it('should return "20" for 16,4', () => test('{{ 16 | plus: 4 }}', '20'))
|
||||
it('should return "195.357" for 183.357,12',
|
||||
() => test('{{ 183.357 | plus: 12 }}', '195.357'))
|
||||
it('should convert first arg as number', () => test('{{ "4" | plus: 2 }}', '6'))
|
||||
it('should convert both args as number', () => test('{{ "4" | plus: "2" }}', '6'))
|
||||
})
|
||||
describe('round', function () {
|
||||
it('should return "1" for 1.2', () => test('{{1.2|round}}', '1'))
|
||||
it('should return "3" for 2.7', () => test('{{2.7|round}}', '3'))
|
||||
it('should return "183.36" for 183.357,2',
|
||||
() => test('{{183.357|round: 2}}', '183.36'))
|
||||
it('should convert string to number', () => test('{{"2.7"|round}}', '3'))
|
||||
})
|
||||
describe('times', function () {
|
||||
it('should return "6" for 3,2', () => test('{{ 3 | times: 2 }}', '6'))
|
||||
it('should return "168" for 24,7', () => test('{{ 24 | times: 7 }}', '168'))
|
||||
it('should return "2200.284" for 183.357,12',
|
||||
() => test('{{ 183.357 | times: 12 }}', '2200.284'))
|
||||
it('should convert string to number', () => test('{{ "24" | times: "7" }}', '168'))
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,8 @@
|
||||
import { test } from 'test/stub/render'
|
||||
|
||||
describe('filters/object', function () {
|
||||
describe('default', function () {
|
||||
it('should use default when falsy', () => test('{{false |default: "a"}}', 'a'))
|
||||
it('should not use default when truthy', () => test('{{true |default: "a"}}', 'true'))
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,176 @@
|
||||
import { test } from 'test/stub/render'
|
||||
|
||||
describe('filters/string', function () {
|
||||
describe('append', function () {
|
||||
it('should return "-3abc" for -3, "abc"',
|
||||
() => test('{{ -3 | append: "abc" }}', '-3abc'))
|
||||
it('should return "abar" for "a",foo', () => test('{{ "a" | append: foo }}', 'abar'))
|
||||
})
|
||||
describe('capitalize', function () {
|
||||
it('should capitalize first', () => test('{{ "i am good" | capitalize }}', 'I am good'))
|
||||
})
|
||||
describe('concat', function () {
|
||||
it('should concat arrays', () => test(`
|
||||
{%- assign fruits = "apples, oranges, peaches" | split: ", " -%}
|
||||
{%- assign vegetables = "carrots, turnips, potatoes" | split: ", " -%}
|
||||
|
||||
{%- assign everything = fruits | concat: vegetables -%}
|
||||
|
||||
{%- for item in everything -%}
|
||||
- {{ item }}
|
||||
{% endfor -%}`, `- apples
|
||||
- oranges
|
||||
- peaches
|
||||
- carrots
|
||||
- turnips
|
||||
- potatoes
|
||||
`))
|
||||
it('should support chained concat', () => test(`
|
||||
{%- assign fruits = "apples, oranges, peaches" | split: ", " -%}
|
||||
{%- assign vegetables = "carrots, turnips, potatoes" | split: ", " -%}
|
||||
{%- assign furniture = "chairs, tables, shelves" | split: ", " -%}
|
||||
{%- assign everything = fruits | concat: vegetables | concat: furniture -%}
|
||||
|
||||
{%- for item in everything -%}
|
||||
- {{ item }}
|
||||
{% endfor -%}`, `- apples
|
||||
- oranges
|
||||
- peaches
|
||||
- carrots
|
||||
- turnips
|
||||
- potatoes
|
||||
- chairs
|
||||
- tables
|
||||
- shelves
|
||||
`))
|
||||
})
|
||||
describe('downcase', function () {
|
||||
it('should return "parker moore" for "Parker Moore"',
|
||||
() => test('{{ "Parker Moore" | downcase }}', 'parker moore'))
|
||||
it('should return "apple" for "apple"',
|
||||
() => test('{{ "apple" | downcase }}', 'apple'))
|
||||
})
|
||||
describe('split', function () {
|
||||
it('should support split/first', function () {
|
||||
const src = '{% assign my_array = "apples, oranges, peaches, plums" | split: ", " %}' +
|
||||
'{{ my_array | first }}'
|
||||
return test(src, 'apples')
|
||||
})
|
||||
})
|
||||
it('should support upcase', () => test('{{ "Parker Moore" | upcase }}', 'PARKER MOORE'))
|
||||
it('should support lstrip', function () {
|
||||
const src = '{{ " So much room for activities! " | lstrip }}'
|
||||
return test(src, 'So much room for activities! ')
|
||||
})
|
||||
it('should support string_with_newlines', function () {
|
||||
const src = '{% capture string_with_newlines %}\n' +
|
||||
'Hello\n' +
|
||||
'there\n' +
|
||||
'{% endcapture %}' +
|
||||
'{{ string_with_newlines | newline_to_br }}'
|
||||
const dst = '<br />' +
|
||||
'Hello<br />' +
|
||||
'there<br />'
|
||||
return test(src, dst)
|
||||
})
|
||||
it('should support prepend', function () {
|
||||
return test('{% assign url = "liquidmarkup.com" %}' +
|
||||
'{{ "/index.html" | prepend: url }}',
|
||||
'liquidmarkup.com/index.html')
|
||||
})
|
||||
it('should support remove', function () {
|
||||
return test('{{ "I strained to see the train through the rain" | remove: "rain" }}',
|
||||
'I sted to see the t through the ')
|
||||
})
|
||||
it('should support remove_first', function () {
|
||||
return test('{{ "I strained to see the train through the rain" | remove_first: "rain" }}',
|
||||
'I sted to see the train through the rain')
|
||||
})
|
||||
it('should support replace', function () {
|
||||
return test('{{ "Take my protein pills and put my helmet on" | replace: "my", "your" }}',
|
||||
'Take your protein pills and put your helmet on')
|
||||
})
|
||||
it('should support replace_first', function () {
|
||||
return test('{% assign my_string = "Take my protein pills and put my helmet on" %}\n' +
|
||||
'{{ my_string | replace_first: "my", "your" }}',
|
||||
'\nTake your protein pills and put my helmet on')
|
||||
})
|
||||
it('should support rstrip', function () {
|
||||
return test('{{ " So much room for activities! " | rstrip }}',
|
||||
' So much room for activities!')
|
||||
})
|
||||
it('should support split', function () {
|
||||
return test('{% assign beatles = "John, Paul, George, Ringo" | split: ", " %}' +
|
||||
'{% for member in beatles %}' +
|
||||
'{{ member }} ' +
|
||||
'{% endfor %}',
|
||||
'John Paul George Ringo ')
|
||||
})
|
||||
it('should support strip', function () {
|
||||
return test('{{ " So much room for activities! " | strip }}',
|
||||
'So much room for activities!')
|
||||
})
|
||||
it('should support strip_newlines', function () {
|
||||
return test('{% capture string_with_newlines %}\n' +
|
||||
'Hello\nthere\n{% endcapture %}' +
|
||||
'{{ string_with_newlines | strip_newlines }}',
|
||||
'Hellothere')
|
||||
})
|
||||
describe('truncate', function () {
|
||||
it('should truncate when string too long', function () {
|
||||
return test('{{ "Ground control to Major Tom." | truncate: 20 }}',
|
||||
'Ground control to...')
|
||||
})
|
||||
it('should not truncate when string not long enough', function () {
|
||||
return test('{{ "Ground control to Major Tom." | truncate: 80 }}',
|
||||
'Ground control to Major Tom.')
|
||||
})
|
||||
it('should truncate with custom ellipsis', function () {
|
||||
return test('{{ "Ground control to Major Tom." | truncate: 25,", and so on" }}',
|
||||
'Ground control, and so on')
|
||||
})
|
||||
it('should truncate with empty custom ellipsis', function () {
|
||||
return test('{{ "Ground control to Major Tom." | truncate: 20, "" }}',
|
||||
'Ground control to Ma')
|
||||
})
|
||||
it('should not truncate when short enough', function () {
|
||||
return test('{{ "12345" | truncate: 5 }}', '12345')
|
||||
})
|
||||
it('should truncate to "..." when len <= 3', function () {
|
||||
return test('{{ "12345" | truncate: 2 }}', '...')
|
||||
})
|
||||
it('should not truncate if length is exactly len', function () {
|
||||
return test('{{ "12345" | truncate: 5 }}', '12345')
|
||||
})
|
||||
it('should default to 50', function () {
|
||||
return test('{{ "1234567890123456789012345678901234567890123456789abc" | truncate }}', '12345678901234567890123456789012345678901234567...')
|
||||
})
|
||||
})
|
||||
describe('truncatewords', function () {
|
||||
it('should truncate when too many words', function () {
|
||||
return test('{{ "Ground control to Major Tom." | truncatewords: 3 }}',
|
||||
'Ground control to...')
|
||||
})
|
||||
it('should not truncate when not enough words', function () {
|
||||
return test('{{ "Ground control to Major Tom." | truncatewords: 8 }}',
|
||||
'Ground control to Major Tom.')
|
||||
})
|
||||
it('should truncate with custom ellipsis', function () {
|
||||
return test('{{ "Ground control to Major Tom." | truncatewords: 3, "--" }}',
|
||||
'Ground control to--')
|
||||
})
|
||||
it('should truncate with empty custom ellipsis', function () {
|
||||
return test('{{ "Ground control to Major Tom." | truncatewords: 3, "" }}',
|
||||
'Ground control to')
|
||||
})
|
||||
it('should allow multiple space chars between', function () {
|
||||
return test('{{ "1 \t2 3 \n4" | truncatewords: 3 }}', '1 2 3...')
|
||||
})
|
||||
it('should show ellipsis if length is exactly len', function () {
|
||||
return test('{{ "1 2 3" | truncatewords: 3 }}', '1 2 3...')
|
||||
})
|
||||
it('should default len to 15', function () {
|
||||
return test('{{ "1 2 3 4 5 6 7 8 9 a b c d e f" | truncatewords }}', '1 2 3 4 5 6 7 8 9 a b c d e f...')
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,15 @@
|
||||
import { test } from 'test/stub/render'
|
||||
|
||||
describe('filters/url', function () {
|
||||
describe('url_decode', function () {
|
||||
it('should decode %xx and +',
|
||||
() => test('{{ "%27Stop%21%27+said+Fred" | url_decode }}', "'Stop!' said Fred"))
|
||||
})
|
||||
|
||||
describe('url_encode', function () {
|
||||
it('should encode @',
|
||||
() => test('{{ "[email protected]" | url_encode }}', 'john%40liquid.com'))
|
||||
it('should encode <space>',
|
||||
() => test('{{ "Tetsuro Takara" | url_encode }}', 'Tetsuro+Takara'))
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,79 @@
|
||||
import Liquid from 'src/liquid'
|
||||
import { expect, use } from 'chai'
|
||||
import * as chaiAsPromised from 'chai-as-promised'
|
||||
|
||||
use(chaiAsPromised)
|
||||
|
||||
describe('tags/assign', function () {
|
||||
const liquid = new Liquid()
|
||||
it('should throw when variable expression illegal', function () {
|
||||
const src = '{% assign / %}'
|
||||
const ctx = {}
|
||||
return expect(liquid.parseAndRender(src, ctx)).to.be.rejectedWith(/illegal/)
|
||||
})
|
||||
it('should support assign to a string', async function () {
|
||||
const src = '{% assign foo="bar" %}{{foo}}'
|
||||
const html = await liquid.parseAndRender(src)
|
||||
return expect(html).to.equal('bar')
|
||||
})
|
||||
it('should support assign to a number', async function () {
|
||||
const src = '{% assign foo=10086 %}{{foo}}'
|
||||
const html = await liquid.parseAndRender(src)
|
||||
return expect(html).to.equal('10086')
|
||||
})
|
||||
it('should shading rather than overwriting', async function () {
|
||||
const ctx = { foo: 'foo' }
|
||||
const src = '{% assign foo="FOO" %}{{foo}}'
|
||||
const html = await liquid.parseAndRender(src, ctx)
|
||||
expect(html).to.equal('FOO')
|
||||
expect(ctx.foo).to.equal('foo')
|
||||
})
|
||||
it('should assign as array', async function () {
|
||||
const src = '{% assign foo=(1..3) %}{{foo}}'
|
||||
const html = await liquid.parseAndRender(src)
|
||||
return expect(html).to.equal('[1,2,3]')
|
||||
})
|
||||
it('should assign as filter result', async function () {
|
||||
const src = '{% assign foo="a b" | capitalize | split: " " | first %}{{foo}}'
|
||||
const html = await liquid.parseAndRender(src)
|
||||
return expect(html).to.equal('A')
|
||||
})
|
||||
it('should assign as filter across multiple lines as result', async function () {
|
||||
const src = `{% assign foo="a b"
|
||||
| capitalize
|
||||
| split: " "
|
||||
| first %}{{foo}}`
|
||||
const html = await liquid.parseAndRender(src)
|
||||
return expect(html).to.equal('A')
|
||||
})
|
||||
it('should assign var-1', async function () {
|
||||
const src = '{% assign var-1 = 5 %}{{ var-1 }}'
|
||||
const html = await liquid.parseAndRender(src)
|
||||
return expect(html).to.equal('5')
|
||||
})
|
||||
it('should assign var-', async function () {
|
||||
const src = '{% assign var- = 5 %}{{ var- }}'
|
||||
const html = await liquid.parseAndRender(src)
|
||||
return expect(html).to.equal('5')
|
||||
})
|
||||
it('should assign -var', async function () {
|
||||
const src = '{% assign -let = 5 %}{{ -let }}'
|
||||
const html = await liquid.parseAndRender(src)
|
||||
return expect(html).to.equal('5')
|
||||
})
|
||||
it('should assign -5-5', async function () {
|
||||
const src = '{% assign -5-5 = 5 %}{{ -5-5 }}'
|
||||
const html = await liquid.parseAndRender(src)
|
||||
return expect(html).to.equal('5')
|
||||
})
|
||||
it('should assign 4-3', async function () {
|
||||
const src = '{% assign 4-3 = 5 %}{{ 4-3 }}'
|
||||
const html = await liquid.parseAndRender(src)
|
||||
return expect(html).to.equal('5')
|
||||
})
|
||||
it('should not assign -6', async function () {
|
||||
const src = '{% assign -6 = 5 %}{{ -6 }}'
|
||||
const html = await liquid.parseAndRender(src)
|
||||
return expect(html).to.equal('-6')
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,35 @@
|
||||
import Liquid from 'src/liquid'
|
||||
import { expect, use } from 'chai'
|
||||
import * as chaiAsPromised from 'chai-as-promised'
|
||||
|
||||
use(chaiAsPromised)
|
||||
|
||||
describe('tags/capture', function () {
|
||||
const liquid = new Liquid()
|
||||
|
||||
it('should support capture', async function () {
|
||||
const src = '{% capture f %}{{"a" | capitalize}}{%endcapture%}{{f}}'
|
||||
const html = await liquid.parseAndRender(src)
|
||||
return expect(html).to.equal('A')
|
||||
})
|
||||
|
||||
it('should shading rather than overwriting', async function () {
|
||||
const src = '{% capture var %}10{% endcapture %}{{var}}'
|
||||
const ctx = { 'var': 20 }
|
||||
const html = await liquid.parseAndRender(src, ctx)
|
||||
expect(html).to.equal('10')
|
||||
expect(ctx.var).to.equal(20)
|
||||
})
|
||||
|
||||
it('should throw on invalid identifier', function () {
|
||||
const src = '{% capture = %}{%endcapture%}'
|
||||
return expect(liquid.parseAndRender(src))
|
||||
.to.be.rejectedWith(/= not valid identifier/)
|
||||
})
|
||||
|
||||
it('should throw when capture not closed', function () {
|
||||
const src = '{%capture c%}{{c}}'
|
||||
return expect(liquid.parseAndRender(src))
|
||||
.to.be.rejectedWith(/tag .* not closed/)
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,51 @@
|
||||
import Liquid from 'src/liquid'
|
||||
import { expect, use } from 'chai'
|
||||
import * as chaiAsPromised from 'chai-as-promised'
|
||||
|
||||
use(chaiAsPromised)
|
||||
|
||||
describe('tags/case', function () {
|
||||
const liquid = new Liquid()
|
||||
|
||||
it('should reject if not closed', function () {
|
||||
const src = '{% case "foo"%}'
|
||||
return expect(liquid.parseAndRender(src))
|
||||
.to.be.rejectedWith(/{% case "foo"%} not closed/)
|
||||
})
|
||||
it('should hit the specified case', async function () {
|
||||
const src = '{% case "foo"%}' +
|
||||
'{% when "foo" %}foo{% when "bar"%}bar' +
|
||||
'{%endcase%}'
|
||||
const html = await liquid.parseAndRender(src)
|
||||
return expect(html).to.equal('foo')
|
||||
})
|
||||
it('should resolve blank as empty string', async function () {
|
||||
const src = '{% case blank %}{% when ""%}bar{%endcase%}'
|
||||
const html = await liquid.parseAndRender(src)
|
||||
return expect(html).to.equal('bar')
|
||||
})
|
||||
it('should resolve empty as empty string', async function () {
|
||||
const src = '{% case empty %}{% when ""%}bar{%endcase%}'
|
||||
const html = await liquid.parseAndRender(src)
|
||||
return expect(html).to.equal('bar')
|
||||
})
|
||||
it('should accept empty string as branch name', async function () {
|
||||
const src = '{% case "" %}{% when ""%}bar{%endcase%}'
|
||||
const html = await liquid.parseAndRender(src)
|
||||
return expect(html).to.equal('bar')
|
||||
})
|
||||
it('should support boolean case', async function () {
|
||||
const src = '{% case false %}' +
|
||||
'{% when "foo" %}foo{% when false%}bar' +
|
||||
'{%endcase%}'
|
||||
const html = await liquid.parseAndRender(src)
|
||||
return expect(html).to.equal('bar')
|
||||
})
|
||||
it('should support else branch', async function () {
|
||||
const src = '{% case "a" %}' +
|
||||
'{% when "b" %}b{% when "c"%}c{%else %}d' +
|
||||
'{%endcase%}'
|
||||
const html = await liquid.parseAndRender(src)
|
||||
return expect(html).to.equal('d')
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,34 @@
|
||||
import Liquid from 'src/liquid'
|
||||
import { expect, use } from 'chai'
|
||||
import * as chaiAsPromised from 'chai-as-promised'
|
||||
|
||||
use(chaiAsPromised)
|
||||
|
||||
describe('tags/comment', function () {
|
||||
const liquid = new Liquid()
|
||||
it('should support empty content', function () {
|
||||
const src = '{% comment %}{% raw%}'
|
||||
return expect(liquid.parseAndRender(src))
|
||||
.to.be.rejectedWith(/{% comment %} not closed/)
|
||||
})
|
||||
it('should ignore plain string', async function () {
|
||||
const src = 'My name is {% comment %}super{% endcomment %} Shopify.'
|
||||
const html = await liquid.parseAndRender(src)
|
||||
return expect(html).to.equal('My name is Shopify.')
|
||||
})
|
||||
it('should ignore output tokens', async function () {
|
||||
const src = '{% comment %}\n{{ foo}} \n{% endcomment %}'
|
||||
const html = await liquid.parseAndRender(src)
|
||||
return expect(html).to.equal('')
|
||||
})
|
||||
it('should ignore tag tokens', async function () {
|
||||
const src = '{% comment %}{%if true%}true{%else%}false{%endif%}{% endcomment %}'
|
||||
const html = await liquid.parseAndRender(src)
|
||||
return expect(html).to.equal('')
|
||||
})
|
||||
it('should ignore un-balenced tag tokens', async function () {
|
||||
const src = '{% comment %}{%if true%}true{%else%}false{% endcomment %}'
|
||||
const html = await liquid.parseAndRender(src)
|
||||
return expect(html).to.equal('')
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,38 @@
|
||||
import Liquid from 'src/liquid'
|
||||
import { expect, use } from 'chai'
|
||||
import * as chaiAsPromised from 'chai-as-promised'
|
||||
|
||||
use(chaiAsPromised)
|
||||
|
||||
describe('tags/cycle', function () {
|
||||
const liquid = new Liquid()
|
||||
|
||||
it('should support cycle', async function () {
|
||||
const src = "{% cycle '1', '2', '3' %}"
|
||||
const html = await liquid.parseAndRender(src + src + src + src)
|
||||
return expect(html).to.equal('1231')
|
||||
})
|
||||
|
||||
it('should throw when cycle candidates empty', function () {
|
||||
return expect(liquid.parseAndRender('{%cycle%}'))
|
||||
.to.be.rejectedWith(/empty candidates/)
|
||||
})
|
||||
|
||||
it('should support cycle in for block', async function () {
|
||||
const src = '{% for i in (1..5) %}{% cycle one, "e"%}{% endfor %}'
|
||||
const ctx = {
|
||||
one: 1
|
||||
}
|
||||
const html = await liquid.parseAndRender(src, ctx)
|
||||
return expect(html).to.equal('1e1e1')
|
||||
})
|
||||
|
||||
it('should support cycle group', async function () {
|
||||
const src = "{% cycle one: '1', '2', '3'%}" +
|
||||
"{% cycle 1: '1', '2', '3'%}" +
|
||||
"{% cycle 2: '1', '2', '3'%}"
|
||||
const ctx = { one: 1 }
|
||||
const html = await liquid.parseAndRender(src, ctx)
|
||||
return expect(html).to.equal('121')
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,58 @@
|
||||
import Liquid from 'src/liquid'
|
||||
import { expect, use } from 'chai'
|
||||
import * as chaiAsPromised from 'chai-as-promised'
|
||||
|
||||
use(chaiAsPromised)
|
||||
|
||||
describe('tags/decrement', function () {
|
||||
const liquid = new Liquid()
|
||||
it('should throw when variable expression illegal', function () {
|
||||
const src = '{% decrement / %}{{var}}'
|
||||
const ctx = {}
|
||||
return expect(liquid.parseAndRender(src, ctx)).to.be.rejectedWith(/illegal/)
|
||||
})
|
||||
|
||||
it('should decrement undefined variable', async function () {
|
||||
const src = '{% decrement var %}{% decrement var %}{% decrement var %}'
|
||||
const html = await liquid.parseAndRender(src)
|
||||
return expect(html).to.equal('-1-2-3')
|
||||
})
|
||||
|
||||
it('should decrement defined variable', async function () {
|
||||
const src = '{% decrement var %}{% decrement var %}{% decrement var %}'
|
||||
const ctx = { 'var': 10 }
|
||||
const html = await liquid.parseAndRender(src, ctx)
|
||||
expect(html).to.equal('987')
|
||||
expect(ctx.var).to.equal(7)
|
||||
})
|
||||
|
||||
it('should be independent from assign', async function () {
|
||||
const src = '{% assign var=10 %}{% decrement var %}{% decrement var %}{% decrement var %}'
|
||||
const html = await liquid.parseAndRender(src)
|
||||
return expect(html).to.equal('-1-2-3')
|
||||
})
|
||||
|
||||
it('should be independent from capture', async function () {
|
||||
const src = '{% capture var %}10{% endcapture %}{% decrement var %}{% decrement var %}{% decrement var %}'
|
||||
const html = await liquid.parseAndRender(src)
|
||||
return expect(html).to.equal('-1-2-3')
|
||||
})
|
||||
|
||||
it('should not shading assign', async function () {
|
||||
const src = '{% assign var=10 %}{% decrement var %}{% decrement var %}{% decrement var %} {{var}}'
|
||||
const html = await liquid.parseAndRender(src)
|
||||
return expect(html).to.equal('-1-2-3 10')
|
||||
})
|
||||
|
||||
it('should not shading capture', async function () {
|
||||
const src = '{% capture var %}10{% endcapture %}{% decrement var %}{% decrement var %}{% decrement var %} {{var}}'
|
||||
const html = await liquid.parseAndRender(src)
|
||||
return expect(html).to.equal('-1-2-3 10')
|
||||
})
|
||||
|
||||
it('should share the same variable with increment', async function () {
|
||||
const src = '{%increment var%}{%increment var%}{%decrement var%}{%decrement var%}{%increment var%}'
|
||||
const html = await liquid.parseAndRender(src)
|
||||
return expect(html).to.equal('01100')
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,204 @@
|
||||
import Liquid from 'src/liquid'
|
||||
import { expect, use } from 'chai'
|
||||
import * as chaiAsPromised from 'chai-as-promised'
|
||||
import { Context } from 'src/scope/scope'
|
||||
|
||||
use(chaiAsPromised)
|
||||
|
||||
describe('tags/for', function () {
|
||||
let liquid: Liquid, ctx: Context
|
||||
before(function () {
|
||||
liquid = new Liquid()
|
||||
liquid.registerTag('throwingTag', {
|
||||
render: function () { throw new Error('intended render error') }
|
||||
})
|
||||
ctx = {
|
||||
one: 1,
|
||||
// eslint-disable-next-line
|
||||
strObj: new String(''),
|
||||
emptyObj: {},
|
||||
nullProtoObj: Object.create(null),
|
||||
obj: { foo: 'bar', coo: 'haa' },
|
||||
alpha: ['a', 'b', 'c'],
|
||||
emptyArray: []
|
||||
}
|
||||
})
|
||||
it('should support array', async function () {
|
||||
const src = '{%for c in alpha%}{{c}}{%endfor%}'
|
||||
const html = await liquid.parseAndRender(src, ctx)
|
||||
return expect(html).to.equal('abc')
|
||||
})
|
||||
|
||||
it('should support object', async function () {
|
||||
const src = '{%for item in obj%}{{item[0]}},{{item[1]}}-{%else%}b{%endfor%}'
|
||||
const html = await liquid.parseAndRender(src, ctx)
|
||||
return expect(html).to.equal('foo,bar-coo,haa-')
|
||||
})
|
||||
|
||||
describe('scope', function () {
|
||||
it('should read super scope', async function () {
|
||||
const src = '{%for a in (1..2)%}{{num}}{%endfor%}'
|
||||
const html = await liquid.parseAndRender(src, { num: 1 })
|
||||
return expect(html).to.equal('11')
|
||||
})
|
||||
it('should write super scope', async function () {
|
||||
const src = '{%for a in (1..2)%}{{num}}{%assign num = 2%}{%endfor%}'
|
||||
const html = await liquid.parseAndRender(src, { num: 1 })
|
||||
return expect(html).to.equal('12')
|
||||
})
|
||||
})
|
||||
|
||||
describe('illegal', function () {
|
||||
it('should reject when for not closed', function () {
|
||||
const src = '{%for c in alpha%}{{c}}'
|
||||
return expect(liquid.parseAndRender(src, ctx))
|
||||
.to.be.rejectedWith(/tag .* not closed/)
|
||||
})
|
||||
|
||||
it('should reject when inner templates rejected', function () {
|
||||
const src = '{%for c in alpha%}{%throwingTag%}{%endfor%}'
|
||||
return expect(liquid.parseAndRender(src, ctx))
|
||||
.to.be.rejectedWith(/intended render error/)
|
||||
})
|
||||
})
|
||||
|
||||
describe('else', function () {
|
||||
it('should goto else for empty array', async function () {
|
||||
const src = '{%for c in emptyArray%}a{%else%}b{%endfor%}'
|
||||
const html = await liquid.parseAndRender(src, ctx)
|
||||
return expect(html).to.equal('b')
|
||||
})
|
||||
|
||||
it('should treat non-empty string as one single element', async function () {
|
||||
const src = '{%for c in "abc"%}x{{c}}{%else%}y{%endfor%}'
|
||||
const html = await liquid.parseAndRender(src, ctx)
|
||||
return expect(html).to.equal('xabc')
|
||||
})
|
||||
|
||||
it('should goto else for empty string', async function () {
|
||||
const src = '{%for c in ""%}a{%else%}b{%endfor%}'
|
||||
const html = await liquid.parseAndRender(src, ctx)
|
||||
return expect(html).to.equal('b')
|
||||
})
|
||||
|
||||
it('should goto else for empty string object', async function () {
|
||||
// it should be false although `new String` is none-conform
|
||||
const src = '{%for c in strObj%}a{%else%}b{%endfor%}'
|
||||
const html = await liquid.parseAndRender(src, ctx)
|
||||
return expect(html).to.equal('b')
|
||||
})
|
||||
|
||||
it('should goto else for empty object', async function () {
|
||||
const src = '{%for c in emptyObj%}a{%else%}b{%endfor%}'
|
||||
const html = await liquid.parseAndRender(src, ctx)
|
||||
return expect(html).to.equal('b')
|
||||
})
|
||||
|
||||
it('should goto else for null-prototyped object', async function () {
|
||||
const src = '{%for c in nullProtoObj%}a{%else%}b{%endfor%}'
|
||||
const html = await liquid.parseAndRender(src, ctx)
|
||||
return expect(html).to.equal('b')
|
||||
})
|
||||
})
|
||||
|
||||
it('should support for with forloop', async function () {
|
||||
const src = '{%for c in alpha%}' +
|
||||
'{{forloop.first}}.{{forloop.index}}.{{forloop.index0}}.' +
|
||||
'{{forloop.last}}.{{forloop.length}}.' +
|
||||
'{{forloop.rindex}}.{{forloop.rindex0}}' +
|
||||
'{{c}}\n' +
|
||||
'{%endfor%}'
|
||||
const dst = 'true.1.0.false.3.3.2a\n' +
|
||||
'false.2.1.false.3.2.1b\n' +
|
||||
'false.3.2.true.3.1.0c\n'
|
||||
const html = await liquid.parseAndRender(src, ctx)
|
||||
return expect(html).to.equal(dst)
|
||||
})
|
||||
|
||||
it('should support for with continue', async function () {
|
||||
const src = '{% for i in (1..5) %}' +
|
||||
'{{i}}{% continue %}after' +
|
||||
'{% endfor %}'
|
||||
const html = await liquid.parseAndRender(src, ctx)
|
||||
return expect(html).to.equal('12345')
|
||||
})
|
||||
it('should support for with break', async function () {
|
||||
const src = '{% for i in (one..5) %}' +
|
||||
'{% if i == 4 %}{% break %}{% endif %}' +
|
||||
'{{ i }}' +
|
||||
'{% endfor %}'
|
||||
const html = await liquid.parseAndRender(src, ctx)
|
||||
return expect(html).to.equal('123')
|
||||
})
|
||||
|
||||
describe('limit', function () {
|
||||
it('should support for with limit', async function () {
|
||||
const src = '{% for i in (1..5) limit:2 %}{{ i }}{% endfor %}'
|
||||
const html = await liquid.parseAndRender(src, ctx)
|
||||
return expect(html).to.equal('12')
|
||||
})
|
||||
it('should set forloop.last properly', async function () {
|
||||
const src = '{%for i in (1..10) limit:2 offset:3%}{{forloop.last}} {%endfor%}'
|
||||
const html = await liquid.parseAndRender(src, ctx)
|
||||
return expect(html).to.equal('false true ')
|
||||
})
|
||||
it('should set forloop.first properly', async function () {
|
||||
const src = '{%for i in (1..10) limit:2 offset:3%}{{forloop.first}} {%endfor%}'
|
||||
const html = await liquid.parseAndRender(src, ctx)
|
||||
return expect(html).to.equal('true false ')
|
||||
})
|
||||
it('should set forloop.length properly', function () {
|
||||
const src = '{%for i in (1..10) limit:2 offset:3%}{{forloop.length}} {%endfor%}'
|
||||
return expect(liquid.parseAndRender(src, ctx))
|
||||
.to.eventually.equal('2 2 ')
|
||||
})
|
||||
})
|
||||
|
||||
describe('offset', function () {
|
||||
it('should support offset with limit', async function () {
|
||||
const src = '{% for i in (1..10) limit:2 offset:5%}{{ i }}{% endfor %}'
|
||||
const html = await liquid.parseAndRender(src, ctx)
|
||||
return expect(html).to.equal('67')
|
||||
})
|
||||
it('should set index properly', async function () {
|
||||
const src = '{%for i in (1..10) limit:2 offset:3%}{{forloop.index}} {%endfor%}'
|
||||
const html = await liquid.parseAndRender(src, ctx)
|
||||
return expect(html).to.equal('1 2 ')
|
||||
})
|
||||
it('should set index0 properly', async function () {
|
||||
const src = '{%for i in (1..10) limit:2 offset:3%}{{forloop.index0}} {%endfor%}'
|
||||
const html = await liquid.parseAndRender(src, ctx)
|
||||
return expect(html).to.equal('0 1 ')
|
||||
})
|
||||
it('should set rindex properly', async function () {
|
||||
const src = '{%for i in (1..10) limit:2 offset:3%}{{forloop.rindex}} {%endfor%}'
|
||||
const html = await liquid.parseAndRender(src, ctx)
|
||||
return expect(html).to.equal('2 1 ')
|
||||
})
|
||||
it('should set rindex0 properly', async function () {
|
||||
const src = '{%for i in (1..10) limit:2 offset:3%}{{forloop.rindex0}} {%endfor%}'
|
||||
const html = await liquid.parseAndRender(src, ctx)
|
||||
return expect(html).to.equal('1 0 ')
|
||||
})
|
||||
})
|
||||
|
||||
describe('reverse', function () {
|
||||
it('should support for reversed in the last position', async function () {
|
||||
const src = '{% for i in (1..5) limit:2 reversed %}{{ i }}{% endfor %}'
|
||||
const html = await liquid.parseAndRender(src, ctx)
|
||||
return expect(html).to.equal('21')
|
||||
})
|
||||
|
||||
it('should support for reversed in the first position', async function () {
|
||||
const src = '{% for i in (1..5) reversed limit:2 %}{{ i }}{% endfor %}'
|
||||
const html = await liquid.parseAndRender(src, ctx)
|
||||
return expect(html).to.equal('21')
|
||||
})
|
||||
|
||||
it('should support for reversed in the middle position', async function () {
|
||||
const src = '{% for i in (1..5) offset:2 reversed limit:4 %}{{ i }}{% endfor %}'
|
||||
const html = await liquid.parseAndRender(src, ctx)
|
||||
return expect(html).to.equal('543')
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,113 @@
|
||||
import Liquid from 'src/liquid'
|
||||
import { expect } from 'chai'
|
||||
|
||||
describe('tags/if', function () {
|
||||
const liquid = new Liquid()
|
||||
const ctx = {
|
||||
one: 1,
|
||||
two: 2,
|
||||
emptyString: '',
|
||||
emptyArray: []
|
||||
}
|
||||
|
||||
it('should throw if not closed', function () {
|
||||
const src = '{% if false%}yes'
|
||||
return expect(liquid.parseAndRender(src, ctx))
|
||||
.to.be.rejectedWith(/tag {% if false%} not closed/)
|
||||
})
|
||||
it('should support nested', async function () {
|
||||
const src = '{%if false%}{%if true%}{%else%}a{%endif%}{%endif%}'
|
||||
const html = await liquid.parseAndRender(src, ctx)
|
||||
return expect(html).to.equal('')
|
||||
})
|
||||
|
||||
describe('single value as condition', function () {
|
||||
it('should support boolean', async function () {
|
||||
const src = '{% if false %}1{%elsif true%}2{%else%}3{%endif%}'
|
||||
const html = await liquid.parseAndRender(src, ctx)
|
||||
return expect(html).to.equal('2')
|
||||
})
|
||||
it('should treat Array truthy', async function () {
|
||||
const src = '{%if emptyArray%}a{%endif%}'
|
||||
const html = await liquid.parseAndRender(src, ctx)
|
||||
return expect(html).to.equal('a')
|
||||
})
|
||||
it('should return true if empty string', async function () {
|
||||
const src = '{%if emptyString%}a{%endif%}'
|
||||
const html = await liquid.parseAndRender(src, ctx)
|
||||
return expect(html).to.equal('a')
|
||||
})
|
||||
})
|
||||
describe('expression as condition', function () {
|
||||
it('should support ==', async function () {
|
||||
const src = '{% if 2==3 %}yes{%else%}no{%endif%}'
|
||||
const html = await liquid.parseAndRender(src, ctx)
|
||||
return expect(html).to.equal('no')
|
||||
})
|
||||
it('should support >=', async function () {
|
||||
const src = '{% if 1>=2 and one<two %}a{%endif%}'
|
||||
const html = await liquid.parseAndRender(src, ctx)
|
||||
return expect(html).to.equal('')
|
||||
})
|
||||
it('should support !=', async function () {
|
||||
const src = '{% if one!=two %}yes{%else%}no{%endif%}'
|
||||
const html = await liquid.parseAndRender(src, ctx)
|
||||
return expect(html).to.equal('yes')
|
||||
})
|
||||
it('should support value and expression', async function () {
|
||||
const src = `X{%if version and version != '' %}x{{version}}y{%endif%}Y`
|
||||
const ctx = { 'version': '' }
|
||||
const html = await liquid.parseAndRender(src, ctx)
|
||||
return expect(html).to.equal('XY')
|
||||
})
|
||||
})
|
||||
describe('comparasion to null', function () {
|
||||
it('should evaluate false for null < 10', async function () {
|
||||
const src = '{% if null < 10 %}yes{% else %}no{% endif %}'
|
||||
const html = await liquid.parseAndRender(src, ctx)
|
||||
return expect(html).to.equal('no')
|
||||
})
|
||||
|
||||
it('should evaluate false for null > 10', async function () {
|
||||
const src = '{% if null > 10 %}yes{% else %}no{% endif %}'
|
||||
const html = await liquid.parseAndRender(src, ctx)
|
||||
return expect(html).to.equal('no')
|
||||
})
|
||||
|
||||
it('should evaluate false for null <= 10', async function () {
|
||||
const src = '{% if null <= 10 %}yes{% else %}no{% endif %}'
|
||||
const html = await liquid.parseAndRender(src, ctx)
|
||||
return expect(html).to.equal('no')
|
||||
})
|
||||
|
||||
it('should evaluate false for null >= 10', async function () {
|
||||
const src = '{% if null >= 10 %}yes{% else %}no{% endif %}'
|
||||
const html = await liquid.parseAndRender(src, ctx)
|
||||
return expect(html).to.equal('no')
|
||||
})
|
||||
|
||||
it('should evaluate false for 10 < null', async function () {
|
||||
const src = '{% if 10 < null %}yes{% else %}no{% endif %}'
|
||||
const html = await liquid.parseAndRender(src, ctx)
|
||||
return expect(html).to.equal('no')
|
||||
})
|
||||
|
||||
it('should evaluate false for 10 > null', async function () {
|
||||
const src = '{% if 10 > null %}yes{% else %}no{% endif %}'
|
||||
const html = await liquid.parseAndRender(src, ctx)
|
||||
return expect(html).to.equal('no')
|
||||
})
|
||||
|
||||
it('should evaluate false for 10 <= null', async function () {
|
||||
const src = '{% if 10 <= null %}yes{% else %}no{% endif %}'
|
||||
const html = await liquid.parseAndRender(src, ctx)
|
||||
return expect(html).to.equal('no')
|
||||
})
|
||||
|
||||
it('should evaluate false for 10 >= null', async function () {
|
||||
const src = '{% if 10 >= null %}yes{% else %}no{% endif %}'
|
||||
const html = await liquid.parseAndRender(src, ctx)
|
||||
return expect(html).to.equal('no')
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,147 @@
|
||||
import Liquid from 'src/liquid'
|
||||
import { expect } from 'chai'
|
||||
import { mock, restore } from 'test/stub/mockfs'
|
||||
|
||||
describe('tags/include', function () {
|
||||
let liquid: Liquid
|
||||
before(function () {
|
||||
liquid = new Liquid({
|
||||
root: '/',
|
||||
extname: '.html'
|
||||
})
|
||||
})
|
||||
afterEach(restore)
|
||||
it('should support include', async function () {
|
||||
mock({
|
||||
'/current.html': 'bar{% include "bar/foo.html" %}bar',
|
||||
'/bar/foo.html': 'foo'
|
||||
})
|
||||
const html = await liquid.renderFile('/current.html')
|
||||
return expect(html).to.equal('barfoobar')
|
||||
})
|
||||
it('should support template string', async function () {
|
||||
mock({
|
||||
'/current.html': 'bar{% include "bar/{{name}}" %}bar',
|
||||
'/bar/foo.html': 'foo'
|
||||
})
|
||||
const html = await liquid.renderFile('/current.html', { name: 'foo.html' })
|
||||
return expect(html).to.equal('barfoobar')
|
||||
})
|
||||
|
||||
it('should throw when not specified', function () {
|
||||
mock({
|
||||
'/parent.html': '{%include%}'
|
||||
})
|
||||
return liquid.renderFile('/parent.html').catch(function (e) {
|
||||
expect(e.name).to.equal('RenderError')
|
||||
expect(e.message).to.match(/cannot include with empty filename/)
|
||||
})
|
||||
})
|
||||
|
||||
it('should throw when not exist', function () {
|
||||
mock({
|
||||
'/parent.html': '{%include not-exist%}'
|
||||
})
|
||||
return liquid.renderFile('/parent.html').catch(function (e) {
|
||||
expect(e.name).to.equal('RenderError')
|
||||
expect(e.message).to.match(/cannot include with empty filename/)
|
||||
})
|
||||
})
|
||||
|
||||
it('should support include with relative path', async function () {
|
||||
mock({
|
||||
'/bar/foo.html': 'foo',
|
||||
'/foo/relative.html': 'bar{% include "../bar/foo.html" %}bar'
|
||||
})
|
||||
const html = await liquid.renderFile('foo/relative.html')
|
||||
return expect(html).to.equal('barfoobar')
|
||||
})
|
||||
|
||||
it('should support include: hash list', async function () {
|
||||
mock({
|
||||
'/hash.html': '{% assign name="harttle" %}{% include "user.html", role: "admin", alias: name %}',
|
||||
'/user.html': '{{name}} : {{role}} : {{alias}}'
|
||||
})
|
||||
const html = await liquid.renderFile('hash.html')
|
||||
return expect(html).to.equal('harttle : admin : harttle')
|
||||
})
|
||||
|
||||
it('should support include: parent scope', async function () {
|
||||
mock({
|
||||
'/scope.html': '{% assign shape="triangle" %}{% assign color="yellow" %}{% include "color.html" %}',
|
||||
'/color.html': 'color:{{color}}, shape:{{shape}}'
|
||||
})
|
||||
const html = await liquid.renderFile('scope.html')
|
||||
return expect(html).to.equal('color:yellow, shape:triangle')
|
||||
})
|
||||
|
||||
it('should support include: with', async function () {
|
||||
mock({
|
||||
'/with.html': '{% include "color" with "red", shape: "rect" %}',
|
||||
'/color.html': 'color:{{color}}, shape:{{shape}}'
|
||||
})
|
||||
const html = await liquid.renderFile('with.html')
|
||||
return expect(html).to.equal('color:red, shape:rect')
|
||||
})
|
||||
|
||||
it('should support nested includes', async function () {
|
||||
mock({
|
||||
'/personInfo.html': 'This is a person {% include "card.html" %}',
|
||||
'/card.html': '<p>{{person.firstName}} {{person.lastName}}<br/>{% include "address" %}</p>',
|
||||
'/address.html': 'City: {{person.address.city}}'
|
||||
})
|
||||
const ctx = {
|
||||
person: {
|
||||
firstName: 'Joe',
|
||||
lastName: 'Shmoe',
|
||||
address: {
|
||||
city: 'Dallas'
|
||||
}
|
||||
}
|
||||
}
|
||||
const html = await liquid.renderFile('personInfo.html', ctx)
|
||||
return expect(html).to.equal('This is a person <p>Joe Shmoe<br/>City: Dallas</p>')
|
||||
})
|
||||
|
||||
describe('static partial', function () {
|
||||
it('should support filename with extention', async function () {
|
||||
mock({
|
||||
'/parent.html': 'X{% include child.html color:"red" %}Y',
|
||||
'/child.html': 'child with {{color}}'
|
||||
})
|
||||
const staticLiquid = new Liquid({ dynamicPartials: false, root: '/' })
|
||||
const html = await staticLiquid.renderFile('parent.html')
|
||||
return expect(html).to.equal('Xchild with redY')
|
||||
})
|
||||
|
||||
it('should support parent paths', async function () {
|
||||
mock({
|
||||
'/parent.html': 'X{% include bar/./../foo/child.html %}Y',
|
||||
'/foo/child.html': 'child'
|
||||
})
|
||||
const staticLiquid = new Liquid({ dynamicPartials: false, root: '/' })
|
||||
const html = await staticLiquid.renderFile('parent.html')
|
||||
return expect(html).to.equal('XchildY')
|
||||
})
|
||||
|
||||
it('should support subpaths', async function () {
|
||||
mock({
|
||||
'/parent.html': 'X{% include foo/child.html %}Y',
|
||||
'/foo/child.html': 'child'
|
||||
})
|
||||
const staticLiquid = new Liquid({ dynamicPartials: false, root: '/' })
|
||||
const html = await staticLiquid.renderFile('parent.html')
|
||||
return expect(html).to.equal('XchildY')
|
||||
})
|
||||
|
||||
it('should support comma separated arguments', async function () {
|
||||
mock({
|
||||
'/parent.html': 'X{% include child.html, color:"red" %}Y',
|
||||
'/child.html': 'child with {{color}}'
|
||||
})
|
||||
const staticLiquid = new Liquid({ dynamicPartials: false, root: '/' })
|
||||
const html = await staticLiquid.renderFile('parent.html')
|
||||
return expect(html).to.equal('Xchild with redY')
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,47 @@
|
||||
import Liquid from 'src/liquid'
|
||||
import { expect, use } from 'chai'
|
||||
import * as chaiAsPromised from 'chai-as-promised'
|
||||
|
||||
use(chaiAsPromised)
|
||||
|
||||
describe('tags/increment', function () {
|
||||
const liquid = new Liquid()
|
||||
|
||||
it('should increment undefined variable', async function () {
|
||||
const src = '{% increment one %}{% increment one %}{% increment one %}'
|
||||
const html = await liquid.parseAndRender(src)
|
||||
return expect(html).to.equal('012')
|
||||
})
|
||||
|
||||
it('should increment defined variable', async function () {
|
||||
const src = '{% increment one %}{% increment one %}{% increment one %}'
|
||||
const ctx = { one: 7 }
|
||||
const html = await liquid.parseAndRender(src, ctx)
|
||||
expect(html).to.equal('789')
|
||||
expect(ctx.one).to.equal(10)
|
||||
})
|
||||
|
||||
it('should be independent from assign', async function () {
|
||||
const src = '{% assign var=10 %}{% increment var %}{% increment var %}{% increment var %}'
|
||||
const html = await liquid.parseAndRender(src)
|
||||
return expect(html).to.equal('012')
|
||||
})
|
||||
|
||||
it('should be independent from capture', async function () {
|
||||
const src = '{% capture var %}10{% endcapture %}{% increment var %}{% increment var %}{% increment var %}'
|
||||
const html = await liquid.parseAndRender(src)
|
||||
return expect(html).to.equal('012')
|
||||
})
|
||||
|
||||
it('should not shading assign', async function () {
|
||||
const src = '{% assign var=10 %}{% increment var %}{% increment var %}{% increment var %} {{var}}'
|
||||
const html = await liquid.parseAndRender(src)
|
||||
return expect(html).to.equal('012 10')
|
||||
})
|
||||
|
||||
it('should not shading capture', async function () {
|
||||
const src = '{% capture var %}10{% endcapture %}{% increment var %}{% increment var %}{% increment var %} {{var}}'
|
||||
const html = await liquid.parseAndRender(src)
|
||||
return expect(html).to.equal('012 10')
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,136 @@
|
||||
import Liquid from 'src/liquid'
|
||||
import { expect } from 'chai'
|
||||
import { mock, restore } from 'test/stub/mockfs'
|
||||
|
||||
describe('tags/layout', function () {
|
||||
let liquid: Liquid
|
||||
before(function () {
|
||||
liquid = new Liquid({
|
||||
root: '/',
|
||||
extname: '.html'
|
||||
})
|
||||
})
|
||||
afterEach(restore)
|
||||
|
||||
it('should throw when block not closed', function () {
|
||||
mock({
|
||||
'/parent.html': 'parent'
|
||||
})
|
||||
const src = '{% layout "parent" %}{%block%}A'
|
||||
return expect(liquid.parseAndRender(src)).to
|
||||
.be.rejectedWith(/tag {%block%} not closed/)
|
||||
})
|
||||
it('should throw when filename not specified', function () {
|
||||
mock({
|
||||
'/parent.html': '{%layout%}'
|
||||
})
|
||||
return liquid.renderFile('/parent.html').catch(function (e) {
|
||||
expect(e.name).to.equal('RenderError')
|
||||
expect(e.message).to.match(/cannot apply layout with empty filename/)
|
||||
})
|
||||
})
|
||||
describe('anonymous block', function () {
|
||||
it('should handle anonymous block', async function () {
|
||||
mock({
|
||||
'/parent.html': 'X{%block%}{%endblock%}Y'
|
||||
})
|
||||
const src = '{% layout "parent.html" %}{%block%}A{%endblock%}'
|
||||
const html = await liquid.parseAndRender(src)
|
||||
return expect(html).to.equal('XAY')
|
||||
})
|
||||
it('should handle top level contents as anonymous block', async function () {
|
||||
mock({
|
||||
'/parent.html': 'X{%block%}{%endblock%}Y'
|
||||
})
|
||||
const src = '{% layout "parent.html" %}A'
|
||||
const html = await liquid.parseAndRender(src)
|
||||
return expect(html).to.equal('XAY')
|
||||
})
|
||||
})
|
||||
it('should handle named blocks', async function () {
|
||||
mock({
|
||||
'/parent.html': 'X{% block "a"%}{% endblock %}Y{% block b%}{%endblock%}Z'
|
||||
})
|
||||
const src = '{% layout "parent.html" %}' +
|
||||
'{%block a%}A{%endblock%}' +
|
||||
'{%block b%}B{%endblock%}'
|
||||
const html = await liquid.parseAndRender(src)
|
||||
return expect(html).to.equal('XAYBZ')
|
||||
})
|
||||
it('should support default block content', async function () {
|
||||
mock({
|
||||
'/parent.html': 'X{% block "a"%}A{% endblock %}Y{% block b%}B{%endblock%}Z'
|
||||
})
|
||||
const src = '{% layout "parent.html" %}{%block a%}a{%endblock%}'
|
||||
const html = await liquid.parseAndRender(src)
|
||||
return expect(html).to.equal('XaYBZ')
|
||||
})
|
||||
it('should handle nested block', async function () {
|
||||
mock({
|
||||
'/grand.html': 'X{%block a%}G{%endblock%}Y',
|
||||
'/parent.html': '{%layout "grand" %}{%block a%}P{%endblock%}',
|
||||
'/main.html': '{%layout "parent"%}{%block a%}A{%endblock%}'
|
||||
})
|
||||
const html = await liquid.renderFile('/main.html')
|
||||
return expect(html).to.equal('XAY')
|
||||
})
|
||||
it('should not bleed scope into included layout', async function () {
|
||||
mock({
|
||||
'/parent.html': 'X{%block a%}{%endblock%}Y{%block b%}{%endblock%}Z',
|
||||
'/main.html': '{%layout "parent"%}' +
|
||||
'{%block a%}A{%endblock%}' +
|
||||
'{%block b%}I{%include "included"%}J{%endblock%}',
|
||||
'/included.html': '{%layout "parent"%}{%block a%}a{%endblock%}'
|
||||
})
|
||||
const html = await liquid.renderFile('main')
|
||||
return expect(html).to.equal('XAYIXaYZJZ')
|
||||
})
|
||||
it('should support hash list', async function () {
|
||||
mock({
|
||||
'/parent.html': '{{color}}{%block%}{%endblock%}',
|
||||
'/main.html': '{% layout "parent.html" color:"black"%}{%block%}A{%endblock%}'
|
||||
})
|
||||
const html = await liquid.renderFile('/main.html')
|
||||
return expect(html).to.equal('blackA')
|
||||
})
|
||||
it('should support multiple hash', async function () {
|
||||
mock({
|
||||
'/parent.html': '{{color}}{{bg}}{%block%}{%endblock%}',
|
||||
'/main.html': '{% layout "parent.html" color:"black", bg:"red"%}{%block%}A{%endblock%}'
|
||||
})
|
||||
const html = await liquid.renderFile('/main.html')
|
||||
return expect(html).to.equal('blackredA')
|
||||
})
|
||||
|
||||
describe('static partial', function () {
|
||||
it('should support filename with extention', async function () {
|
||||
mock({
|
||||
'/parent.html': '{{color}}{%block%}{%endblock%}',
|
||||
'/main.html': '{% layout parent.html color:"black"%}{%block%}A{%endblock%}'
|
||||
})
|
||||
const staticLiquid = new Liquid({ root: '/', dynamicPartials: false })
|
||||
const html = await staticLiquid.renderFile('/main.html')
|
||||
return expect(html).to.equal('blackA')
|
||||
})
|
||||
|
||||
it('should support parent paths', async function () {
|
||||
mock({
|
||||
'/foo/parent.html': '{{color}}{%block%}{%endblock%}',
|
||||
'/main.html': '{% layout bar/../foo/parent.html color:"black"%}{%block%}A{%endblock%}'
|
||||
})
|
||||
const staticLiquid = new Liquid({ root: '/', dynamicPartials: false })
|
||||
const html = await staticLiquid.renderFile('/main.html')
|
||||
return expect(html).to.equal('blackA')
|
||||
})
|
||||
|
||||
it('should support subpaths', async function () {
|
||||
mock({
|
||||
'/foo/parent.html': '{{color}}{%block%}{%endblock%}',
|
||||
'/main.html': '{% layout foo/parent.html color:"black"%}{%block%}A{%endblock%}'
|
||||
})
|
||||
const staticLiquid = new Liquid({ root: '/', dynamicPartials: false })
|
||||
const html = await staticLiquid.renderFile('/main.html')
|
||||
return expect(html).to.equal('blackA')
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,22 @@
|
||||
import Liquid from 'src/liquid'
|
||||
import { expect } from 'chai'
|
||||
|
||||
describe('tags/raw', function () {
|
||||
const liquid = new Liquid()
|
||||
it('should support raw 1', async function () {
|
||||
const p = liquid.parseAndRender('{% raw%}')
|
||||
return expect(p).be.rejectedWith(/{% raw%} not closed/)
|
||||
})
|
||||
it('should support raw 2', async function () {
|
||||
const src = '{% raw %}{{ 5 | plus: 6 }}{% endraw %} is equal to 11.'
|
||||
const dst = '{{ 5 | plus: 6 }} is equal to 11.'
|
||||
const html = await liquid.parseAndRender(src)
|
||||
return expect(html).to.equal(dst)
|
||||
})
|
||||
it('should support raw 3', async function () {
|
||||
const src = '{% raw %}\n{{ foo}} \n{% endraw %}'
|
||||
const dst = '\n{{ foo}} \n'
|
||||
const html = await liquid.parseAndRender(src)
|
||||
return expect(html).to.equal(dst)
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,78 @@
|
||||
import Liquid from 'src/liquid'
|
||||
import { expect } from 'chai'
|
||||
|
||||
describe('tags/tablerow', function () {
|
||||
const liquid = new Liquid()
|
||||
|
||||
it('should support tablerow', async function () {
|
||||
const src = '{% tablerow i in (1..3)%}{{ i }}{% endtablerow %}'
|
||||
const dst = '<tr class="row1"><td class="col1">1</td><td class="col2">2</td><td class="col3">3</td></tr>'
|
||||
const html = await liquid.parseAndRender(src)
|
||||
return expect(html).to.equal(dst)
|
||||
})
|
||||
|
||||
it('should support cols', async function () {
|
||||
const src = '{% tablerow i in alpha cols:2 %}{{ i }}{% endtablerow %}'
|
||||
const ctx = {
|
||||
alpha: ['a', 'b', 'c']
|
||||
}
|
||||
const dst =
|
||||
'<tr class="row1"><td class="col1">a</td><td class="col2">b</td></tr>' +
|
||||
'<tr class="row2"><td class="col1">c</td></tr>'
|
||||
const html = await liquid.parseAndRender(src, ctx)
|
||||
return expect(html).to.equal(dst)
|
||||
})
|
||||
|
||||
it('should support cols set to 0', async function () {
|
||||
const src = '{% tablerow i in (1..3) cols:0 %}{{ i }}{% endtablerow %}'
|
||||
const dst = '<tr class="row1"><td class="col1">1</td><td class="col2">2</td><td class="col3">3</td></tr>'
|
||||
const html = await liquid.parseAndRender(src)
|
||||
return expect(html).to.equal(dst)
|
||||
})
|
||||
|
||||
it('should support empty tablerow', async function () {
|
||||
const src = '{% tablerow i in (1..0) cols:2 %}{{ i }}{% endtablerow %}'
|
||||
const dst = ''
|
||||
const html = await liquid.parseAndRender(src)
|
||||
return expect(html).to.equal(dst)
|
||||
})
|
||||
|
||||
it('should support empty array', async function () {
|
||||
const src = '{% tablerow i in alpha.z cols:2 %}{{ i }}{% endtablerow %}'
|
||||
const dst = ''
|
||||
const html = await liquid.parseAndRender(src)
|
||||
return expect(html).to.equal(dst)
|
||||
})
|
||||
|
||||
it('should throw when tablerow not closed', function () {
|
||||
const src = '{% tablerow i in (1..0) cols:2 %}{{ i }}'
|
||||
return expect(liquid.parseAndRender(src))
|
||||
.to.be.rejectedWith(/tag .* not closed/)
|
||||
})
|
||||
|
||||
it('should support tablerow with range', async function () {
|
||||
const src = '{% tablerow i in (1..5) cols:2 %}{{ i }}{% endtablerow %}'
|
||||
const dst =
|
||||
'<tr class="row1"><td class="col1">1</td><td class="col2">2</td></tr>' +
|
||||
'<tr class="row2"><td class="col1">3</td><td class="col2">4</td></tr>' +
|
||||
'<tr class="row3"><td class="col1">5</td></tr>'
|
||||
const html = await liquid.parseAndRender(src)
|
||||
return expect(html).to.equal(dst)
|
||||
})
|
||||
|
||||
it('should support tablerow with limit', async function () {
|
||||
const src = '{% tablerow i in (1..5) cols:2 limit:3 %}{{ i }}{% endtablerow %}'
|
||||
const dst =
|
||||
'<tr class="row1"><td class="col1">1</td><td class="col2">2</td></tr>' +
|
||||
'<tr class="row2"><td class="col1">3</td></tr>'
|
||||
const html = await liquid.parseAndRender(src)
|
||||
return expect(html).to.equal(dst)
|
||||
})
|
||||
|
||||
it('should support tablerow with offset', async function () {
|
||||
const src = '{% tablerow i in (1..5) cols:2 offset:3 %}{{ i }}{% endtablerow %}'
|
||||
const dst = '<tr class="row1"><td class="col1">4</td><td class="col2">5</td></tr>'
|
||||
const html = await liquid.parseAndRender(src)
|
||||
return expect(html).to.equal(dst)
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,37 @@
|
||||
import Liquid from 'src/liquid'
|
||||
import { expect, use } from 'chai'
|
||||
import * as chaiAsPromised from 'chai-as-promised'
|
||||
|
||||
use(chaiAsPromised)
|
||||
|
||||
describe('tags/unless', function () {
|
||||
let liquid: Liquid
|
||||
before(() => { liquid = new Liquid() })
|
||||
|
||||
it('should render else when predicate yields true', async function () {
|
||||
// 0 is truthy
|
||||
const src = '{% unless 0 %}yes{%else%}no{%endunless%}'
|
||||
const html = await liquid.parseAndRender(src)
|
||||
return expect(html).to.equal('no')
|
||||
})
|
||||
it('should render unless when predicate yields false', async function () {
|
||||
const src = '{% unless false %}yes{%else%}no{%endunless%}'
|
||||
const html = await liquid.parseAndRender(src)
|
||||
return expect(html).to.equal('yes')
|
||||
})
|
||||
it('should reject when tag not closed', function () {
|
||||
const src = '{% unless 1>2 %}yes'
|
||||
return expect(liquid.parseAndRender(src))
|
||||
.to.be.rejectedWith(/tag {% unless 1>2 %} not closed/)
|
||||
})
|
||||
it('should render unless when predicate yields false and else undefined', async function () {
|
||||
const src = '{% unless 1>2 %}yes{%endunless%}'
|
||||
const html = await liquid.parseAndRender(src)
|
||||
return expect(html).to.equal('yes')
|
||||
})
|
||||
it('should render "" when predicate yields false and else undefined', async function () {
|
||||
const src = '{% unless 1<2 %}yes{%endunless%}'
|
||||
const html = await liquid.parseAndRender(src)
|
||||
return expect(html).to.equal('')
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user