fix: enumerate Promises (e.g. in for & tablerow) (#237)

* fix: enumerate Promise<array> (e.g. in {% for ... %})

Previously, a Promise of an array was not being enumerated in
{% for %}, for example. This is misleading since the library
handles promises elsewhere (e.g. if you {% assign x = promiseArray %}
and then {% for v in x %}, it worked just fine.

This PR makes Promises of arrays handled by changing toEnumerable
to handle then-ables. This affects other iterators, too, e.g. tablerow,
so I put in a test for that as well.
This commit is contained in:
Tejas Manohar
2020-06-28 09:55:56 +08:00
committed by GitHub
parent 11ffd65503
commit 941dd668fe
4 changed files with 20 additions and 2 deletions
+1 -1
View File
@@ -36,7 +36,7 @@ export default {
}, },
render: function * (ctx: Context, emitter: Emitter) { render: function * (ctx: Context, emitter: Emitter) {
const r = this.liquid.renderer const r = this.liquid.renderer
let collection = toEnumerable(evalToken(this.collection, ctx)) let collection = toEnumerable(yield evalToken(this.collection, ctx))
if (!collection.length) { if (!collection.length) {
yield r.renderTemplates(this.elseTemplates, ctx, emitter) yield r.renderTemplates(this.elseTemplates, ctx, emitter)
+1 -1
View File
@@ -30,7 +30,7 @@ export default {
}, },
render: function * (ctx: Context, emitter: Emitter) { render: function * (ctx: Context, emitter: Emitter) {
let collection = toEnumerable(evalToken(this.collection, ctx)) let collection = toEnumerable(yield evalToken(this.collection, ctx))
const hash = yield this.hash.render(ctx) const hash = yield this.hash.render(ctx)
const offset = hash.offset || 0 const offset = hash.offset || 0
const limit = (hash.limit === undefined) ? collection.length : hash.limit const limit = (hash.limit === undefined) ? collection.length : hash.limit
+8
View File
@@ -20,15 +20,23 @@ describe('tags/for', function () {
nullProtoObj: Object.create(null), nullProtoObj: Object.create(null),
obj: { foo: 'bar', coo: 'haa' }, obj: { foo: 'bar', coo: 'haa' },
alpha: ['a', 'b', 'c'], alpha: ['a', 'b', 'c'],
promiseArray: Promise.resolve(['a', 'b', 'c']),
emptyArray: [] emptyArray: []
} }
}) })
it('should support array', async function () { it('should support array', async function () {
const src = '{%for c in alpha%}{{c}}{%endfor%}' const src = '{%for c in alpha%}{{c}}{%endfor%}'
const html = await liquid.parseAndRender(src, scope) const html = await liquid.parseAndRender(src, scope)
return expect(html).to.equal('abc') return expect(html).to.equal('abc')
}) })
it('should support promise of array', async function () {
const src = '{%for c in promiseArray%}{{c}}{%endfor%}'
const html = await liquid.parseAndRender(src, scope)
return expect(html).to.equal('abc')
})
it('should support object', async function () { it('should support object', async function () {
const src = '{%for item in obj%}{{item[0]}},{{item[1]}}-{%else%}b{%endfor%}' const src = '{%for item in obj%}{{item[0]}},{{item[1]}}-{%else%}b{%endfor%}'
const html = await liquid.parseAndRender(src, scope) const html = await liquid.parseAndRender(src, scope)
+10
View File
@@ -14,6 +14,16 @@ describe('tags/tablerow', function () {
return expect(html).to.equal(dst) return expect(html).to.equal(dst)
}) })
it('should support promises', async function () {
const src = '{% tablerow i in promiseNumbers %}{{ i }}{% endtablerow %}'
const ctx = {
promiseNumbers: Promise.resolve([1,2,3])
}
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, ctx)
return expect(html).to.equal(dst)
})
it('should support cols', async function () { it('should support cols', async function () {
const src = '{% tablerow i in alpha cols:2 %}{{ i }}{% endtablerow %}' const src = '{% tablerow i in alpha cols:2 %}{{ i }}{% endtablerow %}'
const ctx = { const ctx = {