/** * Normal Template */ var TOKEN_RE = new RegExp("(\{[\=\:\#\/].+?\})"), COMMAND_RE = new RegExp("^\{[\:\/\=]"); var xpath = function (path) { if (path === '$last') { return "$last"; } if (/\||;|\$|~/.test(path)) { throw new Error("Invalid characters in path '" + path + "'"); } path = path.replace(/\//g, ".").replace(/'|"/, ""); if (path == ".") { return "d"; } else if (/^\./.test(path)) { return "data" + path; } else { return "d." + path; } } /** * Template filters. Add your own to this dictionary. */ exports.filters = { str: function (val) { // used to override default filtering. return val.toString(); }, strip: function (val) { return val.toString().replace(/<([^>]+)>/g, ""); }, html: function (val) { return val.toString().replace(/&/g, "&").replace(/>/g, ">"). replace(//g, ">"). replace(/ 0)) '); stack.unshift("a" + depth + "[i" + depth + "]"); code.push('for (var i' + depth + ' = 0,l' + depth + ' = a' + depth + '.length; i' + depth + ' < l' + depth + '; i' + depth + '++) {$last = (i' + depth + ' == l' + depth + '-1); d = a' + depth + '[i' + depth + '];'); continue; case "else": case "e": 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 '{' code.push('res.push("{");'); continue; case "rb": // output right curly bracket '}' code.push('res.push("}");'); continue; case "!": // comment continue; } } else if (token[1] == "/") { // close tag if (token[2] == ":") { var cmd = token.substring(3, token.length-1).split(" ")[0]; switch (cmd) { case "if": 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": 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": tag = nesting.pop(); if (tag == "reduce") { stack.shift(); code.push('}; $last = false; d = ' + stack[0] + ';'); } else { throw new Error("Unbalanced 'reduce' close tag" + (tag ? ", expecting '" + tag + "' close tag" : "")); } continue; } } } else if (token[1] == "=") { // interpolation var parts = token.substring(2, token.length-1).split(" "), pre = "", post = ""; for (var j = 0; j < parts.length-1; j++) { pre += "filters." + parts[j] + "("; post += ")"; } if (pre == "") { if (filters.defaultfilter) { pre = "df("; post = ")"; } } code.push('v = ' + xpath(parts[j]) + ';if (v != undefined) res.push(' + pre + 'v' + post +');'); continue; } } // plain text code.push('res.push("' + token.replace(/\\/g, "\\\\").replace(/\r/g, "").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("")); return function (data) { return func(data, filters) }; }