Permalink
Browse files

really poorly written {% else if ... %}

  • Loading branch information...
1 parent fcc569c commit 988b87f1e2c2cbd3116c732bd97a197a179fb6f4 @paularmstrong committed Sep 16, 2011
Showing with 65 additions and 33 deletions.
  1. +56 −33 lib/tags.js
  2. +9 −0 tests/tags.test.js
View
@@ -47,60 +47,49 @@ exports.include = function (indent) {
, '})();'].join('\n' + indent);
};
-
-/**
-* This is the 'if' tag compiler
-* Example 'If' tag syntax:
-* {% if x %}
-* <p>{{x}}</p>
-* {% endif %}
-*
-* {% if !x %}
-* <p>No x found</p>
-* {% else %}
-* <p>{{x}}</p>
-* {% endif %}
-*
-* {% if x == y %}, {% if x < y %}, {% if x in y %}, {% if x != y %}
-*/
-exports['if'] = function (indent) {
- var operand1 = this.args[0],
- operator = this.args[1],
- operand2 = this.args[2],
- negation = false,
- out;
-
- indent = indent || '';
+function checkIfArgs(leftOperand, operator, rightOperand) {
+ var negation = false;
// Check if there is negation
- if (operand1[0] === '!') {
+ if (leftOperand[0] === '!') {
negation = true;
- operand1 = operand1.substr(1);
+ leftOperand = leftOperand.substr(1);
}
+
// '!something == else' - this syntax is forbidden. Use 'something != else' instead
if (negation && operator) {
throw new Error('Invalid syntax for "if" tag');
}
// Check for valid argument
- operand1 = parser.parseVariable(operand1);
- if (!helpers.isLiteral(operand1.name) && !helpers.isValidName(operand1.name)) {
- throw new Error('Invalid arguments (' + operand1.name + ') passed to "if" tag');
+ if (!helpers.isLiteral(leftOperand.name) && !helpers.isValidName(leftOperand.name)) {
+ throw new Error('Invalid arguments (' + leftOperand.name + ') passed to "if" tag');
}
// Check for valid operator
if (operator && ['==', '<', '>', '!=', '<=', '>=', '===', '!==', 'in'].indexOf(operator) === -1) {
throw new Error('Invalid operator (' + operator + ') passed to "if" tag');
}
// Check for presence of operand 2 if operator is present
- if (operator && typeof operand2 === 'undefined') {
+ if (operator && !rightOperand) {
throw new Error('Missing argument in "if" tag');
}
// Check for valid argument
- operand2 = parser.parseVariable(operand2);
- if (operator && !helpers.isLiteral(operand2.name) && !helpers.isValidName(operand2.name)) {
- throw new Error('Invalid arguments (' + operand2.name + ') passed to "if" tag');
+ if (operator && !helpers.isLiteral(rightOperand.name) && !helpers.isValidName(rightOperand.name)) {
+ throw new Error('Invalid arguments (' + rightOperand.name + ') passed to "if" tag');
}
+ return negation;
+}
+
+exports['if'] = function (indent) {
+ var operand1 = parser.parseVariable(this.args[0]),
+ operator = this.args[1],
+ operand2 = parser.parseVariable(this.args[2]),
+ negation = checkIfArgs(operand1, operator, operand2),
+ out;
+
+ indent = indent || '';
+
out = ['(function () {'];
out.push(helpers.setVar('__op1', operand1));
if (operand2.name === '') {
@@ -135,6 +124,40 @@ exports.else = function (indent) {
if (_.last(this.parent).name !== 'if') {
throw new Error('Cannot call else tag outside of "if" context.');
}
+
+ var ifarg = this.args.shift(),
+ operand1, operator, operand2, negation, out;
+
+ if (ifarg) {
+ operand1 = parser.parseVariable(this.args[0]);
+ operator = this.args[1];
+ operand2 = parser.parseVariable(this.args[2]);
+ negation = checkIfArgs(operand1, operator, operand2);
+ out = [];
+
+ if (operand2.name === '') {
+ out.push('} else if (' + (negation ? '!' : '!!') + '__op1) {');
+ out.push(parser.compile.call(this, indent + ' '));
+ out.push('}');
+ } else {
+ out.push(helpers.setVar('__op2', operand2));
+
+ if (typeof operator !== 'undefined') {
+ if (operator === 'in') {
+ out.push('} else if (');
+ out.push(' (Array.isArray(__op2) && __op2.indexOf(__op1) > -1) ||');
+ out.push(' (typeof __op2 === "string" && __op2.indexOf(__op1) > -1) ||');
+ out.push(' (!Array.isArray(__op2) && typeof __op2 === "object" && __op1 in __op2)');
+ out.push(') {');
+ } else {
+ out.push('} else if (__op1 ' + helpers.escape(operator) + ' __op2) {');
+ }
+ }
+ }
+
+ return out.join('\n', indent);
+ }
+
return indent + '} else {';
};
View
@@ -45,6 +45,15 @@ exports.if = testCase({
swig.fromString('{% for i in foo %}hi!{% else %}nope{% endfor %}');
}, Error, 'Cannot call else tag outside of "if" context.');
test.done();
+ },
+
+ 'else if': function (test) {
+ var tmpl8 = swig.fromString('{% if foo|length > 2 %}foo{% else if foo|length < 2 %}bar{% endif %}');
+ test.strictEqual(tmpl8.render({ foo: [1, 2, 3] }), 'foo');
+ test.strictEqual(tmpl8.render({ foo: [1, 2] }), '');
+ test.strictEqual(tmpl8.render({ foo: [1] }), 'bar');
+
+ test.done();
}
});

0 comments on commit 988b87f

Please sign in to comment.