diff --git a/src/twig.expression.js b/src/twig.expression.js index 80a8b4dc..52ba04ce 100644 --- a/src/twig.expression.js +++ b/src/twig.expression.js @@ -576,14 +576,14 @@ module.exports = function (Twig) { }, { type: Twig.expression.type.slice, - regex: /^\[(\d*:\d*)\]/, + regex: /^\[(-?\w*:-?\w*)\]/, next: Twig.expression.set.operationsExtended, compile(token, stack, output) { const sliceRange = token.match[1].split(':'); // SliceStart can be undefined when we pass parameters to the slice filter later - const sliceStart = (sliceRange[0]) ? parseInt(sliceRange[0], 10) : undefined; - const sliceEnd = (sliceRange[1]) ? parseInt(sliceRange[1], 10) : undefined; + const sliceStart = sliceRange[0]; + const sliceEnd = sliceRange[1]; token.value = 'slice'; token.params = [sliceStart, sliceEnd]; @@ -596,11 +596,39 @@ module.exports = function (Twig) { output.push(token); }, - parse(token, stack) { + parse(token, stack, context) { const input = stack.pop(); - const {params} = token; + let {params} = token; const state = this; + if (parseInt(params[0], 10).toString() === params[0]) { + params[0] = parseInt(params[0], 10); + } else { + const value = context[params[0]]; + if (state.template.options.strictVariables && value === undefined) { + throw new Twig.Error('Variable "' + params[0] + '" does not exist.'); + } + + params[0] = value; + } + + if (params[1]) { + if (parseInt(params[1], 10).toString() === params[1]) { + params[1] = parseInt(params[1], 10); + } else { + const value = context[params[1]]; + if (state.template.options.strictVariables && value === undefined) { + throw new Twig.Error('Variable "' + params[1] + '" does not exist.'); + } + + if (value === undefined) { + params = [params[0]]; + } else { + params[1] = value; + } + } + } + stack.push(Twig.filter.call(state, token.value, input, params)); } }, diff --git a/test/test.expressions.js b/test/test.expressions.js index fb414283..ebacf719 100644 --- a/test/test.expressions.js +++ b/test/test.expressions.js @@ -455,6 +455,12 @@ describe('Twig.js Expressions ->', function () { output.should.equal('23'); }); + it('should support slice shorthand (full form) with variables as arguments', function () { + const testTemplate = twig({debug: true, trace: true, data: '{{ "12345"[start:length] }}'}); + const output = testTemplate.render({start: 2, length: 3}); + output.should.equal('345'); + }); + it('should support slice shorthand (omit first)', function () { const testTemplate = twig({data: '{{ "12345"[:2] }}'}); const output = testTemplate.render(); diff --git a/test/test.filters.js b/test/test.filters.js index a0323ab0..c832d2c8 100644 --- a/test/test.filters.js +++ b/test/test.filters.js @@ -640,6 +640,10 @@ describe('Twig.js Filters ->', function () { const testTemplate = twig({data: '{{ \'12345\'|slice(1, 2) }}'}); testTemplate.render().should.equal('23'); }); + it('should slice a string with variables as arguments', function () { + const testTemplate = twig({data: '{{ \'12345\'|slice(start, length) }}'}); + testTemplate.render({start: 2, length: 3}).should.equal('345'); + }); it('should slice a string to the end', function () { const testTemplate = twig({data: '{{ \'12345\'|slice(2) }}'}); testTemplate.render().should.equal('345');