Skip to content
This repository has been archived by the owner on Aug 14, 2023. It is now read-only.

Commit

Permalink
Added checks for syntax errors (unbalanced tags, not closed tags)
Browse files Browse the repository at this point in the history
  • Loading branch information
gmosx committed Jan 25, 2010
1 parent 82e9122 commit a3683ae
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 19 deletions.
49 changes: 38 additions & 11 deletions lib/normal-template.js
Expand Up @@ -42,9 +42,10 @@ exports.compile = function(src, options) {
// v = curent value, d = cursor, a = reduced array, df = default filter, res = result
var code = ['var v,a,d = data,res = [];'],
stack = ["data"],
nesting = [],
tokens = src.split(TOKEN_RE);

var filters;
var filters, tag;

if (options && options.filters) {
filters = {};
Expand Down Expand Up @@ -72,19 +73,22 @@ exports.compile = function(src, options) {

switch (cmd) {
case "if":
nesting.push("if");
val = xpath(arg);
code.push('if (' + val + ' != undefined) {');
continue;

case "select":
case "s":
nesting.push("select");
val = xpath(arg);
code.push('d = ' + val + ';if (d != undefined) {');
stack.unshift(val.replace(/^d\./, stack[0] + "."));
continue;

case "reduce":
case "r":
nesting.push("reduce");
val = xpath(arg);
var depth = stack.length;
code.push('var a' + depth + ' = ' + val + ';if ((a' + depth + ' != undefined) && (a' + depth + '.length > 0)) ');
Expand All @@ -94,16 +98,20 @@ exports.compile = function(src, options) {

case "else":
case "e":
code.push('} else {');
tag = nesting.pop();
if (tag) {
code.push('} else {');
nesting.push(tag);
} else {
throw new Error("Unbalanced 'else' tag");
}
continue;

case "lb": // output left curly bracket '{'
case "lcb":
code.push('res.push("{");');
continue;

case "rb": // output right curly bracket '}'
case "rcb":
code.push('res.push("}");');
continue;

Expand All @@ -113,23 +121,37 @@ exports.compile = function(src, options) {
} else if (token[1] == "/") { // close tag
if (token[2] == ":") {
var cmd = token.substring(3, token.length-1).split(" ")[0];

switch (cmd) {
case "if":
code.push('};');
tag = nesting.pop();
if (tag == "if") {
code.push('};');
} else {
throw new Error("Unbalanced 'if' close tag" + (tag ? ", expecting '" + tag + "' close tag" : ""));
}
continue;

case "select":
case "s":
stack.shift();
code.push('};d = ' + stack[0] + ';');
tag = nesting.pop();
if (tag == "select") {
stack.shift();
code.push('};d = ' + stack[0] + ';');
} else {
throw new Error("Unbalanced 'select' close tag" + (tag ? ", expecting '" + tag + "' close tag" : ""));
}
continue;

case "reduce":
case "r":
var depth = stack.length;
stack.shift();
code.push('};d = ' + stack[0] + ';');
tag = nesting.pop();
if (tag == "reduce") {
stack.shift();
code.push('};d = ' + stack[0] + ';');
} else {
throw new Error("Unbalanced 'reduce' close tag" + (tag ? ", expecting '" + tag + "' close tag" : ""));
}
continue;
}
}
Expand All @@ -153,6 +175,11 @@ exports.compile = function(src, options) {
code.push('res.push("' + token.replace(/\n/g, "\\n").replace(/"/g, '\\"') + '");');
}

tag = nesting.pop();
if (tag) {
throw new Error("Unbalanced '" + tag + "' tag, is not closed");
}

code.push('return res.join("");');

var func = new Function("data", "filters", code.join(""));
Expand Down
2 changes: 1 addition & 1 deletion tests/all-tests.js
@@ -1,5 +1,5 @@
exports.testNormalTemplate = require("./normal-template-tests");
exports.testNormalTPP = require("./normal-template/tpp-tests");

if (require.main === module.id)
if (require.main == module.id)
require("os").exit(require("test/runner").run(exports));
34 changes: 27 additions & 7 deletions tests/normal-template-tests.js
Expand Up @@ -15,7 +15,7 @@ exports.testComments = function() {
assert.isEqual("Hello Stella", t(data));
}

exports.testWith = function() {
exports.testSelect = function() {
var t = compile("Hello {:select user}{=name}, {=age}{/:select}");
var data = {user: {name: "George", age: "34"}};
assert.isEqual("Hello George, 34", t(data));
Expand Down Expand Up @@ -57,7 +57,7 @@ exports.testIfElse = function() {
assert.isEqual("cool this is outer", t(data));
}

exports.testWithOr = function() {
exports.testSelectElse = function() {
var t = compile("{:s cool}cool{:e}not cool{/:s}");
var data = {};
assert.isEqual("not cool", t(data));
Expand All @@ -76,13 +76,13 @@ exports.testInterpolateNone = function() {
}

exports.testDot = function() {
var t = compile("{:s cool}{=.}{:s}not cool{/:s}");
var t = compile("{:s cool}{=.}{:e}not cool{/:s}");
var data = {cool: 34};
assert.isEqual("34", t(data));
}

exports.testReduceOr = function() {
var t = compile('{:r articles}<li>{=title}: {=content}</li>{:or}no articles{/:r}');
exports.testReduceElse = function() {
var t = compile('{:r articles}<li>{=title}: {=content}</li>{:e}no articles{/:r}');
var data = {articles: [
{title: "Hello1", content: "World1"},
{title: "Hello2", content: "World2"},
Expand All @@ -98,7 +98,7 @@ exports.testReduceOr = function() {
}

// stupid, but lets test this.
exports.testWithReduceOr = function() {
exports.testSelectReduceElse = function() {
var t = compile("{:s articles}{:r .}<li>{=title}: {=content}</li>{/:r}{:e}no articles{/:s}");
var data = {articles: [
{title: "Hello1", content: "World1"},
Expand Down Expand Up @@ -153,7 +153,27 @@ exports.testQuotesEscaping = function() {
}

exports.testCurlyBrackets = function() {
var t = compile('enclose in {:lcb}brackets{:rcb}');
var t = compile('enclose in {:lb}brackets{:rb}');
var data = {};
assert.isEqual('enclose in {brackets}', t(data));
}

exports.testSyntaxErrors = function() {
try {
compile("{/:s articles}articles")
} catch (e) {
assert.isEqual("Error: Unbalanced 'select' close tag", e.toString());
}

try {
compile("{:if user}{:s articles}articles{/:if}")
} catch (e) {
assert.isEqual("Error: Unbalanced 'if' close tag, expecting 'select' close tag", e.toString());
}

try {
compile("{:if user}{:s articles}articles")
} catch (e) {
assert.isEqual("Error: Unbalanced 'select' tag, is not closed", e.toString());
}
}

0 comments on commit a3683ae

Please sign in to comment.