diff --git a/docs/source/tags/for.md b/docs/source/tags/for.md index 0accd6ca0..f34e8a68e 100644 --- a/docs/source/tags/for.md +++ b/docs/source/tags/for.md @@ -106,7 +106,7 @@ There's a `forloop` object available inside `for` loops. It's used to indicate t The `forloop.first`, `forloop.last` and `forloop.length` property: Input -``` +```liquid {% for i in (1..5) %} {%- if forloop.first == true -%} First {%- elsif forloop.last == true -%} Last @@ -116,7 +116,7 @@ Input ``` Output -``` +```text First 5 5 @@ -218,3 +218,29 @@ Output ```text 6 5 4 3 2 1 ``` + +When used with additional parameters, order is important. Leading with `reversed` reverses the order of the loop before executing the other parameters. + +Input +```liquid +{% for i in (1..8) reversed limit: 4 %} + {{ i }} +{% endfor %} +``` + +Output +```text +8 7 6 5 +``` + +Input +```liquid +{% for i in (1..8) limit: 4 reversed %} + {{ i }} +{% endfor %} +``` + +Output +```text +4 3 2 1 +``` diff --git a/src/builtin/tags/for.ts b/src/builtin/tags/for.ts index 3f1000d33..b8f43d667 100644 --- a/src/builtin/tags/for.ts +++ b/src/builtin/tags/for.ts @@ -18,7 +18,7 @@ export default { this.variable = variable.content this.collection = collection - this.hash = new Hash(toknenizer.remaining()) + this.hash = new Hash(tokenizer.remaining()) this.templates = [] this.elseTemplates = [] @@ -46,9 +46,12 @@ export default { const hash = yield this.hash.render(ctx) const offset = hash.offset || 0 const limit = (hash.limit === undefined) ? collection.length : hash.limit + const reversedIndex = Reflect.ownKeys(hash).indexOf('reversed') + // reverse collection before slicing if 'reversed' is 1st parameter + if (reversedIndex === 0) collection.reverse() collection = collection.slice(offset, offset + limit) - if ('reversed' in hash) collection.reverse() + if (reversedIndex > 0) collection.reverse() const scope = { forloop: new ForloopDrop(collection.length) } ctx.push(scope) diff --git a/test/integration/builtin/tags/for.ts b/test/integration/builtin/tags/for.ts index fd82fbd53..81ccb97e0 100644 --- a/test/integration/builtin/tags/for.ts +++ b/test/integration/builtin/tags/for.ts @@ -207,25 +207,26 @@ describe('tags/for', function () { }) }) - describe('reverse', function () { + describe('reversed', 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 src = '{% for i in (1..8) limit:2 reversed %}{{ i }}{% endfor %}' const html = await liquid.parseAndRender(src, scope) 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 src = '{% for i in (1..8) reversed limit:2 %}{{ i }}{% endfor %}' const html = await liquid.parseAndRender(src, scope) - return expect(html).to.equal('21') + return expect(html).to.equal('87') }) 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 src = '{% for i in (1..8) offset:2 reversed limit:3 %}{{ i }}{% endfor %}' const html = await liquid.parseAndRender(src) return expect(html).to.equal('543') }) }) + describe('sync', function () { it('should support sync', function () { const src = '{% for i in (1..5) %}{{i}}{%endfor%}'