Add support for depthed resolution of data fields
This commit is contained in:
@@ -223,5 +223,7 @@ export var logger = {
|
||||
export function log(level, obj) { logger.log(level, obj); }
|
||||
|
||||
export var createFrame = function(object) {
|
||||
return Utils.extend({}, object);
|
||||
var frame = Utils.extend({}, object);
|
||||
frame._parent = object;
|
||||
return frame;
|
||||
};
|
||||
|
||||
@@ -310,11 +310,7 @@ Compiler.prototype = {
|
||||
|
||||
DATA: function(data) {
|
||||
this.options.data = true;
|
||||
if (data.id.isScoped || data.id.depth) {
|
||||
throw new Exception('Scoped data references are not supported: ' + data.original, data);
|
||||
}
|
||||
|
||||
this.opcode('lookupData');
|
||||
this.opcode('lookupData', data.id.depth);
|
||||
var parts = data.id.parts;
|
||||
for(var i=0, l=parts.length; i<l; i++) {
|
||||
this.opcode('lookup', parts[i]);
|
||||
|
||||
@@ -403,8 +403,12 @@ JavaScriptCompiler.prototype = {
|
||||
// On stack, after: data, ...
|
||||
//
|
||||
// Push the data lookup operator
|
||||
lookupData: function() {
|
||||
this.pushStackLiteral('data');
|
||||
lookupData: function(depth) {
|
||||
if (!depth) {
|
||||
this.pushStackLiteral('data');
|
||||
} else {
|
||||
this.pushStackLiteral('this.data(data, ' + depth + ')');
|
||||
}
|
||||
},
|
||||
|
||||
// [pushStringParam]
|
||||
|
||||
@@ -77,6 +77,12 @@ export function template(templateSpec, env) {
|
||||
}
|
||||
return data;
|
||||
},
|
||||
data: function(data, depth) {
|
||||
while (data && depth--) {
|
||||
data = data._parent;
|
||||
}
|
||||
return data;
|
||||
},
|
||||
merge: function(param, common) {
|
||||
var ret = param || common;
|
||||
|
||||
|
||||
+19
-16
@@ -85,22 +85,6 @@ describe('data', function() {
|
||||
equals("Hello undefined", result, "@foo as a parameter retrieves template data");
|
||||
});
|
||||
|
||||
it("parameter data throws when using this scope references", function() {
|
||||
var string = "{{#goodbyes}}{{text}} cruel {{@./name}}! {{/goodbyes}}";
|
||||
|
||||
shouldThrow(function() {
|
||||
CompilerContext.compile(string);
|
||||
}, Error);
|
||||
});
|
||||
|
||||
it("parameter data throws when using parent scope references", function() {
|
||||
var string = "{{#goodbyes}}{{text}} cruel {{@../name}}! {{/goodbyes}}";
|
||||
|
||||
shouldThrow(function() {
|
||||
CompilerContext.compile(string);
|
||||
}, Error);
|
||||
});
|
||||
|
||||
it("parameter data throws when using complex scope references", function() {
|
||||
var string = "{{#goodbyes}}{{text}} cruel {{@foo/../name}}! {{/goodbyes}}";
|
||||
|
||||
@@ -251,4 +235,23 @@ describe('data', function() {
|
||||
equals('hello', result);
|
||||
});
|
||||
});
|
||||
|
||||
describe('nesting', function() {
|
||||
it('the root context can be looked up via @root', function() {
|
||||
var template = CompilerContext.compile('{{#helper}}{{#helper}}{{@./depth}} {{@../depth}} {{@../../depth}}{{/helper}}{{/helper}}');
|
||||
var result = template({foo: 'hello'}, {
|
||||
helpers: {
|
||||
helper: function(options) {
|
||||
var frame = Handlebars.createFrame(options.data);
|
||||
frame.depth = options.data.depth + 1;
|
||||
return options.fn(this, {data: frame});
|
||||
}
|
||||
},
|
||||
data: {
|
||||
depth: 0
|
||||
}
|
||||
});
|
||||
equals('2 1 0', result);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -21,6 +21,10 @@ describe('parser', function() {
|
||||
equals(ast_for("{{@foo}}"), "{{ @ID:foo [] }}\n");
|
||||
});
|
||||
|
||||
it('parses simple mustaches with data paths', function() {
|
||||
equals(ast_for("{{@../foo}}"), "{{ @ID:foo [] }}\n");
|
||||
});
|
||||
|
||||
it('parses mustaches with paths', function() {
|
||||
equals(ast_for("{{foo/bar}}"), "{{ PATH:foo/bar [] }}\n");
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user