Using this.__get__ inside of functions called as expressions now works.
This commit is contained in:
+31
-9
@@ -2,7 +2,6 @@ Handlebars = {
|
||||
compile: function(string) {
|
||||
var compiler = new Handlebars.Compiler(string);
|
||||
var result = compiler.compile();
|
||||
console.log(result);
|
||||
return new Function("context", "fallback", "fallback = fallback || {}; var stack = [];" + result);
|
||||
},
|
||||
|
||||
@@ -19,11 +18,34 @@ Handlebars.Compiler = function(string) {
|
||||
this.fn = "var out = ''; var lookup; ";
|
||||
this.newlines = "";
|
||||
this.comment = false;
|
||||
}
|
||||
};
|
||||
|
||||
Handlebars.ParseError = function(message) {
|
||||
this.message = message;
|
||||
}
|
||||
};
|
||||
|
||||
Handlebars.Context = function(stack) {
|
||||
this.__stack__ = stack;
|
||||
this.__get__ = function(path) {
|
||||
var context = this;
|
||||
var parsedPath = Handlebars.parsePath(path);
|
||||
var depth = parsedPath[0];
|
||||
var parts = parsedPath[1];
|
||||
if (depth > 0) {
|
||||
context = this.__stack__[stack.length - depth];
|
||||
}
|
||||
|
||||
for (var i = 0; i < parts.length; i++) {
|
||||
context = context[parts[i]];
|
||||
}
|
||||
|
||||
return context;
|
||||
};
|
||||
};
|
||||
Handlebars.buildContext = function(context, stack) {
|
||||
Handlebars.Context.prototype = context;
|
||||
return new Handlebars.Context(stack);
|
||||
};
|
||||
|
||||
// Returns a two element array containing the numbers of contexts to back up the stack and
|
||||
// the properties to dig into on the current context
|
||||
@@ -57,7 +79,7 @@ Handlebars.parsePath = function(path) {
|
||||
}
|
||||
|
||||
return [depth, dig];
|
||||
}
|
||||
};
|
||||
|
||||
Handlebars.helperMissing = function(object, fn) {
|
||||
var ret = "";
|
||||
@@ -120,7 +142,8 @@ Handlebars.Compiler.prototype = {
|
||||
|
||||
addExpression: function(mustache) {
|
||||
var expr = this.lookupFor(mustache);
|
||||
this.fn += "out = out + (Handlebars.isFunction(" + expr + ") ? " + expr + "() : " + expr + "); ";
|
||||
this.fn += "if (Handlebars.isFunction(" + expr + ")) out = out + " + expr + ".call(Handlebars.buildContext(context, stack)); ";
|
||||
this.fn += "else if(typeof " + expr + "!== 'undefined') out = out + " + expr + "; ";
|
||||
},
|
||||
|
||||
lookupFor: function(param) {
|
||||
@@ -186,11 +209,11 @@ Handlebars.Compiler.prototype = {
|
||||
// each function made internally needs a unique IDs. These are locals, so they
|
||||
// don't need to be globally unique, just per compiler
|
||||
var fnId = "fn" + this.pointer.toString();
|
||||
|
||||
this.fn += "var proxy = Handlebars.buildContext(" + param + ", stack);";
|
||||
this.fn += "var " + fnId + " = function(context) {" + result + "}; ";
|
||||
this.fn += "lookup = " + this.lookupFor(mustache) + "; ";
|
||||
this.fn += "if(Handlebars.isFunction(lookup)) out = out + lookup.call(" + param + ", " + fnId + "); ";
|
||||
this.fn += "else if(typeof lookup !== 'undefined') out = out + Handlebars.helperMissing.call(" + param + ", lookup, " + fnId + "); ";
|
||||
this.fn += "if(Handlebars.isFunction(lookup)) out = out + lookup.call(proxy, " + fnId + "); ";
|
||||
this.fn += "else if(typeof lookup !== 'undefined') out = out + Handlebars.helperMissing.call(proxy, lookup, " + fnId + "); ";
|
||||
|
||||
this.fn += "stack.pop();";
|
||||
this.openBlock = false;
|
||||
@@ -207,4 +230,3 @@ Handlebars.Compiler.prototype = {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+18
-1
@@ -88,6 +88,15 @@ test("block with complex lookup", function() {
|
||||
"Templates can access variables in contexts up the stack with relative path syntax");
|
||||
});
|
||||
|
||||
test("helper with complex lookup", function() {
|
||||
var string = "{{#goodbyes}}{{link}}{{/goodbyes}}"
|
||||
var hash = {prefix: "/root", goodbyes: [{text: "Goodbye", url: "goodbye"}]};
|
||||
var fallback = {link: function() {
|
||||
return "<a href='" + this.__get__("../prefix") + "/" + this.url + "'>" + this.text + "</a>"
|
||||
}};
|
||||
shouldCompileTo(string, [hash, fallback], "<a href='/root/goodbye'>Goodbye</a>")
|
||||
});
|
||||
|
||||
test("block with deep nested complex lookup", function() {
|
||||
var string = "{{#outer}}Goodbye {{#inner}}cruel {{../../omg}}{{/inner}}{{/outer}}";
|
||||
var hash = {omg: "OMG!", outer: [{ inner: [{ text: "goodbye" }] }] };
|
||||
@@ -107,7 +116,7 @@ test("block helper staying in the same context", function() {
|
||||
var string = "{{#form}}<p>{{name}}</p>{{/form}}"
|
||||
var template = Handlebars.compile(string);
|
||||
|
||||
result = template({form: function(fn) { return "<form>" + fn(this) + "</form>" }, name: "Yehuda"});
|
||||
result = template({form: function(fn) { console.log(fn); return "<form>" + fn(this) + "</form>" }, name: "Yehuda"});
|
||||
equal(result, "<form><p>Yehuda</p></form>");
|
||||
});
|
||||
|
||||
@@ -119,6 +128,14 @@ test("block helper passing a new context", function() {
|
||||
equal(result, "<form><p>Yehuda</p></form>");
|
||||
});
|
||||
|
||||
test("block helper passing a complex path context", function() {
|
||||
var string = "{{#form yehuda/cat}}<p>{{name}}</p>{{/form}}"
|
||||
var template = Handlebars.compile(string);
|
||||
|
||||
result = template({form: function(fn) { return "<form>" + fn(this) + "</form>" }, yehuda: {name: "Yehuda", cat: {name: "Harold"}}});
|
||||
equal(result, "<form><p>Harold</p></form>");
|
||||
});
|
||||
|
||||
test("nested block helpers", function() {
|
||||
var string = "{{#form yehuda}}<p>{{name}}</p>{{#link}}Hello{{/link}}{{/form}}"
|
||||
var template = Handlebars.compile(string);
|
||||
|
||||
Reference in New Issue
Block a user