Finish compatibility with the old handlebars:

* foo"bar" is an invalid param
* {{foo}}bar{{/baz}} is invalid
* fix a number of issues with inverse sections
* add partials
This commit is contained in:
wycats
2010-12-03 16:49:04 -05:00
parent 9a6f77af56
commit f205cec745
8 changed files with 173 additions and 96 deletions
+63 -28
View File
@@ -1,7 +1,7 @@
if(exports) {
var inspect = function(obj) {
require("sys").print(require("sys").inspect(obj) + "\n");
}
};
var Handlebars = {};
Handlebars.AST = require("handlebars/ast");
Handlebars.Visitor = require("handlebars/jison_ext").Visitor;
@@ -21,7 +21,7 @@ Handlebars.Context.prototype = {
// Make a shallow copy of the Context
clone: function() {
var context = new Handlebars.Context;
var context = new Handlebars.Context();
context.data = this.data;
context.fallback = this.fallback;
return context;
@@ -61,14 +61,14 @@ Handlebars.K = function() { return this; };
Handlebars.proxy = function(obj) {
var Proxy = this.K;
Proxy.prototype = obj;
return new Proxy;
return new Proxy();
}
Handlebars.Runtime = function(context, fallback, stack) {
this.stack = stack || [];
this.buffer = "";
var newContext = this.context = new Handlebars.Context;
var newContext = this.context = new Handlebars.Context();
if(context && context.isContext) {
newContext.data = context.data;
@@ -118,7 +118,7 @@ Handlebars.Runtime.prototype = {
if(buf && mustache.escaped) { buf = Handlebars.Utils.escapeExpression(buf); }
this.buffer = this.buffer + (buf == null ? '' : buf);
this.buffer = this.buffer + ((buf == null || buf === false) ? '' : buf);
},
block: function(block) {
@@ -135,41 +135,75 @@ Handlebars.Runtime.prototype = {
params = this.evaluateParams(mustache.params);
}
var context = this.wrapContext();
params.push(this.wrapProgram(block.program));
this.buffer = this.buffer + data.apply(this.wrapContext(), params);
var result = data.apply(this.wrapContext(), params);
this.buffer = this.buffer + result;
if(block.program.inverse) {
params.pop();
params.push(this.wrapProgram(block.program.inverse));
var result = data.not.apply(this.wrapContext(), params);
this.buffer = this.buffer + result;
}
},
// TODO: Block and Inverse can share code
partial: function(partial) {
var partials = this.context.evaluate({depth: 0, parts: ["partials"]}, this.stack).data || {};
var id = partial.id.original;
var partialBody = partials[partial.id.original];
if(!partialBody) {
throw new Handlebars.Exception("The partial " + partial.id.original + " does not exist");
}
if(typeof partialBody === "string") {
var program = Handlebars.parse(partialBody);
partials[id] = program;
} else {
program = partialBody;
}
if(partial.context) {
var context = this.accept(partial.context);
} else {
var context = this.context;
}
var runtime = new Handlebars.Runtime(context, this.context.fallback, this.stack.slice(0));
this.buffer = this.buffer + runtime.accept(program);
},
not: function(context, fn) {
return fn(context);
},
// TODO: Write down the actual spec for inverse sections...
inverse: function(block) {
var mustache = block.mustache,
id = mustache.id;
id = mustache.id,
not;
var idObj = this.accept(id),
data = idObj.data,
isInverse = Handlebars.Utils.isEmpty(data);
if(toString.call(data) !== "[object Function]") {
params = [data];
data = this.context.evaluate({depth: 0, parts: ["helperMissing"]}, this.stack).data;
id = "helperMissing";
var context = this.wrapContext();
if(toString.call(data) === "[object Function]") {
params = this.evaluateParams(mustache.params);
id = id.parts.join("/");
data = data.apply(context, params);
if(Handlebars.Utils.isEmpty(data)) { isInverse = true }
if(data.not) { not = data.not } else { not = this.not }
} else {
params = this.evaluateParams(mustache.params);
id = id.parts.join("/");
not = this.not;
}
if(isInverse) {
var not = data.not;
if(not) {
var context = this.wrapContext();
params.push(this.wrapProgram(block.program));
this.buffer = this.buffer + not.apply(this.wrapContext(), params);
} else {
throw new Handlebars.Exception("Not .not property found on " + id);
}
}
var result = not(context, this.wrapProgram(block.program));
if(result != null) { this.buffer = this.buffer + result; }
return;
},
content: function(content) {
@@ -183,7 +217,7 @@ Handlebars.Runtime.prototype = {
params[i] = this.accept(params[i]).data;
}
if(params.length === 0) { params = [undefined]; }
if(params.length === 0) { params = [this.wrapContext()]; }
return params;
},
@@ -222,3 +256,4 @@ Handlebars.Runtime.prototype = {
if(exports) {
exports.Runtime = Handlebars.Runtime;
}