This commit is contained in:
Jason Davies
2010-11-11 23:28:01 +00:00
3 changed files with 38 additions and 16 deletions
+13 -12
View File
@@ -4,9 +4,9 @@ var Handlebars = {
compile: function(string) {
if (Handlebars.compilerCache[string] == null) {
var fnBody = Handlebars.compileFunctionBody(string);
var fn = new Function("context", "fallback", "Handlebars", fnBody);
var fn = new Function("context", "fallback", "stack", "Handlebars", fnBody);
Handlebars.compilerCache[string] =
function(context, fallback) { return fn(context, fallback, Handlebars); };
function(context, fallback, stack) { return fn(context, fallback, stack, Handlebars); };
}
return Handlebars.compilerCache[string];
@@ -14,14 +14,14 @@ var Handlebars = {
compileToString: function(string) {
var fnBody = Handlebars.compileFunctionBody(string);
return "function(context, fallback) { " + fnBody + "}";
return "function(context, fallback, stack) { " + fnBody + "}";
},
compileFunctionBody: function(string) {
var compiler = new Handlebars.Compiler(string);
compiler.compile();
return "fallback = fallback || {}; var stack = [];" + compiler.fn;
return "fallback = fallback || {}; var stack = stack || [];" + compiler.fn;
},
isFunction: function(fn) {
@@ -85,7 +85,7 @@ var Handlebars = {
context = stack[stack.length - depth];
}
for (var i = 0; i < parts.length && typeof context !== "undefined"; i++) {
for (var i = 0; i < parts.length && typeof context !== "undefined" && context != null ; i++) {
context = context[parts[i]];
}
@@ -118,8 +118,8 @@ var Handlebars = {
parsePath: function(path) {
if (path == null) {
return [0, []];
} else if (Handlebars.pathPatterns[path] != null) {
return Handlebars.pathPatterns[path];
} else if (Handlebars.pathPatterns["hbs-" + path] != null) {
return Handlebars.pathPatterns["hbs-" + path];
}
var parts = path.split("/");
@@ -147,7 +147,7 @@ var Handlebars = {
}
var ret = [depth, dig];
Handlebars.pathPatterns[path] = ret;
Handlebars.pathPatterns["hbs" + path] = ret;
return ret;
},
@@ -387,10 +387,11 @@ Handlebars.Compiler.prototype = {
// don't need to be globally unique, just per compiler
var fnId = "fn" + this.pointer.toString();
this.fn += "var wrappedContext = Handlebars.buildContext(context, stack);";
this.fn += "stack.push(context);";
this.fn += "var " + fnId + " = function(context) {" + result + "}; ";
this.fn += "lookup = " + this.lookupFor(mustache) + "; ";
this.fn += "arg = " + param + ";";
this.fn += "stack.push(context);";
if (compiler.continueInverted) {
var invertedCompiler = this.compileToEndOfBlock(mustache);
this.fn += " var " + fnId + "Not = function(context) { " + invertedCompiler.fn + " };";
@@ -398,7 +399,7 @@ Handlebars.Compiler.prototype = {
else {
this.fn += " var " + fnId + "Not = null;";
}
this.fn += "out = out + Handlebars.handleBlock(lookup, wrappedContext, " + param + ", " + fnId + ", " + fnId + "Not);"
this.fn += "out = out + Handlebars.handleBlock(lookup, wrappedContext, arg, " + fnId + ", " + fnId + "Not);"
this.fn += "stack.pop();";
this.openBlock = false;
@@ -407,7 +408,7 @@ Handlebars.Compiler.prototype = {
addPartial: function(mustache, param) {
// either used a cached copy of the partial or compile a new one
this.fn += "if (typeof fallback['partials'] === 'undefined' || typeof fallback['partials']['" + mustache + "'] === 'undefined') throw new Handlebars.Exception('Attempted to render undefined partial: " + mustache + "');";
this.fn += "out = out + Handlebars.compilePartial(fallback['partials']['" + mustache + "'])(" + param + ", fallback);";
this.fn += "out = out + Handlebars.compilePartial(fallback['partials']['" + mustache + "'])(" + param + ", fallback, stack);";
},
parseMustache: function() {
+25 -4
View File
@@ -209,6 +209,20 @@ test("helper with complex lookup", function() {
shouldCompileTo(string, [hash, fallback], "<a href='/root/goodbye'>Goodbye</a>")
});
test("helper block with complex lookup expression", function() {
var string = "{{#goodbyes}}{{../name}}{{/goodbyes}}"
var hash = {name: "Alan"};
var fallback = {goodbyes: function(context, fn) {
var out = "";
var byes = ["Goodbye", "goodbye", "GOODBYE"];
for (var i = 0,j = byes.length; i < j; i++) {
out += byes[i] + " " + fn(context) + "! ";
}
return out;
}};
shouldCompileTo(string, [hash, fallback], "Goodbye Alan! goodbye Alan! GOODBYE Alan! ");
});
test("helper with complex lookup and nested template", function() {
var string = "{{#goodbyes}}{{#link}}{{text}}{{/link}}{{/goodbyes}}";
var hash = {prefix: '/root', goodbyes: [{text: "Goodbye", url: "goodbye"}]};
@@ -360,10 +374,17 @@ test("rendering undefined partial throws an exception", function() {
});
test("GH-14: a partial preceding a selector", function() {
var string = "Dudes: {{>dude}} {{another_dude}}";
var dude = "{{name}}";
var hash = {name:"Jeepers", another_dude:"Creepers"};
shouldCompileTo(string, [hash, {partials: {dude:dude}}], "Dudes: Jeepers Creepers", "Regular selectors can follow a partial");
var string = "Dudes: {{>dude}} {{another_dude}}";
var dude = "{{name}}";
var hash = {name:"Jeepers", another_dude:"Creepers"};
shouldCompileTo(string, [hash, {partials: {dude:dude}}], "Dudes: Jeepers Creepers", "Regular selectors can follow a partial");
});
test("Partial containing complex expression", function() {
var template = "Dudes: {{#dudes}}{{> dude}} {{/dudes}}";
var dude = "{{../salutation}} {{name}}";
var hash = {salutation: "Mr.", dudes: [{name: "Yehuda"}, {name: "Alan"}]};
shouldCompileTo(template, [hash, {partials: {dude: dude}}], "Dudes: Mr. Yehuda Mr. Alan ");
});
module("safestring");
Executable → Regular
View File