summaryrefslogtreecommitdiffstats
path: root/lib/handlebars/runtime.js
diff options
context:
space:
mode:
authorwycats <wycats@gmail.com>2010-11-26 23:45:38 -0800
committerwycats <wycats@gmail.com>2010-11-26 23:45:38 -0800
commit454d0a85b7333fb6675e759ae1259a0e5dc6c6b7 (patch)
tree19518ae78ffc5d5b4cc306efe240948603ae5e98 /lib/handlebars/runtime.js
parent3b0970d8aa969c79b19fa737dc990ce7c62699d2 (diff)
downloadhandlebars.js-454d0a85b7333fb6675e759ae1259a0e5dc6c6b7.zip
handlebars.js-454d0a85b7333fb6675e759ae1259a0e5dc6c6b7.tar.gz
handlebars.js-454d0a85b7333fb6675e759ae1259a0e5dc6c6b7.tar.bz2
Add initial support for blocks
Diffstat (limited to 'lib/handlebars/runtime.js')
-rw-r--r--lib/handlebars/runtime.js66
1 files changed, 63 insertions, 3 deletions
diff --git a/lib/handlebars/runtime.js b/lib/handlebars/runtime.js
index 80defd8..1e676ea 100644
--- a/lib/handlebars/runtime.js
+++ b/lib/handlebars/runtime.js
@@ -7,6 +7,10 @@ if(exports) {
Handlebars.Visitor = require("handlebars/jison_ext").Visitor;
}
+// A Context wraps data, and makes it possible to extract a
+// 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) {
this.data = data;
this.fallback = fallback;
@@ -15,6 +19,7 @@ Handlebars.Context = function(data, fallback) {
Handlebars.Context.prototype = {
isContext: true,
+ // Make a shallow copy of the Context
clone: function() {
var context = new Handlebars.Context;
context.data = this.data;
@@ -22,9 +27,19 @@ Handlebars.Context.prototype = {
return context;
},
+ // Search for an object inside the Context's data. The
+ // path parameter is an object with parts
+ // ("person/name" represented as ["person", "name"]),
+ // and depth (the amount of levels to go up the stack,
+ // originally represented as ..). The stack parameter
+ // is the objects already searched from the root of
+ // the original Context in order to get to this point.
+ //
+ // Return a new Context wrapping the data found in
+ // the search.
evaluate: function(path, stack) {
var context = this.clone();
- var depth = path.depth, dig = path.dig, parts = path.parts;
+ var depth = path.depth, parts = path.parts;
if(depth > stack.length) { context.data = null; }
else if(depth > 0) { context = stack[stack.length - depth].clone(); }
@@ -85,7 +100,7 @@ Handlebars.Runtime.prototype = {
mustache: function(mustache) {
var idObj = this.accept(mustache.id);
- var params = mustache.params;
+ var params = this.evaluateParams(mustache.params);
for(var i=0, l=params.length; i<l; i++) {
params[i] = this.accept(params[i]).data;
@@ -99,18 +114,63 @@ Handlebars.Runtime.prototype = {
}
},
+ block: function(block) {
+ var mustache = block.mustache,
+ id = mustache.id;
+
+ var idObj = this.accept(mustache.id),
+ data = idObj.data;
+
+ if(toString.call(data) !== "[object Function]") {
+ params = [data];
+ data = this.context.evaluate({depth: 0, parts: ["helperMissing"]}, this.stack).data;
+ } else {
+ params = this.evaluateParams(mustache.params);
+ }
+
+ var context = this.wrapContext();
+ params.push(this.wrapProgram(block.program));
+ this.buffer = this.buffer + data.apply(this.wrapContext(), params);
+ },
+
content: function(content) {
this.buffer += content.string;
},
+ evaluateParams: function(params) {
+ for(var i=0, l=params.length; i<l; i++) {
+ params[i] = this.accept(params[i]).data;
+ }
+ return params;
+ },
+
wrapContext: function() {
- var proxy = Handlebars.proxy(this.context.data);
+ var data = this.context.data;
+ var proxy = Handlebars.proxy(data);
var context = proxy.__context__ = this.context;
var stack = proxy.__stack__ = this.stack.slice(0);
proxy.__get__ = function(path) {
return context.evaluate(path, stack).data
};
+
+ proxy.isWrappedContext = true;
+ proxy.__data__ = data;
+
+ return proxy;
+ },
+
+ wrapProgram: function(program) {
+ var runtime = this, stack = this.stack.slice(0);
+ stack.push(this.context);
+ var fallback = this.context.fallback;
+
+ return function(context) {
+ if(context.isWrappedContext) { context = context.__data__; }
+ var runtime = new Handlebars.Runtime(context, fallback, stack);
+ runtime.accept(program);
+ return runtime.buffer;
+ }
}
}