Browse files

Use latest upstream Handlebars.js from git.

This version (finally!) includes all the bug fixes that were in
Selleck's customized Handlebars build.
  • Loading branch information...
1 parent 574bcff commit 376cfaefd8e2455ecdcc36ed689699ee9fa0b6b8 @rgrove committed Jun 28, 2011
Showing with 276 additions and 135 deletions.
  1. +1 −1 lib/selleck.js
  2. +275 −134 support/handlebars/handlebars.js
View
2 lib/selleck.js
@@ -407,7 +407,7 @@ function render(source, view, layout, partials, callback) {
template = Handlebars.compile(source);
}
- html = template(view, null, partials);
+ html = template(view, {partials: partials});
} catch (ex) {
return callback(ex);
}
View
409 support/handlebars/handlebars.js
@@ -3,9 +3,9 @@
var handlebars = (function(){
var parser = {trace: function trace() { },
yy: {},
-symbols_: {"error":2,"root":3,"program":4,"EOF":5,"statements":6,"simpleInverse":7,"statement":8,"openInverse":9,"closeBlock":10,"openBlock":11,"mustache":12,"partial":13,"CONTENT":14,"COMMENT":15,"OPEN_BLOCK":16,"inMustache":17,"CLOSE":18,"OPEN_INVERSE":19,"OPEN_ENDBLOCK":20,"path":21,"OPEN":22,"OPEN_UNESCAPED":23,"OPEN_PARTIAL":24,"params":25,"param":26,"STRING":27,"pathSegments":28,"SEP":29,"ID":30,"$accept":0,"$end":1},
-terminals_: {2:"error",5:"EOF",14:"CONTENT",15:"COMMENT",16:"OPEN_BLOCK",18:"CLOSE",19:"OPEN_INVERSE",20:"OPEN_ENDBLOCK",22:"OPEN",23:"OPEN_UNESCAPED",24:"OPEN_PARTIAL",27:"STRING",29:"SEP",30:"ID"},
-productions_: [0,[3,2],[4,3],[4,1],[4,0],[6,1],[6,2],[8,3],[8,3],[8,1],[8,1],[8,1],[8,1],[11,3],[9,3],[10,3],[12,3],[12,3],[13,3],[13,4],[7,2],[17,2],[17,1],[25,2],[25,1],[26,1],[26,1],[21,1],[28,3],[28,1]],
+symbols_: {"error":2,"root":3,"program":4,"EOF":5,"statements":6,"simpleInverse":7,"statement":8,"openInverse":9,"closeBlock":10,"openBlock":11,"mustache":12,"partial":13,"CONTENT":14,"COMMENT":15,"OPEN_BLOCK":16,"inMustache":17,"CLOSE":18,"OPEN_INVERSE":19,"OPEN_ENDBLOCK":20,"path":21,"OPEN":22,"OPEN_UNESCAPED":23,"OPEN_PARTIAL":24,"params":25,"hash":26,"param":27,"STRING":28,"INTEGER":29,"BOOLEAN":30,"hashSegments":31,"hashSegment":32,"ID":33,"EQUALS":34,"pathSegments":35,"SEP":36,"$accept":0,"$end":1},
+terminals_: {2:"error",5:"EOF",14:"CONTENT",15:"COMMENT",16:"OPEN_BLOCK",18:"CLOSE",19:"OPEN_INVERSE",20:"OPEN_ENDBLOCK",22:"OPEN",23:"OPEN_UNESCAPED",24:"OPEN_PARTIAL",28:"STRING",29:"INTEGER",30:"BOOLEAN",33:"ID",34:"EQUALS",36:"SEP"},
+productions_: [0,[3,2],[4,3],[4,1],[4,0],[6,1],[6,2],[8,3],[8,3],[8,1],[8,1],[8,1],[8,1],[11,3],[9,3],[10,3],[12,3],[12,3],[13,3],[13,4],[7,2],[17,3],[17,2],[17,2],[17,1],[25,2],[25,1],[27,1],[27,1],[27,1],[27,1],[26,1],[31,2],[31,1],[32,3],[32,3],[32,3],[32,3],[21,1],[35,3],[35,1]],
performAction: function anonymous(yytext,yyleng,yylineno,yy,yystate,$$,_$) {
var $0 = $$.length - 1;
@@ -34,44 +34,66 @@ case 11: this.$ = new yy.ContentNode($$[$0])
break;
case 12: this.$ = new yy.CommentNode($$[$0])
break;
-case 13: this.$ = new yy.MustacheNode($$[$0-1])
+case 13: this.$ = new yy.MustacheNode($$[$0-1][0], $$[$0-1][1])
break;
-case 14: this.$ = new yy.MustacheNode($$[$0-1])
+case 14: this.$ = new yy.MustacheNode($$[$0-1][0], $$[$0-1][1])
break;
case 15: this.$ = $$[$0-1]
break;
-case 16: this.$ = new yy.MustacheNode($$[$0-1])
+case 16: this.$ = new yy.MustacheNode($$[$0-1][0], $$[$0-1][1])
break;
-case 17: this.$ = new yy.MustacheNode($$[$0-1], true)
+case 17: this.$ = new yy.MustacheNode($$[$0-1][0], $$[$0-1][1], true)
break;
case 18: this.$ = new yy.PartialNode($$[$0-1])
break;
case 19: this.$ = new yy.PartialNode($$[$0-2], $$[$0-1])
break;
case 20:
break;
-case 21: this.$ = [$$[$0-1]].concat($$[$0])
+case 21: this.$ = [[$$[$0-2]].concat($$[$0-1]), $$[$0]]
break;
-case 22: this.$ = [$$[$0]]
+case 22: this.$ = [[$$[$0-1]].concat($$[$0]), null]
break;
-case 23: $$[$0-1].push($$[$0]); this.$ = $$[$0-1];
+case 23: this.$ = [[$$[$0-1]], $$[$0]]
break;
-case 24: this.$ = [$$[$0]]
+case 24: this.$ = [[$$[$0]], null]
break;
-case 25: this.$ = $$[$0]
+case 25: $$[$0-1].push($$[$0]); this.$ = $$[$0-1];
break;
-case 26: this.$ = new yy.StringNode($$[$0])
+case 26: this.$ = [$$[$0]]
break;
-case 27: this.$ = new yy.IdNode($$[$0])
+case 27: this.$ = $$[$0]
break;
-case 28: $$[$0-2].push($$[$0]); this.$ = $$[$0-2];
+case 28: this.$ = new yy.StringNode($$[$0])
break;
-case 29: this.$ = [$$[$0]]
+case 29: this.$ = new yy.IntegerNode($$[$0])
+break;
+case 30: this.$ = new yy.BooleanNode($$[$0])
+break;
+case 31: this.$ = new yy.HashNode($$[$0])
+break;
+case 32: $$[$0-1].push($$[$0]); this.$ = $$[$0-1]
+break;
+case 33: this.$ = [$$[$0]]
+break;
+case 34: this.$ = [$$[$0-2], $$[$0]]
+break;
+case 35: this.$ = [$$[$0-2], new yy.StringNode($$[$0])]
+break;
+case 36: this.$ = [$$[$0-2], new yy.IntegerNode($$[$0])]
+break;
+case 37: this.$ = [$$[$0-2], new yy.BooleanNode($$[$0])]
+break;
+case 38: this.$ = new yy.IdNode($$[$0])
+break;
+case 39: $$[$0-2].push($$[$0]); this.$ = $$[$0-2];
+break;
+case 40: this.$ = [$$[$0]]
break;
}
},
-table: [{3:1,4:2,5:[2,4],6:3,8:4,9:5,11:6,12:7,13:8,14:[1,9],15:[1,10],16:[1,12],19:[1,11],22:[1,13],23:[1,14],24:[1,15]},{1:[3]},{5:[1,16]},{5:[2,3],7:17,8:18,9:5,11:6,12:7,13:8,14:[1,9],15:[1,10],16:[1,12],19:[1,19],20:[2,3],22:[1,13],23:[1,14],24:[1,15]},{5:[2,5],14:[2,5],15:[2,5],16:[2,5],19:[2,5],20:[2,5],22:[2,5],23:[2,5],24:[2,5]},{4:20,6:3,8:4,9:5,11:6,12:7,13:8,14:[1,9],15:[1,10],16:[1,12],19:[1,11],20:[2,4],22:[1,13],23:[1,14],24:[1,15]},{4:21,6:3,8:4,9:5,11:6,12:7,13:8,14:[1,9],15:[1,10],16:[1,12],19:[1,11],20:[2,4],22:[1,13],23:[1,14],24:[1,15]},{5:[2,9],14:[2,9],15:[2,9],16:[2,9],19:[2,9],20:[2,9],22:[2,9],23:[2,9],24:[2,9]},{5:[2,10],14:[2,10],15:[2,10],16:[2,10],19:[2,10],20:[2,10],22:[2,10],23:[2,10],24:[2,10]},{5:[2,11],14:[2,11],15:[2,11],16:[2,11],19:[2,11],20:[2,11],22:[2,11],23:[2,11],24:[2,11]},{5:[2,12],14:[2,12],15:[2,12],16:[2,12],19:[2,12],20:[2,12],22:[2,12],23:[2,12],24:[2,12]},{17:22,21:23,28:24,30:[1,25]},{17:26,21:23,28:24,30:[1,25]},{17:27,21:23,28:24,30:[1,25]},{17:28,21:23,28:24,30:[1,25]},{21:29,28:24,30:[1,25]},{1:[2,1]},{6:30,8:4,9:5,11:6,12:7,13:8,14:[1,9],15:[1,10],16:[1,12],19:[1,11],22:[1,13],23:[1,14],24:[1,15]},{5:[2,6],14:[2,6],15:[2,6],16:[2,6],19:[2,6],20:[2,6],22:[2,6],23:[2,6],24:[2,6]},{17:22,18:[1,31],21:23,28:24,30:[1,25]},{10:32,20:[1,33]},{10:34,20:[1,33]},{18:[1,35]},{18:[2,22],21:38,25:36,26:37,27:[1,39],28:24,30:[1,25]},{18:[2,27],27:[2,27],29:[1,40],30:[2,27]},{18:[2,29],27:[2,29],29:[2,29],30:[2,29]},{18:[1,41]},{18:[1,42]},{18:[1,43]},{18:[1,44],21:45,28:24,30:[1,25]},{5:[2,2],8:18,9:5,11:6,12:7,13:8,14:[1,9],15:[1,10],16:[1,12],19:[1,11],20:[2,2],22:[1,13],23:[1,14],24:[1,15]},{14:[2,20],15:[2,20],16:[2,20],19:[2,20],22:[2,20],23:[2,20],24:[2,20]},{5:[2,7],14:[2,7],15:[2,7],16:[2,7],19:[2,7],20:[2,7],22:[2,7],23:[2,7],24:[2,7]},{21:46,28:24,30:[1,25]},{5:[2,8],14:[2,8],15:[2,8],16:[2,8],19:[2,8],20:[2,8],22:[2,8],23:[2,8],24:[2,8]},{14:[2,14],15:[2,14],16:[2,14],19:[2,14],20:[2,14],22:[2,14],23:[2,14],24:[2,14]},{18:[2,21],21:38,26:47,27:[1,39],28:24,30:[1,25]},{18:[2,24],27:[2,24],30:[2,24]},{18:[2,25],27:[2,25],30:[2,25]},{18:[2,26],27:[2,26],30:[2,26]},{30:[1,48]},{14:[2,13],15:[2,13],16:[2,13],19:[2,13],20:[2,13],22:[2,13],23:[2,13],24:[2,13]},{5:[2,16],14:[2,16],15:[2,16],16:[2,16],19:[2,16],20:[2,16],22:[2,16],23:[2,16],24:[2,16]},{5:[2,17],14:[2,17],15:[2,17],16:[2,17],19:[2,17],20:[2,17],22:[2,17],23:[2,17],24:[2,17]},{5:[2,18],14:[2,18],15:[2,18],16:[2,18],19:[2,18],20:[2,18],22:[2,18],23:[2,18],24:[2,18]},{18:[1,49]},{18:[1,50]},{18:[2,23],27:[2,23],30:[2,23]},{18:[2,28],27:[2,28],29:[2,28],30:[2,28]},{5:[2,19],14:[2,19],15:[2,19],16:[2,19],19:[2,19],20:[2,19],22:[2,19],23:[2,19],24:[2,19]},{5:[2,15],14:[2,15],15:[2,15],16:[2,15],19:[2,15],20:[2,15],22:[2,15],23:[2,15],24:[2,15]}],
-defaultActions: {16:[2,1]},
+table: [{3:1,4:2,5:[2,4],6:3,8:4,9:5,11:6,12:7,13:8,14:[1,9],15:[1,10],16:[1,12],19:[1,11],22:[1,13],23:[1,14],24:[1,15]},{1:[3]},{5:[1,16]},{5:[2,3],7:17,8:18,9:5,11:6,12:7,13:8,14:[1,9],15:[1,10],16:[1,12],19:[1,19],20:[2,3],22:[1,13],23:[1,14],24:[1,15]},{5:[2,5],14:[2,5],15:[2,5],16:[2,5],19:[2,5],20:[2,5],22:[2,5],23:[2,5],24:[2,5]},{4:20,6:3,8:4,9:5,11:6,12:7,13:8,14:[1,9],15:[1,10],16:[1,12],19:[1,11],20:[2,4],22:[1,13],23:[1,14],24:[1,15]},{4:21,6:3,8:4,9:5,11:6,12:7,13:8,14:[1,9],15:[1,10],16:[1,12],19:[1,11],20:[2,4],22:[1,13],23:[1,14],24:[1,15]},{5:[2,9],14:[2,9],15:[2,9],16:[2,9],19:[2,9],20:[2,9],22:[2,9],23:[2,9],24:[2,9]},{5:[2,10],14:[2,10],15:[2,10],16:[2,10],19:[2,10],20:[2,10],22:[2,10],23:[2,10],24:[2,10]},{5:[2,11],14:[2,11],15:[2,11],16:[2,11],19:[2,11],20:[2,11],22:[2,11],23:[2,11],24:[2,11]},{5:[2,12],14:[2,12],15:[2,12],16:[2,12],19:[2,12],20:[2,12],22:[2,12],23:[2,12],24:[2,12]},{17:22,21:23,33:[1,25],35:24},{17:26,21:23,33:[1,25],35:24},{17:27,21:23,33:[1,25],35:24},{17:28,21:23,33:[1,25],35:24},{21:29,33:[1,25],35:24},{1:[2,1]},{6:30,8:4,9:5,11:6,12:7,13:8,14:[1,9],15:[1,10],16:[1,12],19:[1,11],22:[1,13],23:[1,14],24:[1,15]},{5:[2,6],14:[2,6],15:[2,6],16:[2,6],19:[2,6],20:[2,6],22:[2,6],23:[2,6],24:[2,6]},{17:22,18:[1,31],21:23,33:[1,25],35:24},{10:32,20:[1,33]},{10:34,20:[1,33]},{18:[1,35]},{18:[2,24],21:40,25:36,26:37,27:38,28:[1,41],29:[1,42],30:[1,43],31:39,32:44,33:[1,45],35:24},{18:[2,38],28:[2,38],29:[2,38],30:[2,38],33:[2,38],36:[1,46]},{18:[2,40],28:[2,40],29:[2,40],30:[2,40],33:[2,40],36:[2,40]},{18:[1,47]},{18:[1,48]},{18:[1,49]},{18:[1,50],21:51,33:[1,25],35:24},{5:[2,2],8:18,9:5,11:6,12:7,13:8,14:[1,9],15:[1,10],16:[1,12],19:[1,11],20:[2,2],22:[1,13],23:[1,14],24:[1,15]},{14:[2,20],15:[2,20],16:[2,20],19:[2,20],22:[2,20],23:[2,20],24:[2,20]},{5:[2,7],14:[2,7],15:[2,7],16:[2,7],19:[2,7],20:[2,7],22:[2,7],23:[2,7],24:[2,7]},{21:52,33:[1,25],35:24},{5:[2,8],14:[2,8],15:[2,8],16:[2,8],19:[2,8],20:[2,8],22:[2,8],23:[2,8],24:[2,8]},{14:[2,14],15:[2,14],16:[2,14],19:[2,14],20:[2,14],22:[2,14],23:[2,14],24:[2,14]},{18:[2,22],21:40,26:53,27:54,28:[1,41],29:[1,42],30:[1,43],31:39,32:44,33:[1,45],35:24},{18:[2,23]},{18:[2,26],28:[2,26],29:[2,26],30:[2,26],33:[2,26]},{18:[2,31],32:55,33:[1,56]},{18:[2,27],28:[2,27],29:[2,27],30:[2,27],33:[2,27]},{18:[2,28],28:[2,28],29:[2,28],30:[2,28],33:[2,28]},{18:[2,29],28:[2,29],29:[2,29],30:[2,29],33:[2,29]},{18:[2,30],28:[2,30],29:[2,30],30:[2,30],33:[2,30]},{18:[2,33],33:[2,33]},{18:[2,40],28:[2,40],29:[2,40],30:[2,40],33:[2,40],34:[1,57],36:[2,40]},{33:[1,58]},{14:[2,13],15:[2,13],16:[2,13],19:[2,13],20:[2,13],22:[2,13],23:[2,13],24:[2,13]},{5:[2,16],14:[2,16],15:[2,16],16:[2,16],19:[2,16],20:[2,16],22:[2,16],23:[2,16],24:[2,16]},{5:[2,17],14:[2,17],15:[2,17],16:[2,17],19:[2,17],20:[2,17],22:[2,17],23:[2,17],24:[2,17]},{5:[2,18],14:[2,18],15:[2,18],16:[2,18],19:[2,18],20:[2,18],22:[2,18],23:[2,18],24:[2,18]},{18:[1,59]},{18:[1,60]},{18:[2,21]},{18:[2,25],28:[2,25],29:[2,25],30:[2,25],33:[2,25]},{18:[2,32],33:[2,32]},{34:[1,57]},{21:61,28:[1,62],29:[1,63],30:[1,64],33:[1,25],35:24},{18:[2,39],28:[2,39],29:[2,39],30:[2,39],33:[2,39],36:[2,39]},{5:[2,19],14:[2,19],15:[2,19],16:[2,19],19:[2,19],20:[2,19],22:[2,19],23:[2,19],24:[2,19]},{5:[2,15],14:[2,15],15:[2,15],16:[2,15],19:[2,15],20:[2,15],22:[2,15],23:[2,15],24:[2,15]},{18:[2,34],33:[2,34]},{18:[2,35],33:[2,35]},{18:[2,36],33:[2,36]},{18:[2,37],33:[2,37]}],
+defaultActions: {16:[2,1],37:[2,23],53:[2,21]},
parseError: function parseError(str, hash) {
throw new Error(str);
},
@@ -396,26 +418,38 @@ case 9: yy_.yytext = yy_.yytext.substr(3,yy_.yyleng-5); this.begin("INITIAL"); r
break;
case 10: return 22;
break;
-case 11: return 29;
+case 11: return 34;
+break;
+case 12: return 33;
+break;
+case 13: return 33;
+break;
+case 14: return 36;
break;
-case 12: /*ignore whitespace*/
+case 15: /*ignore whitespace*/
break;
-case 13: this.begin("INITIAL"); return 18;
+case 16: this.begin("INITIAL"); return 18;
break;
-case 14: this.begin("INITIAL"); return 18;
+case 17: this.begin("INITIAL"); return 18;
break;
-case 15: yy_.yytext = yy_.yytext.substr(1,yy_.yyleng-2).replace(/\\"/g,'"'); return 27;
+case 18: yy_.yytext = yy_.yytext.substr(1,yy_.yyleng-2).replace(/\\"/g,'"'); return 28;
break;
-case 16: return 30;
+case 19: return 30;
break;
-case 17: return 'INVALID';
+case 20: return 30;
break;
-case 18: return 5;
+case 21: return 29;
+break;
+case 22: return 33;
+break;
+case 23: return 'INVALID';
+break;
+case 24: return 5;
break;
}
};
-lexer.rules = [/^[^\x00]*?(?=(\{\{))/,/^[^\x00]+/,/^\{\{>/,/^\{\{#/,/^\{\{\//,/^\{\{\^/,/^\{\{\s*else\b/,/^\{\{\{/,/^\{\{&/,/^\{\{![\s\S]*?\}\}/,/^\{\{/,/^\//,/^\s+/,/^\}\}\}/,/^\}\}/,/^"(\\["]|[^"])*"/,/^[a-zA-Z0-9_.-]+(?=[} /])/,/^./,/^$/];
-lexer.conditions = {"mu":{"rules":[2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18],"inclusive":false},"INITIAL":{"rules":[0,1,18],"inclusive":true}};return lexer;})()
+lexer.rules = [/^[^\x00]*?(?=(\{\{))/,/^[^\x00]+/,/^\{\{>/,/^\{\{#/,/^\{\{\//,/^\{\{\^/,/^\{\{\s*else\b/,/^\{\{\{/,/^\{\{&/,/^\{\{![\s\S]*?\}\}/,/^\{\{/,/^=/,/^\.(?=[} ])/,/^\.\./,/^[/.]/,/^\s+/,/^\}\}\}/,/^\}\}/,/^"(\\["]|[^"])*"/,/^true(?=[}\s])/,/^false(?=[}\s])/,/^[0-9]+(?=[}\s])/,/^[a-zA-Z0-9_$-]+(?=[=}\s/.])/,/^./,/^$/];
+lexer.conditions = {"mu":{"rules":[2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24],"inclusive":false},"INITIAL":{"rules":[0,1,24],"inclusive":true}};return lexer;})()
parser.lexer = lexer;
return parser;
})();
@@ -437,9 +471,12 @@ if (typeof module !== 'undefined' && require.main === module) {
exports.main(typeof process !== 'undefined' ? process.argv.slice(1) : require("system").args);
}
};
+;
// lib/handlebars/base.js
var Handlebars = {};
+Handlebars.VERSION = "1.0.beta.2";
+
Handlebars.Parser = handlebars;
Handlebars.parse = function(string) {
@@ -451,22 +488,6 @@ Handlebars.print = function(ast) {
return new Handlebars.PrintVisitor().accept(ast);
};
-Handlebars.Runtime = {};
-
-Handlebars.Runtime.compile = function(string) {
- var ast = Handlebars.parse(string);
-
- return function(context, helpers, partials) {
- helpers = helpers || Handlebars.helpers;
- partials = partials || Handlebars.partials;
-
- var internalContext = new Handlebars.Context(context, helpers, partials);
- var runtime = new Handlebars.Runtime(internalContext);
- runtime.accept(ast);
- return runtime.buffer;
- };
-};
-
Handlebars.helpers = {};
Handlebars.partials = {};
@@ -479,6 +500,14 @@ Handlebars.registerPartial = function(name, str) {
this.partials[name] = str;
};
+Handlebars.registerHelper('helperMissing', function(arg) {
+ if(arguments.length === 2) {
+ return undefined;
+ } else {
+ throw new Error("Could not find property '" + arg + "'");
+ }
+});
+
Handlebars.registerHelper('blockHelperMissing', function(context, fn, inverse) {
inverse = inverse || function() {};
@@ -531,7 +560,7 @@ Handlebars.registerHelper('if', function(context, fn, inverse) {
});
Handlebars.registerHelper('unless', function(context, fn, inverse) {
- Handlebars.helpers['if'].call(this, context, inverse, fn);
+ return Handlebars.helpers['if'].call(this, context, inverse, fn);
});
Handlebars.registerHelper('with', function(context, fn) {
@@ -558,10 +587,11 @@ Handlebars.log = function(level, str) { Handlebars.logger.log(level, str); };
if(inverse) { this.inverse = new Handlebars.AST.ProgramNode(inverse); }
};
- Handlebars.AST.MustacheNode = function(params, unescaped) {
+ Handlebars.AST.MustacheNode = function(params, hash, unescaped) {
this.type = "mustache";
this.id = params[0];
this.params = params.slice(1);
+ this.hash = hash;
this.escaped = !unescaped;
};
@@ -599,9 +629,14 @@ Handlebars.log = function(level, str) { Handlebars.logger.log(level, str); };
this.string = string;
};
+ Handlebars.AST.HashNode = function(pairs) {
+ this.type = "hash";
+ this.pairs = pairs;
+ };
+
Handlebars.AST.IdNode = function(parts) {
this.type = "ID";
- this.original = parts.join("/");
+ this.original = parts.join(".");
var dig = [], depth = 0;
@@ -614,6 +649,7 @@ Handlebars.log = function(level, str) { Handlebars.logger.log(level, str); };
}
this.parts = dig;
+ this.string = dig.join('.');
this.depth = depth;
this.isSimple = (dig.length === 1) && (depth === 0);
};
@@ -623,6 +659,16 @@ Handlebars.log = function(level, str) { Handlebars.logger.log(level, str); };
this.string = string;
};
+ Handlebars.AST.IntegerNode = function(integer) {
+ this.type = "INTEGER";
+ this.integer = integer;
+ };
+
+ Handlebars.AST.BooleanNode = function(bool) {
+ this.type = "BOOLEAN";
+ this.bool = bool;
+ };
+
Handlebars.AST.CommentNode = function(comment) {
this.type = "comment";
this.comment = comment;
@@ -657,14 +703,14 @@ Handlebars.SafeString.prototype.toString = function() {
">": ">",
'"': """,
"'": "'",
- "/": "/"
+ "`": "`"
};
- var badChars = /&(?!\w+;)|[<>"'\/]/g;
- var possible = /[&<>"'\/]/;
+ var badChars = /&(?!\w+;)|[<>"'`]/g;
+ var possible = /[&<>"'`]/;
var escapeChar = function(chr) {
- return escape[chr] || "&amp;"
+ return escape[chr] || "&amp;";
};
Handlebars.Utils = {
@@ -695,15 +741,15 @@ Handlebars.SafeString.prototype.toString = function() {
}
};
})();;
-// lib/handlebars/vm.js
+// lib/handlebars/compiler.js
Handlebars.Compiler = function() {};
Handlebars.JavaScriptCompiler = function() {};
(function(Compiler, JavaScriptCompiler) {
Compiler.OPCODE_MAP = {
appendContent: 1,
getContext: 2,
- lookupWithFallback: 3,
+ lookupWithHelpers: 3,
lookup: 4,
append: 5,
invokeMustache: 6,
@@ -714,13 +760,15 @@ Handlebars.JavaScriptCompiler = function() {};
invokeProgram: 11,
invokePartial: 12,
push: 13,
- invokeInverse: 14
+ invokeInverse: 14,
+ assignToHash: 15,
+ pushStringParam: 16
};
Compiler.MULTI_PARAM_OPCODES = {
appendContent: 1,
getContext: 1,
- lookupWithFallback: 1,
+ lookupWithHelpers: 1,
lookup: 1,
invokeMustache: 2,
pushString: 1,
@@ -729,7 +777,9 @@ Handlebars.JavaScriptCompiler = function() {};
invokeProgram: 2,
invokePartial: 1,
push: 1,
- invokeInverse: 1
+ invokeInverse: 1,
+ assignToHash: 1,
+ pushStringParam: 1
};
Compiler.DISASSEMBLE_MAP = {};
@@ -744,6 +794,8 @@ Handlebars.JavaScriptCompiler = function() {};
};
Compiler.prototype = {
+ compiler: Compiler,
+
disassemble: function() {
var opcodes = this.opcodes, opcode, nextCode;
var out = [], str, name, value;
@@ -782,9 +834,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);
},
@@ -809,7 +862,7 @@ Handlebars.JavaScriptCompiler = function() {};
},
compileProgram: function(program) {
- var result = new Compiler().compile(program);
+ var result = new this.compiler().compile(program, this.options);
var guid = this.guid++;
this.usePartial = this.usePartial || result.usePartial;
@@ -828,20 +881,14 @@ Handlebars.JavaScriptCompiler = function() {};
block: function(block) {
var mustache = block.mustache;
- var params = mustache.params, depth, child, inverse, inverseGuid;
-
- this.pushParams(params);
+ var depth, child, inverse, inverseGuid;
- // ID lookup is now on the stack
- this.ID(mustache.id);
+ var params = this.setupStackForMustache(mustache);
var programGuid = this.compileProgram(block.program);
if(block.program.inverse) {
inverseGuid = this.compileProgram(block.program.inverse);
- }
-
- if(block.program.inverse) {
this.declare('inverse', inverseGuid);
}
@@ -858,6 +905,20 @@ Handlebars.JavaScriptCompiler = function() {};
this.opcode('append');
},
+ hash: function(hash) {
+ var pairs = hash.pairs, pair, val;
+
+ this.opcode('push', '{}');
+
+ for(var i=0, l=pairs.length; i<l; i++) {
+ pair = pairs[i];
+ val = pair[1];
+
+ this.accept(val);
+ this.opcode('assignToHash', pair[0]);
+ }
+ },
+
partial: function(partial) {
var id = partial.id;
this.usePartial = true;
@@ -877,10 +938,7 @@ Handlebars.JavaScriptCompiler = function() {};
},
mustache: function(mustache) {
- var params = mustache.params;
-
- this.pushParams(params);
- this.ID(mustache.id);
+ var params = this.setupStackForMustache(mustache);
this.opcode('invokeMustache', params.length, mustache.id.original);
@@ -896,7 +954,7 @@ Handlebars.JavaScriptCompiler = function() {};
this.opcode('getContext', id.depth);
- this.opcode('lookupWithFallback', id.parts[0] || null);
+ this.opcode('lookupWithHelpers', id.parts[0] || null);
for(var i=1, l=id.parts.length; i<l; i++) {
this.opcode('lookup', id.parts[i]);
@@ -907,14 +965,33 @@ Handlebars.JavaScriptCompiler = function() {};
this.opcode('pushString', string.string);
},
+ INTEGER: function(integer) {
+ this.opcode('push', integer.integer);
+ },
+
+ BOOLEAN: function(bool) {
+ this.opcode('push', bool.bool);
+ },
+
comment: function() {},
+ // HELPERS
pushParams: function(params) {
var i = params.length, param;
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);
+ }
}
},
@@ -937,15 +1014,33 @@ Handlebars.JavaScriptCompiler = function() {};
this.depths[depth] = true;
this.depths.list.push(depth);
}
+ },
+
+ setupStackForMustache: function(mustache) {
+ var params = mustache.params;
+
+ this.pushParams(params);
+
+ if(mustache.hash) {
+ this.hash(mustache.hash);
+ } else {
+ this.opcode('push', '{}');
+ }
+
+ this.ID(mustache.id);
+
+ return params;
}
};
JavaScriptCompiler.prototype = {
// PUBLIC API: You can override these methods in a subclass to provide
// alternative compiled forms for name lookup and buffering semantics
nameLookup: function(parent, name, type) {
- if(JavaScriptCompiler.RESERVED_WORDS[name] || name.indexOf('-') !== -1) {
+ if(JavaScriptCompiler.RESERVED_WORDS[name] || name.indexOf('-') !== -1 || !isNaN(name)) {
return parent + "['" + name + "']";
+ } else if (/^[0-9]+$/.test(name)) {
+ return parent + "[" + name + "]";
} else {
return parent + "." + name;
}
@@ -960,17 +1055,17 @@ 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();
this.stackSlot = 0;
this.stackVars = [];
this.registers = {list: []};
- this.compileChildren(environment, data);
+ this.compileChildren(environment, options);
Handlebars.log(Handlebars.logger.DEBUG, environment.disassemble() + "\n\n");
@@ -1064,13 +1159,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"));
@@ -1084,10 +1178,12 @@ Handlebars.JavaScriptCompiler = function() {};
container.children = this.environment.children;
- return function(context, helpers, partials, data, $depth) {
+ return function(context, options, $depth) {
try {
- var args = Array.prototype.slice.call(arguments);
- args.unshift(Handlebars);
+ options = options || {};
+ var args = [Handlebars, context, options.helpers, options.partials, options.data];
+ var depth = Array.prototype.slice.call(arguments, 2);
+ args = args.concat(depth);
return container.render.apply(container, args);
} catch(e) {
throw e;
@@ -1127,11 +1223,17 @@ Handlebars.JavaScriptCompiler = function() {};
}
},
- lookupWithFallback: function(name) {
+ lookupWithHelpers: function(name) {
if(name) {
- this.pushStack(this.nameLookup('currentContext', name, 'context'));
- var topStack = this.topStack();
- this.source.push("if(" + topStack + " === undefined) { " + topStack + " = " + this.nameLookup('helpers', name, 'helper') + "; }");
+ var topStack = this.nextStack();
+
+ var toPush = "if('" + name + "' in helpers) { " + topStack +
+ " = " + this.nameLookup('helpers', name, 'helper') +
+ "; } else { " + topStack + " = " +
+ this.nameLookup('currentContext', name, 'context') +
+ "; }";
+
+ this.source.push(toPush);
} else {
this.pushStack("currentContext");
}
@@ -1142,6 +1244,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));
},
@@ -1151,58 +1258,70 @@ Handlebars.JavaScriptCompiler = function() {};
},
invokeMustache: function(paramSize, original) {
- var params = ["context"], fn, slot;
+ this.populateParams(paramSize, this.quotedString(original), "{}", null, function(nextStack, helperMissingString, id) {
+ this.source.push("else if(" + id + "=== undefined) { " + nextStack + " = helpers.helperMissing.call(" + helperMissingString + "); }");
+ this.source.push("else { " + nextStack + " = " + id + "; }");
+ });
+ },
- fn = this.popStack();
+ invokeProgram: function(guid, paramSize) {
+ var inverse = this.programExpression(this.inverse);
+ var mainProgram = this.programExpression(guid);
- for(var i=0; i<paramSize; i++) {
- params.push(this.popStack());
- }
+ this.populateParams(paramSize, null, mainProgram, inverse, function(nextStack, helperMissingString, id) {
+ this.source.push("else { " + nextStack + " = helpers.blockHelperMissing.call(" + helperMissingString + "); }");
+ });
+ },
- if(this.data) { params.push("data"); }
+ populateParams: function(paramSize, helperId, program, inverse, fn) {
+ var id = this.popStack(), nextStack;
+ var params = [], param, stringParam;
- var paramString = params.join(", ");
- var helperMissing = ["context"].concat(this.quotedString(original)).concat(params.slice(1));
+ var hash = this.popStack();
- slot = this.nextStack();
+ this.register('tmp1', program);
+ this.source.push('tmp1.hash = ' + hash + ';');
- if(paramSize === 0) {
- // TODO: This case is not listed in the mustache spec. Is it important?
- this.source.push("if(typeof " + fn + " === 'function') { " + slot + " = " + fn + ".call(" + paramString + "); }");
- } else {
- this.source.push("if(typeof " + fn + " === 'function') { " + slot + " = " + fn + ".call(" + paramString + "); } else { " + slot + " = helpers.helperMissing.call(" + helperMissing + ") }");
+ if(this.options.stringParams) {
+ this.source.push('tmp1.contexts = [];');
}
- },
-
- invokeProgram: function(guid, paramSize) {
- var inverse = this.programExpression(this.inverse);
-
- var fn = this.popStack();
- var id = fn;
-
- var params = ["context"];
- var blockMissingParams = ["context", id];
for(var i=0; i<paramSize; i++) {
- var param = this.popStack();
+ param = this.popStack();
params.push(param);
- blockMissingParams.push(param);
+
+ if(this.options.stringParams) {
+ this.source.push('tmp1.contexts.push(' + this.popStack() + ');');
+ }
}
- var mainProgram = this.programExpression(guid);
+ if(inverse) {
+ this.source.push('tmp1.fn = tmp1;');
+ this.source.push('tmp1.inverse = ' + inverse + ';');
+ }
- params.push(mainProgram, inverse);
- blockMissingParams.push(mainProgram, inverse);
+ if(this.options.data) {
+ this.source.push('tmp1.data = data;');
+ }
+
+ params.push('tmp1');
- if(this.data) {
- params.push("data");
- blockMissingParams.push("data");
+ // TODO: This is legacy behavior. Deprecate and remove.
+ if(inverse) {
+ params.push(inverse);
}
- var nextStack = this.nextStack();
+ this.populateCall(params, id, helperId || id, fn);
+ },
+
+ populateCall: function(params, id, helperId, fn) {
+ var paramString = ["context"].concat(params).join(", ");
+ var helperMissingString = ["context"].concat(helperId).concat(params).join(", ");
- this.source.push("if(typeof " + id + " === 'function') { " + nextStack + " = " + id + ".call(" + params.join(", ") + "); }");
- this.source.push("else { " + nextStack + " = helpers.blockHelperMissing.call(" + blockMissingParams.join(", ") + "); }");
+ nextStack = this.nextStack();
+
+ this.source.push("if(typeof " + id + " === 'function') { " + nextStack + " = " + id + ".call(" + paramString + "); }");
+ fn.call(this, nextStack, helperMissingString, id);
},
invokeInverse: function(guid) {
@@ -1216,19 +1335,26 @@ Handlebars.JavaScriptCompiler = function() {};
this.pushStack("this.invokePartial(" + this.nameLookup('partials', context, 'partial') + ", '" + context + "', " + this.popStack() + ", helpers, partials);");
},
+ assignToHash: function(key) {
+ var value = this.popStack();
+ var hash = this.topStack();
+
+ this.source.push(hash + "['" + key + "'] = " + value + ";");
+ },
+
// HELPERS
compiler: JavaScriptCompiler,
- compileChildren: function(environment, data) {
+ compileChildren: function(environment, options) {
var children = environment.children, child, compiler;
var compiled = [];
for(var i=0, l=children.length; i<l; i++) {
child = children[i];
compiler = new this.compiler();
- compiled[i] = compiler.compile(child, data);
+ compiled[i] = compiler.compile(child, options);
}
environment.rawChildren = children;
@@ -1242,7 +1368,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];
@@ -1320,31 +1446,46 @@ Handlebars.JavaScriptCompiler = function() {};
})(Handlebars.Compiler, Handlebars.JavaScriptCompiler);
Handlebars.VM = {
- programWithDepth: function(fn) {
- var args = Array.prototype.slice.call(arguments, 1);
- return function(context) {
- return fn.apply(this, [context].concat(args));
+ programWithDepth: function(fn, helpers, partials, data, $depth) {
+ var args = Array.prototype.slice.call(arguments, 4);
+
+ return function(context, options) {
+ options = options || {};
+
+ options = {
+ helpers: options.helpers || helpers,
+ partials: options.partials || partials,
+ data: options.data || data
+ };
+
+ return fn.apply(this, [context, options].concat(args));
};
},
program: function(fn, helpers, partials, data) {
- return function(context) {
- return fn(context, helpers, partials, data);
+ return function(context, options) {
+ options = options || {};
+
+ return fn(context, {
+ helpers: options.helpers || helpers,
+ partials: options.partials || partials,
+ data: options.data || data
+ });
};
},
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) {
throw new Handlebars.Exception("The partial " + name + " could not be found");
} else if(partial instanceof Function) {
- return partial(context, helpers, partials);
+ return partial(context, {helpers: helpers, partials: partials});
} else {
partials[name] = Handlebars.VM.compile(partial);
- return partials[name](context, helpers, partials);
+ return partials[name](context, {helpers: helpers, partials: partials});
}
}
};

0 comments on commit 376cfae

Please sign in to comment.