123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102 |
- var regStr = "{{(.+)}}";
- var localRegex = new RegExp(regStr);
- var globalRegex = new RegExp(regStr, "g");
-
- function hasMultipleStatements(str) {
- return (str.indexOf(";") !== -1)
- }
-
- function Func(args) {
- return Function.apply(this, args);
- }
- Func.prototype = Function.prototype;
-
- module.exports = function(str, vals) {
- str = str.replace(/\s+/g, " ").replace(/}}/g, "}}\n");
- this.string = str;
- this.vals = vals;
- this.subs = [];
-
- var matches = str.match(globalRegex);
-
- if (!matches)
- return;
-
- matches.forEach(function(m) {
- var str = m.match(localRegex)[1];
-
- //Add user defined arguments
- var args = [];
- vals.forEach(function(v) {
- args.push(v);
- });
-
- //We also need a callback function, for async things
- args.push("cb");
-
- //We want to automatically return if there's only one statement
- if (hasMultipleStatements(str))
- args.push(str);
- else
- args.push("return ("+str+")");
-
- this.subs.push({
- func: new Func(args),
- match: m+"\n"
- });
- }.bind(this));
- }
-
- module.exports.prototype.exec = function(vals, cb) {
- var str = this.string;
-
- //Prepare generic arguments
- var args = [];
- for (var i in vals) {
- var index = this.vals.indexOf(i);
-
- if (index === -1)
- throw new Error("Error: argument "+i+" doesn't exist");
-
- args[index] = vals[i];
- }
-
- var numArgs = args.length;
-
- //Keep track of how many callbacks we're waiting for
- var cbsRemaining = this.subs.length;
-
- //Replace
- this.subs.forEach(function(sub, i) {
-
- //Create a callback function for each substitute
- args[numArgs] = function(err, res) {
- if (err)
- throw err;
-
- str = str.replace(sub.match, res);
-
- //If this is the last callback to be executed,
- //call back with the resulting string
- if (cbsRemaining <= 0)
- cb(str);
- cbsRemaining -= 1;
- }
-
- var ret = sub.func.apply(null, args);
-
- //If the substitute's function returns anything, we use that directly,
- //but if it doesn't, we wait for a callback
- if (ret !== undefined) {
- str = str.replace(sub.match, ret);
- if (cbsRemaining <= 0)
- cb(str);
- cbsRemaining -= 1;
- }
- });
-
- //If there's no asynchronous functions to wait for,
- //just call back immediately
- if (cbsRemaining === 0)
- return cb(str);
- }
|