Add support for passing String parameters to helper
This commit is contained in:
@@ -60,7 +60,7 @@ var Handlebars = require("handlebars");
|
||||
|
||||
Handlebars.AST.IdNode = function(parts) {
|
||||
this.type = "ID";
|
||||
this.original = parts.join("/");
|
||||
this.original = parts.join(".");
|
||||
|
||||
var dig = [], depth = 0;
|
||||
|
||||
@@ -73,6 +73,7 @@ var Handlebars = require("handlebars");
|
||||
}
|
||||
|
||||
this.parts = dig;
|
||||
this.string = dig.join('.');
|
||||
this.depth = depth;
|
||||
this.isSimple = (dig.length === 1) && (depth === 0);
|
||||
};
|
||||
|
||||
+48
-23
@@ -20,7 +20,8 @@ Handlebars.JavaScriptCompiler = function() {};
|
||||
invokePartial: 12,
|
||||
push: 13,
|
||||
invokeInverse: 14,
|
||||
assignToHash: 15
|
||||
assignToHash: 15,
|
||||
pushStringParam: 16
|
||||
};
|
||||
|
||||
Compiler.MULTI_PARAM_OPCODES = {
|
||||
@@ -36,7 +37,8 @@ Handlebars.JavaScriptCompiler = function() {};
|
||||
invokePartial: 1,
|
||||
push: 1,
|
||||
invokeInverse: 1,
|
||||
assignToHash: 1
|
||||
assignToHash: 1,
|
||||
pushStringParam: 1
|
||||
};
|
||||
|
||||
Compiler.DISASSEMBLE_MAP = {};
|
||||
@@ -89,9 +91,10 @@ Handlebars.JavaScriptCompiler = function() {};
|
||||
|
||||
guid: 0,
|
||||
|
||||
compile: function(program) {
|
||||
compile: function(program, options) {
|
||||
this.children = [];
|
||||
this.depths = {list: []};
|
||||
this.options = options || {};
|
||||
return this.program(program);
|
||||
},
|
||||
|
||||
@@ -116,7 +119,7 @@ Handlebars.JavaScriptCompiler = function() {};
|
||||
},
|
||||
|
||||
compileProgram: function(program) {
|
||||
var result = new Compiler().compile(program);
|
||||
var result = new Compiler().compile(program, this.options);
|
||||
var guid = this.guid++;
|
||||
|
||||
this.usePartial = this.usePartial || result.usePartial;
|
||||
@@ -227,7 +230,17 @@ Handlebars.JavaScriptCompiler = function() {};
|
||||
|
||||
while(i--) {
|
||||
param = params[i];
|
||||
this[param.type](param);
|
||||
|
||||
if(this.options.stringParams) {
|
||||
if(param.depth) {
|
||||
this.addDepth(param.depth);
|
||||
}
|
||||
|
||||
this.opcode('getContext', param.depth || 0);
|
||||
this.opcode('pushStringParam', param.string);
|
||||
} else {
|
||||
this[param.type](param);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -289,9 +302,9 @@ Handlebars.JavaScriptCompiler = function() {};
|
||||
},
|
||||
// END PUBLIC API
|
||||
|
||||
compile: function(environment, data) {
|
||||
compile: function(environment, options) {
|
||||
this.environment = environment;
|
||||
this.data = data;
|
||||
this.options = options || {};
|
||||
|
||||
this.preamble();
|
||||
|
||||
@@ -299,7 +312,7 @@ Handlebars.JavaScriptCompiler = function() {};
|
||||
this.stackVars = [];
|
||||
this.registers = {list: []};
|
||||
|
||||
this.compileChildren(environment, data);
|
||||
this.compileChildren(environment, options);
|
||||
|
||||
Handlebars.log(Handlebars.logger.DEBUG, environment.disassemble() + "\n\n");
|
||||
|
||||
@@ -393,13 +406,12 @@ Handlebars.JavaScriptCompiler = function() {};
|
||||
|
||||
var params = ["Handlebars", "context", "helpers", "partials"];
|
||||
|
||||
if(this.data) { params.push("data"); }
|
||||
if(this.options.data) { params.push("data"); }
|
||||
|
||||
for(var i=0, l=this.environment.depths.list.length; i<l; i++) {
|
||||
params.push("depth" + this.environment.depths.list[i]);
|
||||
}
|
||||
|
||||
|
||||
if(params.length === 4 && !this.environment.usePartial) { params.pop(); }
|
||||
|
||||
params.push(this.source.join("\n"));
|
||||
@@ -477,6 +489,11 @@ Handlebars.JavaScriptCompiler = function() {};
|
||||
this.source.push(topStack + " = " + this.nameLookup(topStack, name, 'context') + ";");
|
||||
},
|
||||
|
||||
pushStringParam: function(string) {
|
||||
this.pushStack("currentContext");
|
||||
this.pushString(string);
|
||||
},
|
||||
|
||||
pushString: function(string) {
|
||||
this.pushStack(this.quotedString(string));
|
||||
},
|
||||
@@ -503,24 +520,32 @@ Handlebars.JavaScriptCompiler = function() {};
|
||||
|
||||
populateParams: function(paramSize, helperId, program, inverse, fn) {
|
||||
var id = this.popStack(), nextStack;
|
||||
var params = [];
|
||||
var params = [], param, stringParam;
|
||||
|
||||
var hash = this.popStack();
|
||||
|
||||
for(var i=0; i<paramSize; i++) {
|
||||
var param = this.popStack();
|
||||
params.push(param);
|
||||
}
|
||||
|
||||
this.register('tmp1', program);
|
||||
this.source.push('tmp1.hash = ' + hash + ';');
|
||||
|
||||
if(this.options.stringParams) {
|
||||
this.source.push('tmp1.contexts = [];');
|
||||
}
|
||||
|
||||
for(var i=0; i<paramSize; i++) {
|
||||
param = this.popStack();
|
||||
params.push(param);
|
||||
|
||||
if(this.options.stringParams) {
|
||||
this.source.push('tmp1.contexts.push(' + this.popStack() + ');');
|
||||
}
|
||||
}
|
||||
|
||||
if(inverse) {
|
||||
this.source.push('tmp1.fn = tmp1;');
|
||||
this.source.push('tmp1.inverse = ' + inverse + ';');
|
||||
}
|
||||
|
||||
if(this.data) {
|
||||
if(this.options.data) {
|
||||
this.source.push('tmp1.data = data;');
|
||||
}
|
||||
|
||||
@@ -566,7 +591,7 @@ Handlebars.JavaScriptCompiler = function() {};
|
||||
|
||||
compiler: JavaScriptCompiler,
|
||||
|
||||
compileChildren: function(environment, data) {
|
||||
compileChildren: function(environment, options) {
|
||||
var children = environment.children, child, compiler;
|
||||
var compiled = [];
|
||||
|
||||
@@ -574,7 +599,7 @@ Handlebars.JavaScriptCompiler = function() {};
|
||||
child = children[i];
|
||||
compiler = new this.compiler();
|
||||
|
||||
compiled[i] = compiler.compile(child, data);
|
||||
compiled[i] = compiler.compile(child, options);
|
||||
}
|
||||
|
||||
environment.rawChildren = children;
|
||||
@@ -588,7 +613,7 @@ Handlebars.JavaScriptCompiler = function() {};
|
||||
|
||||
var depths = this.environment.rawChildren[guid].depths.list;
|
||||
|
||||
if(this.data) { programParams.push("data"); }
|
||||
if(this.options.data) { programParams.push("data"); }
|
||||
|
||||
for(var i=0, l = depths.length; i<l; i++) {
|
||||
depth = depths[i];
|
||||
@@ -681,10 +706,10 @@ Handlebars.VM = {
|
||||
};
|
||||
},
|
||||
noop: function() { return ""; },
|
||||
compile: function(string, data) {
|
||||
compile: function(string, options) {
|
||||
var ast = Handlebars.parse(string);
|
||||
var environment = new Handlebars.Compiler().compile(ast);
|
||||
return new Handlebars.JavaScriptCompiler().compile(environment, data);
|
||||
var environment = new Handlebars.Compiler().compile(ast, options);
|
||||
return new Handlebars.JavaScriptCompiler().compile(environment, options);
|
||||
},
|
||||
invokePartial: function(partial, name, context, helpers, partials) {
|
||||
if(partial === undefined) {
|
||||
|
||||
+84
-7
@@ -524,7 +524,7 @@ test("overriding property lookup", function() {
|
||||
|
||||
|
||||
test("passing in data to a compiled function that expects data - works with helpers", function() {
|
||||
var template = Handlebars.compile("{{hello}}", true);
|
||||
var template = Handlebars.compile("{{hello}}", {data: true});
|
||||
|
||||
var helpers = {
|
||||
hello: function(options) {
|
||||
@@ -537,7 +537,7 @@ test("passing in data to a compiled function that expects data - works with help
|
||||
});
|
||||
|
||||
test("passing in data to a compiled function that expects data - works with helpers and parameters", function() {
|
||||
var template = Handlebars.compile("{{hello world}}", true);
|
||||
var template = Handlebars.compile("{{hello world}}", {data: true});
|
||||
|
||||
var helpers = {
|
||||
hello: function(noun, options) {
|
||||
@@ -550,7 +550,7 @@ test("passing in data to a compiled function that expects data - works with help
|
||||
});
|
||||
|
||||
test("passing in data to a compiled function that expects data - works with block helpers", function() {
|
||||
var template = Handlebars.compile("{{#hello}}{{world}}{{/hello}}", true);
|
||||
var template = Handlebars.compile("{{#hello}}{{world}}{{/hello}}", {data: true});
|
||||
|
||||
var helpers = {
|
||||
hello: function(fn) {
|
||||
@@ -566,7 +566,7 @@ test("passing in data to a compiled function that expects data - works with bloc
|
||||
});
|
||||
|
||||
test("passing in data to a compiled function that expects data - works with block helpers that use ..", function() {
|
||||
var template = Handlebars.compile("{{#hello}}{{world ../zomg}}{{/hello}}", true);
|
||||
var template = Handlebars.compile("{{#hello}}{{world ../zomg}}{{/hello}}", {data: true});
|
||||
|
||||
var helpers = {
|
||||
hello: function(fn) {
|
||||
@@ -582,7 +582,7 @@ test("passing in data to a compiled function that expects data - works with bloc
|
||||
});
|
||||
|
||||
test("passing in data to a compiled function that expects data - data is passed to with block helpers where children use ..", function() {
|
||||
var template = Handlebars.compile("{{#hello}}{{world ../zomg}}{{/hello}}", true);
|
||||
var template = Handlebars.compile("{{#hello}}{{world ../zomg}}{{/hello}}", {data: true});
|
||||
|
||||
var helpers = {
|
||||
hello: function(fn, inverse) {
|
||||
@@ -598,7 +598,7 @@ test("passing in data to a compiled function that expects data - data is passed
|
||||
});
|
||||
|
||||
test("you can override inherited data when invoking a helper", function() {
|
||||
var template = Handlebars.compile("{{#hello}}{{world zomg}}{{/hello}}", true);
|
||||
var template = Handlebars.compile("{{#hello}}{{world zomg}}{{/hello}}", {data: true});
|
||||
|
||||
var helpers = {
|
||||
hello: function(fn) {
|
||||
@@ -615,7 +615,7 @@ test("you can override inherited data when invoking a helper", function() {
|
||||
|
||||
|
||||
test("you can override inherited data when invoking a helper with depth", function() {
|
||||
var template = Handlebars.compile("{{#hello}}{{world ../zomg}}{{/hello}}", true);
|
||||
var template = Handlebars.compile("{{#hello}}{{world ../zomg}}{{/hello}}", {data: true});
|
||||
|
||||
var helpers = {
|
||||
hello: function(fn) {
|
||||
@@ -701,3 +701,80 @@ test("block helpers can take an optional hash", function() {
|
||||
var result = template({}, helpers);
|
||||
equals(result, "GOODBYE CRUEL world");
|
||||
});
|
||||
|
||||
test("arguments to helpers can be retrieved from options hash in string form", function() {
|
||||
var template = Handlebars.compile('{{wycats is.a slave.driver}}', {stringParams: true});
|
||||
|
||||
var helpers = {
|
||||
wycats: function(passiveVoice, noun, options) {
|
||||
return "HELP ME MY BOSS " + passiveVoice + ' ' + noun;
|
||||
}
|
||||
};
|
||||
|
||||
var result = template({}, helpers);
|
||||
|
||||
equals(result, "HELP ME MY BOSS is.a slave.driver");
|
||||
});
|
||||
|
||||
test("when using block form, arguments to helpers can be retrieved from options hash in string form", function() {
|
||||
var template = Handlebars.compile('{{#wycats is.a slave.driver}}help :({{/wycats}}', {stringParams: true});
|
||||
|
||||
var helpers = {
|
||||
wycats: function(passiveVoice, noun, options) {
|
||||
return "HELP ME MY BOSS " + passiveVoice + ' ' +
|
||||
noun + ': ' + options.fn(this);
|
||||
}
|
||||
};
|
||||
|
||||
var result = template({}, helpers);
|
||||
|
||||
equals(result, "HELP ME MY BOSS is.a slave.driver: help :(");
|
||||
});
|
||||
|
||||
test("when inside a block in String mode, .. passes the appropriate context in the options hash", function() {
|
||||
var template = Handlebars.compile('{{#with dale}}{{tomdale ../need dad.joke}}{{/with}}', {stringParams: true});
|
||||
|
||||
var helpers = {
|
||||
tomdale: function(desire, noun, options) {
|
||||
return "STOP ME FROM READING HACKER NEWS I " +
|
||||
options.contexts[0][desire] + " " + noun;
|
||||
},
|
||||
|
||||
"with": function(context, options) {
|
||||
return options.fn(options.contexts[0][context]);
|
||||
}
|
||||
};
|
||||
|
||||
var result = template({
|
||||
dale: {},
|
||||
|
||||
need: 'need-a'
|
||||
}, helpers);
|
||||
|
||||
equals(result, "STOP ME FROM READING HACKER NEWS I need-a dad.joke");
|
||||
});
|
||||
|
||||
test("when inside a block in String mode, .. passes the appropriate context in the options hash to a block helper", function() {
|
||||
var template = Handlebars.compile('{{#with dale}}{{#tomdale ../need dad.joke}}wot{{/tomdale}}{{/with}}', {stringParams: true});
|
||||
|
||||
var helpers = {
|
||||
tomdale: function(desire, noun, options) {
|
||||
return "STOP ME FROM READING HACKER NEWS I " +
|
||||
options.contexts[0][desire] + " " + noun + " " +
|
||||
options.fn(this);
|
||||
},
|
||||
|
||||
"with": function(context, options) {
|
||||
return options.fn(options.contexts[0][context]);
|
||||
}
|
||||
};
|
||||
|
||||
var result = template({
|
||||
dale: {},
|
||||
|
||||
need: 'need-a'
|
||||
}, helpers);
|
||||
|
||||
equals(result, "STOP ME FROM READING HACKER NEWS I need-a dad.joke wot");
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user