Make it possible to register helpers and partials and then skip passing in the helpers or partials later

This commit is contained in:
wycats
2010-12-11 18:10:56 -08:00
parent fdc8e425d0
commit 5097c18912
3 changed files with 45 additions and 24 deletions
+23 -2
View File
@@ -25,12 +25,33 @@ Handlebars.print = function(ast) {
Handlebars.compile = function(string) { Handlebars.compile = function(string) {
var ast = Handlebars.parse(string); var ast = Handlebars.parse(string);
return function(context, fallback) { return function(context, helpers, partials) {
var runtime = new Handlebars.Runtime(context, fallback); var helpers, partials;
if(!helpers) {
helpers = this.helpers;
}
if(!partials) {
partials = this.partials;
}
var runtime = new Handlebars.Runtime(context, helpers, partials);
runtime.accept(ast); runtime.accept(ast);
return runtime.buffer; return runtime.buffer;
}; };
}; };
Handlebars.helpers = {};
Handlebars.partials = {};
Handlebars.registerHelper = function(name, fn) {
this.helpers[name] = fn;
};
Handlebars.registerPartial = function(name, str) {
this.partials[name] = str;
};
// END(BROWSER) // END(BROWSER)
exports.Handlebars = Handlebars; exports.Handlebars = Handlebars;
+17 -17
View File
@@ -19,9 +19,10 @@ Handlebars.Exception = require("handlebars/utils").Exception;
// new Context given a path. For instance, if the data // new Context given a path. For instance, if the data
// is { person: { name: "Alan" } }, a Context wrapping // is { person: { name: "Alan" } }, a Context wrapping
// "Alan" can be extracted by searching for "person/name" // "Alan" can be extracted by searching for "person/name"
Handlebars.Context = function(data, fallback) { Handlebars.Context = function(data, helpers, partials) {
this.data = data; this.data = data;
this.fallback = fallback; this.helpers = helpers || {};
this.partials = partials || {};
}; };
Handlebars.Context.prototype = { Handlebars.Context.prototype = {
@@ -29,7 +30,7 @@ Handlebars.Context.prototype = {
// Make a shallow copy of the Context // Make a shallow copy of the Context
clone: function() { clone: function() {
return new Handlebars.Context(this.data, this.fallback); return new Handlebars.Context(this.data, this.helpers, this.partials);
}, },
// Search for an object inside the Context's data. The // Search for an object inside the Context's data. The
@@ -54,7 +55,7 @@ Handlebars.Context.prototype = {
} }
if(parts.length === 1 && context.data === undefined) { if(parts.length === 1 && context.data === undefined) {
context.data = context.fallback[parts[0]]; context.data = context.helpers[parts[0]];
} }
return context; return context;
@@ -69,18 +70,14 @@ Handlebars.proxy = function(obj) {
return new Proxy(); return new Proxy();
}; };
Handlebars.Runtime = function(context, fallback, stack) { Handlebars.Runtime = function(context, helpers, partials, stack) {
this.stack = stack || []; this.stack = stack || [];
this.buffer = ""; this.buffer = "";
var newContext = this.context = new Handlebars.Context();
if(context && context.isContext) { if(context && context.isContext) {
newContext.data = context.data; this.context = context.clone();
newContext.fallback = context.fallback;
} else { } else {
newContext.data = context; this.context = new Handlebars.Context(context, helpers, partials)
newContext.fallback = fallback || {};
} }
}; };
@@ -139,7 +136,7 @@ Handlebars.Runtime.prototype = {
if(toString.call(data) !== "[object Function]") { if(toString.call(data) !== "[object Function]") {
params = [data]; params = [data];
data = this.context.fallback.helperMissing; data = this.context.helpers.helperMissing;
} else { } else {
params = this.evaluateParams(mustache.params); params = this.evaluateParams(mustache.params);
} }
@@ -157,7 +154,7 @@ Handlebars.Runtime.prototype = {
}, },
partial: function(partial) { partial: function(partial) {
var partials = this.context.fallback.partials || {}; var partials = this.context.partials || {};
var id = partial.id.original; var id = partial.id.original;
var partialBody = partials[partial.id.original]; var partialBody = partials[partial.id.original];
@@ -179,7 +176,7 @@ Handlebars.Runtime.prototype = {
} else { } else {
context = this.context; context = this.context;
} }
var runtime = new Handlebars.Runtime(context, this.context.fallback, this.stack.slice(0)); var runtime = new Handlebars.Runtime(context, null, null, this.stack.slice(0));
this.buffer = this.buffer + runtime.program(program); this.buffer = this.buffer + runtime.program(program);
}, },
@@ -252,13 +249,16 @@ Handlebars.Runtime.prototype = {
}, },
wrapProgram: function(program) { wrapProgram: function(program) {
var runtime = this, stack = this.stack.slice(0); var runtime = this,
stack = this.stack.slice(0),
helpers = this.context.helpers,
partials = this.context.partials;
stack.push(this.context); stack.push(this.context);
var fallback = this.context.fallback;
return function(context) { return function(context) {
if(context && context.isWrappedContext) { context = context.__data__; } if(context && context.isWrappedContext) { context = context.__data__; }
var runtime = new Handlebars.Runtime(context, fallback, stack); var runtime = new Handlebars.Runtime(context, helpers, partials, stack);
runtime.program(program); runtime.program(program);
return runtime.buffer; return runtime.buffer;
}; };
+5 -5
View File
@@ -378,7 +378,7 @@ test("basic partials", function() {
var string = "Dudes: {{#dudes}}{{> dude}}{{/dudes}}"; var string = "Dudes: {{#dudes}}{{> dude}}{{/dudes}}";
var partial = "{{name}} ({{url}}) "; var partial = "{{name}} ({{url}}) ";
var hash = {dudes: [{name: "Yehuda", url: "http://yehuda"}, {name: "Alan", url: "http://alan"}]}; var hash = {dudes: [{name: "Yehuda", url: "http://yehuda"}, {name: "Alan", url: "http://alan"}]};
shouldCompileTo(string, [hash, {partials: {dude: partial}}], "Dudes: Yehuda (http://yehuda) Alan (http://alan) ", shouldCompileTo(string, [hash, {}, {dude: partial}], "Dudes: Yehuda (http://yehuda) Alan (http://alan) ",
"Basic partials output based on current context."); "Basic partials output based on current context.");
}); });
@@ -386,7 +386,7 @@ test("partials with context", function() {
var string = "Dudes: {{>dude dudes}}"; var string = "Dudes: {{>dude dudes}}";
var partial = "{{#this}}{{name}} ({{url}}) {{/this}}"; var partial = "{{#this}}{{name}} ({{url}}) {{/this}}";
var hash = {dudes: [{name: "Yehuda", url: "http://yehuda"}, {name: "Alan", url: "http://alan"}]}; var hash = {dudes: [{name: "Yehuda", url: "http://yehuda"}, {name: "Alan", url: "http://alan"}]};
shouldCompileTo(string, [hash, {partials: {dude: partial}}], "Dudes: Yehuda (http://yehuda) Alan (http://alan) ", shouldCompileTo(string, [hash, {}, {dude: partial}], "Dudes: Yehuda (http://yehuda) Alan (http://alan) ",
"Partials can be passed a context"); "Partials can be passed a context");
}); });
@@ -395,7 +395,7 @@ test("partial in a partial", function() {
var dude = "{{name}} {{> url}} "; var dude = "{{name}} {{> url}} ";
var url = "<a href='{{url}}'>{{url}}</a>"; var url = "<a href='{{url}}'>{{url}}</a>";
var hash = {dudes: [{name: "Yehuda", url: "http://yehuda"}, {name: "Alan", url: "http://alan"}]}; var hash = {dudes: [{name: "Yehuda", url: "http://yehuda"}, {name: "Alan", url: "http://alan"}]};
shouldCompileTo(string, [hash, {partials: {dude: dude, url: url}}], "Dudes: Yehuda <a href='http://yehuda'>http://yehuda</a> Alan <a href='http://alan'>http://alan</a> ", "Partials are rendered inside of other partials"); shouldCompileTo(string, [hash, {}, {dude: dude, url: url}], "Dudes: Yehuda <a href='http://yehuda'>http://yehuda</a> Alan <a href='http://alan'>http://alan</a> ", "Partials are rendered inside of other partials");
}); });
test("rendering undefined partial throws an exception", function() { test("rendering undefined partial throws an exception", function() {
@@ -409,14 +409,14 @@ test("GH-14: a partial preceding a selector", function() {
var string = "Dudes: {{>dude}} {{another_dude}}"; var string = "Dudes: {{>dude}} {{another_dude}}";
var dude = "{{name}}"; var dude = "{{name}}";
var hash = {name:"Jeepers", another_dude:"Creepers"}; var hash = {name:"Jeepers", another_dude:"Creepers"};
shouldCompileTo(string, [hash, {partials: {dude:dude}}], "Dudes: Jeepers Creepers", "Regular selectors can follow a partial"); shouldCompileTo(string, [hash, {}, {dude:dude}], "Dudes: Jeepers Creepers", "Regular selectors can follow a partial");
}); });
test("Partial containing complex expression", function() { test("Partial containing complex expression", function() {
var template = "Dudes: {{#dudes}}{{> dude}} {{/dudes}}"; var template = "Dudes: {{#dudes}}{{> dude}} {{/dudes}}";
var dude = "{{../salutation}} {{name}}"; var dude = "{{../salutation}} {{name}}";
var hash = {salutation: "Mr.", dudes: [{name: "Yehuda"}, {name: "Alan"}]}; var hash = {salutation: "Mr.", dudes: [{name: "Yehuda"}, {name: "Alan"}]};
shouldCompileTo(template, [hash, {partials: {dude: dude}}], "Dudes: Mr. Yehuda Mr. Alan "); shouldCompileTo(template, [hash, {}, {dude: dude}], "Dudes: Mr. Yehuda Mr. Alan ");
}); });
module("String literal parameters"); module("String literal parameters");