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:
+63
-28
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user