Reworked the way that expression work a good bit. They're a lot less error prone now.
This commit is contained in:
+35
-25
@@ -78,23 +78,28 @@ var Handlebars = {
|
||||
return compiled;
|
||||
},
|
||||
|
||||
evalExpression: function(path, context, stack) {
|
||||
var parsedPath = Handlebars.parsePath(path);
|
||||
var depth = parsedPath[0];
|
||||
var parts = parsedPath[1];
|
||||
if (depth > stack.length) {
|
||||
context = null;
|
||||
} else if (depth > 0) {
|
||||
context = stack[stack.length - depth];
|
||||
}
|
||||
|
||||
for (var i = 0; i < parts.length && context !== undefined; i++) {
|
||||
context = context[parts[i]];
|
||||
}
|
||||
|
||||
return context;
|
||||
},
|
||||
|
||||
buildContext: function(context, stack) {
|
||||
var ContextWrapper = function(stack) {
|
||||
this.__stack__ = stack.slice(0);
|
||||
this.__get__ = function(path) {
|
||||
var context = this;
|
||||
var parsedPath = Handlebars.parsePath(path);
|
||||
var depth = parsedPath[0];
|
||||
var parts = parsedPath[1];
|
||||
if (depth > 0) {
|
||||
context = this.__stack__[this.__stack__.length - depth];
|
||||
}
|
||||
|
||||
for (var i = 0; i < parts.length; i++) {
|
||||
context = context[parts[i]];
|
||||
}
|
||||
|
||||
return context;
|
||||
return Handlebars.evalExpression(path, this, this.__stack__);
|
||||
};
|
||||
};
|
||||
|
||||
@@ -102,13 +107,18 @@ var Handlebars = {
|
||||
return new ContextWrapper(stack);
|
||||
},
|
||||
|
||||
// Returns a two element array containing the numbers of contexts to back up the stack and
|
||||
// spot to memoize paths to speed up loops and subsequent parses
|
||||
pathPatterns: {},
|
||||
|
||||
// returns a two element array containing the numbers of contexts to back up the stack and
|
||||
// the properties to dig into on the current context
|
||||
//
|
||||
// For example, if the path is "../../alan/name", the result will be [2, ["alan", "name"]].
|
||||
// for example, if the path is "../../alan/name", the result will be [2, ["alan", "name"]].
|
||||
parsePath: function(path) {
|
||||
if (path == null) {
|
||||
return [0, []];
|
||||
} else if (Handlebars.pathPatterns[path] != null) {
|
||||
return Handlebars.pathPatterns[path];
|
||||
}
|
||||
|
||||
var parts = path.split("/");
|
||||
@@ -134,8 +144,10 @@ var Handlebars = {
|
||||
dig.push(parts[i]);
|
||||
}
|
||||
}
|
||||
|
||||
return [depth, dig];
|
||||
|
||||
var ret = [depth, dig];
|
||||
Handlebars.pathPatterns[path] = ret;
|
||||
return ret;
|
||||
},
|
||||
|
||||
isEmpty: function(value) {
|
||||
@@ -180,6 +192,7 @@ var Handlebars = {
|
||||
|
||||
handleExpression: function(lookup, context, arg, isEscaped) {
|
||||
var out = "";
|
||||
|
||||
if (Handlebars.isFunction(lookup)) {
|
||||
out = out + Handlebars.filterOutput(lookup.call(context, arg), isEscaped);
|
||||
} else if(!Handlebars.isEmpty(lookup)) {
|
||||
@@ -330,15 +343,12 @@ Handlebars.Compiler.prototype = {
|
||||
var depth = parsed[0];
|
||||
var parts = parsed[1];
|
||||
|
||||
var paramExpr = "";
|
||||
for(var i = 0; i < parts.length; i++) {
|
||||
paramExpr += "['" + parts[i] + "']";
|
||||
}
|
||||
|
||||
if (depth > 0) {
|
||||
return "( stack[stack.length - " + depth + "]" + paramExpr + ")";
|
||||
if (depth > 0 || parts.length > 1) {
|
||||
return "(Handlebars.evalExpression('" + param + "', context, stack))";
|
||||
} else if (parts.length == 1) {
|
||||
return "(context['" + parts[0] + "'] || fallback['" + parts[0] + "'])";
|
||||
} else {
|
||||
return "( context" + paramExpr + " != null ? context" + paramExpr + " : fallback" + paramExpr + " )";
|
||||
return "(context || fallback)";
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
@@ -103,6 +103,11 @@ test("bad idea nested paths", function() {
|
||||
shouldCompileTo(string, hash, "world world world ", "Same context (.) is ignored in paths");
|
||||
});
|
||||
|
||||
test("complex but empty paths", function() {
|
||||
shouldCompileTo("{{person/name}}", {person: {name: null}}, "");
|
||||
shouldCompileTo("{{person/name}}", {person: {}}, "");
|
||||
});
|
||||
|
||||
test("this keyword in paths", function() {
|
||||
var string = "{{#goodbyes}}{{this}}{{/goodbyes}}";
|
||||
var hash = {goodbyes: ["goodbye", "Goodbye", "GOODBYE"]};
|
||||
|
||||
Reference in New Issue
Block a user