Skip to content
This repository has been archived by the owner on Apr 11, 2018. It is now read-only.

Commit

Permalink
Allow set tag to use bracket notation for object properties
Browse files Browse the repository at this point in the history
  • Loading branch information
hegemonic committed Jan 10, 2014
1 parent 09f7e24 commit dcc9de6
Show file tree
Hide file tree
Showing 2 changed files with 70 additions and 10 deletions.
59 changes: 51 additions & 8 deletions lib/tags/set.js
Expand Up @@ -14,6 +14,13 @@
* {% set bar += index|default(3) %}
* // => 3
*
* @example
* // foods = {};
* // food = 'chili';
* {% set foods[food] = "con queso" %}
* {{ foods.chili }}
* // => con queso
*
* @param {literal} varname The variable name to assign the value to.
* @param {literal} assignement Any valid JavaScript assignement. <code data-language="js">=, +=, *=, /=, -=</code>
* @param {*} value Valid variable output.
Expand All @@ -23,25 +30,61 @@ exports.compile = function (compiler, args) {
};

exports.parse = function (str, line, parser, types) {
var nameSet;
var nameSet = '',
propertyName = '';

parser.on(types.VAR, function (token) {
if (!this.out.length) {
nameSet = token.match;
this.out.push(
// Prevent the set from spilling into global scope
'_ctx.' + nameSet
);
if (propertyName) {
// Tell the parser where to find the variable
propertyName += '_ctx.' + token.match;
return;
}

if (!parser.out.length) {
nameSet += token.match;
return;
}

return true;
});

parser.on(types.BRACKETOPEN, function (token) {
if (!propertyName && !this.out.length) {
propertyName = token.match;
return;
}

return true;
});

parser.on(types.STRING, function (token) {
if (propertyName && !this.out.length) {
propertyName += token.match;
return;
}

return true;
});

parser.on(types.BRACKETCLOSE, function (token) {
if (propertyName && !this.out.length) {
nameSet += propertyName + token.match;
propertyName = '';
return;
}

return true;
});

parser.on(types.ASSIGNMENT, function (token) {
if (this.out.length !== 1 || !nameSet) {
if (this.out.length || !nameSet) {
throw new Error('Unexpected assignment "' + token.match + '" on line ' + line + '.');
}

this.out.push(
// Prevent the set from spilling into global scope
'_ctx.' + nameSet
);
this.out.push(token.match);
});

Expand Down
21 changes: 19 additions & 2 deletions tests/tags/set.test.js
Expand Up @@ -3,7 +3,17 @@ var swig = require('../../lib/swig'),
_ = require('lodash'),
Swig = swig.Swig;

var cases = [
var leftCases = [
'foo[bar]',
'foo[\'bar\']',
'foo["bar"]',
'foo[\'bar.baz\']',
'foo["bar.baz"]',
'foo[\'bar=baz\']',
'foo["bar=baz"]'
];

var rightCases = [
{ code: '= 1', result: '1' },
{ code: '= "burritos"', result: 'burritos' },
{ code: '= 1 + 3', result: '4' },
Expand All @@ -18,7 +28,14 @@ var cases = [

describe('Tag: set', function () {

_.each(cases, function (c) {
_.each(leftCases, function (c) {
var s = '{% set bar = "bar" %}{% set ' + c + ' = "con queso" %}';
it(s, function () {
expect(swig.render(s + '{{ ' + c + ' }}', { locals: { foo: {} }})).to.equal('con queso');
});
});

_.each(rightCases, function (c) {
var s = '{% set foo ' + c.code + ' %}';
it(s, function () {
expect(swig.render(s + '{{ foo }}', { locals: { foo: 1 }})).to.equal(c.result);
Expand Down

0 comments on commit dcc9de6

Please sign in to comment.