handlebars-source 1.0.0.rc4 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of handlebars-source might be problematic. Click here for more details.
- data/dist/handlebars.js +1122 -1441
- data/dist/handlebars.runtime.js +87 -191
- metadata +5 -5
data/dist/handlebars.js
CHANGED
@@ -1,66 +1,22 @@
|
|
1
|
-
/*
|
2
|
-
|
3
|
-
Copyright (C) 2011 by Yehuda Katz
|
4
|
-
|
5
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
-
of this software and associated documentation files (the "Software"), to deal
|
7
|
-
in the Software without restriction, including without limitation the rights
|
8
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
-
copies of the Software, and to permit persons to whom the Software is
|
10
|
-
furnished to do so, subject to the following conditions:
|
11
|
-
|
12
|
-
The above copyright notice and this permission notice shall be included in
|
13
|
-
all copies or substantial portions of the Software.
|
14
|
-
|
15
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
-
THE SOFTWARE.
|
22
|
-
|
23
|
-
*/
|
24
|
-
|
25
|
-
// lib/handlebars/browser-prefix.js
|
26
|
-
var Handlebars = {};
|
27
|
-
|
28
|
-
(function(Handlebars, undefined) {
|
29
|
-
;
|
30
1
|
// lib/handlebars/base.js
|
31
2
|
|
32
|
-
|
33
|
-
Handlebars
|
3
|
+
/*jshint eqnull:true*/
|
4
|
+
this.Handlebars = {};
|
34
5
|
|
35
|
-
Handlebars
|
36
|
-
|
37
|
-
|
38
|
-
3: '>= 1.0.0-rc.4'
|
39
|
-
};
|
6
|
+
(function(Handlebars) {
|
7
|
+
|
8
|
+
Handlebars.VERSION = "1.0.rc.1";
|
40
9
|
|
41
10
|
Handlebars.helpers = {};
|
42
11
|
Handlebars.partials = {};
|
43
12
|
|
44
|
-
var toString = Object.prototype.toString,
|
45
|
-
functionType = '[object Function]',
|
46
|
-
objectType = '[object Object]';
|
47
|
-
|
48
13
|
Handlebars.registerHelper = function(name, fn, inverse) {
|
49
|
-
if
|
50
|
-
|
51
|
-
Handlebars.Utils.extend(this.helpers, name);
|
52
|
-
} else {
|
53
|
-
if (inverse) { fn.not = inverse; }
|
54
|
-
this.helpers[name] = fn;
|
55
|
-
}
|
14
|
+
if(inverse) { fn.not = inverse; }
|
15
|
+
this.helpers[name] = fn;
|
56
16
|
};
|
57
17
|
|
58
18
|
Handlebars.registerPartial = function(name, str) {
|
59
|
-
|
60
|
-
Handlebars.Utils.extend(this.partials, name);
|
61
|
-
} else {
|
62
|
-
this.partials[name] = str;
|
63
|
-
}
|
19
|
+
this.partials[name] = str;
|
64
20
|
};
|
65
21
|
|
66
22
|
Handlebars.registerHelper('helperMissing', function(arg) {
|
@@ -71,9 +27,13 @@ Handlebars.registerHelper('helperMissing', function(arg) {
|
|
71
27
|
}
|
72
28
|
});
|
73
29
|
|
30
|
+
var toString = Object.prototype.toString, functionType = "[object Function]";
|
31
|
+
|
74
32
|
Handlebars.registerHelper('blockHelperMissing', function(context, options) {
|
75
33
|
var inverse = options.inverse || function() {}, fn = options.fn;
|
76
34
|
|
35
|
+
|
36
|
+
var ret = "";
|
77
37
|
var type = toString.call(context);
|
78
38
|
|
79
39
|
if(type === functionType) { context = context.call(this); }
|
@@ -102,53 +62,22 @@ Handlebars.createFrame = Object.create || function(object) {
|
|
102
62
|
return obj;
|
103
63
|
};
|
104
64
|
|
105
|
-
Handlebars.logger = {
|
106
|
-
DEBUG: 0, INFO: 1, WARN: 2, ERROR: 3, level: 3,
|
107
|
-
|
108
|
-
methodMap: {0: 'debug', 1: 'info', 2: 'warn', 3: 'error'},
|
109
|
-
|
110
|
-
// can be overridden in the host environment
|
111
|
-
log: function(level, obj) {
|
112
|
-
if (Handlebars.logger.level <= level) {
|
113
|
-
var method = Handlebars.logger.methodMap[level];
|
114
|
-
if (typeof console !== 'undefined' && console[method]) {
|
115
|
-
console[method].call(console, obj);
|
116
|
-
}
|
117
|
-
}
|
118
|
-
}
|
119
|
-
};
|
120
|
-
|
121
|
-
Handlebars.log = function(level, obj) { Handlebars.logger.log(level, obj); };
|
122
|
-
|
123
65
|
Handlebars.registerHelper('each', function(context, options) {
|
124
66
|
var fn = options.fn, inverse = options.inverse;
|
125
|
-
var
|
67
|
+
var ret = "", data;
|
126
68
|
|
127
69
|
if (options.data) {
|
128
70
|
data = Handlebars.createFrame(options.data);
|
129
71
|
}
|
130
72
|
|
131
|
-
if(context &&
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
ret = ret + fn(context[i], { data: data });
|
136
|
-
}
|
137
|
-
} else {
|
138
|
-
for(var key in context) {
|
139
|
-
if(context.hasOwnProperty(key)) {
|
140
|
-
if(data) { data.key = key; }
|
141
|
-
ret = ret + fn(context[key], {data: data});
|
142
|
-
i++;
|
143
|
-
}
|
144
|
-
}
|
73
|
+
if(context && context.length > 0) {
|
74
|
+
for(var i=0, j=context.length; i<j; i++) {
|
75
|
+
if (data) { data.index = i; }
|
76
|
+
ret = ret + fn(context[i], { data: data });
|
145
77
|
}
|
146
|
-
}
|
147
|
-
|
148
|
-
if(i === 0){
|
78
|
+
} else {
|
149
79
|
ret = inverse(this);
|
150
80
|
}
|
151
|
-
|
152
81
|
return ret;
|
153
82
|
});
|
154
83
|
|
@@ -164,128 +93,125 @@ Handlebars.registerHelper('if', function(context, options) {
|
|
164
93
|
});
|
165
94
|
|
166
95
|
Handlebars.registerHelper('unless', function(context, options) {
|
167
|
-
|
96
|
+
var fn = options.fn, inverse = options.inverse;
|
97
|
+
options.fn = inverse;
|
98
|
+
options.inverse = fn;
|
99
|
+
|
100
|
+
return Handlebars.helpers['if'].call(this, context, options);
|
168
101
|
});
|
169
102
|
|
170
103
|
Handlebars.registerHelper('with', function(context, options) {
|
171
|
-
|
104
|
+
return options.fn(context);
|
172
105
|
});
|
173
106
|
|
174
|
-
Handlebars.registerHelper('log', function(context
|
175
|
-
|
176
|
-
Handlebars.log(level, context);
|
107
|
+
Handlebars.registerHelper('log', function(context) {
|
108
|
+
Handlebars.log(context);
|
177
109
|
});
|
110
|
+
|
111
|
+
}(this.Handlebars));
|
178
112
|
;
|
179
113
|
// lib/handlebars/compiler/parser.js
|
180
114
|
/* Jison generated parser */
|
181
115
|
var handlebars = (function(){
|
182
116
|
var parser = {trace: function trace() { },
|
183
117
|
yy: {},
|
184
|
-
symbols_: {"error":2,"root":3,"program":4,"EOF":5,"
|
185
|
-
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",
|
186
|
-
productions_: [0,[3,2],[4,
|
118
|
+
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,"DATA":27,"param":28,"STRING":29,"INTEGER":30,"BOOLEAN":31,"hashSegments":32,"hashSegment":33,"ID":34,"EQUALS":35,"pathSegments":36,"SEP":37,"$accept":0,"$end":1},
|
119
|
+
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:"DATA",29:"STRING",30:"INTEGER",31:"BOOLEAN",34:"ID",35:"EQUALS",37:"SEP"},
|
120
|
+
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],[17,1],[25,2],[25,1],[28,1],[28,1],[28,1],[28,1],[28,1],[26,1],[32,2],[32,1],[33,3],[33,3],[33,3],[33,3],[33,3],[21,1],[36,3],[36,1]],
|
187
121
|
performAction: function anonymous(yytext,yyleng,yylineno,yy,yystate,$$,_$) {
|
188
122
|
|
189
123
|
var $0 = $$.length - 1;
|
190
124
|
switch (yystate) {
|
191
125
|
case 1: return $$[$0-1];
|
192
126
|
break;
|
193
|
-
case 2: this.$ = new yy.ProgramNode([], $$[$0]);
|
127
|
+
case 2: this.$ = new yy.ProgramNode($$[$0-2], $$[$0]);
|
194
128
|
break;
|
195
|
-
case 3: this.$ = new yy.ProgramNode($$[$0
|
129
|
+
case 3: this.$ = new yy.ProgramNode($$[$0]);
|
196
130
|
break;
|
197
|
-
case 4: this.$ = new yy.ProgramNode(
|
131
|
+
case 4: this.$ = new yy.ProgramNode([]);
|
198
132
|
break;
|
199
|
-
case 5: this.$ =
|
133
|
+
case 5: this.$ = [$$[$0]];
|
200
134
|
break;
|
201
|
-
case 6: this.$ =
|
135
|
+
case 6: $$[$0-1].push($$[$0]); this.$ = $$[$0-1];
|
202
136
|
break;
|
203
|
-
case 7: this.$ = new yy.
|
137
|
+
case 7: this.$ = new yy.BlockNode($$[$0-2], $$[$0-1].inverse, $$[$0-1], $$[$0]);
|
204
138
|
break;
|
205
|
-
case 8: this.$ = [$$[$0]];
|
139
|
+
case 8: this.$ = new yy.BlockNode($$[$0-2], $$[$0-1], $$[$0-1].inverse, $$[$0]);
|
206
140
|
break;
|
207
|
-
case 9:
|
141
|
+
case 9: this.$ = $$[$0];
|
208
142
|
break;
|
209
|
-
case 10: this.$ =
|
143
|
+
case 10: this.$ = $$[$0];
|
210
144
|
break;
|
211
|
-
case 11: this.$ = new yy.
|
145
|
+
case 11: this.$ = new yy.ContentNode($$[$0]);
|
212
146
|
break;
|
213
|
-
case 12: this.$ = $$[$0];
|
147
|
+
case 12: this.$ = new yy.CommentNode($$[$0]);
|
214
148
|
break;
|
215
|
-
case 13: this.$ = $$[$0];
|
149
|
+
case 13: this.$ = new yy.MustacheNode($$[$0-1][0], $$[$0-1][1]);
|
216
150
|
break;
|
217
|
-
case 14: this.$ = new yy.
|
151
|
+
case 14: this.$ = new yy.MustacheNode($$[$0-1][0], $$[$0-1][1]);
|
218
152
|
break;
|
219
|
-
case 15: this.$ =
|
153
|
+
case 15: this.$ = $$[$0-1];
|
220
154
|
break;
|
221
155
|
case 16: this.$ = new yy.MustacheNode($$[$0-1][0], $$[$0-1][1]);
|
222
156
|
break;
|
223
|
-
case 17: this.$ = new yy.MustacheNode($$[$0-1][0], $$[$0-1][1]);
|
224
|
-
break;
|
225
|
-
case 18: this.$ = $$[$0-1];
|
157
|
+
case 17: this.$ = new yy.MustacheNode($$[$0-1][0], $$[$0-1][1], true);
|
226
158
|
break;
|
227
|
-
case
|
159
|
+
case 18: this.$ = new yy.PartialNode($$[$0-1]);
|
228
160
|
break;
|
229
|
-
case
|
161
|
+
case 19: this.$ = new yy.PartialNode($$[$0-2], $$[$0-1]);
|
230
162
|
break;
|
231
|
-
case
|
163
|
+
case 20:
|
232
164
|
break;
|
233
|
-
case
|
165
|
+
case 21: this.$ = [[$$[$0-2]].concat($$[$0-1]), $$[$0]];
|
234
166
|
break;
|
235
|
-
case
|
167
|
+
case 22: this.$ = [[$$[$0-1]].concat($$[$0]), null];
|
236
168
|
break;
|
237
|
-
case
|
169
|
+
case 23: this.$ = [[$$[$0-1]], $$[$0]];
|
238
170
|
break;
|
239
|
-
case
|
171
|
+
case 24: this.$ = [[$$[$0]], null];
|
240
172
|
break;
|
241
|
-
case
|
173
|
+
case 25: this.$ = [[new yy.DataNode($$[$0])], null];
|
242
174
|
break;
|
243
|
-
case
|
175
|
+
case 26: $$[$0-1].push($$[$0]); this.$ = $$[$0-1];
|
244
176
|
break;
|
245
|
-
case
|
177
|
+
case 27: this.$ = [$$[$0]];
|
246
178
|
break;
|
247
|
-
case
|
179
|
+
case 28: this.$ = $$[$0];
|
248
180
|
break;
|
249
|
-
case
|
181
|
+
case 29: this.$ = new yy.StringNode($$[$0]);
|
250
182
|
break;
|
251
|
-
case
|
183
|
+
case 30: this.$ = new yy.IntegerNode($$[$0]);
|
252
184
|
break;
|
253
|
-
case
|
185
|
+
case 31: this.$ = new yy.BooleanNode($$[$0]);
|
254
186
|
break;
|
255
|
-
case
|
187
|
+
case 32: this.$ = new yy.DataNode($$[$0]);
|
256
188
|
break;
|
257
|
-
case
|
189
|
+
case 33: this.$ = new yy.HashNode($$[$0]);
|
258
190
|
break;
|
259
|
-
case
|
191
|
+
case 34: $$[$0-1].push($$[$0]); this.$ = $$[$0-1];
|
260
192
|
break;
|
261
|
-
case
|
193
|
+
case 35: this.$ = [$$[$0]];
|
262
194
|
break;
|
263
|
-
case
|
195
|
+
case 36: this.$ = [$$[$0-2], $$[$0]];
|
264
196
|
break;
|
265
|
-
case
|
197
|
+
case 37: this.$ = [$$[$0-2], new yy.StringNode($$[$0])];
|
266
198
|
break;
|
267
|
-
case
|
199
|
+
case 38: this.$ = [$$[$0-2], new yy.IntegerNode($$[$0])];
|
268
200
|
break;
|
269
|
-
case
|
201
|
+
case 39: this.$ = [$$[$0-2], new yy.BooleanNode($$[$0])];
|
270
202
|
break;
|
271
|
-
case
|
203
|
+
case 40: this.$ = [$$[$0-2], new yy.DataNode($$[$0])];
|
272
204
|
break;
|
273
|
-
case
|
205
|
+
case 41: this.$ = new yy.IdNode($$[$0]);
|
274
206
|
break;
|
275
|
-
case
|
207
|
+
case 42: $$[$0-2].push($$[$0]); this.$ = $$[$0-2];
|
276
208
|
break;
|
277
|
-
case
|
278
|
-
break;
|
279
|
-
case 45: this.$ = new yy.IdNode($$[$0]);
|
280
|
-
break;
|
281
|
-
case 46: $$[$0-2].push($$[$0]); this.$ = $$[$0-2];
|
282
|
-
break;
|
283
|
-
case 47: this.$ = [$$[$0]];
|
209
|
+
case 43: this.$ = [$$[$0]];
|
284
210
|
break;
|
285
211
|
}
|
286
212
|
},
|
287
|
-
table: [{3:1,4:2,5:[2,
|
288
|
-
defaultActions: {
|
213
|
+
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,27:[1,24],34:[1,26],36:25},{17:27,21:23,27:[1,24],34:[1,26],36:25},{17:28,21:23,27:[1,24],34:[1,26],36:25},{17:29,21:23,27:[1,24],34:[1,26],36:25},{21:30,34:[1,26],36:25},{1:[2,1]},{6:31,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,32],21:23,27:[1,24],34:[1,26],36:25},{10:33,20:[1,34]},{10:35,20:[1,34]},{18:[1,36]},{18:[2,24],21:41,25:37,26:38,27:[1,45],28:39,29:[1,42],30:[1,43],31:[1,44],32:40,33:46,34:[1,47],36:25},{18:[2,25]},{18:[2,41],27:[2,41],29:[2,41],30:[2,41],31:[2,41],34:[2,41],37:[1,48]},{18:[2,43],27:[2,43],29:[2,43],30:[2,43],31:[2,43],34:[2,43],37:[2,43]},{18:[1,49]},{18:[1,50]},{18:[1,51]},{18:[1,52],21:53,34:[1,26],36: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:54,34:[1,26],36: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,22],21:41,26:55,27:[1,45],28:56,29:[1,42],30:[1,43],31:[1,44],32:40,33:46,34:[1,47],36:25},{18:[2,23]},{18:[2,27],27:[2,27],29:[2,27],30:[2,27],31:[2,27],34:[2,27]},{18:[2,33],33:57,34:[1,58]},{18:[2,28],27:[2,28],29:[2,28],30:[2,28],31:[2,28],34:[2,28]},{18:[2,29],27:[2,29],29:[2,29],30:[2,29],31:[2,29],34:[2,29]},{18:[2,30],27:[2,30],29:[2,30],30:[2,30],31:[2,30],34:[2,30]},{18:[2,31],27:[2,31],29:[2,31],30:[2,31],31:[2,31],34:[2,31]},{18:[2,32],27:[2,32],29:[2,32],30:[2,32],31:[2,32],34:[2,32]},{18:[2,35],34:[2,35]},{18:[2,43],27:[2,43],29:[2,43],30:[2,43],31:[2,43],34:[2,43],35:[1,59],37:[2,43]},{34:[1,60]},{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,61]},{18:[1,62]},{18:[2,21]},{18:[2,26],27:[2,26],29:[2,26],30:[2,26],31:[2,26],34:[2,26]},{18:[2,34],34:[2,34]},{35:[1,59]},{21:63,27:[1,67],29:[1,64],30:[1,65],31:[1,66],34:[1,26],36:25},{18:[2,42],27:[2,42],29:[2,42],30:[2,42],31:[2,42],34:[2,42],37:[2,42]},{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,36],34:[2,36]},{18:[2,37],34:[2,37]},{18:[2,38],34:[2,38]},{18:[2,39],34:[2,39]},{18:[2,40],34:[2,40]}],
|
214
|
+
defaultActions: {16:[2,1],24:[2,25],38:[2,23],55:[2,21]},
|
289
215
|
parseError: function parseError(str, hash) {
|
290
216
|
throw new Error(str);
|
291
217
|
},
|
@@ -566,241 +492,250 @@ lexer.performAction = function anonymous(yy,yy_,$avoiding_name_collisions,YY_STA
|
|
566
492
|
|
567
493
|
var YYSTATE=YY_START;
|
568
494
|
switch($avoiding_name_collisions) {
|
569
|
-
case 0:
|
570
|
-
break;
|
571
|
-
case 1:
|
495
|
+
case 0:
|
572
496
|
if(yy_.yytext.slice(-1) !== "\\") this.begin("mu");
|
573
497
|
if(yy_.yytext.slice(-1) === "\\") yy_.yytext = yy_.yytext.substr(0,yy_.yyleng-1), this.begin("emu");
|
574
498
|
if(yy_.yytext) return 14;
|
575
499
|
|
576
500
|
break;
|
577
|
-
case
|
501
|
+
case 1: return 14;
|
578
502
|
break;
|
579
|
-
case
|
503
|
+
case 2:
|
580
504
|
if(yy_.yytext.slice(-1) !== "\\") this.popState();
|
581
505
|
if(yy_.yytext.slice(-1) === "\\") yy_.yytext = yy_.yytext.substr(0,yy_.yyleng-1);
|
582
506
|
return 14;
|
583
507
|
|
584
508
|
break;
|
585
|
-
case
|
586
|
-
break;
|
587
|
-
case 5: this.begin("par"); return 24;
|
588
|
-
break;
|
589
|
-
case 6: return 16;
|
590
|
-
break;
|
591
|
-
case 7: return 20;
|
592
|
-
break;
|
593
|
-
case 8: return 19;
|
509
|
+
case 3: return 24;
|
594
510
|
break;
|
595
|
-
case
|
511
|
+
case 4: return 16;
|
596
512
|
break;
|
597
|
-
case
|
513
|
+
case 5: return 20;
|
598
514
|
break;
|
599
|
-
case
|
515
|
+
case 6: return 19;
|
600
516
|
break;
|
601
|
-
case
|
517
|
+
case 7: return 19;
|
602
518
|
break;
|
603
|
-
case
|
519
|
+
case 8: return 23;
|
604
520
|
break;
|
605
|
-
case
|
521
|
+
case 9: return 23;
|
606
522
|
break;
|
607
|
-
case
|
523
|
+
case 10: yy_.yytext = yy_.yytext.substr(3,yy_.yyleng-5); this.popState(); return 15;
|
608
524
|
break;
|
609
|
-
case
|
525
|
+
case 11: return 22;
|
610
526
|
break;
|
611
|
-
case
|
527
|
+
case 12: return 35;
|
612
528
|
break;
|
613
|
-
case
|
529
|
+
case 13: return 34;
|
614
530
|
break;
|
615
|
-
case
|
531
|
+
case 14: return 34;
|
616
532
|
break;
|
617
|
-
case
|
533
|
+
case 15: return 37;
|
618
534
|
break;
|
619
|
-
case
|
535
|
+
case 16: /*ignore whitespace*/
|
620
536
|
break;
|
621
|
-
case
|
537
|
+
case 17: this.popState(); return 18;
|
622
538
|
break;
|
623
|
-
case
|
539
|
+
case 18: this.popState(); return 18;
|
624
540
|
break;
|
625
|
-
case
|
541
|
+
case 19: yy_.yytext = yy_.yytext.substr(1,yy_.yyleng-2).replace(/\\"/g,'"'); return 29;
|
626
542
|
break;
|
627
|
-
case
|
543
|
+
case 20: yy_.yytext = yy_.yytext.substr(1,yy_.yyleng-2).replace(/\\"/g,'"'); return 29;
|
628
544
|
break;
|
629
|
-
case
|
545
|
+
case 21: yy_.yytext = yy_.yytext.substr(1); return 27;
|
630
546
|
break;
|
631
|
-
case
|
547
|
+
case 22: return 31;
|
632
548
|
break;
|
633
|
-
case
|
549
|
+
case 23: return 31;
|
634
550
|
break;
|
635
|
-
case
|
551
|
+
case 24: return 30;
|
636
552
|
break;
|
637
|
-
case
|
553
|
+
case 25: return 34;
|
638
554
|
break;
|
639
|
-
case
|
555
|
+
case 26: yy_.yytext = yy_.yytext.substr(1, yy_.yyleng-2); return 34;
|
640
556
|
break;
|
641
|
-
case
|
557
|
+
case 27: return 'INVALID';
|
642
558
|
break;
|
643
|
-
case
|
559
|
+
case 28: return 5;
|
644
560
|
break;
|
645
561
|
}
|
646
562
|
};
|
647
|
-
lexer.rules = [/^(
|
648
|
-
lexer.conditions = {"mu":{"rules":[5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28
|
563
|
+
lexer.rules = [/^(?:[^\x00]*?(?=(\{\{)))/,/^(?:[^\x00]+)/,/^(?:[^\x00]{2,}?(?=(\{\{|$)))/,/^(?:\{\{>)/,/^(?:\{\{#)/,/^(?:\{\{\/)/,/^(?:\{\{\^)/,/^(?:\{\{\s*else\b)/,/^(?:\{\{\{)/,/^(?:\{\{&)/,/^(?:\{\{![\s\S]*?\}\})/,/^(?:\{\{)/,/^(?:=)/,/^(?:\.(?=[} ]))/,/^(?:\.\.)/,/^(?:[\/.])/,/^(?:\s+)/,/^(?:\}\}\})/,/^(?:\}\})/,/^(?:"(\\["]|[^"])*")/,/^(?:'(\\[']|[^'])*')/,/^(?:@[a-zA-Z]+)/,/^(?:true(?=[}\s]))/,/^(?:false(?=[}\s]))/,/^(?:[0-9]+(?=[}\s]))/,/^(?:[a-zA-Z0-9_$-]+(?=[=}\s\/.]))/,/^(?:\[[^\]]*\])/,/^(?:.)/,/^(?:$)/];
|
564
|
+
lexer.conditions = {"mu":{"rules":[3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28],"inclusive":false},"emu":{"rules":[2],"inclusive":false},"INITIAL":{"rules":[0,1,28],"inclusive":true}};
|
649
565
|
return lexer;})();
|
650
566
|
parser.lexer = lexer;
|
651
567
|
function Parser () { this.yy = {}; }Parser.prototype = parser;parser.Parser = Parser;
|
652
568
|
return new Parser;
|
653
|
-
})()
|
569
|
+
})();
|
570
|
+
if (typeof require !== 'undefined' && typeof exports !== 'undefined') {
|
571
|
+
exports.parser = handlebars;
|
572
|
+
exports.Parser = handlebars.Parser;
|
573
|
+
exports.parse = function () { return handlebars.parse.apply(handlebars, arguments); };
|
574
|
+
exports.main = function commonjsMain(args) {
|
575
|
+
if (!args[1])
|
576
|
+
throw new Error('Usage: '+args[0]+' FILE');
|
577
|
+
var source, cwd;
|
578
|
+
if (typeof process !== 'undefined') {
|
579
|
+
source = require('fs').readFileSync(require('path').resolve(args[1]), "utf8");
|
580
|
+
} else {
|
581
|
+
source = require("file").path(require("file").cwd()).join(args[1]).read({charset: "utf-8"});
|
582
|
+
}
|
583
|
+
return exports.parser.parse(source);
|
584
|
+
};
|
585
|
+
if (typeof module !== 'undefined' && require.main === module) {
|
586
|
+
exports.main(typeof process !== 'undefined' ? process.argv.slice(1) : require("system").args);
|
587
|
+
}
|
588
|
+
};
|
589
|
+
;
|
654
590
|
// lib/handlebars/compiler/base.js
|
655
|
-
|
656
591
|
Handlebars.Parser = handlebars;
|
657
592
|
|
658
|
-
Handlebars.parse = function(
|
593
|
+
Handlebars.parse = function(string) {
|
594
|
+
Handlebars.Parser.yy = Handlebars.AST;
|
595
|
+
return Handlebars.Parser.parse(string);
|
596
|
+
};
|
659
597
|
|
660
|
-
|
661
|
-
|
598
|
+
Handlebars.print = function(ast) {
|
599
|
+
return new Handlebars.PrintVisitor().accept(ast);
|
600
|
+
};
|
662
601
|
|
663
|
-
|
664
|
-
|
602
|
+
Handlebars.logger = {
|
603
|
+
DEBUG: 0, INFO: 1, WARN: 2, ERROR: 3, level: 3,
|
604
|
+
|
605
|
+
// override in the host environment
|
606
|
+
log: function(level, str) {}
|
665
607
|
};
|
608
|
+
|
609
|
+
Handlebars.log = function(level, str) { Handlebars.logger.log(level, str); };
|
666
610
|
;
|
667
611
|
// lib/handlebars/compiler/ast.js
|
668
|
-
|
612
|
+
(function() {
|
669
613
|
|
670
|
-
Handlebars.AST
|
671
|
-
this.type = "program";
|
672
|
-
this.statements = statements;
|
673
|
-
if(inverse) { this.inverse = new Handlebars.AST.ProgramNode(inverse); }
|
674
|
-
};
|
614
|
+
Handlebars.AST = {};
|
675
615
|
|
676
|
-
Handlebars.AST.
|
677
|
-
|
678
|
-
|
679
|
-
|
616
|
+
Handlebars.AST.ProgramNode = function(statements, inverse) {
|
617
|
+
this.type = "program";
|
618
|
+
this.statements = statements;
|
619
|
+
if(inverse) { this.inverse = new Handlebars.AST.ProgramNode(inverse); }
|
620
|
+
};
|
680
621
|
|
681
|
-
|
682
|
-
|
622
|
+
Handlebars.AST.MustacheNode = function(rawParams, hash, unescaped) {
|
623
|
+
this.type = "mustache";
|
624
|
+
this.escaped = !unescaped;
|
625
|
+
this.hash = hash;
|
683
626
|
|
684
|
-
|
685
|
-
|
686
|
-
var eligibleHelper = this.eligibleHelper = id.isSimple;
|
627
|
+
var id = this.id = rawParams[0];
|
628
|
+
var params = this.params = rawParams.slice(1);
|
687
629
|
|
688
|
-
|
689
|
-
|
690
|
-
|
691
|
-
this.isHelper = eligibleHelper && (params.length || hash);
|
630
|
+
// a mustache is an eligible helper if:
|
631
|
+
// * its id is simple (a single part, not `this` or `..`)
|
632
|
+
var eligibleHelper = this.eligibleHelper = id.isSimple;
|
692
633
|
|
693
|
-
|
694
|
-
|
695
|
-
|
696
|
-
|
634
|
+
// a mustache is definitely a helper if:
|
635
|
+
// * it is an eligible helper, and
|
636
|
+
// * it has at least one parameter or hash segment
|
637
|
+
this.isHelper = eligibleHelper && (params.length || hash);
|
697
638
|
|
698
|
-
|
699
|
-
|
700
|
-
|
701
|
-
|
702
|
-
|
639
|
+
// if a mustache is an eligible helper but not a definite
|
640
|
+
// helper, it is ambiguous, and will be resolved in a later
|
641
|
+
// pass or at runtime.
|
642
|
+
};
|
643
|
+
|
644
|
+
Handlebars.AST.PartialNode = function(id, context) {
|
645
|
+
this.type = "partial";
|
646
|
+
|
647
|
+
// TODO: disallow complex IDs
|
648
|
+
|
649
|
+
this.id = id;
|
650
|
+
this.context = context;
|
651
|
+
};
|
703
652
|
|
704
|
-
Handlebars.AST.BlockNode = function(mustache, program, inverse, close) {
|
705
653
|
var verifyMatch = function(open, close) {
|
706
654
|
if(open.original !== close.original) {
|
707
655
|
throw new Handlebars.Exception(open.original + " doesn't match " + close.original);
|
708
656
|
}
|
709
657
|
};
|
710
658
|
|
711
|
-
|
712
|
-
|
713
|
-
|
714
|
-
|
715
|
-
|
659
|
+
Handlebars.AST.BlockNode = function(mustache, program, inverse, close) {
|
660
|
+
verifyMatch(mustache.id, close);
|
661
|
+
this.type = "block";
|
662
|
+
this.mustache = mustache;
|
663
|
+
this.program = program;
|
664
|
+
this.inverse = inverse;
|
716
665
|
|
717
|
-
|
718
|
-
|
719
|
-
|
720
|
-
};
|
666
|
+
if (this.inverse && !this.program) {
|
667
|
+
this.isInverse = true;
|
668
|
+
}
|
669
|
+
};
|
721
670
|
|
722
|
-
Handlebars.AST.ContentNode = function(string) {
|
723
|
-
|
724
|
-
|
725
|
-
};
|
671
|
+
Handlebars.AST.ContentNode = function(string) {
|
672
|
+
this.type = "content";
|
673
|
+
this.string = string;
|
674
|
+
};
|
726
675
|
|
727
|
-
Handlebars.AST.HashNode = function(pairs) {
|
728
|
-
|
729
|
-
|
730
|
-
};
|
676
|
+
Handlebars.AST.HashNode = function(pairs) {
|
677
|
+
this.type = "hash";
|
678
|
+
this.pairs = pairs;
|
679
|
+
};
|
731
680
|
|
732
|
-
Handlebars.AST.IdNode = function(parts) {
|
733
|
-
|
734
|
-
|
681
|
+
Handlebars.AST.IdNode = function(parts) {
|
682
|
+
this.type = "ID";
|
683
|
+
this.original = parts.join(".");
|
735
684
|
|
736
|
-
|
685
|
+
var dig = [], depth = 0;
|
737
686
|
|
738
|
-
|
739
|
-
|
687
|
+
for(var i=0,l=parts.length; i<l; i++) {
|
688
|
+
var part = parts[i];
|
740
689
|
|
741
|
-
|
742
|
-
if
|
743
|
-
else
|
744
|
-
else { this.isScoped = true; }
|
690
|
+
if(part === "..") { depth++; }
|
691
|
+
else if(part === "." || part === "this") { this.isScoped = true; }
|
692
|
+
else { dig.push(part); }
|
745
693
|
}
|
746
|
-
else { dig.push(part); }
|
747
|
-
}
|
748
|
-
|
749
|
-
this.parts = dig;
|
750
|
-
this.string = dig.join('.');
|
751
|
-
this.depth = depth;
|
752
694
|
|
753
|
-
|
754
|
-
|
755
|
-
|
695
|
+
this.parts = dig;
|
696
|
+
this.string = dig.join('.');
|
697
|
+
this.depth = depth;
|
756
698
|
|
757
|
-
|
758
|
-
|
699
|
+
// an ID is simple if it only has one part, and that part is not
|
700
|
+
// `..` or `this`.
|
701
|
+
this.isSimple = parts.length === 1 && !this.isScoped && depth === 0;
|
702
|
+
};
|
759
703
|
|
760
|
-
Handlebars.AST.
|
761
|
-
|
762
|
-
|
763
|
-
};
|
704
|
+
Handlebars.AST.DataNode = function(id) {
|
705
|
+
this.type = "DATA";
|
706
|
+
this.id = id;
|
707
|
+
};
|
764
708
|
|
765
|
-
Handlebars.AST.
|
766
|
-
|
767
|
-
|
768
|
-
};
|
709
|
+
Handlebars.AST.StringNode = function(string) {
|
710
|
+
this.type = "STRING";
|
711
|
+
this.string = string;
|
712
|
+
};
|
769
713
|
|
770
|
-
Handlebars.AST.
|
771
|
-
|
772
|
-
|
773
|
-
|
774
|
-
};
|
714
|
+
Handlebars.AST.IntegerNode = function(integer) {
|
715
|
+
this.type = "INTEGER";
|
716
|
+
this.integer = integer;
|
717
|
+
};
|
775
718
|
|
776
|
-
Handlebars.AST.
|
777
|
-
|
778
|
-
|
779
|
-
|
780
|
-
};
|
719
|
+
Handlebars.AST.BooleanNode = function(bool) {
|
720
|
+
this.type = "BOOLEAN";
|
721
|
+
this.bool = bool;
|
722
|
+
};
|
781
723
|
|
782
|
-
Handlebars.AST.
|
783
|
-
|
784
|
-
|
785
|
-
|
786
|
-
};
|
724
|
+
Handlebars.AST.CommentNode = function(comment) {
|
725
|
+
this.type = "comment";
|
726
|
+
this.comment = comment;
|
727
|
+
};
|
787
728
|
|
788
|
-
|
789
|
-
this.type = "comment";
|
790
|
-
this.comment = comment;
|
791
|
-
};
|
792
|
-
;
|
729
|
+
})();;
|
793
730
|
// lib/handlebars/utils.js
|
794
|
-
|
795
|
-
var errorProps = ['description', 'fileName', 'lineNumber', 'message', 'name', 'number', 'stack'];
|
796
|
-
|
797
731
|
Handlebars.Exception = function(message) {
|
798
732
|
var tmp = Error.prototype.constructor.apply(this, arguments);
|
799
733
|
|
800
|
-
|
801
|
-
|
802
|
-
this[errorProps[idx]] = tmp[errorProps[idx]];
|
734
|
+
for (var p in tmp) {
|
735
|
+
if (tmp.hasOwnProperty(p)) { this[p] = tmp[p]; }
|
803
736
|
}
|
737
|
+
|
738
|
+
this.message = tmp.message;
|
804
739
|
};
|
805
740
|
Handlebars.Exception.prototype = new Error();
|
806
741
|
|
@@ -812,1326 +747,1101 @@ Handlebars.SafeString.prototype.toString = function() {
|
|
812
747
|
return this.string.toString();
|
813
748
|
};
|
814
749
|
|
815
|
-
|
816
|
-
|
817
|
-
|
818
|
-
|
819
|
-
|
820
|
-
|
821
|
-
|
822
|
-
|
750
|
+
(function() {
|
751
|
+
var escape = {
|
752
|
+
"&": "&",
|
753
|
+
"<": "<",
|
754
|
+
">": ">",
|
755
|
+
'"': """,
|
756
|
+
"'": "'",
|
757
|
+
"`": "`"
|
758
|
+
};
|
823
759
|
|
824
|
-
var badChars = /[&<>"'`]/g;
|
825
|
-
var possible = /[&<>"'`]/;
|
760
|
+
var badChars = /[&<>"'`]/g;
|
761
|
+
var possible = /[&<>"'`]/;
|
826
762
|
|
827
|
-
var escapeChar = function(chr) {
|
828
|
-
|
829
|
-
};
|
763
|
+
var escapeChar = function(chr) {
|
764
|
+
return escape[chr] || "&";
|
765
|
+
};
|
830
766
|
|
831
|
-
Handlebars.Utils = {
|
832
|
-
|
833
|
-
|
834
|
-
if(
|
835
|
-
|
767
|
+
Handlebars.Utils = {
|
768
|
+
escapeExpression: function(string) {
|
769
|
+
// don't escape SafeStrings, since they're already safe
|
770
|
+
if (string instanceof Handlebars.SafeString) {
|
771
|
+
return string.toString();
|
772
|
+
} else if (string == null || string === false) {
|
773
|
+
return "";
|
836
774
|
}
|
837
|
-
}
|
838
|
-
},
|
839
|
-
|
840
|
-
escapeExpression: function(string) {
|
841
|
-
// don't escape SafeStrings, since they're already safe
|
842
|
-
if (string instanceof Handlebars.SafeString) {
|
843
|
-
return string.toString();
|
844
|
-
} else if (string == null || string === false) {
|
845
|
-
return "";
|
846
|
-
}
|
847
|
-
|
848
|
-
// Force a string conversion as this will be done by the append regardless and
|
849
|
-
// the regex test will do this transparently behind the scenes, causing issues if
|
850
|
-
// an object's to string has escaped characters in it.
|
851
|
-
string = string.toString();
|
852
775
|
|
853
|
-
|
854
|
-
|
855
|
-
|
776
|
+
if(!possible.test(string)) { return string; }
|
777
|
+
return string.replace(badChars, escapeChar);
|
778
|
+
},
|
856
779
|
|
857
|
-
|
858
|
-
|
859
|
-
|
860
|
-
|
861
|
-
|
862
|
-
|
863
|
-
|
780
|
+
isEmpty: function(value) {
|
781
|
+
if (typeof value === "undefined") {
|
782
|
+
return true;
|
783
|
+
} else if (value === null) {
|
784
|
+
return true;
|
785
|
+
} else if (value === false) {
|
786
|
+
return true;
|
787
|
+
} else if(Object.prototype.toString.call(value) === "[object Array]" && value.length === 0) {
|
788
|
+
return true;
|
789
|
+
} else {
|
790
|
+
return false;
|
791
|
+
}
|
864
792
|
}
|
865
|
-
}
|
866
|
-
}
|
867
|
-
;
|
793
|
+
};
|
794
|
+
})();;
|
868
795
|
// lib/handlebars/compiler/compiler.js
|
869
796
|
|
870
797
|
/*jshint eqnull:true*/
|
871
|
-
|
872
|
-
|
798
|
+
Handlebars.Compiler = function() {};
|
799
|
+
Handlebars.JavaScriptCompiler = function() {};
|
873
800
|
|
874
|
-
|
875
|
-
//
|
876
|
-
//
|
877
|
-
//
|
801
|
+
(function(Compiler, JavaScriptCompiler) {
|
802
|
+
// the foundHelper register will disambiguate helper lookup from finding a
|
803
|
+
// function in a context. This is necessary for mustache compatibility, which
|
804
|
+
// requires that context functions in blocks are evaluated by blockHelperMissing,
|
805
|
+
// and then proceed as if the resulting value was provided to blockHelperMissing.
|
878
806
|
|
879
|
-
Compiler.prototype = {
|
880
|
-
|
807
|
+
Compiler.prototype = {
|
808
|
+
compiler: Compiler,
|
881
809
|
|
882
|
-
|
883
|
-
|
810
|
+
disassemble: function() {
|
811
|
+
var opcodes = this.opcodes, opcode, out = [], params, param;
|
884
812
|
|
885
|
-
|
886
|
-
|
813
|
+
for (var i=0, l=opcodes.length; i<l; i++) {
|
814
|
+
opcode = opcodes[i];
|
887
815
|
|
888
|
-
|
889
|
-
|
890
|
-
|
891
|
-
|
892
|
-
|
893
|
-
|
894
|
-
|
895
|
-
|
816
|
+
if (opcode.opcode === 'DECLARE') {
|
817
|
+
out.push("DECLARE " + opcode.name + "=" + opcode.value);
|
818
|
+
} else {
|
819
|
+
params = [];
|
820
|
+
for (var j=0; j<opcode.args.length; j++) {
|
821
|
+
param = opcode.args[j];
|
822
|
+
if (typeof param === "string") {
|
823
|
+
param = "\"" + param.replace("\n", "\\n") + "\"";
|
824
|
+
}
|
825
|
+
params.push(param);
|
896
826
|
}
|
897
|
-
|
827
|
+
out.push(opcode.opcode + " " + params.join(" "));
|
898
828
|
}
|
899
|
-
out.push(opcode.opcode + " " + params.join(" "));
|
900
829
|
}
|
901
|
-
}
|
902
830
|
|
903
|
-
|
904
|
-
|
905
|
-
equals: function(other) {
|
906
|
-
var len = this.opcodes.length;
|
907
|
-
if (other.opcodes.length !== len) {
|
908
|
-
return false;
|
909
|
-
}
|
831
|
+
return out.join("\n");
|
832
|
+
},
|
910
833
|
|
911
|
-
|
912
|
-
|
913
|
-
|
914
|
-
|
915
|
-
|
916
|
-
|
917
|
-
|
918
|
-
|
919
|
-
|
834
|
+
guid: 0,
|
835
|
+
|
836
|
+
compile: function(program, options) {
|
837
|
+
this.children = [];
|
838
|
+
this.depths = {list: []};
|
839
|
+
this.options = options;
|
840
|
+
|
841
|
+
// These changes will propagate to the other compiler components
|
842
|
+
var knownHelpers = this.options.knownHelpers;
|
843
|
+
this.options.knownHelpers = {
|
844
|
+
'helperMissing': true,
|
845
|
+
'blockHelperMissing': true,
|
846
|
+
'each': true,
|
847
|
+
'if': true,
|
848
|
+
'unless': true,
|
849
|
+
'with': true,
|
850
|
+
'log': true
|
851
|
+
};
|
852
|
+
if (knownHelpers) {
|
853
|
+
for (var name in knownHelpers) {
|
854
|
+
this.options.knownHelpers[name] = knownHelpers[name];
|
920
855
|
}
|
921
856
|
}
|
922
|
-
}
|
923
|
-
|
924
|
-
len = this.children.length;
|
925
|
-
if (other.children.length !== len) {
|
926
|
-
return false;
|
927
|
-
}
|
928
|
-
for (i = 0; i < len; i++) {
|
929
|
-
if (!this.children[i].equals(other.children[i])) {
|
930
|
-
return false;
|
931
|
-
}
|
932
|
-
}
|
933
|
-
|
934
|
-
return true;
|
935
|
-
},
|
936
857
|
|
937
|
-
|
938
|
-
|
939
|
-
compile: function(program, options) {
|
940
|
-
this.children = [];
|
941
|
-
this.depths = {list: []};
|
942
|
-
this.options = options;
|
943
|
-
|
944
|
-
// These changes will propagate to the other compiler components
|
945
|
-
var knownHelpers = this.options.knownHelpers;
|
946
|
-
this.options.knownHelpers = {
|
947
|
-
'helperMissing': true,
|
948
|
-
'blockHelperMissing': true,
|
949
|
-
'each': true,
|
950
|
-
'if': true,
|
951
|
-
'unless': true,
|
952
|
-
'with': true,
|
953
|
-
'log': true
|
954
|
-
};
|
955
|
-
if (knownHelpers) {
|
956
|
-
for (var name in knownHelpers) {
|
957
|
-
this.options.knownHelpers[name] = knownHelpers[name];
|
958
|
-
}
|
959
|
-
}
|
858
|
+
return this.program(program);
|
859
|
+
},
|
960
860
|
|
961
|
-
|
962
|
-
|
861
|
+
accept: function(node) {
|
862
|
+
return this[node.type](node);
|
863
|
+
},
|
963
864
|
|
964
|
-
|
965
|
-
|
966
|
-
|
865
|
+
program: function(program) {
|
866
|
+
var statements = program.statements, statement;
|
867
|
+
this.opcodes = [];
|
967
868
|
|
968
|
-
|
969
|
-
|
970
|
-
|
869
|
+
for(var i=0, l=statements.length; i<l; i++) {
|
870
|
+
statement = statements[i];
|
871
|
+
this[statement.type](statement);
|
872
|
+
}
|
873
|
+
this.isSimple = l === 1;
|
971
874
|
|
972
|
-
|
973
|
-
|
974
|
-
|
975
|
-
}
|
976
|
-
this.isSimple = l === 1;
|
875
|
+
this.depths.list = this.depths.list.sort(function(a, b) {
|
876
|
+
return a - b;
|
877
|
+
});
|
977
878
|
|
978
|
-
|
979
|
-
|
980
|
-
});
|
879
|
+
return this;
|
880
|
+
},
|
981
881
|
|
982
|
-
|
983
|
-
|
882
|
+
compileProgram: function(program) {
|
883
|
+
var result = new this.compiler().compile(program, this.options);
|
884
|
+
var guid = this.guid++, depth;
|
984
885
|
|
985
|
-
|
986
|
-
var result = new this.compiler().compile(program, this.options);
|
987
|
-
var guid = this.guid++, depth;
|
886
|
+
this.usePartial = this.usePartial || result.usePartial;
|
988
887
|
|
989
|
-
|
888
|
+
this.children[guid] = result;
|
990
889
|
|
991
|
-
|
890
|
+
for(var i=0, l=result.depths.list.length; i<l; i++) {
|
891
|
+
depth = result.depths.list[i];
|
992
892
|
|
993
|
-
|
994
|
-
|
893
|
+
if(depth < 2) { continue; }
|
894
|
+
else { this.addDepth(depth - 1); }
|
895
|
+
}
|
995
896
|
|
996
|
-
|
997
|
-
|
998
|
-
}
|
897
|
+
return guid;
|
898
|
+
},
|
999
899
|
|
1000
|
-
|
1001
|
-
|
900
|
+
block: function(block) {
|
901
|
+
var mustache = block.mustache,
|
902
|
+
program = block.program,
|
903
|
+
inverse = block.inverse;
|
1002
904
|
|
1003
|
-
|
1004
|
-
|
1005
|
-
|
1006
|
-
inverse = block.inverse;
|
905
|
+
if (program) {
|
906
|
+
program = this.compileProgram(program);
|
907
|
+
}
|
1007
908
|
|
1008
|
-
|
1009
|
-
|
1010
|
-
|
909
|
+
if (inverse) {
|
910
|
+
inverse = this.compileProgram(inverse);
|
911
|
+
}
|
1011
912
|
|
1012
|
-
|
1013
|
-
inverse = this.compileProgram(inverse);
|
1014
|
-
}
|
913
|
+
var type = this.classifyMustache(mustache);
|
1015
914
|
|
1016
|
-
|
915
|
+
if (type === "helper") {
|
916
|
+
this.helperMustache(mustache, program, inverse);
|
917
|
+
} else if (type === "simple") {
|
918
|
+
this.simpleMustache(mustache);
|
1017
919
|
|
1018
|
-
|
1019
|
-
|
1020
|
-
|
1021
|
-
|
920
|
+
// now that the simple mustache is resolved, we need to
|
921
|
+
// evaluate it by executing `blockHelperMissing`
|
922
|
+
this.opcode('pushProgram', program);
|
923
|
+
this.opcode('pushProgram', inverse);
|
924
|
+
this.opcode('pushLiteral', '{}');
|
925
|
+
this.opcode('blockValue');
|
926
|
+
} else {
|
927
|
+
this.ambiguousMustache(mustache, program, inverse);
|
928
|
+
|
929
|
+
// now that the simple mustache is resolved, we need to
|
930
|
+
// evaluate it by executing `blockHelperMissing`
|
931
|
+
this.opcode('pushProgram', program);
|
932
|
+
this.opcode('pushProgram', inverse);
|
933
|
+
this.opcode('pushLiteral', '{}');
|
934
|
+
this.opcode('ambiguousBlockValue');
|
935
|
+
}
|
1022
936
|
|
1023
|
-
|
1024
|
-
|
1025
|
-
this.opcode('pushProgram', program);
|
1026
|
-
this.opcode('pushProgram', inverse);
|
1027
|
-
this.opcode('emptyHash');
|
1028
|
-
this.opcode('blockValue');
|
1029
|
-
} else {
|
1030
|
-
this.ambiguousMustache(mustache, program, inverse);
|
937
|
+
this.opcode('append');
|
938
|
+
},
|
1031
939
|
|
1032
|
-
|
1033
|
-
|
1034
|
-
this.opcode('pushProgram', program);
|
1035
|
-
this.opcode('pushProgram', inverse);
|
1036
|
-
this.opcode('emptyHash');
|
1037
|
-
this.opcode('ambiguousBlockValue');
|
1038
|
-
}
|
940
|
+
hash: function(hash) {
|
941
|
+
var pairs = hash.pairs, pair, val;
|
1039
942
|
|
1040
|
-
|
1041
|
-
},
|
943
|
+
this.opcode('push', '{}');
|
1042
944
|
|
1043
|
-
|
1044
|
-
|
945
|
+
for(var i=0, l=pairs.length; i<l; i++) {
|
946
|
+
pair = pairs[i];
|
947
|
+
val = pair[1];
|
1045
948
|
|
1046
|
-
|
949
|
+
this.accept(val);
|
950
|
+
this.opcode('assignToHash', pair[0]);
|
951
|
+
}
|
952
|
+
},
|
1047
953
|
|
1048
|
-
|
1049
|
-
|
1050
|
-
|
954
|
+
partial: function(partial) {
|
955
|
+
var id = partial.id;
|
956
|
+
this.usePartial = true;
|
1051
957
|
|
1052
|
-
if
|
1053
|
-
|
1054
|
-
this.addDepth(val.depth);
|
1055
|
-
}
|
1056
|
-
this.opcode('getContext', val.depth || 0);
|
1057
|
-
this.opcode('pushStringParam', val.stringModeValue, val.type);
|
958
|
+
if(partial.context) {
|
959
|
+
this.ID(partial.context);
|
1058
960
|
} else {
|
1059
|
-
this.
|
961
|
+
this.opcode('push', 'depth0');
|
1060
962
|
}
|
1061
963
|
|
1062
|
-
this.opcode('
|
1063
|
-
|
1064
|
-
|
1065
|
-
},
|
964
|
+
this.opcode('invokePartial', id.original);
|
965
|
+
this.opcode('append');
|
966
|
+
},
|
1066
967
|
|
1067
|
-
|
1068
|
-
|
1069
|
-
|
968
|
+
content: function(content) {
|
969
|
+
this.opcode('appendContent', content.string);
|
970
|
+
},
|
1070
971
|
|
1071
|
-
|
1072
|
-
this.
|
1073
|
-
|
1074
|
-
this.opcode('push', 'depth0');
|
1075
|
-
}
|
972
|
+
mustache: function(mustache) {
|
973
|
+
var options = this.options;
|
974
|
+
var type = this.classifyMustache(mustache);
|
1076
975
|
|
1077
|
-
|
1078
|
-
|
1079
|
-
|
976
|
+
if (type === "simple") {
|
977
|
+
this.simpleMustache(mustache);
|
978
|
+
} else if (type === "helper") {
|
979
|
+
this.helperMustache(mustache);
|
980
|
+
} else {
|
981
|
+
this.ambiguousMustache(mustache);
|
982
|
+
}
|
1080
983
|
|
1081
|
-
|
1082
|
-
|
1083
|
-
|
984
|
+
if(mustache.escaped && !options.noEscape) {
|
985
|
+
this.opcode('appendEscaped');
|
986
|
+
} else {
|
987
|
+
this.opcode('append');
|
988
|
+
}
|
989
|
+
},
|
1084
990
|
|
1085
|
-
|
1086
|
-
|
1087
|
-
var type = this.classifyMustache(mustache);
|
991
|
+
ambiguousMustache: function(mustache, program, inverse) {
|
992
|
+
var id = mustache.id, name = id.parts[0];
|
1088
993
|
|
1089
|
-
|
1090
|
-
this.simpleMustache(mustache);
|
1091
|
-
} else if (type === "helper") {
|
1092
|
-
this.helperMustache(mustache);
|
1093
|
-
} else {
|
1094
|
-
this.ambiguousMustache(mustache);
|
1095
|
-
}
|
994
|
+
this.opcode('getContext', id.depth);
|
1096
995
|
|
1097
|
-
|
1098
|
-
this.opcode('
|
1099
|
-
} else {
|
1100
|
-
this.opcode('append');
|
1101
|
-
}
|
1102
|
-
},
|
996
|
+
this.opcode('pushProgram', program);
|
997
|
+
this.opcode('pushProgram', inverse);
|
1103
998
|
|
1104
|
-
|
1105
|
-
|
1106
|
-
name = id.parts[0],
|
1107
|
-
isBlock = program != null || inverse != null;
|
999
|
+
this.opcode('invokeAmbiguous', name);
|
1000
|
+
},
|
1108
1001
|
|
1109
|
-
|
1002
|
+
simpleMustache: function(mustache, program, inverse) {
|
1003
|
+
var id = mustache.id;
|
1110
1004
|
|
1111
|
-
|
1112
|
-
|
1005
|
+
if (id.type === 'DATA') {
|
1006
|
+
this.DATA(id);
|
1007
|
+
} else if (id.parts.length) {
|
1008
|
+
this.ID(id);
|
1009
|
+
} else {
|
1010
|
+
// Simplified ID for `this`
|
1011
|
+
this.addDepth(id.depth);
|
1012
|
+
this.opcode('getContext', id.depth);
|
1013
|
+
this.opcode('pushContext');
|
1014
|
+
}
|
1113
1015
|
|
1114
|
-
|
1115
|
-
|
1016
|
+
this.opcode('resolvePossibleLambda');
|
1017
|
+
},
|
1116
1018
|
|
1117
|
-
|
1118
|
-
|
1019
|
+
helperMustache: function(mustache, program, inverse) {
|
1020
|
+
var params = this.setupFullMustacheParams(mustache, program, inverse),
|
1021
|
+
name = mustache.id.parts[0];
|
1119
1022
|
|
1120
|
-
|
1121
|
-
|
1122
|
-
|
1123
|
-
|
1124
|
-
|
1125
|
-
|
1023
|
+
if (this.options.knownHelpers[name]) {
|
1024
|
+
this.opcode('invokeKnownHelper', params.length, name);
|
1025
|
+
} else if (this.knownHelpersOnly) {
|
1026
|
+
throw new Error("You specified knownHelpersOnly, but used the unknown helper " + name);
|
1027
|
+
} else {
|
1028
|
+
this.opcode('invokeHelper', params.length, name);
|
1029
|
+
}
|
1030
|
+
},
|
1031
|
+
|
1032
|
+
ID: function(id) {
|
1126
1033
|
this.addDepth(id.depth);
|
1127
1034
|
this.opcode('getContext', id.depth);
|
1128
|
-
this.opcode('pushContext');
|
1129
|
-
}
|
1130
1035
|
|
1131
|
-
|
1132
|
-
|
1036
|
+
var name = id.parts[0];
|
1037
|
+
if (!name) {
|
1038
|
+
this.opcode('pushContext');
|
1039
|
+
} else {
|
1040
|
+
this.opcode('lookupOnContext', id.parts[0]);
|
1041
|
+
}
|
1133
1042
|
|
1134
|
-
|
1135
|
-
|
1136
|
-
|
1043
|
+
for(var i=1, l=id.parts.length; i<l; i++) {
|
1044
|
+
this.opcode('lookup', id.parts[i]);
|
1045
|
+
}
|
1046
|
+
},
|
1137
1047
|
|
1138
|
-
|
1139
|
-
this.
|
1140
|
-
|
1141
|
-
|
1142
|
-
|
1143
|
-
|
1144
|
-
|
1145
|
-
|
1048
|
+
DATA: function(data) {
|
1049
|
+
this.options.data = true;
|
1050
|
+
this.opcode('lookupData', data.id);
|
1051
|
+
},
|
1052
|
+
|
1053
|
+
STRING: function(string) {
|
1054
|
+
this.opcode('pushString', string.string);
|
1055
|
+
},
|
1146
1056
|
|
1147
|
-
|
1148
|
-
|
1149
|
-
|
1057
|
+
INTEGER: function(integer) {
|
1058
|
+
this.opcode('pushLiteral', integer.integer);
|
1059
|
+
},
|
1150
1060
|
|
1151
|
-
|
1152
|
-
|
1153
|
-
|
1154
|
-
} else {
|
1155
|
-
this.opcode('lookupOnContext', id.parts[0]);
|
1156
|
-
}
|
1061
|
+
BOOLEAN: function(bool) {
|
1062
|
+
this.opcode('pushLiteral', bool.bool);
|
1063
|
+
},
|
1157
1064
|
|
1158
|
-
|
1159
|
-
this.opcode('lookup', id.parts[i]);
|
1160
|
-
}
|
1161
|
-
},
|
1065
|
+
comment: function() {},
|
1162
1066
|
|
1163
|
-
|
1164
|
-
|
1165
|
-
|
1166
|
-
|
1067
|
+
// HELPERS
|
1068
|
+
opcode: function(name) {
|
1069
|
+
this.opcodes.push({ opcode: name, args: [].slice.call(arguments, 1) });
|
1070
|
+
},
|
1167
1071
|
|
1168
|
-
|
1169
|
-
|
1170
|
-
|
1072
|
+
declare: function(name, value) {
|
1073
|
+
this.opcodes.push({ opcode: 'DECLARE', name: name, value: value });
|
1074
|
+
},
|
1171
1075
|
|
1172
|
-
|
1173
|
-
|
1174
|
-
|
1076
|
+
addDepth: function(depth) {
|
1077
|
+
if(isNaN(depth)) { throw new Error("EWOT"); }
|
1078
|
+
if(depth === 0) { return; }
|
1175
1079
|
|
1176
|
-
|
1177
|
-
|
1178
|
-
|
1080
|
+
if(!this.depths[depth]) {
|
1081
|
+
this.depths[depth] = true;
|
1082
|
+
this.depths.list.push(depth);
|
1083
|
+
}
|
1084
|
+
},
|
1179
1085
|
|
1180
|
-
|
1086
|
+
classifyMustache: function(mustache) {
|
1087
|
+
var isHelper = mustache.isHelper;
|
1088
|
+
var isEligible = mustache.eligibleHelper;
|
1089
|
+
var options = this.options;
|
1181
1090
|
|
1182
|
-
|
1183
|
-
|
1184
|
-
|
1185
|
-
},
|
1091
|
+
// if ambiguous, we can possibly resolve the ambiguity now
|
1092
|
+
if (isEligible && !isHelper) {
|
1093
|
+
var name = mustache.id.parts[0];
|
1186
1094
|
|
1187
|
-
|
1188
|
-
|
1189
|
-
|
1095
|
+
if (options.knownHelpers[name]) {
|
1096
|
+
isHelper = true;
|
1097
|
+
} else if (options.knownHelpersOnly) {
|
1098
|
+
isEligible = false;
|
1099
|
+
}
|
1100
|
+
}
|
1190
1101
|
|
1191
|
-
|
1192
|
-
|
1193
|
-
|
1102
|
+
if (isHelper) { return "helper"; }
|
1103
|
+
else if (isEligible) { return "ambiguous"; }
|
1104
|
+
else { return "simple"; }
|
1105
|
+
},
|
1194
1106
|
|
1195
|
-
|
1196
|
-
|
1197
|
-
this.depths.list.push(depth);
|
1198
|
-
}
|
1199
|
-
},
|
1107
|
+
pushParams: function(params) {
|
1108
|
+
var i = params.length, param;
|
1200
1109
|
|
1201
|
-
|
1202
|
-
|
1203
|
-
var isEligible = mustache.eligibleHelper;
|
1204
|
-
var options = this.options;
|
1110
|
+
while(i--) {
|
1111
|
+
param = params[i];
|
1205
1112
|
|
1206
|
-
|
1207
|
-
|
1208
|
-
|
1113
|
+
if(this.options.stringParams) {
|
1114
|
+
if(param.depth) {
|
1115
|
+
this.addDepth(param.depth);
|
1116
|
+
}
|
1209
1117
|
|
1210
|
-
|
1211
|
-
|
1212
|
-
|
1213
|
-
|
1118
|
+
this.opcode('getContext', param.depth || 0);
|
1119
|
+
this.opcode('pushStringParam', param.string);
|
1120
|
+
} else {
|
1121
|
+
this[param.type](param);
|
1122
|
+
}
|
1214
1123
|
}
|
1215
|
-
}
|
1124
|
+
},
|
1216
1125
|
|
1217
|
-
|
1218
|
-
|
1219
|
-
|
1220
|
-
},
|
1126
|
+
setupMustacheParams: function(mustache) {
|
1127
|
+
var params = mustache.params;
|
1128
|
+
this.pushParams(params);
|
1221
1129
|
|
1222
|
-
|
1223
|
-
|
1130
|
+
if(mustache.hash) {
|
1131
|
+
this.hash(mustache.hash);
|
1132
|
+
} else {
|
1133
|
+
this.opcode('pushLiteral', '{}');
|
1134
|
+
}
|
1224
1135
|
|
1225
|
-
|
1226
|
-
|
1136
|
+
return params;
|
1137
|
+
},
|
1227
1138
|
|
1228
|
-
|
1229
|
-
|
1230
|
-
|
1231
|
-
|
1139
|
+
// this will replace setupMustacheParams when we're done
|
1140
|
+
setupFullMustacheParams: function(mustache, program, inverse) {
|
1141
|
+
var params = mustache.params;
|
1142
|
+
this.pushParams(params);
|
1232
1143
|
|
1233
|
-
|
1234
|
-
|
1144
|
+
this.opcode('pushProgram', program);
|
1145
|
+
this.opcode('pushProgram', inverse);
|
1146
|
+
|
1147
|
+
if(mustache.hash) {
|
1148
|
+
this.hash(mustache.hash);
|
1235
1149
|
} else {
|
1236
|
-
this
|
1150
|
+
this.opcode('pushLiteral', '{}');
|
1237
1151
|
}
|
1238
|
-
}
|
1239
|
-
},
|
1240
1152
|
|
1241
|
-
|
1242
|
-
var params = mustache.params;
|
1243
|
-
this.pushParams(params);
|
1244
|
-
|
1245
|
-
if(mustache.hash) {
|
1246
|
-
this.hash(mustache.hash);
|
1247
|
-
} else {
|
1248
|
-
this.opcode('emptyHash');
|
1153
|
+
return params;
|
1249
1154
|
}
|
1155
|
+
};
|
1250
1156
|
|
1251
|
-
|
1252
|
-
|
1157
|
+
var Literal = function(value) {
|
1158
|
+
this.value = value;
|
1159
|
+
};
|
1253
1160
|
|
1254
|
-
|
1255
|
-
|
1256
|
-
|
1257
|
-
|
1161
|
+
JavaScriptCompiler.prototype = {
|
1162
|
+
// PUBLIC API: You can override these methods in a subclass to provide
|
1163
|
+
// alternative compiled forms for name lookup and buffering semantics
|
1164
|
+
nameLookup: function(parent, name, type) {
|
1165
|
+
if (/^[0-9]+$/.test(name)) {
|
1166
|
+
return parent + "[" + name + "]";
|
1167
|
+
} else if (JavaScriptCompiler.isValidJavaScriptVariableName(name)) {
|
1168
|
+
return parent + "." + name;
|
1169
|
+
}
|
1170
|
+
else {
|
1171
|
+
return parent + "['" + name + "']";
|
1172
|
+
}
|
1173
|
+
},
|
1258
1174
|
|
1259
|
-
|
1260
|
-
|
1175
|
+
appendToBuffer: function(string) {
|
1176
|
+
if (this.environment.isSimple) {
|
1177
|
+
return "return " + string + ";";
|
1178
|
+
} else {
|
1179
|
+
return "buffer += " + string + ";";
|
1180
|
+
}
|
1181
|
+
},
|
1261
1182
|
|
1262
|
-
|
1263
|
-
this.
|
1264
|
-
}
|
1265
|
-
this.opcode('emptyHash');
|
1266
|
-
}
|
1183
|
+
initializeBuffer: function() {
|
1184
|
+
return this.quotedString("");
|
1185
|
+
},
|
1267
1186
|
|
1268
|
-
|
1269
|
-
|
1270
|
-
};
|
1187
|
+
namespace: "Handlebars",
|
1188
|
+
// END PUBLIC API
|
1271
1189
|
|
1272
|
-
|
1273
|
-
|
1274
|
-
};
|
1190
|
+
compile: function(environment, options, context, asObject) {
|
1191
|
+
this.environment = environment;
|
1192
|
+
this.options = options || {};
|
1275
1193
|
|
1276
|
-
|
1277
|
-
// PUBLIC API: You can override these methods in a subclass to provide
|
1278
|
-
// alternative compiled forms for name lookup and buffering semantics
|
1279
|
-
nameLookup: function(parent, name /* , type*/) {
|
1280
|
-
if (/^[0-9]+$/.test(name)) {
|
1281
|
-
return parent + "[" + name + "]";
|
1282
|
-
} else if (JavaScriptCompiler.isValidJavaScriptVariableName(name)) {
|
1283
|
-
return parent + "." + name;
|
1284
|
-
}
|
1285
|
-
else {
|
1286
|
-
return parent + "['" + name + "']";
|
1287
|
-
}
|
1288
|
-
},
|
1194
|
+
Handlebars.log(Handlebars.logger.DEBUG, this.environment.disassemble() + "\n\n");
|
1289
1195
|
|
1290
|
-
|
1291
|
-
|
1292
|
-
|
1293
|
-
|
1294
|
-
|
1295
|
-
appendToBuffer: true,
|
1296
|
-
content: string,
|
1297
|
-
toString: function() { return "buffer += " + string + ";"; }
|
1196
|
+
this.name = this.environment.name;
|
1197
|
+
this.isChild = !!context;
|
1198
|
+
this.context = context || {
|
1199
|
+
programs: [],
|
1200
|
+
aliases: { }
|
1298
1201
|
};
|
1299
|
-
}
|
1300
|
-
},
|
1301
1202
|
|
1302
|
-
|
1303
|
-
return this.quotedString("");
|
1304
|
-
},
|
1203
|
+
this.preamble();
|
1305
1204
|
|
1306
|
-
|
1307
|
-
|
1205
|
+
this.stackSlot = 0;
|
1206
|
+
this.stackVars = [];
|
1207
|
+
this.registers = { list: [] };
|
1208
|
+
this.compileStack = [];
|
1308
1209
|
|
1309
|
-
|
1310
|
-
this.environment = environment;
|
1311
|
-
this.options = options || {};
|
1210
|
+
this.compileChildren(environment, options);
|
1312
1211
|
|
1313
|
-
|
1212
|
+
var opcodes = environment.opcodes, opcode;
|
1314
1213
|
|
1315
|
-
|
1316
|
-
this.isChild = !!context;
|
1317
|
-
this.context = context || {
|
1318
|
-
programs: [],
|
1319
|
-
environments: [],
|
1320
|
-
aliases: { }
|
1321
|
-
};
|
1214
|
+
this.i = 0;
|
1322
1215
|
|
1323
|
-
|
1216
|
+
for(l=opcodes.length; this.i<l; this.i++) {
|
1217
|
+
opcode = opcodes[this.i];
|
1324
1218
|
|
1325
|
-
|
1326
|
-
|
1327
|
-
|
1328
|
-
|
1329
|
-
|
1219
|
+
if(opcode.opcode === 'DECLARE') {
|
1220
|
+
this[opcode.name] = opcode.value;
|
1221
|
+
} else {
|
1222
|
+
this[opcode.opcode].apply(this, opcode.args);
|
1223
|
+
}
|
1224
|
+
}
|
1330
1225
|
|
1331
|
-
|
1226
|
+
return this.createFunctionContext(asObject);
|
1227
|
+
},
|
1332
1228
|
|
1333
|
-
|
1229
|
+
nextOpcode: function() {
|
1230
|
+
var opcodes = this.environment.opcodes, opcode = opcodes[this.i + 1];
|
1231
|
+
return opcodes[this.i + 1];
|
1232
|
+
},
|
1334
1233
|
|
1335
|
-
|
1234
|
+
eat: function(opcode) {
|
1235
|
+
this.i = this.i + 1;
|
1236
|
+
},
|
1336
1237
|
|
1337
|
-
|
1338
|
-
|
1238
|
+
preamble: function() {
|
1239
|
+
var out = [];
|
1339
1240
|
|
1340
|
-
if(
|
1341
|
-
|
1241
|
+
if (!this.isChild) {
|
1242
|
+
var namespace = this.namespace;
|
1243
|
+
var copies = "helpers = helpers || " + namespace + ".helpers;";
|
1244
|
+
if (this.environment.usePartial) { copies = copies + " partials = partials || " + namespace + ".partials;"; }
|
1245
|
+
if (this.options.data) { copies = copies + " data = data || {};"; }
|
1246
|
+
out.push(copies);
|
1342
1247
|
} else {
|
1343
|
-
|
1248
|
+
out.push('');
|
1344
1249
|
}
|
1345
|
-
}
|
1346
|
-
|
1347
|
-
return this.createFunctionContext(asObject);
|
1348
|
-
},
|
1349
1250
|
|
1350
|
-
|
1351
|
-
|
1352
|
-
|
1353
|
-
|
1354
|
-
|
1355
|
-
eat: function() {
|
1356
|
-
this.i = this.i + 1;
|
1357
|
-
},
|
1358
|
-
|
1359
|
-
preamble: function() {
|
1360
|
-
var out = [];
|
1361
|
-
|
1362
|
-
if (!this.isChild) {
|
1363
|
-
var namespace = this.namespace;
|
1364
|
-
var copies = "helpers = helpers || " + namespace + ".helpers;";
|
1365
|
-
if (this.environment.usePartial) { copies = copies + " partials = partials || " + namespace + ".partials;"; }
|
1366
|
-
if (this.options.data) { copies = copies + " data = data || {};"; }
|
1367
|
-
out.push(copies);
|
1368
|
-
} else {
|
1369
|
-
out.push('');
|
1370
|
-
}
|
1371
|
-
|
1372
|
-
if (!this.environment.isSimple) {
|
1373
|
-
out.push(", buffer = " + this.initializeBuffer());
|
1374
|
-
} else {
|
1375
|
-
out.push("");
|
1376
|
-
}
|
1377
|
-
|
1378
|
-
// track the last context pushed into place to allow skipping the
|
1379
|
-
// getContext opcode when it would be a noop
|
1380
|
-
this.lastContext = 0;
|
1381
|
-
this.source = out;
|
1382
|
-
},
|
1251
|
+
if (!this.environment.isSimple) {
|
1252
|
+
out.push(", buffer = " + this.initializeBuffer());
|
1253
|
+
} else {
|
1254
|
+
out.push("");
|
1255
|
+
}
|
1383
1256
|
|
1384
|
-
|
1385
|
-
|
1257
|
+
// track the last context pushed into place to allow skipping the
|
1258
|
+
// getContext opcode when it would be a noop
|
1259
|
+
this.lastContext = 0;
|
1260
|
+
this.source = out;
|
1261
|
+
},
|
1386
1262
|
|
1387
|
-
|
1388
|
-
|
1389
|
-
}
|
1263
|
+
createFunctionContext: function(asObject) {
|
1264
|
+
var locals = this.stackVars.concat(this.registers.list);
|
1390
1265
|
|
1391
|
-
|
1392
|
-
|
1393
|
-
for (var alias in this.context.aliases) {
|
1394
|
-
this.source[1] = this.source[1] + ', ' + alias + '=' + this.context.aliases[alias];
|
1266
|
+
if(locals.length > 0) {
|
1267
|
+
this.source[1] = this.source[1] + ", " + locals.join(", ");
|
1395
1268
|
}
|
1396
|
-
}
|
1397
1269
|
|
1398
|
-
|
1399
|
-
|
1400
|
-
|
1401
|
-
|
1402
|
-
|
1403
|
-
|
1404
|
-
|
1405
|
-
}
|
1270
|
+
// Generate minimizer alias mappings
|
1271
|
+
if (!this.isChild) {
|
1272
|
+
var aliases = [];
|
1273
|
+
for (var alias in this.context.aliases) {
|
1274
|
+
this.source[1] = this.source[1] + ', ' + alias + '=' + this.context.aliases[alias];
|
1275
|
+
}
|
1276
|
+
}
|
1406
1277
|
|
1407
|
-
|
1408
|
-
|
1409
|
-
|
1278
|
+
if (this.source[1]) {
|
1279
|
+
this.source[1] = "var " + this.source[1].substring(2) + ";";
|
1280
|
+
}
|
1410
1281
|
|
1411
|
-
|
1282
|
+
// Merge children
|
1283
|
+
if (!this.isChild) {
|
1284
|
+
this.source[1] += '\n' + this.context.programs.join('\n') + '\n';
|
1285
|
+
}
|
1412
1286
|
|
1413
|
-
|
1414
|
-
|
1415
|
-
|
1287
|
+
if (!this.environment.isSimple) {
|
1288
|
+
this.source.push("return buffer;");
|
1289
|
+
}
|
1416
1290
|
|
1417
|
-
|
1418
|
-
var source = this.mergeSource();
|
1291
|
+
var params = this.isChild ? ["depth0", "data"] : ["Handlebars", "depth0", "helpers", "partials", "data"];
|
1419
1292
|
|
1420
|
-
|
1421
|
-
|
1422
|
-
|
1423
|
-
source = "this.compilerInfo = ["+revision+",'"+versions+"'];\n"+source;
|
1424
|
-
}
|
1293
|
+
for(var i=0, l=this.environment.depths.list.length; i<l; i++) {
|
1294
|
+
params.push("depth" + this.environment.depths.list[i]);
|
1295
|
+
}
|
1425
1296
|
|
1426
|
-
|
1427
|
-
|
1297
|
+
if (asObject) {
|
1298
|
+
params.push(this.source.join("\n "));
|
1428
1299
|
|
1429
|
-
|
1430
|
-
} else {
|
1431
|
-
var functionSource = 'function ' + (this.name || '') + '(' + params.join(',') + ') {\n ' + source + '}';
|
1432
|
-
Handlebars.log(Handlebars.logger.DEBUG, functionSource + "\n\n");
|
1433
|
-
return functionSource;
|
1434
|
-
}
|
1435
|
-
},
|
1436
|
-
mergeSource: function() {
|
1437
|
-
// WARN: We are not handling the case where buffer is still populated as the source should
|
1438
|
-
// not have buffer append operations as their final action.
|
1439
|
-
var source = '',
|
1440
|
-
buffer;
|
1441
|
-
for (var i = 0, len = this.source.length; i < len; i++) {
|
1442
|
-
var line = this.source[i];
|
1443
|
-
if (line.appendToBuffer) {
|
1444
|
-
if (buffer) {
|
1445
|
-
buffer = buffer + '\n + ' + line.content;
|
1446
|
-
} else {
|
1447
|
-
buffer = line.content;
|
1448
|
-
}
|
1300
|
+
return Function.apply(this, params);
|
1449
1301
|
} else {
|
1450
|
-
|
1451
|
-
|
1452
|
-
|
1453
|
-
}
|
1454
|
-
source += line + '\n ';
|
1302
|
+
var functionSource = 'function ' + (this.name || '') + '(' + params.join(',') + ') {\n ' + this.source.join("\n ") + '}';
|
1303
|
+
Handlebars.log(Handlebars.logger.DEBUG, functionSource + "\n\n");
|
1304
|
+
return functionSource;
|
1455
1305
|
}
|
1456
|
-
}
|
1457
|
-
return source;
|
1458
|
-
},
|
1459
|
-
|
1460
|
-
// [blockValue]
|
1461
|
-
//
|
1462
|
-
// On stack, before: hash, inverse, program, value
|
1463
|
-
// On stack, after: return value of blockHelperMissing
|
1464
|
-
//
|
1465
|
-
// The purpose of this opcode is to take a block of the form
|
1466
|
-
// `{{#foo}}...{{/foo}}`, resolve the value of `foo`, and
|
1467
|
-
// replace it on the stack with the result of properly
|
1468
|
-
// invoking blockHelperMissing.
|
1469
|
-
blockValue: function() {
|
1470
|
-
this.context.aliases.blockHelperMissing = 'helpers.blockHelperMissing';
|
1471
|
-
|
1472
|
-
var params = ["depth0"];
|
1473
|
-
this.setupParams(0, params);
|
1474
|
-
|
1475
|
-
this.replaceStack(function(current) {
|
1476
|
-
params.splice(1, 0, current);
|
1477
|
-
return "blockHelperMissing.call(" + params.join(", ") + ")";
|
1478
|
-
});
|
1479
|
-
},
|
1480
|
-
|
1481
|
-
// [ambiguousBlockValue]
|
1482
|
-
//
|
1483
|
-
// On stack, before: hash, inverse, program, value
|
1484
|
-
// Compiler value, before: lastHelper=value of last found helper, if any
|
1485
|
-
// On stack, after, if no lastHelper: same as [blockValue]
|
1486
|
-
// On stack, after, if lastHelper: value
|
1487
|
-
ambiguousBlockValue: function() {
|
1488
|
-
this.context.aliases.blockHelperMissing = 'helpers.blockHelperMissing';
|
1489
|
-
|
1490
|
-
var params = ["depth0"];
|
1491
|
-
this.setupParams(0, params);
|
1306
|
+
},
|
1492
1307
|
|
1493
|
-
|
1494
|
-
|
1308
|
+
// [blockValue]
|
1309
|
+
//
|
1310
|
+
// On stack, before: hash, inverse, program, value
|
1311
|
+
// On stack, after: return value of blockHelperMissing
|
1312
|
+
//
|
1313
|
+
// The purpose of this opcode is to take a block of the form
|
1314
|
+
// `{{#foo}}...{{/foo}}`, resolve the value of `foo`, and
|
1315
|
+
// replace it on the stack with the result of properly
|
1316
|
+
// invoking blockHelperMissing.
|
1317
|
+
blockValue: function() {
|
1318
|
+
this.context.aliases.blockHelperMissing = 'helpers.blockHelperMissing';
|
1319
|
+
|
1320
|
+
var params = ["depth0"];
|
1321
|
+
this.setupParams(0, params);
|
1322
|
+
|
1323
|
+
this.replaceStack(function(current) {
|
1324
|
+
params.splice(1, 0, current);
|
1325
|
+
return current + " = blockHelperMissing.call(" + params.join(", ") + ")";
|
1326
|
+
});
|
1327
|
+
},
|
1495
1328
|
|
1496
|
-
//
|
1497
|
-
|
1329
|
+
// [ambiguousBlockValue]
|
1330
|
+
//
|
1331
|
+
// On stack, before: hash, inverse, program, value
|
1332
|
+
// Compiler value, before: lastHelper=value of last found helper, if any
|
1333
|
+
// On stack, after, if no lastHelper: same as [blockValue]
|
1334
|
+
// On stack, after, if lastHelper: value
|
1335
|
+
ambiguousBlockValue: function() {
|
1336
|
+
this.context.aliases.blockHelperMissing = 'helpers.blockHelperMissing';
|
1498
1337
|
|
1499
|
-
|
1500
|
-
|
1338
|
+
var params = ["depth0"];
|
1339
|
+
this.setupParams(0, params);
|
1501
1340
|
|
1502
|
-
|
1503
|
-
|
1504
|
-
// On stack, before: ...
|
1505
|
-
// On stack, after: ...
|
1506
|
-
//
|
1507
|
-
// Appends the string value of `content` to the current buffer
|
1508
|
-
appendContent: function(content) {
|
1509
|
-
this.source.push(this.appendToBuffer(this.quotedString(content)));
|
1510
|
-
},
|
1341
|
+
var current = this.topStack();
|
1342
|
+
params.splice(1, 0, current);
|
1511
1343
|
|
1512
|
-
|
1513
|
-
|
1514
|
-
// On stack, before: value, ...
|
1515
|
-
// On stack, after: ...
|
1516
|
-
//
|
1517
|
-
// Coerces `value` to a String and appends it to the current buffer.
|
1518
|
-
//
|
1519
|
-
// If `value` is truthy, or 0, it is coerced into a string and appended
|
1520
|
-
// Otherwise, the empty string is appended
|
1521
|
-
append: function() {
|
1522
|
-
// Force anything that is inlined onto the stack so we don't have duplication
|
1523
|
-
// when we examine local
|
1524
|
-
this.flushInline();
|
1525
|
-
var local = this.popStack();
|
1526
|
-
this.source.push("if(" + local + " || " + local + " === 0) { " + this.appendToBuffer(local) + " }");
|
1527
|
-
if (this.environment.isSimple) {
|
1528
|
-
this.source.push("else { " + this.appendToBuffer("''") + " }");
|
1529
|
-
}
|
1530
|
-
},
|
1344
|
+
this.source.push("if (!" + this.lastHelper + ") { " + current + " = blockHelperMissing.call(" + params.join(", ") + "); }");
|
1345
|
+
},
|
1531
1346
|
|
1532
|
-
|
1533
|
-
|
1534
|
-
|
1535
|
-
|
1536
|
-
|
1537
|
-
|
1538
|
-
|
1539
|
-
|
1347
|
+
// [appendContent]
|
1348
|
+
//
|
1349
|
+
// On stack, before: ...
|
1350
|
+
// On stack, after: ...
|
1351
|
+
//
|
1352
|
+
// Appends the string value of `content` to the current buffer
|
1353
|
+
appendContent: function(content) {
|
1354
|
+
this.source.push(this.appendToBuffer(this.quotedString(content)));
|
1355
|
+
},
|
1540
1356
|
|
1541
|
-
|
1542
|
-
|
1357
|
+
// [append]
|
1358
|
+
//
|
1359
|
+
// On stack, before: value, ...
|
1360
|
+
// On stack, after: ...
|
1361
|
+
//
|
1362
|
+
// Coerces `value` to a String and appends it to the current buffer.
|
1363
|
+
//
|
1364
|
+
// If `value` is truthy, or 0, it is coerced into a string and appended
|
1365
|
+
// Otherwise, the empty string is appended
|
1366
|
+
append: function() {
|
1367
|
+
var local = this.popStack();
|
1368
|
+
this.source.push("if(" + local + " || " + local + " === 0) { " + this.appendToBuffer(local) + " }");
|
1369
|
+
if (this.environment.isSimple) {
|
1370
|
+
this.source.push("else { " + this.appendToBuffer("''") + " }");
|
1371
|
+
}
|
1372
|
+
},
|
1543
1373
|
|
1544
|
-
|
1545
|
-
|
1546
|
-
|
1547
|
-
|
1548
|
-
|
1549
|
-
|
1550
|
-
|
1551
|
-
|
1552
|
-
|
1553
|
-
|
1554
|
-
|
1555
|
-
|
1374
|
+
// [appendEscaped]
|
1375
|
+
//
|
1376
|
+
// On stack, before: value, ...
|
1377
|
+
// On stack, after: ...
|
1378
|
+
//
|
1379
|
+
// Escape `value` and append it to the buffer
|
1380
|
+
appendEscaped: function() {
|
1381
|
+
var opcode = this.nextOpcode(), extra = "";
|
1382
|
+
this.context.aliases.escapeExpression = 'this.escapeExpression';
|
1383
|
+
|
1384
|
+
if(opcode && opcode.opcode === 'appendContent') {
|
1385
|
+
extra = " + " + this.quotedString(opcode.args[0]);
|
1386
|
+
this.eat(opcode);
|
1387
|
+
}
|
1556
1388
|
|
1557
|
-
|
1558
|
-
|
1559
|
-
// On stack, before: ...
|
1560
|
-
// On stack, after: currentContext[name], ...
|
1561
|
-
//
|
1562
|
-
// Looks up the value of `name` on the current context and pushes
|
1563
|
-
// it onto the stack.
|
1564
|
-
lookupOnContext: function(name) {
|
1565
|
-
this.push(this.nameLookup('depth' + this.lastContext, name, 'context'));
|
1566
|
-
},
|
1389
|
+
this.source.push(this.appendToBuffer("escapeExpression(" + this.popStack() + ")" + extra));
|
1390
|
+
},
|
1567
1391
|
|
1568
|
-
|
1569
|
-
|
1570
|
-
|
1571
|
-
|
1572
|
-
|
1573
|
-
|
1574
|
-
|
1575
|
-
|
1576
|
-
|
1392
|
+
// [getContext]
|
1393
|
+
//
|
1394
|
+
// On stack, before: ...
|
1395
|
+
// On stack, after: ...
|
1396
|
+
// Compiler value, after: lastContext=depth
|
1397
|
+
//
|
1398
|
+
// Set the value of the `lastContext` compiler value to the depth
|
1399
|
+
getContext: function(depth) {
|
1400
|
+
if(this.lastContext !== depth) {
|
1401
|
+
this.lastContext = depth;
|
1402
|
+
}
|
1403
|
+
},
|
1577
1404
|
|
1578
|
-
|
1579
|
-
|
1580
|
-
|
1581
|
-
|
1582
|
-
|
1583
|
-
|
1584
|
-
|
1585
|
-
|
1586
|
-
|
1587
|
-
|
1588
|
-
this.replaceStack(function(current) {
|
1589
|
-
return "typeof " + current + " === functionType ? " + current + ".apply(depth0) : " + current;
|
1590
|
-
});
|
1591
|
-
},
|
1405
|
+
// [lookupOnContext]
|
1406
|
+
//
|
1407
|
+
// On stack, before: ...
|
1408
|
+
// On stack, after: currentContext[name], ...
|
1409
|
+
//
|
1410
|
+
// Looks up the value of `name` on the current context and pushes
|
1411
|
+
// it onto the stack.
|
1412
|
+
lookupOnContext: function(name) {
|
1413
|
+
this.pushStack(this.nameLookup('depth' + this.lastContext, name, 'context'));
|
1414
|
+
},
|
1592
1415
|
|
1593
|
-
|
1594
|
-
|
1595
|
-
|
1596
|
-
|
1597
|
-
|
1598
|
-
|
1599
|
-
|
1600
|
-
|
1601
|
-
|
1602
|
-
return current + " == null || " + current + " === false ? " + current + " : " + this.nameLookup(current, name, 'context');
|
1603
|
-
});
|
1604
|
-
},
|
1416
|
+
// [pushContext]
|
1417
|
+
//
|
1418
|
+
// On stack, before: ...
|
1419
|
+
// On stack, after: currentContext, ...
|
1420
|
+
//
|
1421
|
+
// Pushes the value of the current context onto the stack.
|
1422
|
+
pushContext: function() {
|
1423
|
+
this.pushStackLiteral('depth' + this.lastContext);
|
1424
|
+
},
|
1605
1425
|
|
1606
|
-
|
1607
|
-
|
1608
|
-
|
1609
|
-
|
1610
|
-
|
1611
|
-
|
1612
|
-
|
1613
|
-
|
1614
|
-
|
1426
|
+
// [resolvePossibleLambda]
|
1427
|
+
//
|
1428
|
+
// On stack, before: value, ...
|
1429
|
+
// On stack, after: resolved value, ...
|
1430
|
+
//
|
1431
|
+
// If the `value` is a lambda, replace it on the stack by
|
1432
|
+
// the return value of the lambda
|
1433
|
+
resolvePossibleLambda: function() {
|
1434
|
+
this.context.aliases.functionType = '"function"';
|
1435
|
+
|
1436
|
+
this.replaceStack(function(current) {
|
1437
|
+
return "typeof " + current + " === functionType ? " + current + "() : " + current;
|
1438
|
+
});
|
1439
|
+
},
|
1615
1440
|
|
1616
|
-
|
1617
|
-
|
1618
|
-
|
1619
|
-
|
1620
|
-
|
1621
|
-
|
1622
|
-
|
1623
|
-
|
1624
|
-
|
1625
|
-
|
1441
|
+
// [lookup]
|
1442
|
+
//
|
1443
|
+
// On stack, before: value, ...
|
1444
|
+
// On stack, after: value[name], ...
|
1445
|
+
//
|
1446
|
+
// Replace the value on the stack with the result of looking
|
1447
|
+
// up `name` on `value`
|
1448
|
+
lookup: function(name) {
|
1449
|
+
this.replaceStack(function(current) {
|
1450
|
+
return current + " == null || " + current + " === false ? " + current + " : " + this.nameLookup(current, name, 'context');
|
1451
|
+
});
|
1452
|
+
},
|
1626
1453
|
|
1627
|
-
|
1454
|
+
// [lookupData]
|
1455
|
+
//
|
1456
|
+
// On stack, before: ...
|
1457
|
+
// On stack, after: data[id], ...
|
1458
|
+
//
|
1459
|
+
// Push the result of looking up `id` on the current data
|
1460
|
+
lookupData: function(id) {
|
1461
|
+
this.pushStack(this.nameLookup('data', id, 'data'));
|
1462
|
+
},
|
1628
1463
|
|
1629
|
-
|
1464
|
+
// [pushStringParam]
|
1465
|
+
//
|
1466
|
+
// On stack, before: ...
|
1467
|
+
// On stack, after: string, currentContext, ...
|
1468
|
+
//
|
1469
|
+
// This opcode is designed for use in string mode, which
|
1470
|
+
// provides the string value of a parameter along with its
|
1471
|
+
// depth rather than resolving it immediately.
|
1472
|
+
pushStringParam: function(string) {
|
1473
|
+
this.pushStackLiteral('depth' + this.lastContext);
|
1630
1474
|
this.pushString(string);
|
1631
|
-
}
|
1632
|
-
this.pushStackLiteral(string);
|
1633
|
-
}
|
1634
|
-
},
|
1635
|
-
|
1636
|
-
emptyHash: function() {
|
1637
|
-
this.pushStackLiteral('{}');
|
1638
|
-
|
1639
|
-
if (this.options.stringParams) {
|
1640
|
-
this.register('hashTypes', '{}');
|
1641
|
-
this.register('hashContexts', '{}');
|
1642
|
-
}
|
1643
|
-
},
|
1644
|
-
pushHash: function() {
|
1645
|
-
this.hash = {values: [], types: [], contexts: []};
|
1646
|
-
},
|
1647
|
-
popHash: function() {
|
1648
|
-
var hash = this.hash;
|
1649
|
-
this.hash = undefined;
|
1650
|
-
|
1651
|
-
if (this.options.stringParams) {
|
1652
|
-
this.register('hashContexts', '{' + hash.contexts.join(',') + '}');
|
1653
|
-
this.register('hashTypes', '{' + hash.types.join(',') + '}');
|
1654
|
-
}
|
1655
|
-
this.push('{\n ' + hash.values.join(',\n ') + '\n }');
|
1656
|
-
},
|
1657
|
-
|
1658
|
-
// [pushString]
|
1659
|
-
//
|
1660
|
-
// On stack, before: ...
|
1661
|
-
// On stack, after: quotedString(string), ...
|
1662
|
-
//
|
1663
|
-
// Push a quoted version of `string` onto the stack
|
1664
|
-
pushString: function(string) {
|
1665
|
-
this.pushStackLiteral(this.quotedString(string));
|
1666
|
-
},
|
1667
|
-
|
1668
|
-
// [push]
|
1669
|
-
//
|
1670
|
-
// On stack, before: ...
|
1671
|
-
// On stack, after: expr, ...
|
1672
|
-
//
|
1673
|
-
// Push an expression onto the stack
|
1674
|
-
push: function(expr) {
|
1675
|
-
this.inlineStack.push(expr);
|
1676
|
-
return expr;
|
1677
|
-
},
|
1475
|
+
},
|
1678
1476
|
|
1679
|
-
|
1680
|
-
|
1681
|
-
|
1682
|
-
|
1683
|
-
|
1684
|
-
|
1685
|
-
|
1686
|
-
|
1687
|
-
|
1688
|
-
this.pushStackLiteral(value);
|
1689
|
-
},
|
1477
|
+
// [pushString]
|
1478
|
+
//
|
1479
|
+
// On stack, before: ...
|
1480
|
+
// On stack, after: quotedString(string), ...
|
1481
|
+
//
|
1482
|
+
// Push a quoted version of `string` onto the stack
|
1483
|
+
pushString: function(string) {
|
1484
|
+
this.pushStackLiteral(this.quotedString(string));
|
1485
|
+
},
|
1690
1486
|
|
1691
|
-
|
1692
|
-
|
1693
|
-
|
1694
|
-
|
1695
|
-
|
1696
|
-
|
1697
|
-
|
1698
|
-
|
1699
|
-
|
1700
|
-
if (guid != null) {
|
1701
|
-
this.pushStackLiteral(this.programExpression(guid));
|
1702
|
-
} else {
|
1703
|
-
this.pushStackLiteral(null);
|
1704
|
-
}
|
1705
|
-
},
|
1487
|
+
// [push]
|
1488
|
+
//
|
1489
|
+
// On stack, before: ...
|
1490
|
+
// On stack, after: expr, ...
|
1491
|
+
//
|
1492
|
+
// Push an expression onto the stack
|
1493
|
+
push: function(expr) {
|
1494
|
+
this.pushStack(expr);
|
1495
|
+
},
|
1706
1496
|
|
1707
|
-
|
1708
|
-
|
1709
|
-
|
1710
|
-
|
1711
|
-
|
1712
|
-
|
1713
|
-
|
1714
|
-
|
1715
|
-
|
1716
|
-
|
1717
|
-
|
1718
|
-
|
1719
|
-
var helper = this.lastHelper = this.setupHelper(paramSize, name, true);
|
1720
|
-
|
1721
|
-
this.push(helper.name);
|
1722
|
-
this.replaceStack(function(name) {
|
1723
|
-
return name + ' ? ' + name + '.call(' +
|
1724
|
-
helper.callParams + ") " + ": helperMissing.call(" +
|
1725
|
-
helper.helperMissingParams + ")";
|
1726
|
-
});
|
1727
|
-
},
|
1497
|
+
// [pushLiteral]
|
1498
|
+
//
|
1499
|
+
// On stack, before: ...
|
1500
|
+
// On stack, after: value, ...
|
1501
|
+
//
|
1502
|
+
// Pushes a value onto the stack. This operation prevents
|
1503
|
+
// the compiler from creating a temporary variable to hold
|
1504
|
+
// it.
|
1505
|
+
pushLiteral: function(value) {
|
1506
|
+
this.pushStackLiteral(value);
|
1507
|
+
},
|
1728
1508
|
|
1729
|
-
|
1730
|
-
|
1731
|
-
|
1732
|
-
|
1733
|
-
|
1734
|
-
|
1735
|
-
|
1736
|
-
|
1737
|
-
|
1738
|
-
|
1739
|
-
|
1509
|
+
// [pushProgram]
|
1510
|
+
//
|
1511
|
+
// On stack, before: ...
|
1512
|
+
// On stack, after: program(guid), ...
|
1513
|
+
//
|
1514
|
+
// Push a program expression onto the stack. This takes
|
1515
|
+
// a compile-time guid and converts it into a runtime-accessible
|
1516
|
+
// expression.
|
1517
|
+
pushProgram: function(guid) {
|
1518
|
+
if (guid != null) {
|
1519
|
+
this.pushStackLiteral(this.programExpression(guid));
|
1520
|
+
} else {
|
1521
|
+
this.pushStackLiteral(null);
|
1522
|
+
}
|
1523
|
+
},
|
1740
1524
|
|
1741
|
-
|
1742
|
-
|
1743
|
-
|
1744
|
-
|
1745
|
-
|
1746
|
-
|
1747
|
-
|
1748
|
-
|
1749
|
-
|
1750
|
-
|
1751
|
-
|
1752
|
-
|
1753
|
-
|
1754
|
-
|
1755
|
-
|
1756
|
-
|
1757
|
-
|
1758
|
-
|
1759
|
-
|
1760
|
-
|
1761
|
-
var nonHelper = this.nameLookup('depth' + this.lastContext, name, 'context');
|
1762
|
-
var nextStack = this.nextStack();
|
1763
|
-
|
1764
|
-
this.source.push('if (' + nextStack + ' = ' + helperName + ') { ' + nextStack + ' = ' + nextStack + '.call(' + helper.callParams + '); }');
|
1765
|
-
this.source.push('else { ' + nextStack + ' = ' + nonHelper + '; ' + nextStack + ' = typeof ' + nextStack + ' === functionType ? ' + nextStack + '.apply(depth0) : ' + nextStack + '; }');
|
1766
|
-
},
|
1525
|
+
// [invokeHelper]
|
1526
|
+
//
|
1527
|
+
// On stack, before: hash, inverse, program, params..., ...
|
1528
|
+
// On stack, after: result of helper invocation
|
1529
|
+
//
|
1530
|
+
// Pops off the helper's parameters, invokes the helper,
|
1531
|
+
// and pushes the helper's return value onto the stack.
|
1532
|
+
//
|
1533
|
+
// If the helper is not found, `helperMissing` is called.
|
1534
|
+
invokeHelper: function(paramSize, name) {
|
1535
|
+
this.context.aliases.helperMissing = 'helpers.helperMissing';
|
1536
|
+
|
1537
|
+
var helper = this.lastHelper = this.setupHelper(paramSize, name);
|
1538
|
+
this.register('foundHelper', helper.name);
|
1539
|
+
|
1540
|
+
this.pushStack("foundHelper ? foundHelper.call(" +
|
1541
|
+
helper.callParams + ") " + ": helperMissing.call(" +
|
1542
|
+
helper.helperMissingParams + ")");
|
1543
|
+
},
|
1767
1544
|
|
1768
|
-
|
1769
|
-
|
1770
|
-
|
1771
|
-
|
1772
|
-
|
1773
|
-
|
1774
|
-
|
1775
|
-
|
1776
|
-
|
1777
|
-
|
1778
|
-
|
1779
|
-
params.push("data");
|
1780
|
-
}
|
1545
|
+
// [invokeKnownHelper]
|
1546
|
+
//
|
1547
|
+
// On stack, before: hash, inverse, program, params..., ...
|
1548
|
+
// On stack, after: result of helper invocation
|
1549
|
+
//
|
1550
|
+
// This operation is used when the helper is known to exist,
|
1551
|
+
// so a `helperMissing` fallback is not required.
|
1552
|
+
invokeKnownHelper: function(paramSize, name) {
|
1553
|
+
var helper = this.setupHelper(paramSize, name);
|
1554
|
+
this.pushStack(helper.name + ".call(" + helper.callParams + ")");
|
1555
|
+
},
|
1781
1556
|
|
1782
|
-
|
1783
|
-
|
1784
|
-
|
1557
|
+
// [invokeAmbiguous]
|
1558
|
+
//
|
1559
|
+
// On stack, before: hash, inverse, program, params..., ...
|
1560
|
+
// On stack, after: result of disambiguation
|
1561
|
+
//
|
1562
|
+
// This operation is used when an expression like `{{foo}}`
|
1563
|
+
// is provided, but we don't know at compile-time whether it
|
1564
|
+
// is a helper or a path.
|
1565
|
+
//
|
1566
|
+
// This operation emits more code than the other options,
|
1567
|
+
// and can be avoided by passing the `knownHelpers` and
|
1568
|
+
// `knownHelpersOnly` flags at compile-time.
|
1569
|
+
invokeAmbiguous: function(name) {
|
1570
|
+
this.context.aliases.functionType = '"function"';
|
1571
|
+
|
1572
|
+
this.pushStackLiteral('{}');
|
1573
|
+
var helper = this.setupHelper(0, name);
|
1574
|
+
|
1575
|
+
var helperName = this.lastHelper = this.nameLookup('helpers', name, 'helper');
|
1576
|
+
this.register('foundHelper', helperName);
|
1577
|
+
|
1578
|
+
var nonHelper = this.nameLookup('depth' + this.lastContext, name, 'context');
|
1579
|
+
var nextStack = this.nextStack();
|
1580
|
+
|
1581
|
+
this.source.push('if (foundHelper) { ' + nextStack + ' = foundHelper.call(' + helper.callParams + '); }');
|
1582
|
+
this.source.push('else { ' + nextStack + ' = ' + nonHelper + '; ' + nextStack + ' = typeof ' + nextStack + ' === functionType ? ' + nextStack + '() : ' + nextStack + '; }');
|
1583
|
+
},
|
1785
1584
|
|
1786
|
-
|
1787
|
-
|
1788
|
-
|
1789
|
-
|
1790
|
-
|
1791
|
-
|
1792
|
-
|
1793
|
-
|
1794
|
-
|
1795
|
-
|
1796
|
-
|
1797
|
-
|
1798
|
-
|
1799
|
-
type = this.popStack();
|
1800
|
-
context = this.popStack();
|
1801
|
-
}
|
1585
|
+
// [invokePartial]
|
1586
|
+
//
|
1587
|
+
// On stack, before: context, ...
|
1588
|
+
// On stack after: result of partial invocation
|
1589
|
+
//
|
1590
|
+
// This operation pops off a context, invokes a partial with that context,
|
1591
|
+
// and pushes the result of the invocation back.
|
1592
|
+
invokePartial: function(name) {
|
1593
|
+
var params = [this.nameLookup('partials', name, 'partial'), "'" + name + "'", this.popStack(), "helpers", "partials"];
|
1594
|
+
|
1595
|
+
if (this.options.data) {
|
1596
|
+
params.push("data");
|
1597
|
+
}
|
1802
1598
|
|
1803
|
-
|
1804
|
-
|
1805
|
-
|
1806
|
-
}
|
1807
|
-
if (type) {
|
1808
|
-
hash.types.push("'" + key + "': " + type);
|
1809
|
-
}
|
1810
|
-
hash.values.push("'" + key + "': (" + value + ")");
|
1811
|
-
},
|
1599
|
+
this.context.aliases.self = "this";
|
1600
|
+
this.pushStack("self.invokePartial(" + params.join(", ") + ");");
|
1601
|
+
},
|
1812
1602
|
|
1813
|
-
|
1603
|
+
// [assignToHash]
|
1604
|
+
//
|
1605
|
+
// On stack, before: value, hash, ...
|
1606
|
+
// On stack, after: hash, ...
|
1607
|
+
//
|
1608
|
+
// Pops a value and hash off the stack, assigns `hash[key] = value`
|
1609
|
+
// and pushes the hash back onto the stack.
|
1610
|
+
assignToHash: function(key) {
|
1611
|
+
var value = this.popStack();
|
1612
|
+
var hash = this.topStack();
|
1613
|
+
|
1614
|
+
this.source.push(hash + "['" + key + "'] = " + value + ";");
|
1615
|
+
},
|
1814
1616
|
|
1815
|
-
|
1617
|
+
// HELPERS
|
1816
1618
|
|
1817
|
-
|
1818
|
-
var children = environment.children, child, compiler;
|
1619
|
+
compiler: JavaScriptCompiler,
|
1819
1620
|
|
1820
|
-
|
1821
|
-
|
1822
|
-
compiler = new this.compiler();
|
1621
|
+
compileChildren: function(environment, options) {
|
1622
|
+
var children = environment.children, child, compiler;
|
1823
1623
|
|
1824
|
-
var
|
1624
|
+
for(var i=0, l=children.length; i<l; i++) {
|
1625
|
+
child = children[i];
|
1626
|
+
compiler = new this.compiler();
|
1825
1627
|
|
1826
|
-
if (index == null) {
|
1827
1628
|
this.context.programs.push(''); // Placeholder to prevent name conflicts for nested children
|
1828
|
-
index = this.context.programs.length;
|
1629
|
+
var index = this.context.programs.length;
|
1829
1630
|
child.index = index;
|
1830
1631
|
child.name = 'program' + index;
|
1831
1632
|
this.context.programs[index] = compiler.compile(child, options, this.context);
|
1832
|
-
this.context.environments[index] = child;
|
1833
|
-
} else {
|
1834
|
-
child.index = index;
|
1835
|
-
child.name = 'program' + index;
|
1836
|
-
}
|
1837
|
-
}
|
1838
|
-
},
|
1839
|
-
matchExistingProgram: function(child) {
|
1840
|
-
for (var i = 0, len = this.context.environments.length; i < len; i++) {
|
1841
|
-
var environment = this.context.environments[i];
|
1842
|
-
if (environment && environment.equals(child)) {
|
1843
|
-
return i;
|
1844
1633
|
}
|
1845
|
-
}
|
1846
|
-
},
|
1847
|
-
|
1848
|
-
programExpression: function(guid) {
|
1849
|
-
this.context.aliases.self = "this";
|
1634
|
+
},
|
1850
1635
|
|
1851
|
-
|
1852
|
-
|
1853
|
-
}
|
1636
|
+
programExpression: function(guid) {
|
1637
|
+
this.context.aliases.self = "this";
|
1854
1638
|
|
1855
|
-
|
1856
|
-
|
1639
|
+
if(guid == null) {
|
1640
|
+
return "self.noop";
|
1641
|
+
}
|
1857
1642
|
|
1858
|
-
|
1643
|
+
var child = this.environment.children[guid],
|
1644
|
+
depths = child.depths.list, depth;
|
1859
1645
|
|
1860
|
-
|
1861
|
-
depth = depths[i];
|
1646
|
+
var programParams = [child.index, child.name, "data"];
|
1862
1647
|
|
1863
|
-
|
1864
|
-
|
1865
|
-
}
|
1648
|
+
for(var i=0, l = depths.length; i<l; i++) {
|
1649
|
+
depth = depths[i];
|
1866
1650
|
|
1867
|
-
|
1868
|
-
|
1651
|
+
if(depth === 1) { programParams.push("depth0"); }
|
1652
|
+
else { programParams.push("depth" + (depth - 1)); }
|
1653
|
+
}
|
1869
1654
|
|
1870
|
-
|
1871
|
-
|
1872
|
-
|
1873
|
-
|
1655
|
+
if(depths.length === 0) {
|
1656
|
+
return "self.program(" + programParams.join(", ") + ")";
|
1657
|
+
} else {
|
1658
|
+
programParams.shift();
|
1659
|
+
return "self.programWithDepth(" + programParams.join(", ") + ")";
|
1660
|
+
}
|
1661
|
+
},
|
1874
1662
|
|
1875
|
-
|
1876
|
-
|
1877
|
-
this.
|
1878
|
-
|
1879
|
-
}
|
1880
|
-
},
|
1663
|
+
register: function(name, val) {
|
1664
|
+
this.useRegister(name);
|
1665
|
+
this.source.push(name + " = " + val + ";");
|
1666
|
+
},
|
1881
1667
|
|
1882
|
-
|
1883
|
-
|
1884
|
-
|
1668
|
+
useRegister: function(name) {
|
1669
|
+
if(!this.registers[name]) {
|
1670
|
+
this.registers[name] = true;
|
1671
|
+
this.registers.list.push(name);
|
1672
|
+
}
|
1673
|
+
},
|
1885
1674
|
|
1886
|
-
|
1887
|
-
|
1675
|
+
pushStackLiteral: function(item) {
|
1676
|
+
this.compileStack.push(new Literal(item));
|
1677
|
+
return item;
|
1678
|
+
},
|
1888
1679
|
|
1889
|
-
|
1890
|
-
|
1891
|
-
this.
|
1892
|
-
|
1893
|
-
|
1894
|
-
return stack;
|
1895
|
-
},
|
1680
|
+
pushStack: function(item) {
|
1681
|
+
this.source.push(this.incrStack() + " = " + item + ";");
|
1682
|
+
this.compileStack.push("stack" + this.stackSlot);
|
1683
|
+
return "stack" + this.stackSlot;
|
1684
|
+
},
|
1896
1685
|
|
1897
|
-
|
1898
|
-
|
1899
|
-
inline = this.isInline(),
|
1900
|
-
stack;
|
1686
|
+
replaceStack: function(callback) {
|
1687
|
+
var item = callback.call(this, this.topStack());
|
1901
1688
|
|
1902
|
-
|
1903
|
-
|
1904
|
-
|
1905
|
-
var top = this.popStack(true);
|
1689
|
+
this.source.push(this.topStack() + " = " + item + ";");
|
1690
|
+
return "stack" + this.stackSlot;
|
1691
|
+
},
|
1906
1692
|
|
1907
|
-
|
1908
|
-
|
1909
|
-
|
1910
|
-
|
1911
|
-
|
1912
|
-
var name = this.stackSlot ? this.topStackName() : this.incrStack();
|
1693
|
+
nextStack: function(skipCompileStack) {
|
1694
|
+
var name = this.incrStack();
|
1695
|
+
this.compileStack.push("stack" + this.stackSlot);
|
1696
|
+
return name;
|
1697
|
+
},
|
1913
1698
|
|
1914
|
-
|
1915
|
-
|
1916
|
-
}
|
1917
|
-
|
1918
|
-
|
1919
|
-
}
|
1699
|
+
incrStack: function() {
|
1700
|
+
this.stackSlot++;
|
1701
|
+
if(this.stackSlot > this.stackVars.length) { this.stackVars.push("stack" + this.stackSlot); }
|
1702
|
+
return "stack" + this.stackSlot;
|
1703
|
+
},
|
1920
1704
|
|
1921
|
-
|
1705
|
+
popStack: function() {
|
1706
|
+
var item = this.compileStack.pop();
|
1922
1707
|
|
1923
|
-
|
1924
|
-
|
1925
|
-
|
1926
|
-
|
1927
|
-
|
1928
|
-
} else {
|
1929
|
-
// Prevent modification of the context depth variable. Through replaceStack
|
1930
|
-
if (!/^stack/.test(stack)) {
|
1931
|
-
stack = this.nextStack();
|
1708
|
+
if (item instanceof Literal) {
|
1709
|
+
return item.value;
|
1710
|
+
} else {
|
1711
|
+
this.stackSlot--;
|
1712
|
+
return item;
|
1932
1713
|
}
|
1714
|
+
},
|
1933
1715
|
|
1934
|
-
|
1935
|
-
|
1936
|
-
return stack;
|
1937
|
-
},
|
1938
|
-
|
1939
|
-
nextStack: function() {
|
1940
|
-
return this.pushStack();
|
1941
|
-
},
|
1716
|
+
topStack: function() {
|
1717
|
+
var item = this.compileStack[this.compileStack.length - 1];
|
1942
1718
|
|
1943
|
-
|
1944
|
-
|
1945
|
-
|
1946
|
-
|
1947
|
-
},
|
1948
|
-
topStackName: function() {
|
1949
|
-
return "stack" + this.stackSlot;
|
1950
|
-
},
|
1951
|
-
flushInline: function() {
|
1952
|
-
var inlineStack = this.inlineStack;
|
1953
|
-
if (inlineStack.length) {
|
1954
|
-
this.inlineStack = [];
|
1955
|
-
for (var i = 0, len = inlineStack.length; i < len; i++) {
|
1956
|
-
var entry = inlineStack[i];
|
1957
|
-
if (entry instanceof Literal) {
|
1958
|
-
this.compileStack.push(entry);
|
1959
|
-
} else {
|
1960
|
-
this.pushStack(entry);
|
1961
|
-
}
|
1719
|
+
if (item instanceof Literal) {
|
1720
|
+
return item.value;
|
1721
|
+
} else {
|
1722
|
+
return item;
|
1962
1723
|
}
|
1963
|
-
}
|
1964
|
-
},
|
1965
|
-
isInline: function() {
|
1966
|
-
return this.inlineStack.length;
|
1967
|
-
},
|
1724
|
+
},
|
1968
1725
|
|
1969
|
-
|
1970
|
-
|
1971
|
-
|
1726
|
+
quotedString: function(str) {
|
1727
|
+
return '"' + str
|
1728
|
+
.replace(/\\/g, '\\\\')
|
1729
|
+
.replace(/"/g, '\\"')
|
1730
|
+
.replace(/\n/g, '\\n')
|
1731
|
+
.replace(/\r/g, '\\r') + '"';
|
1732
|
+
},
|
1972
1733
|
|
1973
|
-
|
1974
|
-
|
1975
|
-
|
1976
|
-
|
1977
|
-
this.stackSlot--;
|
1978
|
-
}
|
1979
|
-
return item;
|
1980
|
-
}
|
1981
|
-
},
|
1734
|
+
setupHelper: function(paramSize, name) {
|
1735
|
+
var params = [];
|
1736
|
+
this.setupParams(paramSize, params);
|
1737
|
+
var foundHelper = this.nameLookup('helpers', name, 'helper');
|
1982
1738
|
|
1983
|
-
|
1984
|
-
|
1985
|
-
|
1739
|
+
return {
|
1740
|
+
params: params,
|
1741
|
+
name: foundHelper,
|
1742
|
+
callParams: ["depth0"].concat(params).join(", "),
|
1743
|
+
helperMissingParams: ["depth0", this.quotedString(name)].concat(params).join(", ")
|
1744
|
+
};
|
1745
|
+
},
|
1986
1746
|
|
1987
|
-
|
1988
|
-
|
1989
|
-
|
1990
|
-
|
1991
|
-
}
|
1992
|
-
},
|
1747
|
+
// the params and contexts arguments are passed in arrays
|
1748
|
+
// to fill in
|
1749
|
+
setupParams: function(paramSize, params) {
|
1750
|
+
var options = [], contexts = [], param, inverse, program;
|
1993
1751
|
|
1994
|
-
|
1995
|
-
return '"' + str
|
1996
|
-
.replace(/\\/g, '\\\\')
|
1997
|
-
.replace(/"/g, '\\"')
|
1998
|
-
.replace(/\n/g, '\\n')
|
1999
|
-
.replace(/\r/g, '\\r')
|
2000
|
-
.replace(/\u2028/g, '\\u2028') // Per Ecma-262 7.3 + 7.8.4
|
2001
|
-
.replace(/\u2029/g, '\\u2029') + '"';
|
2002
|
-
},
|
1752
|
+
options.push("hash:" + this.popStack());
|
2003
1753
|
|
2004
|
-
|
2005
|
-
|
2006
|
-
this.setupParams(paramSize, params, missingParams);
|
2007
|
-
var foundHelper = this.nameLookup('helpers', name, 'helper');
|
1754
|
+
inverse = this.popStack();
|
1755
|
+
program = this.popStack();
|
2008
1756
|
|
2009
|
-
|
2010
|
-
|
2011
|
-
|
2012
|
-
|
2013
|
-
|
2014
|
-
|
2015
|
-
|
1757
|
+
// Avoid setting fn and inverse if neither are set. This allows
|
1758
|
+
// helpers to do a check for `if (options.fn)`
|
1759
|
+
if (program || inverse) {
|
1760
|
+
if (!program) {
|
1761
|
+
this.context.aliases.self = "this";
|
1762
|
+
program = "self.noop";
|
1763
|
+
}
|
2016
1764
|
|
2017
|
-
|
2018
|
-
|
2019
|
-
|
2020
|
-
|
1765
|
+
if (!inverse) {
|
1766
|
+
this.context.aliases.self = "this";
|
1767
|
+
inverse = "self.noop";
|
1768
|
+
}
|
2021
1769
|
|
2022
|
-
|
1770
|
+
options.push("inverse:" + inverse);
|
1771
|
+
options.push("fn:" + program);
|
1772
|
+
}
|
2023
1773
|
|
2024
|
-
|
2025
|
-
|
1774
|
+
for(var i=0; i<paramSize; i++) {
|
1775
|
+
param = this.popStack();
|
1776
|
+
params.push(param);
|
2026
1777
|
|
2027
|
-
|
2028
|
-
|
2029
|
-
|
2030
|
-
if (!program) {
|
2031
|
-
this.context.aliases.self = "this";
|
2032
|
-
program = "self.noop";
|
1778
|
+
if(this.options.stringParams) {
|
1779
|
+
contexts.push(this.popStack());
|
1780
|
+
}
|
2033
1781
|
}
|
2034
1782
|
|
2035
|
-
if (
|
2036
|
-
|
2037
|
-
inverse = "self.noop";
|
1783
|
+
if (this.options.stringParams) {
|
1784
|
+
options.push("contexts:[" + contexts.join(",") + "]");
|
2038
1785
|
}
|
2039
1786
|
|
2040
|
-
options.
|
2041
|
-
|
2042
|
-
}
|
2043
|
-
|
2044
|
-
for(var i=0; i<paramSize; i++) {
|
2045
|
-
param = this.popStack();
|
2046
|
-
params.push(param);
|
2047
|
-
|
2048
|
-
if(this.options.stringParams) {
|
2049
|
-
types.push(this.popStack());
|
2050
|
-
contexts.push(this.popStack());
|
1787
|
+
if(this.options.data) {
|
1788
|
+
options.push("data:data");
|
2051
1789
|
}
|
2052
|
-
}
|
2053
1790
|
|
2054
|
-
|
2055
|
-
|
2056
|
-
options.push("types:[" + types.join(",") + "]");
|
2057
|
-
options.push("hashContexts:hashContexts");
|
2058
|
-
options.push("hashTypes:hashTypes");
|
2059
|
-
}
|
2060
|
-
|
2061
|
-
if(this.options.data) {
|
2062
|
-
options.push("data:data");
|
1791
|
+
params.push("{" + options.join(",") + "}");
|
1792
|
+
return params.join(", ");
|
2063
1793
|
}
|
1794
|
+
};
|
2064
1795
|
|
2065
|
-
|
2066
|
-
|
2067
|
-
|
2068
|
-
|
2069
|
-
|
2070
|
-
|
2071
|
-
|
2072
|
-
|
1796
|
+
var reservedWords = (
|
1797
|
+
"break else new var" +
|
1798
|
+
" case finally return void" +
|
1799
|
+
" catch for switch while" +
|
1800
|
+
" continue function this with" +
|
1801
|
+
" default if throw" +
|
1802
|
+
" delete in try" +
|
1803
|
+
" do instanceof typeof" +
|
1804
|
+
" abstract enum int short" +
|
1805
|
+
" boolean export interface static" +
|
1806
|
+
" byte extends long super" +
|
1807
|
+
" char final native synchronized" +
|
1808
|
+
" class float package throws" +
|
1809
|
+
" const goto private transient" +
|
1810
|
+
" debugger implements protected volatile" +
|
1811
|
+
" double import public let yield"
|
1812
|
+
).split(" ");
|
1813
|
+
|
1814
|
+
var compilerWords = JavaScriptCompiler.RESERVED_WORDS = {};
|
1815
|
+
|
1816
|
+
for(var i=0, l=reservedWords.length; i<l; i++) {
|
1817
|
+
compilerWords[reservedWords[i]] = true;
|
2073
1818
|
}
|
2074
|
-
};
|
2075
1819
|
|
2076
|
-
|
2077
|
-
|
2078
|
-
|
2079
|
-
|
2080
|
-
|
2081
|
-
|
2082
|
-
" delete in try" +
|
2083
|
-
" do instanceof typeof" +
|
2084
|
-
" abstract enum int short" +
|
2085
|
-
" boolean export interface static" +
|
2086
|
-
" byte extends long super" +
|
2087
|
-
" char final native synchronized" +
|
2088
|
-
" class float package throws" +
|
2089
|
-
" const goto private transient" +
|
2090
|
-
" debugger implements protected volatile" +
|
2091
|
-
" double import public let yield"
|
2092
|
-
).split(" ");
|
2093
|
-
|
2094
|
-
var compilerWords = JavaScriptCompiler.RESERVED_WORDS = {};
|
2095
|
-
|
2096
|
-
for(var i=0, l=reservedWords.length; i<l; i++) {
|
2097
|
-
compilerWords[reservedWords[i]] = true;
|
2098
|
-
}
|
2099
|
-
|
2100
|
-
JavaScriptCompiler.isValidJavaScriptVariableName = function(name) {
|
2101
|
-
if(!JavaScriptCompiler.RESERVED_WORDS[name] && /^[a-zA-Z_$][0-9a-zA-Z_$]+$/.test(name)) {
|
2102
|
-
return true;
|
2103
|
-
}
|
2104
|
-
return false;
|
2105
|
-
};
|
1820
|
+
JavaScriptCompiler.isValidJavaScriptVariableName = function(name) {
|
1821
|
+
if(!JavaScriptCompiler.RESERVED_WORDS[name] && /^[a-zA-Z_$][0-9a-zA-Z_$]+$/.test(name)) {
|
1822
|
+
return true;
|
1823
|
+
}
|
1824
|
+
return false;
|
1825
|
+
};
|
2106
1826
|
|
2107
|
-
Handlebars.
|
2108
|
-
if (input == null || (typeof input !== 'string' && input.constructor !== Handlebars.AST.ProgramNode)) {
|
2109
|
-
throw new Handlebars.Exception("You must pass a string or Handlebars AST to Handlebars.precompile. You passed " + input);
|
2110
|
-
}
|
1827
|
+
})(Handlebars.Compiler, Handlebars.JavaScriptCompiler);
|
2111
1828
|
|
1829
|
+
Handlebars.precompile = function(string, options) {
|
2112
1830
|
options = options || {};
|
2113
|
-
if (!('data' in options)) {
|
2114
|
-
options.data = true;
|
2115
|
-
}
|
2116
|
-
var ast = Handlebars.parse(input);
|
2117
|
-
var environment = new Compiler().compile(ast, options);
|
2118
|
-
return new JavaScriptCompiler().compile(environment, options);
|
2119
|
-
};
|
2120
1831
|
|
2121
|
-
|
2122
|
-
|
2123
|
-
|
2124
|
-
|
1832
|
+
var ast = Handlebars.parse(string);
|
1833
|
+
var environment = new Handlebars.Compiler().compile(ast, options);
|
1834
|
+
return new Handlebars.JavaScriptCompiler().compile(environment, options);
|
1835
|
+
};
|
2125
1836
|
|
1837
|
+
Handlebars.compile = function(string, options) {
|
2126
1838
|
options = options || {};
|
2127
|
-
|
2128
|
-
options.data = true;
|
2129
|
-
}
|
1839
|
+
|
2130
1840
|
var compiled;
|
2131
1841
|
function compile() {
|
2132
|
-
var ast = Handlebars.parse(
|
2133
|
-
var environment = new Compiler().compile(ast, options);
|
2134
|
-
var templateSpec = new JavaScriptCompiler().compile(environment, options, undefined, true);
|
1842
|
+
var ast = Handlebars.parse(string);
|
1843
|
+
var environment = new Handlebars.Compiler().compile(ast, options);
|
1844
|
+
var templateSpec = new Handlebars.JavaScriptCompiler().compile(environment, options, undefined, true);
|
2135
1845
|
return Handlebars.template(templateSpec);
|
2136
1846
|
}
|
2137
1847
|
|
@@ -2143,10 +1853,8 @@ Handlebars.compile = function(input, options) {
|
|
2143
1853
|
return compiled.call(this, context, options);
|
2144
1854
|
};
|
2145
1855
|
};
|
2146
|
-
|
2147
1856
|
;
|
2148
1857
|
// lib/handlebars/runtime.js
|
2149
|
-
|
2150
1858
|
Handlebars.VM = {
|
2151
1859
|
template: function(templateSpec) {
|
2152
1860
|
// Just add water
|
@@ -2157,63 +1865,39 @@ Handlebars.VM = {
|
|
2157
1865
|
program: function(i, fn, data) {
|
2158
1866
|
var programWrapper = this.programs[i];
|
2159
1867
|
if(data) {
|
2160
|
-
|
2161
|
-
} else if
|
2162
|
-
programWrapper
|
1868
|
+
return Handlebars.VM.program(fn, data);
|
1869
|
+
} else if(programWrapper) {
|
1870
|
+
return programWrapper;
|
1871
|
+
} else {
|
1872
|
+
programWrapper = this.programs[i] = Handlebars.VM.program(fn);
|
1873
|
+
return programWrapper;
|
2163
1874
|
}
|
2164
|
-
return programWrapper;
|
2165
1875
|
},
|
2166
1876
|
programWithDepth: Handlebars.VM.programWithDepth,
|
2167
|
-
noop: Handlebars.VM.noop
|
2168
|
-
compilerInfo: null
|
1877
|
+
noop: Handlebars.VM.noop
|
2169
1878
|
};
|
2170
1879
|
|
2171
1880
|
return function(context, options) {
|
2172
1881
|
options = options || {};
|
2173
|
-
|
2174
|
-
|
2175
|
-
var compilerInfo = container.compilerInfo || [],
|
2176
|
-
compilerRevision = compilerInfo[0] || 1,
|
2177
|
-
currentRevision = Handlebars.COMPILER_REVISION;
|
2178
|
-
|
2179
|
-
if (compilerRevision !== currentRevision) {
|
2180
|
-
if (compilerRevision < currentRevision) {
|
2181
|
-
var runtimeVersions = Handlebars.REVISION_CHANGES[currentRevision],
|
2182
|
-
compilerVersions = Handlebars.REVISION_CHANGES[compilerRevision];
|
2183
|
-
throw "Template was precompiled with an older version of Handlebars than the current runtime. "+
|
2184
|
-
"Please update your precompiler to a newer version ("+runtimeVersions+") or downgrade your runtime to an older version ("+compilerVersions+").";
|
2185
|
-
} else {
|
2186
|
-
// Use the embedded version info since the runtime doesn't know about this revision yet
|
2187
|
-
throw "Template was precompiled with a newer version of Handlebars than the current runtime. "+
|
2188
|
-
"Please update your runtime to a newer version ("+compilerInfo[1]+").";
|
2189
|
-
}
|
2190
|
-
}
|
2191
|
-
|
2192
|
-
return result;
|
1882
|
+
return templateSpec.call(container, Handlebars, context, options.helpers, options.partials, options.data);
|
2193
1883
|
};
|
2194
1884
|
},
|
2195
1885
|
|
2196
|
-
programWithDepth: function(
|
2197
|
-
var args = Array.prototype.slice.call(arguments,
|
1886
|
+
programWithDepth: function(fn, data, $depth) {
|
1887
|
+
var args = Array.prototype.slice.call(arguments, 2);
|
2198
1888
|
|
2199
|
-
|
1889
|
+
return function(context, options) {
|
2200
1890
|
options = options || {};
|
2201
1891
|
|
2202
1892
|
return fn.apply(this, [context, options.data || data].concat(args));
|
2203
1893
|
};
|
2204
|
-
program.program = i;
|
2205
|
-
program.depth = args.length;
|
2206
|
-
return program;
|
2207
1894
|
},
|
2208
|
-
program: function(
|
2209
|
-
|
1895
|
+
program: function(fn, data) {
|
1896
|
+
return function(context, options) {
|
2210
1897
|
options = options || {};
|
2211
1898
|
|
2212
1899
|
return fn(context, options.data || data);
|
2213
1900
|
};
|
2214
|
-
program.program = i;
|
2215
|
-
program.depth = 0;
|
2216
|
-
return program;
|
2217
1901
|
},
|
2218
1902
|
noop: function() { return ""; },
|
2219
1903
|
invokePartial: function(partial, name, context, helpers, partials, data) {
|
@@ -2234,6 +1918,3 @@ Handlebars.VM = {
|
|
2234
1918
|
|
2235
1919
|
Handlebars.template = Handlebars.VM.template;
|
2236
1920
|
;
|
2237
|
-
// lib/handlebars/browser-suffix.js
|
2238
|
-
})(Handlebars);
|
2239
|
-
;
|