From 2d192b352fa14ba91f487b8e1fd2f8ce188bb553 Mon Sep 17 00:00:00 2001 From: Jason LaPorte Date: Tue, 13 Aug 2013 14:39:20 -0400 Subject: [PATCH] Added context passing. --- lib/template.js | 39 +++++++++++++++++++++++++++++---------- test.js | 31 +++++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+), 10 deletions(-) diff --git a/lib/template.js b/lib/template.js index 76be0dbe..856a1b85 100644 --- a/lib/template.js +++ b/lib/template.js @@ -1,9 +1,16 @@ module.exports = function(template) { - return function parse(expr) { - if(typeof expr === "number") - return expr.toString(); + function parse(expr, stack) { + var result; + + if(typeof expr === "number") { + stack.push(expr); + + result = expr.toString(); + } else if(typeof expr === "string") { + stack.push(expr); + if(!template.hasOwnProperty(expr)) throw new Error("\"" + expr + "\" not found in language template."); @@ -12,7 +19,7 @@ module.exports = function(template) { throw new Error("\"" + expr + "\" was used in a value context, but is expected in a template context."); else - return template[expr]; + result = template[expr]; } else if(typeof template[expr] === "function") { @@ -20,7 +27,7 @@ module.exports = function(template) { throw new Error("\"" + expr + "\" was used in a value context, but is expected in a template context."); else - return template[expr](); + result = template[expr].call(stack); } else @@ -30,12 +37,14 @@ module.exports = function(template) { else if(Array.isArray(expr) && expr.length && typeof expr[0] === "string") { + stack.push(expr[0]); + if(!template.hasOwnProperty(expr[0])) throw new Error("\"" + expr[0] + "\" not found in language template."); else if(typeof template[expr[0]] === "string") - return template[expr[0]].replace(/\$\d+/g, function(n) { - return parse(expr[n.slice(1)|0]); + result = template[expr[0]].replace(/\$\d+/g, function(n) { + return parse(expr[n.slice(1)|0], stack); }); else if(typeof template[expr[0]] === "function") { @@ -46,9 +55,12 @@ module.exports = function(template) { throw new Error("Template \"" + expr[0] + "\" did not expect " + (expr.length - 1) + " arguments."); else - return template[expr[0]].apply(null, expr.slice(1).map(function(arg) { - return parse(arg); - })); + result = template[expr[0]].apply( + stack, + expr.slice(1).map(function(arg) { + return parse(arg, stack); + }) + ); } else @@ -57,5 +69,12 @@ module.exports = function(template) { else throw new Error("Invalid expression."); + + stack.pop(); + return result; }; + + return function(expr) { + return parse(expr, []); + } }; diff --git a/test.js b/test.js index 2cf5e90f..063326f6 100644 --- a/test.js +++ b/test.js @@ -79,6 +79,37 @@ describe("translation", function() { it("should fail to apply a function template given a value", function() { expect(function() { convert("baz"); }).to.throw(); }); + + it("should provide context to functions", function() { + var convert = template({ + "foo": function(a, b, c) { + expect(this).to.deep.equal(["foo"]); + return "Moop."; + }, + "bar": function() { + expect(this).to.deep.equal(["foo", "bar"]); + return "Boop."; + }, + "baz": function(a) { + expect(this).to.deep.equal(["foo", "baz"]); + return "Soup."; + }, + "quux": function() { + expect(this).to.deep.equal(["foo", "baz", "quux"]); + return "Floop."; + }, + "neem": function(a) { + expect(this).to.deep.equal(["foo", "neem"]); + return "Bloop."; + }, + "glorp": function(a) { + expect(this).to.deep.equal(["foo", "neem", "glorp"]); + return "Rope?"; + } + }); + + convert(["foo", "bar", ["baz", "quux"], ["neem", ["glorp", 42]]]); + }); }); describe("language", function() {