diff --git a/lib/handlebars.js b/lib/handlebars.js
index f0d4e943..a96df4cf 100644
--- a/lib/handlebars.js
+++ b/lib/handlebars.js
@@ -25,12 +25,33 @@ Handlebars.print = function(ast) {
Handlebars.compile = function(string) {
var ast = Handlebars.parse(string);
- return function(context, fallback) {
- var runtime = new Handlebars.Runtime(context, fallback);
+ return function(context, helpers, partials) {
+ var helpers, partials;
+
+ if(!helpers) {
+ helpers = this.helpers;
+ }
+
+ if(!partials) {
+ partials = this.partials;
+ }
+
+ var runtime = new Handlebars.Runtime(context, helpers, partials);
runtime.accept(ast);
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)
exports.Handlebars = Handlebars;
diff --git a/lib/handlebars/runtime.js b/lib/handlebars/runtime.js
index 75b9d9ab..b58ba241 100644
--- a/lib/handlebars/runtime.js
+++ b/lib/handlebars/runtime.js
@@ -19,9 +19,10 @@ Handlebars.Exception = require("handlebars/utils").Exception;
// new Context given a path. For instance, if the data
// is { person: { name: "Alan" } }, a Context wrapping
// "Alan" can be extracted by searching for "person/name"
-Handlebars.Context = function(data, fallback) {
+Handlebars.Context = function(data, helpers, partials) {
this.data = data;
- this.fallback = fallback;
+ this.helpers = helpers || {};
+ this.partials = partials || {};
};
Handlebars.Context.prototype = {
@@ -29,7 +30,7 @@ Handlebars.Context.prototype = {
// Make a shallow copy of the Context
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
@@ -54,7 +55,7 @@ Handlebars.Context.prototype = {
}
if(parts.length === 1 && context.data === undefined) {
- context.data = context.fallback[parts[0]];
+ context.data = context.helpers[parts[0]];
}
return context;
@@ -69,18 +70,14 @@ Handlebars.proxy = function(obj) {
return new Proxy();
};
-Handlebars.Runtime = function(context, fallback, stack) {
+Handlebars.Runtime = function(context, helpers, partials, stack) {
this.stack = stack || [];
this.buffer = "";
- var newContext = this.context = new Handlebars.Context();
-
if(context && context.isContext) {
- newContext.data = context.data;
- newContext.fallback = context.fallback;
+ this.context = context.clone();
} else {
- newContext.data = context;
- newContext.fallback = fallback || {};
+ this.context = new Handlebars.Context(context, helpers, partials)
}
};
@@ -139,7 +136,7 @@ Handlebars.Runtime.prototype = {
if(toString.call(data) !== "[object Function]") {
params = [data];
- data = this.context.fallback.helperMissing;
+ data = this.context.helpers.helperMissing;
} else {
params = this.evaluateParams(mustache.params);
}
@@ -157,7 +154,7 @@ Handlebars.Runtime.prototype = {
},
partial: function(partial) {
- var partials = this.context.fallback.partials || {};
+ var partials = this.context.partials || {};
var id = partial.id.original;
var partialBody = partials[partial.id.original];
@@ -179,7 +176,7 @@ Handlebars.Runtime.prototype = {
} else {
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);
},
@@ -252,13 +249,16 @@ Handlebars.Runtime.prototype = {
},
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);
- var fallback = this.context.fallback;
return function(context) {
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);
return runtime.buffer;
};
diff --git a/spec/qunit_spec.js b/spec/qunit_spec.js
index d1c74a97..4b652a9f 100644
--- a/spec/qunit_spec.js
+++ b/spec/qunit_spec.js
@@ -378,7 +378,7 @@ test("basic partials", function() {
var string = "Dudes: {{#dudes}}{{> dude}}{{/dudes}}";
var partial = "{{name}} ({{url}}) ";
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.");
});
@@ -386,7 +386,7 @@ test("partials with context", function() {
var string = "Dudes: {{>dude dudes}}";
var partial = "{{#this}}{{name}} ({{url}}) {{/this}}";
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");
});
@@ -395,7 +395,7 @@ test("partial in a partial", function() {
var dude = "{{name}} {{> url}} ";
var url = "{{url}}";
var hash = {dudes: [{name: "Yehuda", url: "http://yehuda"}, {name: "Alan", url: "http://alan"}]};
- shouldCompileTo(string, [hash, {partials: {dude: dude, url: url}}], "Dudes: Yehuda http://yehuda Alan http://alan ", "Partials are rendered inside of other partials");
+ shouldCompileTo(string, [hash, {}, {dude: dude, url: url}], "Dudes: Yehuda http://yehuda Alan http://alan ", "Partials are rendered inside of other partials");
});
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 dude = "{{name}}";
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() {
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 ");
+ shouldCompileTo(template, [hash, {}, {dude: dude}], "Dudes: Mr. Yehuda Mr. Alan ");
});
module("String literal parameters");