diff --git a/src/builtin/tags/for.ts b/src/builtin/tags/for.ts index 5b217c694..5dd038f7b 100644 --- a/src/builtin/tags/for.ts +++ b/src/builtin/tags/for.ts @@ -58,7 +58,7 @@ export default { return reversed(collection) }, collection) - const scope = { forloop: new ForloopDrop(collection.length) } + const scope = { forloop: new ForloopDrop(collection.length, this.collection.getText(), this.variable) } ctx.push(scope) for (const item of collection) { scope[this.variable] = item diff --git a/src/builtin/tags/render.ts b/src/builtin/tags/render.ts index 38eb9578b..a6e805d31 100644 --- a/src/builtin/tags/render.ts +++ b/src/builtin/tags/render.ts @@ -62,7 +62,7 @@ export default { const { value, alias } = this['for'] let collection = evalToken(value, ctx) collection = toEnumerable(collection) - scope['forloop'] = new ForloopDrop(collection.length) + scope['forloop'] = new ForloopDrop(collection.length, value.getText(), alias) for (const item of collection) { scope[alias] = item const templates = yield liquid._parsePartialFile(filepath, childCtx.sync) diff --git a/src/builtin/tags/tablerow.ts b/src/builtin/tags/tablerow.ts index 995c1cb90..20047ee7d 100644 --- a/src/builtin/tags/tablerow.ts +++ b/src/builtin/tags/tablerow.ts @@ -7,12 +7,13 @@ export default { parse: function (tagToken: TagToken, remainTokens: TopLevelToken[]) { const tokenizer = new Tokenizer(tagToken.args, this.liquid.options.operatorsTrie) - this.variable = tokenizer.readIdentifier() + const variable = tokenizer.readIdentifier() tokenizer.skipBlank() const tmp = tokenizer.readIdentifier() assert(tmp && tmp.content === 'in', () => `illegal tag: ${tagToken.getText()}`) + this.variable = variable.content this.collection = tokenizer.readValue() this.hash = new Hash(tokenizer.remaining()) this.templates = [] @@ -39,12 +40,12 @@ export default { const cols = hash.cols || collection.length const r = this.liquid.renderer - const tablerowloop = new TablerowloopDrop(collection.length, cols) + const tablerowloop = new TablerowloopDrop(collection.length, cols, this.collection.getText(), this.variable) const scope = { tablerowloop } ctx.push(scope) for (let idx = 0; idx < collection.length; idx++, tablerowloop.next()) { - scope[this.variable.content] = collection[idx] + scope[this.variable] = collection[idx] if (tablerowloop.col0() === 0) { if (tablerowloop.row() !== 1) emitter.write('') emitter.write(``) diff --git a/src/drop/forloop-drop.ts b/src/drop/forloop-drop.ts index c076a0e5b..08b69d7cf 100644 --- a/src/drop/forloop-drop.ts +++ b/src/drop/forloop-drop.ts @@ -2,10 +2,12 @@ import { Drop } from './drop' export class ForloopDrop extends Drop { protected i = 0 + public name: string public length: number - public constructor (length: number) { + public constructor (length: number, collection: string, variable: string) { super() this.length = length + this.name = `${variable}-${collection}` } public next () { this.i++ diff --git a/src/drop/tablerowloop-drop.ts b/src/drop/tablerowloop-drop.ts index 041ef9661..b7bb5b169 100644 --- a/src/drop/tablerowloop-drop.ts +++ b/src/drop/tablerowloop-drop.ts @@ -2,8 +2,8 @@ import { ForloopDrop } from './forloop-drop' export class TablerowloopDrop extends ForloopDrop { private cols: number - public constructor (length: number, cols: number) { - super(length) + public constructor (length: number, cols: number, collection: string, variable: string) { + super(length, collection, variable) this.length = length this.cols = cols } diff --git a/test/integration/builtin/tags/for.ts b/test/integration/builtin/tags/for.ts index fdc1d5ebc..303206c84 100644 --- a/test/integration/builtin/tags/for.ts +++ b/test/integration/builtin/tags/for.ts @@ -45,7 +45,22 @@ describe('tags/for', function () { it('should output forloop', async function () { const src = '{%for i in (1..1)%}{{forloop}}{%endfor%}' const html = await liquid.parseAndRender(src, scope) - return expect(html).to.equal('{"i":0,"length":1}') + return expect(html).to.equal('{"i":0,"length":1,"name":"i-(1..1)"}') + }) + it('should output forloop collection name', async function () { + const src = '{%for c in alpha%}{{forloop.name}}-{{c}}{%endfor%}' + const html = await liquid.parseAndRender(src, scope) + return expect(html).to.equal('c-alpha-ac-alpha-bc-alpha-c') + }) + it('should output forloop property accessor name', async function () { + const src = '{%for c in obj.foo%}{{forloop.name}}-{{c}}{%endfor%}' + const html = await liquid.parseAndRender(src, scope) + return expect(html).to.equal('c-obj.foo-bar') + }) + it('should output forloop quoted name', async function () { + const src = '{%for str in "string"%}{{forloop.name}}-{{str}}{%endfor%}' + const html = await liquid.parseAndRender(src, scope) + return expect(html).to.equal('str-"string"-string') }) describe('illegal', function () { it('should reject when for not closed', function () {