Add initial support for blocks
This commit is contained in:
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user