fix: incorrect scope when using assign with for, fixes #115

* remove AssignScope, CaptureScope, IncrementScope, DecrementScope concepts
* introduce Scope.environments for decrement/increment
* assign to scopes[0] for assign/capture
This commit is contained in:
harttle
2019-03-22 20:38:54 +08:00
parent b7b92c63cf
commit defbb58e66
10 changed files with 37 additions and 131 deletions
+12 -7
View File
@@ -21,13 +21,6 @@ describe('tags/assign', function () {
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)
@@ -76,4 +69,16 @@ describe('tags/assign', function () {
const html = await liquid.parseAndRender(src)
return expect(html).to.equal('-6')
})
describe('scope', function () {
it('should read from parent 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 to the belonging scope', async function () {
const src = '{%for a in (1..2)%}{%assign num = a%}{{a}}{%endfor%} {{num}}'
const html = await liquid.parseAndRender(src, { num: 1 })
return expect(html).to.equal('12 2')
})
})
})
-13
View File
@@ -39,19 +39,6 @@ describe('tags/for', function () {
const html = await liquid.parseAndRender(src, ctx)
return expect(html).to.equal('{"i":0,"length":1}')
})
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}}'
+5 -40
View File
@@ -126,41 +126,6 @@ describe('scope', function () {
expect(await scope.get('one.size')).to.equal(undefined)
})
})
describe('#set', function () {
it('should set nested value', async function () {
await scope.set('posts', {
'first': {
'name': 'A Nice Day'
}
})
await scope.set('category', {
'diary': ['first']
})
expect(await scope.get('posts[category.diary[0]].name'), 'A Nice Day')
})
it('should create parent if needed', async function () {
await scope.set('a.b.c.d', 'COO')
expect(await scope.get('a.b.c.d')).to.equal('COO')
})
it('should keep other properties of parent', async function () {
scope.push({ obj: { foo: 'FOO' } })
await scope.set('obj.bar', 'BAR')
expect(await scope.get('obj.foo')).to.equal('FOO')
})
it('should abort if property cannot be set', async function () {
scope.push({ obj: { foo: 'FOO' } })
await scope.set('obj.foo.bar', 'BAR')
expect(await scope.get('obj.foo')).to.equal('FOO')
})
it("should set parents' corresponding value", async function () {
scope.push({})
await scope.set('foo', 'bar')
scope.pop()
expect(await scope.get('foo')).to.equal('bar')
})
})
describe('strictVariables', async function () {
let scope: Scope
beforeEach(function () {
@@ -172,15 +137,15 @@ describe('scope', function () {
return expect(scope.get('notdefined')).to.be.rejectedWith(/undefined variable: notdefined/)
})
it('should throw when deep variable not exist', async function () {
await scope.set('foo', 'FOO')
scope.contexts.push({ 'foo': 'FOO' })
return expect(scope.get('foo.bar.not.defined')).to.be.rejectedWith(/undefined variable: bar/)
})
it('should throw when itself not defined', async function () {
await scope.set('foo', 'bar')
scope.contexts.push({ 'foo': 'FOO' })
return expect(scope.get('foo.BAR')).to.be.rejectedWith(/undefined variable: BAR/)
})
it('should find variable in parent scope', async function () {
await scope.set('foo', 'foo')
scope.contexts.push({ 'foo': 'foo' })
scope.push({
'bar': 'bar'
})
@@ -196,7 +161,7 @@ describe('scope', function () {
describe('.push()', function () {
it('should push scope', async function () {
await scope.set('bar', 'bar')
scope.contexts.push({ 'bar': 'bar' })
scope.push({
foo: 'foo'
})
@@ -204,7 +169,7 @@ describe('scope', function () {
expect(await scope.get('bar')).to.equal('bar')
})
it('should hide deep properties by push', async function () {
await scope.set('bar', { bar: 'bar' })
scope.contexts.push({ 'bar': { bar: 'bar' } })
scope.push({ bar: { foo: 'foo' } })
expect(await scope.get('bar.foo')).to.equal('foo')
expect(await scope.get('bar.bar')).to.equal(undefined)