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