feat: with & for in render tag, closes #195

This commit is contained in:
harttle
2020-03-04 07:08:54 +08:00
parent aa27a6cd7b
commit 6ea6881f08
67 changed files with 1108 additions and 724 deletions
+31 -4
View File
@@ -6,12 +6,39 @@ import { Context } from '../../../src/context/context'
const expect = chai.expect
describe('Hash', function () {
it('should parse variable', async function () {
const hash = await toThenable(Hash.create('num:foo', new Context({ foo: 3 })))
it('should parse "reverse"', async function () {
const hash = await toThenable(new Hash('reverse').render(new Context({ foo: 3 })))
expect(hash).to.haveOwnProperty('reverse')
expect(hash.reverse).to.be.undefined
})
it('should parse "num:foo"', async function () {
const hash = await toThenable(new Hash('num:foo').render(new Context({ foo: 3 })))
expect(hash.num).to.equal(3)
})
it('should parse literals', async function () {
const hash = await toThenable(Hash.create('num:3', new Context()))
it('should parse "num:3"', async function () {
const hash = await toThenable(new Hash('num:3').render(new Context()))
expect(hash.num).to.equal(3)
})
it('should parse "num: arr[0]"', async function () {
const hash = await toThenable(new Hash('num:3').render(new Context({ arr: [3] })))
expect(hash.num).to.equal(3)
})
it('should parse "num: 2.3"', async function () {
const hash = await toThenable(new Hash('num:2.3').render(new Context()))
expect(hash.num).to.equal(2.3)
})
it('should parse "num:bar.coo"', async function () {
const hash = await toThenable(new Hash('num:bar.coo').render(new Context({ bar: { coo: 3 } })))
expect(hash.num).to.equal(3)
})
it('should parse "num1:2.3 reverse,num2:bar.coo\n num3: arr[0]"', async function () {
const ctx = new Context({ bar: { coo: 3 }, arr: [4] })
const hash = await toThenable(new Hash('num1:2.3 reverse,num2:bar.coo\n num3: arr[0]').render(ctx))
expect(hash).to.deep.equal({
num1: 2.3,
reverse: undefined,
num2: 3,
num3: 4
})
})
})
+4 -4
View File
@@ -19,25 +19,25 @@ describe('Output', function () {
const scope = new Context({
foo: { obj: { arr: ['a', 2] } }
})
const output = new Output({ value: 'foo' } as OutputToken, filters)
const output = new Output({ content: 'foo' } as OutputToken, filters)
await toThenable(output.render(scope, emitter))
return expect(emitter.html).to.equal('[object Object]')
})
it('should skip function property', async function () {
const scope = new Context({ obj: { foo: 'foo', bar: (x: any) => x } })
const output = new Output({ value: 'obj' } as OutputToken, filters)
const output = new Output({ content: 'obj' } as OutputToken, filters)
await toThenable(output.render(scope, emitter))
return expect(emitter.html).to.equal('[object Object]')
})
it('should respect to .toString()', async () => {
const scope = new Context({ obj: { toString: () => 'FOO' } })
const output = new Output({ value: 'obj' } as OutputToken, filters)
const output = new Output({ content: 'obj' } as OutputToken, filters)
await toThenable(output.render(scope, emitter))
return expect(emitter.html).to.equal('FOO')
})
it('should respect to .toString()', async () => {
const scope = new Context({ obj: { toString: () => 'FOO' } })
const output = new Output({ value: 'obj' } as OutputToken, filters)
const output = new Output({ content: 'obj' } as OutputToken, filters)
await toThenable(output.render(scope, emitter))
return expect(emitter.html).to.equal('FOO')
})
+4 -44
View File
@@ -32,7 +32,8 @@ describe('Tag', function () {
expect(function () {
new Tag({ // eslint-disable-line
type: 'tag',
value: 'foo',
content: 'foo',
args: '',
name: 'not-exist'
} as TagToken, [], liquid)
}).to.throw(/tag "not-exist" not found/)
@@ -49,52 +50,11 @@ describe('Tag', function () {
liquid.registerTag('foo', { render: spy })
const token = {
type: 'tag',
value: 'foo',
content: 'foo',
args: '',
name: 'foo'
} as TagToken
await toThenable(new Tag(token, [], liquid).render(ctx, emitter))
expect(spy).to.have.been.called
})
describe('hash', function () {
let spy: sinon.SinonSpy, token: TagToken
beforeEach(function () {
spy = sinon.spy()
liquid.registerTag('foo', { render: spy })
token = {
type: 'tag',
value: 'foo aa:foo bb: arr[0] cc: 2.3\ndd:bar.coo',
name: 'foo',
args: 'aa:foo bb: arr[0] cc: 2.3\ndd:bar.coo'
} as TagToken
})
it('should call tag.render with scope', async function () {
await toThenable(new Tag(token, [], liquid).render(ctx, emitter))
expect(spy).to.have.been.calledWithMatch(ctx)
})
it('should resolve identifier hash', async function () {
await toThenable(new Tag(token, [], liquid).render(ctx, emitter))
expect(spy).to.have.been.calledWithMatch({}, {
aa: 'bar'
})
})
it('should accept space between key/value', async function () {
await toThenable(new Tag(token, [], liquid).render(ctx, emitter))
expect(spy).to.have.been.calledWithMatch({}, {
bb: 2
})
})
it('should resolve number value hash', async function () {
await toThenable(new Tag(token, [], liquid).render(ctx, emitter))
expect(spy).to.have.been.calledWithMatch(ctx, {
cc: 2.3
})
})
it('should resolve property access hash', async function () {
await toThenable(new Tag(token, [], liquid).render(ctx, emitter))
expect(spy).to.have.been.calledWithMatch(ctx, {
dd: 'uoo'
})
})
})
})
-27
View File
@@ -83,33 +83,6 @@ describe('Value', function () {
})
})
describe('#tokenize()', function () {
it('should tokenize a simple value', function () {
expect(Value.tokenize('foo')).to.eql(['foo'])
})
it('should tokenize a value with spaces', function () {
expect(Value.tokenize(' foo \t')).to.eql(['foo'])
})
it('should tokenize a simple filter', function () {
expect(Value.tokenize('foo | add')).to.eql(['foo', '|', 'add'])
})
it('should tokenize a filter with a single argument', function () {
expect(Value.tokenize('foo | add: 1')).to.eql(['foo', '|', 'add', ':', '1'])
})
it('should tokenize array indexing', function () {
expect(Value.tokenize('arr[0]')).to.eql(['arr[0]'])
})
it('should tokenize simple object access', function () {
expect(Value.tokenize('obj["foo"]')).to.eql(['obj["foo"]'])
})
it('should tokenize simple dot syntax object access', function () {
expect(Value.tokenize('obj.foo')).to.eql(['obj.foo'])
})
it('should tokenize complex object property access', function () {
expect(Value.tokenize('obj["complex:string here"]')).to.eql(['obj["complex:string here"]'])
})
})
describe('#value()', function () {
it('should call chained filters correctly', async function () {
const date = sinon.stub().returns('y')