Skip to content

Commit

Permalink
Merge pull request #881 from antoineveldhoven/slice-filter-variables
Browse files Browse the repository at this point in the history
Support variables in slice filter shorthand
  • Loading branch information
willrowe committed Nov 16, 2023
2 parents f08598b + 251e52b commit ab8791b
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 6 deletions.
38 changes: 33 additions & 5 deletions src/twig.expression.js
Original file line number Diff line number Diff line change
Expand Up @@ -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];
Expand All @@ -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));
}
},
Expand Down
6 changes: 5 additions & 1 deletion src/twig.filters.js
Original file line number Diff line number Diff line change
Expand Up @@ -644,9 +644,13 @@ module.exports = function (Twig) {
// Default to start of string
const start = params[0] || 0;
// Default to length of string
const length = params.length > 1 ? params[1] : value.length;
let length = params.length > 1 ? params[1] : value.length;
// Handle negative start values
const startIndex = start >= 0 ? start : Math.max(value.length + start, 0);
// Handle negative length values
if (length < 0) {
length = value.length - startIndex + length;
}

if (Twig.lib.is('Array', value)) {
const output = [];
Expand Down
30 changes: 30 additions & 0 deletions test/test.expressions.js
Original file line number Diff line number Diff line change
Expand Up @@ -467,6 +467,36 @@ describe('Twig.js Expressions ->', function () {
output.should.equal('23');
});

it('should support slice shorthand (full form) with negative start', function () {
const testTemplate = twig({data: '{{ "12345"[-2:1] }}'});
const output = testTemplate.render();
output.should.equal('4');
});

it('should support slice shorthand (full form) with negative lenght', function () {
const testTemplate = twig({data: '{{ "12345"[2:-1] }}'});
const output = testTemplate.render();
output.should.equal('34');
});

it('should support slice shorthand (full form) with variables as arguments', function () {
const testTemplate = twig({data: '{{ "12345"[start:length] }}'});
const output = testTemplate.render({start: 2, length: 3});
output.should.equal('345');
});

it('should support slice shorthand (full form) with variable as argument (omit first)', function () {
const testTemplate = twig({data: '{{ "12345"[:length] }}'});
const output = testTemplate.render({length: 3});
output.should.equal('123');
});

it('should support slice shorthand (full form) variable as argument (omit last)', function () {
const testTemplate = twig({data: '{{ "12345"[start:] }}'});
const output = testTemplate.render({start: 2});
output.should.equal('345');
});

it('should support slice shorthand (omit first)', function () {
const testTemplate = twig({data: '{{ "12345"[:2] }}'});
const output = testTemplate.render();
Expand Down
4 changes: 4 additions & 0 deletions test/test.filters.js
Original file line number Diff line number Diff line change
Expand Up @@ -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');
Expand Down

0 comments on commit ab8791b

Please sign in to comment.