Make it possible for helpers to let downstream helpers know what the path to the current object is

This commit is contained in:
wycats
2010-11-17 18:34:37 -08:00
parent 766497bb55
commit 71dffd95c7
2 changed files with 42 additions and 9 deletions
+15 -8
View File
@@ -183,7 +183,7 @@ var Handlebars = {
}
},
handleBlock: function(lookup, context, arg, fn, notFn) {
handleBlock: function(lookup, context, arg, fn, notFn, name) {
var out = "", args;
originalArgs = arg.length ? arg : [null]
@@ -199,11 +199,11 @@ var Handlebars = {
else {
if (!Handlebars.isEmpty(lookup)) {
// TODO: which case is this, and what does it mean for multiple args
out = out + Handlebars.helperMissing.call(arg[0], lookup, fn);
out = out + Handlebars.helperMissing.call(arg[0], lookup, fn, name);
}
if (notFn != null) {
out = out + Handlebars.helperMissing.not.call(arg[0], lookup, notFn);
out = out + Handlebars.helperMissing.not.call(arg[0], lookup, notFn, name);
}
}
@@ -260,7 +260,7 @@ Handlebars.SafeString.prototype.toString = function() {
return this.string.toString();
}
Handlebars.helperMissing = function(object, fn) {
Handlebars.helperMissing = function(object, fn, name) {
var ret = "";
if(object === true) {
@@ -273,10 +273,17 @@ Handlebars.helperMissing = function(object, fn) {
}
return ret;
} else {
return fn(object);
var ContextWrapper = function(parent) {
this.__path__ = parent.__path__ ? parent.__path__.concat(name) : [name];
};
ContextWrapper.prototype = object;
var proxy = new ContextWrapper(this);
return fn(proxy);
}
};
Handlebars.helperMissing.not = function(context, fn) {
Handlebars.helperMissing.not = function(context, fn, name) {
return fn(context);
}
@@ -404,7 +411,7 @@ Handlebars.Compiler.prototype = {
this.fn += "var " + fnId + " = function(context) {" + result + "}; ";
this.fn += "lookup = " + this.lookupFor(mustache) + "; ";
this.fn += "arg = [" + params.join(", ") + "] ;";
this.fn += "stack.push(context);";
this.fn += "stack.push(context); ";
if (compiler.continueInverted) {
var invertedCompiler = this.compileToEndOfBlock(mustache);
@@ -413,7 +420,7 @@ Handlebars.Compiler.prototype = {
else {
this.fn += " var " + fnId + "Not = null;";
}
this.fn += "out = out + Handlebars.handleBlock(lookup, wrappedContext, arg, " + fnId + ", " + fnId + "Not);"
this.fn += "out = out + Handlebars.handleBlock(lookup, wrappedContext, arg, " + fnId + ", " + fnId + "Not, '" + mustache + "');"
this.fn += "stack.pop();";
this.openBlock = false;
+27 -1
View File
@@ -89,6 +89,32 @@ test("functions with context argument", function() {
"Frank", "functions are called with context arguments");
});
test("functions receive the current path as part of the 'this'", function() {
template = "Hello {{#person}}{{show name}}{{/person}}"
object = { person: { name: "Alan" } };
fallback = {
show: function(context) {
return context + " (from " + this.__path__.join("/") + ")";
}
}
shouldCompileTo(template, [object, fallback], "Hello Alan (from person)")
});
test("block helpers don't mess with the path receive the current path as part of the 'this'", function() {
template = "Hello {{#block}}{{#person}}{{#info}}{{show name}}{{/info}}{{/person}}{{/block}}. {{show other/name}}"
object = { person: { info: { name: "Alan" } }, other: { name: "Yehuda" } };
fallback = {
show: function(context) {
var ret = context;
if(this.__path__) ret += " (from " + this.__path__.join("/") + ")";
return ret;
}, block: function(context, fn) {
return fn(this);
}
}
shouldCompileTo(template, [object, fallback], "Hello Alan (from person/info). Yehuda")
});
test("nested paths", function() {
shouldCompileTo("Goodbye {{alan/expression}} world!", {alan: {expression: "beautiful"}},
"Goodbye beautiful world!", "Nested paths access nested objects");
@@ -432,7 +458,7 @@ test("block multi-params work", function() {
return fn({greeting: "Goodbye", adj: "cruel", noun: "world"});
}}
shouldCompileTo(string, [hash, fallback], "Message: Goodbye cruel world", "block helpers with multiple params");
})
});
module("safestring");