Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Download
80684 views
1
/*!
2
3
handlebars v3.0.0
4
5
Copyright (C) 2011-2014 by Yehuda Katz
6
7
Permission is hereby granted, free of charge, to any person obtaining a copy
8
of this software and associated documentation files (the "Software"), to deal
9
in the Software without restriction, including without limitation the rights
10
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11
copies of the Software, and to permit persons to whom the Software is
12
furnished to do so, subject to the following conditions:
13
14
The above copyright notice and this permission notice shall be included in
15
all copies or substantial portions of the Software.
16
17
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23
THE SOFTWARE.
24
25
@license
26
*/
27
define(
28
'handlebars/utils',["exports"],
29
function(__exports__) {
30
31
/*jshint -W004 */
32
var escape = {
33
"&": "&",
34
"<": "&lt;",
35
">": "&gt;",
36
'"': "&quot;",
37
"'": "&#x27;",
38
"`": "&#x60;"
39
};
40
41
var badChars = /[&<>"'`]/g;
42
var possible = /[&<>"'`]/;
43
44
function escapeChar(chr) {
45
return escape[chr];
46
}
47
48
function extend(obj /* , ...source */) {
49
for (var i = 1; i < arguments.length; i++) {
50
for (var key in arguments[i]) {
51
if (Object.prototype.hasOwnProperty.call(arguments[i], key)) {
52
obj[key] = arguments[i][key];
53
}
54
}
55
}
56
57
return obj;
58
}
59
60
__exports__.extend = extend;var toString = Object.prototype.toString;
61
__exports__.toString = toString;
62
// Sourced from lodash
63
// https://github.com/bestiejs/lodash/blob/master/LICENSE.txt
64
var isFunction = function(value) {
65
return typeof value === 'function';
66
};
67
// fallback for older versions of Chrome and Safari
68
/* istanbul ignore next */
69
if (isFunction(/x/)) {
70
isFunction = function(value) {
71
return typeof value === 'function' && toString.call(value) === '[object Function]';
72
};
73
}
74
var isFunction;
75
__exports__.isFunction = isFunction;
76
/* istanbul ignore next */
77
var isArray = Array.isArray || function(value) {
78
return (value && typeof value === 'object') ? toString.call(value) === '[object Array]' : false;
79
};
80
__exports__.isArray = isArray;
81
// Older IE versions do not directly support indexOf so we must implement our own, sadly.
82
function indexOf(array, value) {
83
for (var i = 0, len = array.length; i < len; i++) {
84
if (array[i] === value) {
85
return i;
86
}
87
}
88
return -1;
89
}
90
91
__exports__.indexOf = indexOf;
92
function escapeExpression(string) {
93
// don't escape SafeStrings, since they're already safe
94
if (string && string.toHTML) {
95
return string.toHTML();
96
} else if (string == null) {
97
return "";
98
} else if (!string) {
99
return string + '';
100
}
101
102
// Force a string conversion as this will be done by the append regardless and
103
// the regex test will do this transparently behind the scenes, causing issues if
104
// an object's to string has escaped characters in it.
105
string = "" + string;
106
107
if(!possible.test(string)) { return string; }
108
return string.replace(badChars, escapeChar);
109
}
110
111
__exports__.escapeExpression = escapeExpression;function isEmpty(value) {
112
if (!value && value !== 0) {
113
return true;
114
} else if (isArray(value) && value.length === 0) {
115
return true;
116
} else {
117
return false;
118
}
119
}
120
121
__exports__.isEmpty = isEmpty;function blockParams(params, ids) {
122
params.path = ids;
123
return params;
124
}
125
126
__exports__.blockParams = blockParams;function appendContextPath(contextPath, id) {
127
return (contextPath ? contextPath + '.' : '') + id;
128
}
129
130
__exports__.appendContextPath = appendContextPath;
131
});
132
define(
133
'handlebars/exception',["exports"],
134
function(__exports__) {
135
136
137
var errorProps = ['description', 'fileName', 'lineNumber', 'message', 'name', 'number', 'stack'];
138
139
function Exception(message, node) {
140
var loc = node && node.loc,
141
line,
142
column;
143
if (loc) {
144
line = loc.start.line;
145
column = loc.start.column;
146
147
message += ' - ' + line + ':' + column;
148
}
149
150
var tmp = Error.prototype.constructor.call(this, message);
151
152
// Unfortunately errors are not enumerable in Chrome (at least), so `for prop in tmp` doesn't work.
153
for (var idx = 0; idx < errorProps.length; idx++) {
154
this[errorProps[idx]] = tmp[errorProps[idx]];
155
}
156
157
if (loc) {
158
this.lineNumber = line;
159
this.column = column;
160
}
161
}
162
163
Exception.prototype = new Error();
164
165
__exports__["default"] = Exception;
166
});
167
define(
168
'handlebars/base',["./utils","./exception","exports"],
169
function(__dependency1__, __dependency2__, __exports__) {
170
171
var Utils = __dependency1__;
172
var Exception = __dependency2__["default"];
173
174
var VERSION = "3.0.0";
175
__exports__.VERSION = VERSION;var COMPILER_REVISION = 6;
176
__exports__.COMPILER_REVISION = COMPILER_REVISION;
177
var REVISION_CHANGES = {
178
1: '<= 1.0.rc.2', // 1.0.rc.2 is actually rev2 but doesn't report it
179
2: '== 1.0.0-rc.3',
180
3: '== 1.0.0-rc.4',
181
4: '== 1.x.x',
182
5: '== 2.0.0-alpha.x',
183
6: '>= 2.0.0-beta.1'
184
};
185
__exports__.REVISION_CHANGES = REVISION_CHANGES;
186
var isArray = Utils.isArray,
187
isFunction = Utils.isFunction,
188
toString = Utils.toString,
189
objectType = '[object Object]';
190
191
function HandlebarsEnvironment(helpers, partials) {
192
this.helpers = helpers || {};
193
this.partials = partials || {};
194
195
registerDefaultHelpers(this);
196
}
197
198
__exports__.HandlebarsEnvironment = HandlebarsEnvironment;HandlebarsEnvironment.prototype = {
199
constructor: HandlebarsEnvironment,
200
201
logger: logger,
202
log: log,
203
204
registerHelper: function(name, fn) {
205
if (toString.call(name) === objectType) {
206
if (fn) { throw new Exception('Arg not supported with multiple helpers'); }
207
Utils.extend(this.helpers, name);
208
} else {
209
this.helpers[name] = fn;
210
}
211
},
212
unregisterHelper: function(name) {
213
delete this.helpers[name];
214
},
215
216
registerPartial: function(name, partial) {
217
if (toString.call(name) === objectType) {
218
Utils.extend(this.partials, name);
219
} else {
220
if (typeof partial === 'undefined') {
221
throw new Exception('Attempting to register a partial as undefined');
222
}
223
this.partials[name] = partial;
224
}
225
},
226
unregisterPartial: function(name) {
227
delete this.partials[name];
228
}
229
};
230
231
function registerDefaultHelpers(instance) {
232
instance.registerHelper('helperMissing', function(/* [args, ]options */) {
233
if(arguments.length === 1) {
234
// A missing field in a {{foo}} constuct.
235
return undefined;
236
} else {
237
// Someone is actually trying to call something, blow up.
238
throw new Exception("Missing helper: '" + arguments[arguments.length-1].name + "'");
239
}
240
});
241
242
instance.registerHelper('blockHelperMissing', function(context, options) {
243
var inverse = options.inverse,
244
fn = options.fn;
245
246
if(context === true) {
247
return fn(this);
248
} else if(context === false || context == null) {
249
return inverse(this);
250
} else if (isArray(context)) {
251
if(context.length > 0) {
252
if (options.ids) {
253
options.ids = [options.name];
254
}
255
256
return instance.helpers.each(context, options);
257
} else {
258
return inverse(this);
259
}
260
} else {
261
if (options.data && options.ids) {
262
var data = createFrame(options.data);
263
data.contextPath = Utils.appendContextPath(options.data.contextPath, options.name);
264
options = {data: data};
265
}
266
267
return fn(context, options);
268
}
269
});
270
271
instance.registerHelper('each', function(context, options) {
272
if (!options) {
273
throw new Exception('Must pass iterator to #each');
274
}
275
276
var fn = options.fn, inverse = options.inverse;
277
var i = 0, ret = "", data;
278
279
var contextPath;
280
if (options.data && options.ids) {
281
contextPath = Utils.appendContextPath(options.data.contextPath, options.ids[0]) + '.';
282
}
283
284
if (isFunction(context)) { context = context.call(this); }
285
286
if (options.data) {
287
data = createFrame(options.data);
288
}
289
290
function execIteration(key, i, last) {
291
if (data) {
292
data.key = key;
293
data.index = i;
294
data.first = i === 0;
295
data.last = !!last;
296
297
if (contextPath) {
298
data.contextPath = contextPath + key;
299
}
300
}
301
302
ret = ret + fn(context[key], {
303
data: data,
304
blockParams: Utils.blockParams([context[key], key], [contextPath + key, null])
305
});
306
}
307
308
if(context && typeof context === 'object') {
309
if (isArray(context)) {
310
for(var j = context.length; i<j; i++) {
311
execIteration(i, i, i === context.length-1);
312
}
313
} else {
314
var priorKey;
315
316
for(var key in context) {
317
if(context.hasOwnProperty(key)) {
318
// We're running the iterations one step out of sync so we can detect
319
// the last iteration without have to scan the object twice and create
320
// an itermediate keys array.
321
if (priorKey) {
322
execIteration(priorKey, i-1);
323
}
324
priorKey = key;
325
i++;
326
}
327
}
328
if (priorKey) {
329
execIteration(priorKey, i-1, true);
330
}
331
}
332
}
333
334
if(i === 0){
335
ret = inverse(this);
336
}
337
338
return ret;
339
});
340
341
instance.registerHelper('if', function(conditional, options) {
342
if (isFunction(conditional)) { conditional = conditional.call(this); }
343
344
// Default behavior is to render the positive path if the value is truthy and not empty.
345
// The `includeZero` option may be set to treat the condtional as purely not empty based on the
346
// behavior of isEmpty. Effectively this determines if 0 is handled by the positive path or negative.
347
if ((!options.hash.includeZero && !conditional) || Utils.isEmpty(conditional)) {
348
return options.inverse(this);
349
} else {
350
return options.fn(this);
351
}
352
});
353
354
instance.registerHelper('unless', function(conditional, options) {
355
return instance.helpers['if'].call(this, conditional, {fn: options.inverse, inverse: options.fn, hash: options.hash});
356
});
357
358
instance.registerHelper('with', function(context, options) {
359
if (isFunction(context)) { context = context.call(this); }
360
361
var fn = options.fn;
362
363
if (!Utils.isEmpty(context)) {
364
if (options.data && options.ids) {
365
var data = createFrame(options.data);
366
data.contextPath = Utils.appendContextPath(options.data.contextPath, options.ids[0]);
367
options = {data:data};
368
}
369
370
return fn(context, options);
371
} else {
372
return options.inverse(this);
373
}
374
});
375
376
instance.registerHelper('log', function(message, options) {
377
var level = options.data && options.data.level != null ? parseInt(options.data.level, 10) : 1;
378
instance.log(level, message);
379
});
380
381
instance.registerHelper('lookup', function(obj, field) {
382
return obj && obj[field];
383
});
384
}
385
386
var logger = {
387
methodMap: { 0: 'debug', 1: 'info', 2: 'warn', 3: 'error' },
388
389
// State enum
390
DEBUG: 0,
391
INFO: 1,
392
WARN: 2,
393
ERROR: 3,
394
level: 1,
395
396
// Can be overridden in the host environment
397
log: function(level, message) {
398
if (typeof console !== 'undefined' && logger.level <= level) {
399
var method = logger.methodMap[level];
400
(console[method] || console.log).call(console, message);
401
}
402
}
403
};
404
__exports__.logger = logger;
405
var log = logger.log;
406
__exports__.log = log;
407
var createFrame = function(object) {
408
var frame = Utils.extend({}, object);
409
frame._parent = object;
410
return frame;
411
};
412
__exports__.createFrame = createFrame;
413
});
414
define(
415
'handlebars/safe-string',["exports"],
416
function(__exports__) {
417
418
// Build out our basic SafeString type
419
function SafeString(string) {
420
this.string = string;
421
}
422
423
SafeString.prototype.toString = SafeString.prototype.toHTML = function() {
424
return "" + this.string;
425
};
426
427
__exports__["default"] = SafeString;
428
});
429
define(
430
'handlebars/runtime',["./utils","./exception","./base","exports"],
431
function(__dependency1__, __dependency2__, __dependency3__, __exports__) {
432
433
var Utils = __dependency1__;
434
var Exception = __dependency2__["default"];
435
var COMPILER_REVISION = __dependency3__.COMPILER_REVISION;
436
var REVISION_CHANGES = __dependency3__.REVISION_CHANGES;
437
var createFrame = __dependency3__.createFrame;
438
439
function checkRevision(compilerInfo) {
440
var compilerRevision = compilerInfo && compilerInfo[0] || 1,
441
currentRevision = COMPILER_REVISION;
442
443
if (compilerRevision !== currentRevision) {
444
if (compilerRevision < currentRevision) {
445
var runtimeVersions = REVISION_CHANGES[currentRevision],
446
compilerVersions = REVISION_CHANGES[compilerRevision];
447
throw new Exception("Template was precompiled with an older version of Handlebars than the current runtime. "+
448
"Please update your precompiler to a newer version ("+runtimeVersions+") or downgrade your runtime to an older version ("+compilerVersions+").");
449
} else {
450
// Use the embedded version info since the runtime doesn't know about this revision yet
451
throw new Exception("Template was precompiled with a newer version of Handlebars than the current runtime. "+
452
"Please update your runtime to a newer version ("+compilerInfo[1]+").");
453
}
454
}
455
}
456
457
__exports__.checkRevision = checkRevision;// TODO: Remove this line and break up compilePartial
458
459
function template(templateSpec, env) {
460
/* istanbul ignore next */
461
if (!env) {
462
throw new Exception("No environment passed to template");
463
}
464
if (!templateSpec || !templateSpec.main) {
465
throw new Exception('Unknown template object: ' + typeof templateSpec);
466
}
467
468
// Note: Using env.VM references rather than local var references throughout this section to allow
469
// for external users to override these as psuedo-supported APIs.
470
env.VM.checkRevision(templateSpec.compiler);
471
472
var invokePartialWrapper = function(partial, context, options) {
473
if (options.hash) {
474
context = Utils.extend({}, context, options.hash);
475
}
476
477
partial = env.VM.resolvePartial.call(this, partial, context, options);
478
var result = env.VM.invokePartial.call(this, partial, context, options);
479
480
if (result == null && env.compile) {
481
options.partials[options.name] = env.compile(partial, templateSpec.compilerOptions, env);
482
result = options.partials[options.name](context, options);
483
}
484
if (result != null) {
485
if (options.indent) {
486
var lines = result.split('\n');
487
for (var i = 0, l = lines.length; i < l; i++) {
488
if (!lines[i] && i + 1 === l) {
489
break;
490
}
491
492
lines[i] = options.indent + lines[i];
493
}
494
result = lines.join('\n');
495
}
496
return result;
497
} else {
498
throw new Exception("The partial " + options.name + " could not be compiled when running in runtime-only mode");
499
}
500
};
501
502
// Just add water
503
var container = {
504
strict: function(obj, name) {
505
if (!(name in obj)) {
506
throw new Exception('"' + name + '" not defined in ' + obj);
507
}
508
return obj[name];
509
},
510
lookup: function(depths, name) {
511
var len = depths.length;
512
for (var i = 0; i < len; i++) {
513
if (depths[i] && depths[i][name] != null) {
514
return depths[i][name];
515
}
516
}
517
},
518
lambda: function(current, context) {
519
return typeof current === 'function' ? current.call(context) : current;
520
},
521
522
escapeExpression: Utils.escapeExpression,
523
invokePartial: invokePartialWrapper,
524
525
fn: function(i) {
526
return templateSpec[i];
527
},
528
529
programs: [],
530
program: function(i, data, declaredBlockParams, blockParams, depths) {
531
var programWrapper = this.programs[i],
532
fn = this.fn(i);
533
if (data || depths || blockParams || declaredBlockParams) {
534
programWrapper = program(this, i, fn, data, declaredBlockParams, blockParams, depths);
535
} else if (!programWrapper) {
536
programWrapper = this.programs[i] = program(this, i, fn);
537
}
538
return programWrapper;
539
},
540
541
data: function(data, depth) {
542
while (data && depth--) {
543
data = data._parent;
544
}
545
return data;
546
},
547
merge: function(param, common) {
548
var ret = param || common;
549
550
if (param && common && (param !== common)) {
551
ret = Utils.extend({}, common, param);
552
}
553
554
return ret;
555
},
556
557
noop: env.VM.noop,
558
compilerInfo: templateSpec.compiler
559
};
560
561
var ret = function(context, options) {
562
options = options || {};
563
var data = options.data;
564
565
ret._setup(options);
566
if (!options.partial && templateSpec.useData) {
567
data = initData(context, data);
568
}
569
var depths,
570
blockParams = templateSpec.useBlockParams ? [] : undefined;
571
if (templateSpec.useDepths) {
572
depths = options.depths ? [context].concat(options.depths) : [context];
573
}
574
575
return templateSpec.main.call(container, context, container.helpers, container.partials, data, blockParams, depths);
576
};
577
ret.isTop = true;
578
579
ret._setup = function(options) {
580
if (!options.partial) {
581
container.helpers = container.merge(options.helpers, env.helpers);
582
583
if (templateSpec.usePartial) {
584
container.partials = container.merge(options.partials, env.partials);
585
}
586
} else {
587
container.helpers = options.helpers;
588
container.partials = options.partials;
589
}
590
};
591
592
ret._child = function(i, data, blockParams, depths) {
593
if (templateSpec.useBlockParams && !blockParams) {
594
throw new Exception('must pass block params');
595
}
596
if (templateSpec.useDepths && !depths) {
597
throw new Exception('must pass parent depths');
598
}
599
600
return program(container, i, templateSpec[i], data, 0, blockParams, depths);
601
};
602
return ret;
603
}
604
605
__exports__.template = template;function program(container, i, fn, data, declaredBlockParams, blockParams, depths) {
606
var prog = function(context, options) {
607
options = options || {};
608
609
return fn.call(container,
610
context,
611
container.helpers, container.partials,
612
options.data || data,
613
blockParams && [options.blockParams].concat(blockParams),
614
depths && [context].concat(depths));
615
};
616
prog.program = i;
617
prog.depth = depths ? depths.length : 0;
618
prog.blockParams = declaredBlockParams || 0;
619
return prog;
620
}
621
622
__exports__.program = program;function resolvePartial(partial, context, options) {
623
if (!partial) {
624
partial = options.partials[options.name];
625
} else if (!partial.call && !options.name) {
626
// This is a dynamic partial that returned a string
627
options.name = partial;
628
partial = options.partials[partial];
629
}
630
return partial;
631
}
632
633
__exports__.resolvePartial = resolvePartial;function invokePartial(partial, context, options) {
634
options.partial = true;
635
636
if(partial === undefined) {
637
throw new Exception("The partial " + options.name + " could not be found");
638
} else if(partial instanceof Function) {
639
return partial(context, options);
640
}
641
}
642
643
__exports__.invokePartial = invokePartial;function noop() { return ""; }
644
645
__exports__.noop = noop;function initData(context, data) {
646
if (!data || !('root' in data)) {
647
data = data ? createFrame(data) : {};
648
data.root = context;
649
}
650
return data;
651
}
652
});
653
define(
654
'handlebars.runtime',["./handlebars/base","./handlebars/safe-string","./handlebars/exception","./handlebars/utils","./handlebars/runtime","exports"],
655
function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __exports__) {
656
657
/*globals Handlebars: true */
658
var base = __dependency1__;
659
660
// Each of these augment the Handlebars object. No need to setup here.
661
// (This is done to easily share code between commonjs and browse envs)
662
var SafeString = __dependency2__["default"];
663
var Exception = __dependency3__["default"];
664
var Utils = __dependency4__;
665
var runtime = __dependency5__;
666
667
// For compatibility and usage outside of module systems, make the Handlebars object a namespace
668
var create = function() {
669
var hb = new base.HandlebarsEnvironment();
670
671
Utils.extend(hb, base);
672
hb.SafeString = SafeString;
673
hb.Exception = Exception;
674
hb.Utils = Utils;
675
hb.escapeExpression = Utils.escapeExpression;
676
677
hb.VM = runtime;
678
hb.template = function(spec) {
679
return runtime.template(spec, hb);
680
};
681
682
return hb;
683
};
684
685
var Handlebars = create();
686
Handlebars.create = create;
687
688
/*jshint -W040 */
689
/* istanbul ignore next */
690
var root = typeof global !== 'undefined' ? global : window,
691
$Handlebars = root.Handlebars;
692
/* istanbul ignore next */
693
Handlebars.noConflict = function() {
694
if (root.Handlebars === Handlebars) {
695
root.Handlebars = $Handlebars;
696
}
697
};
698
699
Handlebars['default'] = Handlebars;
700
701
__exports__["default"] = Handlebars;
702
});
703
define(
704
'handlebars/compiler/ast',["exports"],
705
function(__exports__) {
706
707
var AST = {
708
Program: function(statements, blockParams, strip, locInfo) {
709
this.loc = locInfo;
710
this.type = 'Program';
711
this.body = statements;
712
713
this.blockParams = blockParams;
714
this.strip = strip;
715
},
716
717
MustacheStatement: function(path, params, hash, escaped, strip, locInfo) {
718
this.loc = locInfo;
719
this.type = 'MustacheStatement';
720
721
this.path = path;
722
this.params = params || [];
723
this.hash = hash;
724
this.escaped = escaped;
725
726
this.strip = strip;
727
},
728
729
BlockStatement: function(path, params, hash, program, inverse, openStrip, inverseStrip, closeStrip, locInfo) {
730
this.loc = locInfo;
731
this.type = 'BlockStatement';
732
733
this.path = path;
734
this.params = params || [];
735
this.hash = hash;
736
this.program = program;
737
this.inverse = inverse;
738
739
this.openStrip = openStrip;
740
this.inverseStrip = inverseStrip;
741
this.closeStrip = closeStrip;
742
},
743
744
PartialStatement: function(name, params, hash, strip, locInfo) {
745
this.loc = locInfo;
746
this.type = 'PartialStatement';
747
748
this.name = name;
749
this.params = params || [];
750
this.hash = hash;
751
752
this.indent = '';
753
this.strip = strip;
754
},
755
756
ContentStatement: function(string, locInfo) {
757
this.loc = locInfo;
758
this.type = 'ContentStatement';
759
this.original = this.value = string;
760
},
761
762
CommentStatement: function(comment, strip, locInfo) {
763
this.loc = locInfo;
764
this.type = 'CommentStatement';
765
this.value = comment;
766
767
this.strip = strip;
768
},
769
770
SubExpression: function(path, params, hash, locInfo) {
771
this.loc = locInfo;
772
773
this.type = 'SubExpression';
774
this.path = path;
775
this.params = params || [];
776
this.hash = hash;
777
},
778
779
PathExpression: function(data, depth, parts, original, locInfo) {
780
this.loc = locInfo;
781
this.type = 'PathExpression';
782
783
this.data = data;
784
this.original = original;
785
this.parts = parts;
786
this.depth = depth;
787
},
788
789
StringLiteral: function(string, locInfo) {
790
this.loc = locInfo;
791
this.type = 'StringLiteral';
792
this.original =
793
this.value = string;
794
},
795
796
NumberLiteral: function(number, locInfo) {
797
this.loc = locInfo;
798
this.type = 'NumberLiteral';
799
this.original =
800
this.value = Number(number);
801
},
802
803
BooleanLiteral: function(bool, locInfo) {
804
this.loc = locInfo;
805
this.type = 'BooleanLiteral';
806
this.original =
807
this.value = bool === 'true';
808
},
809
810
Hash: function(pairs, locInfo) {
811
this.loc = locInfo;
812
this.type = 'Hash';
813
this.pairs = pairs;
814
},
815
HashPair: function(key, value, locInfo) {
816
this.loc = locInfo;
817
this.type = 'HashPair';
818
this.key = key;
819
this.value = value;
820
},
821
822
// Public API used to evaluate derived attributes regarding AST nodes
823
helpers: {
824
// a mustache is definitely a helper if:
825
// * it is an eligible helper, and
826
// * it has at least one parameter or hash segment
827
// TODO: Make these public utility methods
828
helperExpression: function(node) {
829
return !!(node.type === 'SubExpression' || node.params.length || node.hash);
830
},
831
832
scopedId: function(path) {
833
return (/^\.|this\b/).test(path.original);
834
},
835
836
// an ID is simple if it only has one part, and that part is not
837
// `..` or `this`.
838
simpleId: function(path) {
839
return path.parts.length === 1 && !AST.helpers.scopedId(path) && !path.depth;
840
}
841
}
842
};
843
844
845
// Must be exported as an object rather than the root of the module as the jison lexer
846
// must modify the object to operate properly.
847
__exports__["default"] = AST;
848
});
849
define(
850
'handlebars/compiler/parser',["exports"],
851
function(__exports__) {
852
853
/* jshint ignore:start */
854
/* istanbul ignore next */
855
/* Jison generated parser */
856
var handlebars = (function(){
857
var parser = {trace: function trace() { },
858
yy: {},
859
symbols_: {"error":2,"root":3,"program":4,"EOF":5,"program_repetition0":6,"statement":7,"mustache":8,"block":9,"rawBlock":10,"partial":11,"content":12,"COMMENT":13,"CONTENT":14,"openRawBlock":15,"END_RAW_BLOCK":16,"OPEN_RAW_BLOCK":17,"helperName":18,"openRawBlock_repetition0":19,"openRawBlock_option0":20,"CLOSE_RAW_BLOCK":21,"openBlock":22,"block_option0":23,"closeBlock":24,"openInverse":25,"block_option1":26,"OPEN_BLOCK":27,"openBlock_repetition0":28,"openBlock_option0":29,"openBlock_option1":30,"CLOSE":31,"OPEN_INVERSE":32,"openInverse_repetition0":33,"openInverse_option0":34,"openInverse_option1":35,"openInverseChain":36,"OPEN_INVERSE_CHAIN":37,"openInverseChain_repetition0":38,"openInverseChain_option0":39,"openInverseChain_option1":40,"inverseAndProgram":41,"INVERSE":42,"inverseChain":43,"inverseChain_option0":44,"OPEN_ENDBLOCK":45,"OPEN":46,"mustache_repetition0":47,"mustache_option0":48,"OPEN_UNESCAPED":49,"mustache_repetition1":50,"mustache_option1":51,"CLOSE_UNESCAPED":52,"OPEN_PARTIAL":53,"partialName":54,"partial_repetition0":55,"partial_option0":56,"param":57,"sexpr":58,"OPEN_SEXPR":59,"sexpr_repetition0":60,"sexpr_option0":61,"CLOSE_SEXPR":62,"hash":63,"hash_repetition_plus0":64,"hashSegment":65,"ID":66,"EQUALS":67,"blockParams":68,"OPEN_BLOCK_PARAMS":69,"blockParams_repetition_plus0":70,"CLOSE_BLOCK_PARAMS":71,"path":72,"dataName":73,"STRING":74,"NUMBER":75,"BOOLEAN":76,"DATA":77,"pathSegments":78,"SEP":79,"$accept":0,"$end":1},
860
terminals_: {2:"error",5:"EOF",13:"COMMENT",14:"CONTENT",16:"END_RAW_BLOCK",17:"OPEN_RAW_BLOCK",21:"CLOSE_RAW_BLOCK",27:"OPEN_BLOCK",31:"CLOSE",32:"OPEN_INVERSE",37:"OPEN_INVERSE_CHAIN",42:"INVERSE",45:"OPEN_ENDBLOCK",46:"OPEN",49:"OPEN_UNESCAPED",52:"CLOSE_UNESCAPED",53:"OPEN_PARTIAL",59:"OPEN_SEXPR",62:"CLOSE_SEXPR",66:"ID",67:"EQUALS",69:"OPEN_BLOCK_PARAMS",71:"CLOSE_BLOCK_PARAMS",74:"STRING",75:"NUMBER",76:"BOOLEAN",77:"DATA",79:"SEP"},
861
productions_: [0,[3,2],[4,1],[7,1],[7,1],[7,1],[7,1],[7,1],[7,1],[12,1],[10,3],[15,5],[9,4],[9,4],[22,6],[25,6],[36,6],[41,2],[43,3],[43,1],[24,3],[8,5],[8,5],[11,5],[57,1],[57,1],[58,5],[63,1],[65,3],[68,3],[18,1],[18,1],[18,1],[18,1],[18,1],[54,1],[54,1],[73,2],[72,1],[78,3],[78,1],[6,0],[6,2],[19,0],[19,2],[20,0],[20,1],[23,0],[23,1],[26,0],[26,1],[28,0],[28,2],[29,0],[29,1],[30,0],[30,1],[33,0],[33,2],[34,0],[34,1],[35,0],[35,1],[38,0],[38,2],[39,0],[39,1],[40,0],[40,1],[44,0],[44,1],[47,0],[47,2],[48,0],[48,1],[50,0],[50,2],[51,0],[51,1],[55,0],[55,2],[56,0],[56,1],[60,0],[60,2],[61,0],[61,1],[64,1],[64,2],[70,1],[70,2]],
862
performAction: function anonymous(yytext,yyleng,yylineno,yy,yystate,$$,_$) {
863
864
var $0 = $$.length - 1;
865
switch (yystate) {
866
case 1: return $$[$0-1];
867
break;
868
case 2:this.$ = new yy.Program($$[$0], null, {}, yy.locInfo(this._$));
869
break;
870
case 3:this.$ = $$[$0];
871
break;
872
case 4:this.$ = $$[$0];
873
break;
874
case 5:this.$ = $$[$0];
875
break;
876
case 6:this.$ = $$[$0];
877
break;
878
case 7:this.$ = $$[$0];
879
break;
880
case 8:this.$ = new yy.CommentStatement(yy.stripComment($$[$0]), yy.stripFlags($$[$0], $$[$0]), yy.locInfo(this._$));
881
break;
882
case 9:this.$ = new yy.ContentStatement($$[$0], yy.locInfo(this._$));
883
break;
884
case 10:this.$ = yy.prepareRawBlock($$[$0-2], $$[$0-1], $$[$0], this._$);
885
break;
886
case 11:this.$ = { path: $$[$0-3], params: $$[$0-2], hash: $$[$0-1] };
887
break;
888
case 12:this.$ = yy.prepareBlock($$[$0-3], $$[$0-2], $$[$0-1], $$[$0], false, this._$);
889
break;
890
case 13:this.$ = yy.prepareBlock($$[$0-3], $$[$0-2], $$[$0-1], $$[$0], true, this._$);
891
break;
892
case 14:this.$ = { path: $$[$0-4], params: $$[$0-3], hash: $$[$0-2], blockParams: $$[$0-1], strip: yy.stripFlags($$[$0-5], $$[$0]) };
893
break;
894
case 15:this.$ = { path: $$[$0-4], params: $$[$0-3], hash: $$[$0-2], blockParams: $$[$0-1], strip: yy.stripFlags($$[$0-5], $$[$0]) };
895
break;
896
case 16:this.$ = { path: $$[$0-4], params: $$[$0-3], hash: $$[$0-2], blockParams: $$[$0-1], strip: yy.stripFlags($$[$0-5], $$[$0]) };
897
break;
898
case 17:this.$ = { strip: yy.stripFlags($$[$0-1], $$[$0-1]), program: $$[$0] };
899
break;
900
case 18:
901
var inverse = yy.prepareBlock($$[$0-2], $$[$0-1], $$[$0], $$[$0], false, this._$),
902
program = new yy.Program([inverse], null, {}, yy.locInfo(this._$));
903
program.chained = true;
904
905
this.$ = { strip: $$[$0-2].strip, program: program, chain: true };
906
907
break;
908
case 19:this.$ = $$[$0];
909
break;
910
case 20:this.$ = {path: $$[$0-1], strip: yy.stripFlags($$[$0-2], $$[$0])};
911
break;
912
case 21:this.$ = yy.prepareMustache($$[$0-3], $$[$0-2], $$[$0-1], $$[$0-4], yy.stripFlags($$[$0-4], $$[$0]), this._$);
913
break;
914
case 22:this.$ = yy.prepareMustache($$[$0-3], $$[$0-2], $$[$0-1], $$[$0-4], yy.stripFlags($$[$0-4], $$[$0]), this._$);
915
break;
916
case 23:this.$ = new yy.PartialStatement($$[$0-3], $$[$0-2], $$[$0-1], yy.stripFlags($$[$0-4], $$[$0]), yy.locInfo(this._$));
917
break;
918
case 24:this.$ = $$[$0];
919
break;
920
case 25:this.$ = $$[$0];
921
break;
922
case 26:this.$ = new yy.SubExpression($$[$0-3], $$[$0-2], $$[$0-1], yy.locInfo(this._$));
923
break;
924
case 27:this.$ = new yy.Hash($$[$0], yy.locInfo(this._$));
925
break;
926
case 28:this.$ = new yy.HashPair($$[$0-2], $$[$0], yy.locInfo(this._$));
927
break;
928
case 29:this.$ = $$[$0-1];
929
break;
930
case 30:this.$ = $$[$0];
931
break;
932
case 31:this.$ = $$[$0];
933
break;
934
case 32:this.$ = new yy.StringLiteral($$[$0], yy.locInfo(this._$));
935
break;
936
case 33:this.$ = new yy.NumberLiteral($$[$0], yy.locInfo(this._$));
937
break;
938
case 34:this.$ = new yy.BooleanLiteral($$[$0], yy.locInfo(this._$));
939
break;
940
case 35:this.$ = $$[$0];
941
break;
942
case 36:this.$ = $$[$0];
943
break;
944
case 37:this.$ = yy.preparePath(true, $$[$0], this._$);
945
break;
946
case 38:this.$ = yy.preparePath(false, $$[$0], this._$);
947
break;
948
case 39: $$[$0-2].push({part: $$[$0], separator: $$[$0-1]}); this.$ = $$[$0-2];
949
break;
950
case 40:this.$ = [{part: $$[$0]}];
951
break;
952
case 41:this.$ = [];
953
break;
954
case 42:$$[$0-1].push($$[$0]);
955
break;
956
case 43:this.$ = [];
957
break;
958
case 44:$$[$0-1].push($$[$0]);
959
break;
960
case 51:this.$ = [];
961
break;
962
case 52:$$[$0-1].push($$[$0]);
963
break;
964
case 57:this.$ = [];
965
break;
966
case 58:$$[$0-1].push($$[$0]);
967
break;
968
case 63:this.$ = [];
969
break;
970
case 64:$$[$0-1].push($$[$0]);
971
break;
972
case 71:this.$ = [];
973
break;
974
case 72:$$[$0-1].push($$[$0]);
975
break;
976
case 75:this.$ = [];
977
break;
978
case 76:$$[$0-1].push($$[$0]);
979
break;
980
case 79:this.$ = [];
981
break;
982
case 80:$$[$0-1].push($$[$0]);
983
break;
984
case 83:this.$ = [];
985
break;
986
case 84:$$[$0-1].push($$[$0]);
987
break;
988
case 87:this.$ = [$$[$0]];
989
break;
990
case 88:$$[$0-1].push($$[$0]);
991
break;
992
case 89:this.$ = [$$[$0]];
993
break;
994
case 90:$$[$0-1].push($$[$0]);
995
break;
996
}
997
},
998
table: [{3:1,4:2,5:[2,41],6:3,13:[2,41],14:[2,41],17:[2,41],27:[2,41],32:[2,41],46:[2,41],49:[2,41],53:[2,41]},{1:[3]},{5:[1,4]},{5:[2,2],7:5,8:6,9:7,10:8,11:9,12:10,13:[1,11],14:[1,18],15:16,17:[1,21],22:14,25:15,27:[1,19],32:[1,20],37:[2,2],42:[2,2],45:[2,2],46:[1,12],49:[1,13],53:[1,17]},{1:[2,1]},{5:[2,42],13:[2,42],14:[2,42],17:[2,42],27:[2,42],32:[2,42],37:[2,42],42:[2,42],45:[2,42],46:[2,42],49:[2,42],53:[2,42]},{5:[2,3],13:[2,3],14:[2,3],17:[2,3],27:[2,3],32:[2,3],37:[2,3],42:[2,3],45:[2,3],46:[2,3],49:[2,3],53:[2,3]},{5:[2,4],13:[2,4],14:[2,4],17:[2,4],27:[2,4],32:[2,4],37:[2,4],42:[2,4],45:[2,4],46:[2,4],49:[2,4],53:[2,4]},{5:[2,5],13:[2,5],14:[2,5],17:[2,5],27:[2,5],32:[2,5],37:[2,5],42:[2,5],45:[2,5],46:[2,5],49:[2,5],53:[2,5]},{5:[2,6],13:[2,6],14:[2,6],17:[2,6],27:[2,6],32:[2,6],37:[2,6],42:[2,6],45:[2,6],46:[2,6],49:[2,6],53:[2,6]},{5:[2,7],13:[2,7],14:[2,7],17:[2,7],27:[2,7],32:[2,7],37:[2,7],42:[2,7],45:[2,7],46:[2,7],49:[2,7],53:[2,7]},{5:[2,8],13:[2,8],14:[2,8],17:[2,8],27:[2,8],32:[2,8],37:[2,8],42:[2,8],45:[2,8],46:[2,8],49:[2,8],53:[2,8]},{18:22,66:[1,30],72:23,73:24,74:[1,25],75:[1,26],76:[1,27],77:[1,29],78:28},{18:31,66:[1,30],72:23,73:24,74:[1,25],75:[1,26],76:[1,27],77:[1,29],78:28},{4:32,6:3,13:[2,41],14:[2,41],17:[2,41],27:[2,41],32:[2,41],37:[2,41],42:[2,41],45:[2,41],46:[2,41],49:[2,41],53:[2,41]},{4:33,6:3,13:[2,41],14:[2,41],17:[2,41],27:[2,41],32:[2,41],42:[2,41],45:[2,41],46:[2,41],49:[2,41],53:[2,41]},{12:34,14:[1,18]},{18:36,54:35,58:37,59:[1,38],66:[1,30],72:23,73:24,74:[1,25],75:[1,26],76:[1,27],77:[1,29],78:28},{5:[2,9],13:[2,9],14:[2,9],16:[2,9],17:[2,9],27:[2,9],32:[2,9],37:[2,9],42:[2,9],45:[2,9],46:[2,9],49:[2,9],53:[2,9]},{18:39,66:[1,30],72:23,73:24,74:[1,25],75:[1,26],76:[1,27],77:[1,29],78:28},{18:40,66:[1,30],72:23,73:24,74:[1,25],75:[1,26],76:[1,27],77:[1,29],78:28},{18:41,66:[1,30],72:23,73:24,74:[1,25],75:[1,26],76:[1,27],77:[1,29],78:28},{31:[2,71],47:42,59:[2,71],66:[2,71],74:[2,71],75:[2,71],76:[2,71],77:[2,71]},{21:[2,30],31:[2,30],52:[2,30],59:[2,30],62:[2,30],66:[2,30],69:[2,30],74:[2,30],75:[2,30],76:[2,30],77:[2,30]},{21:[2,31],31:[2,31],52:[2,31],59:[2,31],62:[2,31],66:[2,31],69:[2,31],74:[2,31],75:[2,31],76:[2,31],77:[2,31]},{21:[2,32],31:[2,32],52:[2,32],59:[2,32],62:[2,32],66:[2,32],69:[2,32],74:[2,32],75:[2,32],76:[2,32],77:[2,32]},{21:[2,33],31:[2,33],52:[2,33],59:[2,33],62:[2,33],66:[2,33],69:[2,33],74:[2,33],75:[2,33],76:[2,33],77:[2,33]},{21:[2,34],31:[2,34],52:[2,34],59:[2,34],62:[2,34],66:[2,34],69:[2,34],74:[2,34],75:[2,34],76:[2,34],77:[2,34]},{21:[2,38],31:[2,38],52:[2,38],59:[2,38],62:[2,38],66:[2,38],69:[2,38],74:[2,38],75:[2,38],76:[2,38],77:[2,38],79:[1,43]},{66:[1,30],78:44},{21:[2,40],31:[2,40],52:[2,40],59:[2,40],62:[2,40],66:[2,40],69:[2,40],74:[2,40],75:[2,40],76:[2,40],77:[2,40],79:[2,40]},{50:45,52:[2,75],59:[2,75],66:[2,75],74:[2,75],75:[2,75],76:[2,75],77:[2,75]},{23:46,36:48,37:[1,50],41:49,42:[1,51],43:47,45:[2,47]},{26:52,41:53,42:[1,51],45:[2,49]},{16:[1,54]},{31:[2,79],55:55,59:[2,79],66:[2,79],74:[2,79],75:[2,79],76:[2,79],77:[2,79]},{31:[2,35],59:[2,35],66:[2,35],74:[2,35],75:[2,35],76:[2,35],77:[2,35]},{31:[2,36],59:[2,36],66:[2,36],74:[2,36],75:[2,36],76:[2,36],77:[2,36]},{18:56,66:[1,30],72:23,73:24,74:[1,25],75:[1,26],76:[1,27],77:[1,29],78:28},{28:57,31:[2,51],59:[2,51],66:[2,51],69:[2,51],74:[2,51],75:[2,51],76:[2,51],77:[2,51]},{31:[2,57],33:58,59:[2,57],66:[2,57],69:[2,57],74:[2,57],75:[2,57],76:[2,57],77:[2,57]},{19:59,21:[2,43],59:[2,43],66:[2,43],74:[2,43],75:[2,43],76:[2,43],77:[2,43]},{18:63,31:[2,73],48:60,57:61,58:64,59:[1,38],63:62,64:65,65:66,66:[1,67],72:23,73:24,74:[1,25],75:[1,26],76:[1,27],77:[1,29],78:28},{66:[1,68]},{21:[2,37],31:[2,37],52:[2,37],59:[2,37],62:[2,37],66:[2,37],69:[2,37],74:[2,37],75:[2,37],76:[2,37],77:[2,37],79:[1,43]},{18:63,51:69,52:[2,77],57:70,58:64,59:[1,38],63:71,64:65,65:66,66:[1,67],72:23,73:24,74:[1,25],75:[1,26],76:[1,27],77:[1,29],78:28},{24:72,45:[1,73]},{45:[2,48]},{4:74,6:3,13:[2,41],14:[2,41],17:[2,41],27:[2,41],32:[2,41],37:[2,41],42:[2,41],45:[2,41],46:[2,41],49:[2,41],53:[2,41]},{45:[2,19]},{18:75,66:[1,30],72:23,73:24,74:[1,25],75:[1,26],76:[1,27],77:[1,29],78:28},{4:76,6:3,13:[2,41],14:[2,41],17:[2,41],27:[2,41],32:[2,41],45:[2,41],46:[2,41],49:[2,41],53:[2,41]},{24:77,45:[1,73]},{45:[2,50]},{5:[2,10],13:[2,10],14:[2,10],17:[2,10],27:[2,10],32:[2,10],37:[2,10],42:[2,10],45:[2,10],46:[2,10],49:[2,10],53:[2,10]},{18:63,31:[2,81],56:78,57:79,58:64,59:[1,38],63:80,64:65,65:66,66:[1,67],72:23,73:24,74:[1,25],75:[1,26],76:[1,27],77:[1,29],78:28},{59:[2,83],60:81,62:[2,83],66:[2,83],74:[2,83],75:[2,83],76:[2,83],77:[2,83]},{18:63,29:82,31:[2,53],57:83,58:64,59:[1,38],63:84,64:65,65:66,66:[1,67],69:[2,53],72:23,73:24,74:[1,25],75:[1,26],76:[1,27],77:[1,29],78:28},{18:63,31:[2,59],34:85,57:86,58:64,59:[1,38],63:87,64:65,65:66,66:[1,67],69:[2,59],72:23,73:24,74:[1,25],75:[1,26],76:[1,27],77:[1,29],78:28},{18:63,20:88,21:[2,45],57:89,58:64,59:[1,38],63:90,64:65,65:66,66:[1,67],72:23,73:24,74:[1,25],75:[1,26],76:[1,27],77:[1,29],78:28},{31:[1,91]},{31:[2,72],59:[2,72],66:[2,72],74:[2,72],75:[2,72],76:[2,72],77:[2,72]},{31:[2,74]},{21:[2,24],31:[2,24],52:[2,24],59:[2,24],62:[2,24],66:[2,24],69:[2,24],74:[2,24],75:[2,24],76:[2,24],77:[2,24]},{21:[2,25],31:[2,25],52:[2,25],59:[2,25],62:[2,25],66:[2,25],69:[2,25],74:[2,25],75:[2,25],76:[2,25],77:[2,25]},{21:[2,27],31:[2,27],52:[2,27],62:[2,27],65:92,66:[1,93],69:[2,27]},{21:[2,87],31:[2,87],52:[2,87],62:[2,87],66:[2,87],69:[2,87]},{21:[2,40],31:[2,40],52:[2,40],59:[2,40],62:[2,40],66:[2,40],67:[1,94],69:[2,40],74:[2,40],75:[2,40],76:[2,40],77:[2,40],79:[2,40]},{21:[2,39],31:[2,39],52:[2,39],59:[2,39],62:[2,39],66:[2,39],69:[2,39],74:[2,39],75:[2,39],76:[2,39],77:[2,39],79:[2,39]},{52:[1,95]},{52:[2,76],59:[2,76],66:[2,76],74:[2,76],75:[2,76],76:[2,76],77:[2,76]},{52:[2,78]},{5:[2,12],13:[2,12],14:[2,12],17:[2,12],27:[2,12],32:[2,12],37:[2,12],42:[2,12],45:[2,12],46:[2,12],49:[2,12],53:[2,12]},{18:96,66:[1,30],72:23,73:24,74:[1,25],75:[1,26],76:[1,27],77:[1,29],78:28},{36:48,37:[1,50],41:49,42:[1,51],43:98,44:97,45:[2,69]},{31:[2,63],38:99,59:[2,63],66:[2,63],69:[2,63],74:[2,63],75:[2,63],76:[2,63],77:[2,63]},{45:[2,17]},{5:[2,13],13:[2,13],14:[2,13],17:[2,13],27:[2,13],32:[2,13],37:[2,13],42:[2,13],45:[2,13],46:[2,13],49:[2,13],53:[2,13]},{31:[1,100]},{31:[2,80],59:[2,80],66:[2,80],74:[2,80],75:[2,80],76:[2,80],77:[2,80]},{31:[2,82]},{18:63,57:102,58:64,59:[1,38],61:101,62:[2,85],63:103,64:65,65:66,66:[1,67],72:23,73:24,74:[1,25],75:[1,26],76:[1,27],77:[1,29],78:28},{30:104,31:[2,55],68:105,69:[1,106]},{31:[2,52],59:[2,52],66:[2,52],69:[2,52],74:[2,52],75:[2,52],76:[2,52],77:[2,52]},{31:[2,54],69:[2,54]},{31:[2,61],35:107,68:108,69:[1,106]},{31:[2,58],59:[2,58],66:[2,58],69:[2,58],74:[2,58],75:[2,58],76:[2,58],77:[2,58]},{31:[2,60],69:[2,60]},{21:[1,109]},{21:[2,44],59:[2,44],66:[2,44],74:[2,44],75:[2,44],76:[2,44],77:[2,44]},{21:[2,46]},{5:[2,21],13:[2,21],14:[2,21],17:[2,21],27:[2,21],32:[2,21],37:[2,21],42:[2,21],45:[2,21],46:[2,21],49:[2,21],53:[2,21]},{21:[2,88],31:[2,88],52:[2,88],62:[2,88],66:[2,88],69:[2,88]},{67:[1,94]},{18:63,57:110,58:64,59:[1,38],66:[1,30],72:23,73:24,74:[1,25],75:[1,26],76:[1,27],77:[1,29],78:28},{5:[2,22],13:[2,22],14:[2,22],17:[2,22],27:[2,22],32:[2,22],37:[2,22],42:[2,22],45:[2,22],46:[2,22],49:[2,22],53:[2,22]},{31:[1,111]},{45:[2,18]},{45:[2,70]},{18:63,31:[2,65],39:112,57:113,58:64,59:[1,38],63:114,64:65,65:66,66:[1,67],69:[2,65],72:23,73:24,74:[1,25],75:[1,26],76:[1,27],77:[1,29],78:28},{5:[2,23],13:[2,23],14:[2,23],17:[2,23],27:[2,23],32:[2,23],37:[2,23],42:[2,23],45:[2,23],46:[2,23],49:[2,23],53:[2,23]},{62:[1,115]},{59:[2,84],62:[2,84],66:[2,84],74:[2,84],75:[2,84],76:[2,84],77:[2,84]},{62:[2,86]},{31:[1,116]},{31:[2,56]},{66:[1,118],70:117},{31:[1,119]},{31:[2,62]},{14:[2,11]},{21:[2,28],31:[2,28],52:[2,28],62:[2,28],66:[2,28],69:[2,28]},{5:[2,20],13:[2,20],14:[2,20],17:[2,20],27:[2,20],32:[2,20],37:[2,20],42:[2,20],45:[2,20],46:[2,20],49:[2,20],53:[2,20]},{31:[2,67],40:120,68:121,69:[1,106]},{31:[2,64],59:[2,64],66:[2,64],69:[2,64],74:[2,64],75:[2,64],76:[2,64],77:[2,64]},{31:[2,66],69:[2,66]},{21:[2,26],31:[2,26],52:[2,26],59:[2,26],62:[2,26],66:[2,26],69:[2,26],74:[2,26],75:[2,26],76:[2,26],77:[2,26]},{13:[2,14],14:[2,14],17:[2,14],27:[2,14],32:[2,14],37:[2,14],42:[2,14],45:[2,14],46:[2,14],49:[2,14],53:[2,14]},{66:[1,123],71:[1,122]},{66:[2,89],71:[2,89]},{13:[2,15],14:[2,15],17:[2,15],27:[2,15],32:[2,15],42:[2,15],45:[2,15],46:[2,15],49:[2,15],53:[2,15]},{31:[1,124]},{31:[2,68]},{31:[2,29]},{66:[2,90],71:[2,90]},{13:[2,16],14:[2,16],17:[2,16],27:[2,16],32:[2,16],37:[2,16],42:[2,16],45:[2,16],46:[2,16],49:[2,16],53:[2,16]}],
999
defaultActions: {4:[2,1],47:[2,48],49:[2,19],53:[2,50],62:[2,74],71:[2,78],76:[2,17],80:[2,82],90:[2,46],97:[2,18],98:[2,70],103:[2,86],105:[2,56],108:[2,62],109:[2,11],121:[2,68],122:[2,29]},
1000
parseError: function parseError(str, hash) {
1001
throw new Error(str);
1002
},
1003
parse: function parse(input) {
1004
var self = this, stack = [0], vstack = [null], lstack = [], table = this.table, yytext = "", yylineno = 0, yyleng = 0, recovering = 0, TERROR = 2, EOF = 1;
1005
this.lexer.setInput(input);
1006
this.lexer.yy = this.yy;
1007
this.yy.lexer = this.lexer;
1008
this.yy.parser = this;
1009
if (typeof this.lexer.yylloc == "undefined")
1010
this.lexer.yylloc = {};
1011
var yyloc = this.lexer.yylloc;
1012
lstack.push(yyloc);
1013
var ranges = this.lexer.options && this.lexer.options.ranges;
1014
if (typeof this.yy.parseError === "function")
1015
this.parseError = this.yy.parseError;
1016
function popStack(n) {
1017
stack.length = stack.length - 2 * n;
1018
vstack.length = vstack.length - n;
1019
lstack.length = lstack.length - n;
1020
}
1021
function lex() {
1022
var token;
1023
token = self.lexer.lex() || 1;
1024
if (typeof token !== "number") {
1025
token = self.symbols_[token] || token;
1026
}
1027
return token;
1028
}
1029
var symbol, preErrorSymbol, state, action, a, r, yyval = {}, p, len, newState, expected;
1030
while (true) {
1031
state = stack[stack.length - 1];
1032
if (this.defaultActions[state]) {
1033
action = this.defaultActions[state];
1034
} else {
1035
if (symbol === null || typeof symbol == "undefined") {
1036
symbol = lex();
1037
}
1038
action = table[state] && table[state][symbol];
1039
}
1040
if (typeof action === "undefined" || !action.length || !action[0]) {
1041
var errStr = "";
1042
if (!recovering) {
1043
expected = [];
1044
for (p in table[state])
1045
if (this.terminals_[p] && p > 2) {
1046
expected.push("'" + this.terminals_[p] + "'");
1047
}
1048
if (this.lexer.showPosition) {
1049
errStr = "Parse error on line " + (yylineno + 1) + ":\n" + this.lexer.showPosition() + "\nExpecting " + expected.join(", ") + ", got '" + (this.terminals_[symbol] || symbol) + "'";
1050
} else {
1051
errStr = "Parse error on line " + (yylineno + 1) + ": Unexpected " + (symbol == 1?"end of input":"'" + (this.terminals_[symbol] || symbol) + "'");
1052
}
1053
this.parseError(errStr, {text: this.lexer.match, token: this.terminals_[symbol] || symbol, line: this.lexer.yylineno, loc: yyloc, expected: expected});
1054
}
1055
}
1056
if (action[0] instanceof Array && action.length > 1) {
1057
throw new Error("Parse Error: multiple actions possible at state: " + state + ", token: " + symbol);
1058
}
1059
switch (action[0]) {
1060
case 1:
1061
stack.push(symbol);
1062
vstack.push(this.lexer.yytext);
1063
lstack.push(this.lexer.yylloc);
1064
stack.push(action[1]);
1065
symbol = null;
1066
if (!preErrorSymbol) {
1067
yyleng = this.lexer.yyleng;
1068
yytext = this.lexer.yytext;
1069
yylineno = this.lexer.yylineno;
1070
yyloc = this.lexer.yylloc;
1071
if (recovering > 0)
1072
recovering--;
1073
} else {
1074
symbol = preErrorSymbol;
1075
preErrorSymbol = null;
1076
}
1077
break;
1078
case 2:
1079
len = this.productions_[action[1]][1];
1080
yyval.$ = vstack[vstack.length - len];
1081
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};
1082
if (ranges) {
1083
yyval._$.range = [lstack[lstack.length - (len || 1)].range[0], lstack[lstack.length - 1].range[1]];
1084
}
1085
r = this.performAction.call(yyval, yytext, yyleng, yylineno, this.yy, action[1], vstack, lstack);
1086
if (typeof r !== "undefined") {
1087
return r;
1088
}
1089
if (len) {
1090
stack = stack.slice(0, -1 * len * 2);
1091
vstack = vstack.slice(0, -1 * len);
1092
lstack = lstack.slice(0, -1 * len);
1093
}
1094
stack.push(this.productions_[action[1]][0]);
1095
vstack.push(yyval.$);
1096
lstack.push(yyval._$);
1097
newState = table[stack[stack.length - 2]][stack[stack.length - 1]];
1098
stack.push(newState);
1099
break;
1100
case 3:
1101
return true;
1102
}
1103
}
1104
return true;
1105
}
1106
};
1107
/* Jison generated lexer */
1108
var lexer = (function(){
1109
var lexer = ({EOF:1,
1110
parseError:function parseError(str, hash) {
1111
if (this.yy.parser) {
1112
this.yy.parser.parseError(str, hash);
1113
} else {
1114
throw new Error(str);
1115
}
1116
},
1117
setInput:function (input) {
1118
this._input = input;
1119
this._more = this._less = this.done = false;
1120
this.yylineno = this.yyleng = 0;
1121
this.yytext = this.matched = this.match = '';
1122
this.conditionStack = ['INITIAL'];
1123
this.yylloc = {first_line:1,first_column:0,last_line:1,last_column:0};
1124
if (this.options.ranges) this.yylloc.range = [0,0];
1125
this.offset = 0;
1126
return this;
1127
},
1128
input:function () {
1129
var ch = this._input[0];
1130
this.yytext += ch;
1131
this.yyleng++;
1132
this.offset++;
1133
this.match += ch;
1134
this.matched += ch;
1135
var lines = ch.match(/(?:\r\n?|\n).*/g);
1136
if (lines) {
1137
this.yylineno++;
1138
this.yylloc.last_line++;
1139
} else {
1140
this.yylloc.last_column++;
1141
}
1142
if (this.options.ranges) this.yylloc.range[1]++;
1143
1144
this._input = this._input.slice(1);
1145
return ch;
1146
},
1147
unput:function (ch) {
1148
var len = ch.length;
1149
var lines = ch.split(/(?:\r\n?|\n)/g);
1150
1151
this._input = ch + this._input;
1152
this.yytext = this.yytext.substr(0, this.yytext.length-len-1);
1153
//this.yyleng -= len;
1154
this.offset -= len;
1155
var oldLines = this.match.split(/(?:\r\n?|\n)/g);
1156
this.match = this.match.substr(0, this.match.length-1);
1157
this.matched = this.matched.substr(0, this.matched.length-1);
1158
1159
if (lines.length-1) this.yylineno -= lines.length-1;
1160
var r = this.yylloc.range;
1161
1162
this.yylloc = {first_line: this.yylloc.first_line,
1163
last_line: this.yylineno+1,
1164
first_column: this.yylloc.first_column,
1165
last_column: lines ?
1166
(lines.length === oldLines.length ? this.yylloc.first_column : 0) + oldLines[oldLines.length - lines.length].length - lines[0].length:
1167
this.yylloc.first_column - len
1168
};
1169
1170
if (this.options.ranges) {
1171
this.yylloc.range = [r[0], r[0] + this.yyleng - len];
1172
}
1173
return this;
1174
},
1175
more:function () {
1176
this._more = true;
1177
return this;
1178
},
1179
less:function (n) {
1180
this.unput(this.match.slice(n));
1181
},
1182
pastInput:function () {
1183
var past = this.matched.substr(0, this.matched.length - this.match.length);
1184
return (past.length > 20 ? '...':'') + past.substr(-20).replace(/\n/g, "");
1185
},
1186
upcomingInput:function () {
1187
var next = this.match;
1188
if (next.length < 20) {
1189
next += this._input.substr(0, 20-next.length);
1190
}
1191
return (next.substr(0,20)+(next.length > 20 ? '...':'')).replace(/\n/g, "");
1192
},
1193
showPosition:function () {
1194
var pre = this.pastInput();
1195
var c = new Array(pre.length + 1).join("-");
1196
return pre + this.upcomingInput() + "\n" + c+"^";
1197
},
1198
next:function () {
1199
if (this.done) {
1200
return this.EOF;
1201
}
1202
if (!this._input) this.done = true;
1203
1204
var token,
1205
match,
1206
tempMatch,
1207
index,
1208
col,
1209
lines;
1210
if (!this._more) {
1211
this.yytext = '';
1212
this.match = '';
1213
}
1214
var rules = this._currentRules();
1215
for (var i=0;i < rules.length; i++) {
1216
tempMatch = this._input.match(this.rules[rules[i]]);
1217
if (tempMatch && (!match || tempMatch[0].length > match[0].length)) {
1218
match = tempMatch;
1219
index = i;
1220
if (!this.options.flex) break;
1221
}
1222
}
1223
if (match) {
1224
lines = match[0].match(/(?:\r\n?|\n).*/g);
1225
if (lines) this.yylineno += lines.length;
1226
this.yylloc = {first_line: this.yylloc.last_line,
1227
last_line: this.yylineno+1,
1228
first_column: this.yylloc.last_column,
1229
last_column: lines ? lines[lines.length-1].length-lines[lines.length-1].match(/\r?\n?/)[0].length : this.yylloc.last_column + match[0].length};
1230
this.yytext += match[0];
1231
this.match += match[0];
1232
this.matches = match;
1233
this.yyleng = this.yytext.length;
1234
if (this.options.ranges) {
1235
this.yylloc.range = [this.offset, this.offset += this.yyleng];
1236
}
1237
this._more = false;
1238
this._input = this._input.slice(match[0].length);
1239
this.matched += match[0];
1240
token = this.performAction.call(this, this.yy, this, rules[index],this.conditionStack[this.conditionStack.length-1]);
1241
if (this.done && this._input) this.done = false;
1242
if (token) return token;
1243
else return;
1244
}
1245
if (this._input === "") {
1246
return this.EOF;
1247
} else {
1248
return this.parseError('Lexical error on line '+(this.yylineno+1)+'. Unrecognized text.\n'+this.showPosition(),
1249
{text: "", token: null, line: this.yylineno});
1250
}
1251
},
1252
lex:function lex() {
1253
var r = this.next();
1254
if (typeof r !== 'undefined') {
1255
return r;
1256
} else {
1257
return this.lex();
1258
}
1259
},
1260
begin:function begin(condition) {
1261
this.conditionStack.push(condition);
1262
},
1263
popState:function popState() {
1264
return this.conditionStack.pop();
1265
},
1266
_currentRules:function _currentRules() {
1267
return this.conditions[this.conditionStack[this.conditionStack.length-1]].rules;
1268
},
1269
topState:function () {
1270
return this.conditionStack[this.conditionStack.length-2];
1271
},
1272
pushState:function begin(condition) {
1273
this.begin(condition);
1274
}});
1275
lexer.options = {};
1276
lexer.performAction = function anonymous(yy,yy_,$avoiding_name_collisions,YY_START) {
1277
1278
1279
function strip(start, end) {
1280
return yy_.yytext = yy_.yytext.substr(start, yy_.yyleng-end);
1281
}
1282
1283
1284
var YYSTATE=YY_START
1285
switch($avoiding_name_collisions) {
1286
case 0:
1287
if(yy_.yytext.slice(-2) === "\\\\") {
1288
strip(0,1);
1289
this.begin("mu");
1290
} else if(yy_.yytext.slice(-1) === "\\") {
1291
strip(0,1);
1292
this.begin("emu");
1293
} else {
1294
this.begin("mu");
1295
}
1296
if(yy_.yytext) return 14;
1297
1298
break;
1299
case 1:return 14;
1300
break;
1301
case 2:
1302
this.popState();
1303
return 14;
1304
1305
break;
1306
case 3:
1307
yy_.yytext = yy_.yytext.substr(5, yy_.yyleng-9);
1308
this.popState();
1309
return 16;
1310
1311
break;
1312
case 4: return 14;
1313
break;
1314
case 5:
1315
this.popState();
1316
return 13;
1317
1318
break;
1319
case 6:return 59;
1320
break;
1321
case 7:return 62;
1322
break;
1323
case 8: return 17;
1324
break;
1325
case 9:
1326
this.popState();
1327
this.begin('raw');
1328
return 21;
1329
1330
break;
1331
case 10:return 53;
1332
break;
1333
case 11:return 27;
1334
break;
1335
case 12:return 45;
1336
break;
1337
case 13:this.popState(); return 42;
1338
break;
1339
case 14:this.popState(); return 42;
1340
break;
1341
case 15:return 32;
1342
break;
1343
case 16:return 37;
1344
break;
1345
case 17:return 49;
1346
break;
1347
case 18:return 46;
1348
break;
1349
case 19:
1350
this.unput(yy_.yytext);
1351
this.popState();
1352
this.begin('com');
1353
1354
break;
1355
case 20:
1356
this.popState();
1357
return 13;
1358
1359
break;
1360
case 21:return 46;
1361
break;
1362
case 22:return 67;
1363
break;
1364
case 23:return 66;
1365
break;
1366
case 24:return 66;
1367
break;
1368
case 25:return 79;
1369
break;
1370
case 26:// ignore whitespace
1371
break;
1372
case 27:this.popState(); return 52;
1373
break;
1374
case 28:this.popState(); return 31;
1375
break;
1376
case 29:yy_.yytext = strip(1,2).replace(/\\"/g,'"'); return 74;
1377
break;
1378
case 30:yy_.yytext = strip(1,2).replace(/\\'/g,"'"); return 74;
1379
break;
1380
case 31:return 77;
1381
break;
1382
case 32:return 76;
1383
break;
1384
case 33:return 76;
1385
break;
1386
case 34:return 75;
1387
break;
1388
case 35:return 69;
1389
break;
1390
case 36:return 71;
1391
break;
1392
case 37:return 66;
1393
break;
1394
case 38:yy_.yytext = strip(1,2); return 66;
1395
break;
1396
case 39:return 'INVALID';
1397
break;
1398
case 40:return 5;
1399
break;
1400
}
1401
};
1402
lexer.rules = [/^(?:[^\x00]*?(?=(\{\{)))/,/^(?:[^\x00]+)/,/^(?:[^\x00]{2,}?(?=(\{\{|\\\{\{|\\\\\{\{|$)))/,/^(?:\{\{\{\{\/[^\s!"#%-,\.\/;->@\[-\^`\{-~]+(?=[=}\s\/.])\}\}\}\})/,/^(?:[^\x00]*?(?=(\{\{\{\{\/)))/,/^(?:[\s\S]*?--(~)?\}\})/,/^(?:\()/,/^(?:\))/,/^(?:\{\{\{\{)/,/^(?:\}\}\}\})/,/^(?:\{\{(~)?>)/,/^(?:\{\{(~)?#)/,/^(?:\{\{(~)?\/)/,/^(?:\{\{(~)?\^\s*(~)?\}\})/,/^(?:\{\{(~)?\s*else\s*(~)?\}\})/,/^(?:\{\{(~)?\^)/,/^(?:\{\{(~)?\s*else\b)/,/^(?:\{\{(~)?\{)/,/^(?:\{\{(~)?&)/,/^(?:\{\{(~)?!--)/,/^(?:\{\{(~)?![\s\S]*?\}\})/,/^(?:\{\{(~)?)/,/^(?:=)/,/^(?:\.\.)/,/^(?:\.(?=([=~}\s\/.)|])))/,/^(?:[\/.])/,/^(?:\s+)/,/^(?:\}(~)?\}\})/,/^(?:(~)?\}\})/,/^(?:"(\\["]|[^"])*")/,/^(?:'(\\[']|[^'])*')/,/^(?:@)/,/^(?:true(?=([~}\s)])))/,/^(?:false(?=([~}\s)])))/,/^(?:-?[0-9]+(?:\.[0-9]+)?(?=([~}\s)])))/,/^(?:as\s+\|)/,/^(?:\|)/,/^(?:([^\s!"#%-,\.\/;->@\[-\^`\{-~]+(?=([=~}\s\/.)|]))))/,/^(?:\[[^\]]*\])/,/^(?:.)/,/^(?:$)/];
1403
lexer.conditions = {"mu":{"rules":[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,32,33,34,35,36,37,38,39,40],"inclusive":false},"emu":{"rules":[2],"inclusive":false},"com":{"rules":[5],"inclusive":false},"raw":{"rules":[3,4],"inclusive":false},"INITIAL":{"rules":[0,1,40],"inclusive":true}};
1404
return lexer;})()
1405
parser.lexer = lexer;
1406
function Parser () { this.yy = {}; }Parser.prototype = parser;parser.Parser = Parser;
1407
return new Parser;
1408
})();__exports__["default"] = handlebars;
1409
/* jshint ignore:end */
1410
});
1411
define(
1412
'handlebars/compiler/visitor',["../exception","./ast","exports"],
1413
function(__dependency1__, __dependency2__, __exports__) {
1414
1415
var Exception = __dependency1__["default"];
1416
var AST = __dependency2__["default"];
1417
1418
function Visitor() {
1419
this.parents = [];
1420
}
1421
1422
Visitor.prototype = {
1423
constructor: Visitor,
1424
mutating: false,
1425
1426
// Visits a given value. If mutating, will replace the value if necessary.
1427
acceptKey: function(node, name) {
1428
var value = this.accept(node[name]);
1429
if (this.mutating) {
1430
// Hacky sanity check:
1431
if (value && (!value.type || !AST[value.type])) {
1432
throw new Exception('Unexpected node type "' + value.type + '" found when accepting ' + name + ' on ' + node.type);
1433
}
1434
node[name] = value;
1435
}
1436
},
1437
1438
// Performs an accept operation with added sanity check to ensure
1439
// required keys are not removed.
1440
acceptRequired: function(node, name) {
1441
this.acceptKey(node, name);
1442
1443
if (!node[name]) {
1444
throw new Exception(node.type + ' requires ' + name);
1445
}
1446
},
1447
1448
// Traverses a given array. If mutating, empty respnses will be removed
1449
// for child elements.
1450
acceptArray: function(array) {
1451
for (var i = 0, l = array.length; i < l; i++) {
1452
this.acceptKey(array, i);
1453
1454
if (!array[i]) {
1455
array.splice(i, 1);
1456
i--;
1457
l--;
1458
}
1459
}
1460
},
1461
1462
accept: function(object) {
1463
if (!object) {
1464
return;
1465
}
1466
1467
if (this.current) {
1468
this.parents.unshift(this.current);
1469
}
1470
this.current = object;
1471
1472
var ret = this[object.type](object);
1473
1474
this.current = this.parents.shift();
1475
1476
if (!this.mutating || ret) {
1477
return ret;
1478
} else if (ret !== false) {
1479
return object;
1480
}
1481
},
1482
1483
Program: function(program) {
1484
this.acceptArray(program.body);
1485
},
1486
1487
MustacheStatement: function(mustache) {
1488
this.acceptRequired(mustache, 'path');
1489
this.acceptArray(mustache.params);
1490
this.acceptKey(mustache, 'hash');
1491
},
1492
1493
BlockStatement: function(block) {
1494
this.acceptRequired(block, 'path');
1495
this.acceptArray(block.params);
1496
this.acceptKey(block, 'hash');
1497
1498
this.acceptKey(block, 'program');
1499
this.acceptKey(block, 'inverse');
1500
},
1501
1502
PartialStatement: function(partial) {
1503
this.acceptRequired(partial, 'name');
1504
this.acceptArray(partial.params);
1505
this.acceptKey(partial, 'hash');
1506
},
1507
1508
ContentStatement: function(/* content */) {},
1509
CommentStatement: function(/* comment */) {},
1510
1511
SubExpression: function(sexpr) {
1512
this.acceptRequired(sexpr, 'path');
1513
this.acceptArray(sexpr.params);
1514
this.acceptKey(sexpr, 'hash');
1515
},
1516
PartialExpression: function(partial) {
1517
this.acceptRequired(partial, 'name');
1518
this.acceptArray(partial.params);
1519
this.acceptKey(partial, 'hash');
1520
},
1521
1522
PathExpression: function(/* path */) {},
1523
1524
StringLiteral: function(/* string */) {},
1525
NumberLiteral: function(/* number */) {},
1526
BooleanLiteral: function(/* bool */) {},
1527
1528
Hash: function(hash) {
1529
this.acceptArray(hash.pairs);
1530
},
1531
HashPair: function(pair) {
1532
this.acceptRequired(pair, 'value');
1533
}
1534
};
1535
1536
__exports__["default"] = Visitor;
1537
});
1538
define(
1539
'handlebars/compiler/whitespace-control',["./visitor","exports"],
1540
function(__dependency1__, __exports__) {
1541
1542
var Visitor = __dependency1__["default"];
1543
1544
function WhitespaceControl() {
1545
}
1546
WhitespaceControl.prototype = new Visitor();
1547
1548
WhitespaceControl.prototype.Program = function(program) {
1549
var isRoot = !this.isRootSeen;
1550
this.isRootSeen = true;
1551
1552
var body = program.body;
1553
for (var i = 0, l = body.length; i < l; i++) {
1554
var current = body[i],
1555
strip = this.accept(current);
1556
1557
if (!strip) {
1558
continue;
1559
}
1560
1561
var _isPrevWhitespace = isPrevWhitespace(body, i, isRoot),
1562
_isNextWhitespace = isNextWhitespace(body, i, isRoot),
1563
1564
openStandalone = strip.openStandalone && _isPrevWhitespace,
1565
closeStandalone = strip.closeStandalone && _isNextWhitespace,
1566
inlineStandalone = strip.inlineStandalone && _isPrevWhitespace && _isNextWhitespace;
1567
1568
if (strip.close) {
1569
omitRight(body, i, true);
1570
}
1571
if (strip.open) {
1572
omitLeft(body, i, true);
1573
}
1574
1575
if (inlineStandalone) {
1576
omitRight(body, i);
1577
1578
if (omitLeft(body, i)) {
1579
// If we are on a standalone node, save the indent info for partials
1580
if (current.type === 'PartialStatement') {
1581
// Pull out the whitespace from the final line
1582
current.indent = (/([ \t]+$)/).exec(body[i-1].original)[1];
1583
}
1584
}
1585
}
1586
if (openStandalone) {
1587
omitRight((current.program || current.inverse).body);
1588
1589
// Strip out the previous content node if it's whitespace only
1590
omitLeft(body, i);
1591
}
1592
if (closeStandalone) {
1593
// Always strip the next node
1594
omitRight(body, i);
1595
1596
omitLeft((current.inverse || current.program).body);
1597
}
1598
}
1599
1600
return program;
1601
};
1602
WhitespaceControl.prototype.BlockStatement = function(block) {
1603
this.accept(block.program);
1604
this.accept(block.inverse);
1605
1606
// Find the inverse program that is involed with whitespace stripping.
1607
var program = block.program || block.inverse,
1608
inverse = block.program && block.inverse,
1609
firstInverse = inverse,
1610
lastInverse = inverse;
1611
1612
if (inverse && inverse.chained) {
1613
firstInverse = inverse.body[0].program;
1614
1615
// Walk the inverse chain to find the last inverse that is actually in the chain.
1616
while (lastInverse.chained) {
1617
lastInverse = lastInverse.body[lastInverse.body.length-1].program;
1618
}
1619
}
1620
1621
var strip = {
1622
open: block.openStrip.open,
1623
close: block.closeStrip.close,
1624
1625
// Determine the standalone candiacy. Basically flag our content as being possibly standalone
1626
// so our parent can determine if we actually are standalone
1627
openStandalone: isNextWhitespace(program.body),
1628
closeStandalone: isPrevWhitespace((firstInverse || program).body)
1629
};
1630
1631
if (block.openStrip.close) {
1632
omitRight(program.body, null, true);
1633
}
1634
1635
if (inverse) {
1636
var inverseStrip = block.inverseStrip;
1637
1638
if (inverseStrip.open) {
1639
omitLeft(program.body, null, true);
1640
}
1641
1642
if (inverseStrip.close) {
1643
omitRight(firstInverse.body, null, true);
1644
}
1645
if (block.closeStrip.open) {
1646
omitLeft(lastInverse.body, null, true);
1647
}
1648
1649
// Find standalone else statments
1650
if (isPrevWhitespace(program.body)
1651
&& isNextWhitespace(firstInverse.body)) {
1652
1653
omitLeft(program.body);
1654
omitRight(firstInverse.body);
1655
}
1656
} else {
1657
if (block.closeStrip.open) {
1658
omitLeft(program.body, null, true);
1659
}
1660
}
1661
1662
return strip;
1663
};
1664
1665
WhitespaceControl.prototype.MustacheStatement = function(mustache) {
1666
return mustache.strip;
1667
};
1668
1669
WhitespaceControl.prototype.PartialStatement =
1670
WhitespaceControl.prototype.CommentStatement = function(node) {
1671
/* istanbul ignore next */
1672
var strip = node.strip || {};
1673
return {
1674
inlineStandalone: true,
1675
open: strip.open,
1676
close: strip.close
1677
};
1678
};
1679
1680
1681
function isPrevWhitespace(body, i, isRoot) {
1682
if (i === undefined) {
1683
i = body.length;
1684
}
1685
1686
// Nodes that end with newlines are considered whitespace (but are special
1687
// cased for strip operations)
1688
var prev = body[i-1],
1689
sibling = body[i-2];
1690
if (!prev) {
1691
return isRoot;
1692
}
1693
1694
if (prev.type === 'ContentStatement') {
1695
return (sibling || !isRoot ? (/\r?\n\s*?$/) : (/(^|\r?\n)\s*?$/)).test(prev.original);
1696
}
1697
}
1698
function isNextWhitespace(body, i, isRoot) {
1699
if (i === undefined) {
1700
i = -1;
1701
}
1702
1703
var next = body[i+1],
1704
sibling = body[i+2];
1705
if (!next) {
1706
return isRoot;
1707
}
1708
1709
if (next.type === 'ContentStatement') {
1710
return (sibling || !isRoot ? (/^\s*?\r?\n/) : (/^\s*?(\r?\n|$)/)).test(next.original);
1711
}
1712
}
1713
1714
// Marks the node to the right of the position as omitted.
1715
// I.e. {{foo}}' ' will mark the ' ' node as omitted.
1716
//
1717
// If i is undefined, then the first child will be marked as such.
1718
//
1719
// If mulitple is truthy then all whitespace will be stripped out until non-whitespace
1720
// content is met.
1721
function omitRight(body, i, multiple) {
1722
var current = body[i == null ? 0 : i + 1];
1723
if (!current || current.type !== 'ContentStatement' || (!multiple && current.rightStripped)) {
1724
return;
1725
}
1726
1727
var original = current.value;
1728
current.value = current.value.replace(multiple ? (/^\s+/) : (/^[ \t]*\r?\n?/), '');
1729
current.rightStripped = current.value !== original;
1730
}
1731
1732
// Marks the node to the left of the position as omitted.
1733
// I.e. ' '{{foo}} will mark the ' ' node as omitted.
1734
//
1735
// If i is undefined then the last child will be marked as such.
1736
//
1737
// If mulitple is truthy then all whitespace will be stripped out until non-whitespace
1738
// content is met.
1739
function omitLeft(body, i, multiple) {
1740
var current = body[i == null ? body.length - 1 : i - 1];
1741
if (!current || current.type !== 'ContentStatement' || (!multiple && current.leftStripped)) {
1742
return;
1743
}
1744
1745
// We omit the last node if it's whitespace only and not preceeded by a non-content node.
1746
var original = current.value;
1747
current.value = current.value.replace(multiple ? (/\s+$/) : (/[ \t]+$/), '');
1748
current.leftStripped = current.value !== original;
1749
return current.leftStripped;
1750
}
1751
1752
__exports__["default"] = WhitespaceControl;
1753
});
1754
define(
1755
'handlebars/compiler/helpers',["../exception","exports"],
1756
function(__dependency1__, __exports__) {
1757
1758
var Exception = __dependency1__["default"];
1759
1760
function SourceLocation(source, locInfo) {
1761
this.source = source;
1762
this.start = {
1763
line: locInfo.first_line,
1764
column: locInfo.first_column
1765
};
1766
this.end = {
1767
line: locInfo.last_line,
1768
column: locInfo.last_column
1769
};
1770
}
1771
1772
__exports__.SourceLocation = SourceLocation;function stripFlags(open, close) {
1773
return {
1774
open: open.charAt(2) === '~',
1775
close: close.charAt(close.length-3) === '~'
1776
};
1777
}
1778
1779
__exports__.stripFlags = stripFlags;function stripComment(comment) {
1780
return comment.replace(/^\{\{~?\!-?-?/, '')
1781
.replace(/-?-?~?\}\}$/, '');
1782
}
1783
1784
__exports__.stripComment = stripComment;function preparePath(data, parts, locInfo) {
1785
/*jshint -W040 */
1786
locInfo = this.locInfo(locInfo);
1787
1788
var original = data ? '@' : '',
1789
dig = [],
1790
depth = 0,
1791
depthString = '';
1792
1793
for(var i=0,l=parts.length; i<l; i++) {
1794
var part = parts[i].part;
1795
original += (parts[i].separator || '') + part;
1796
1797
if (part === '..' || part === '.' || part === 'this') {
1798
if (dig.length > 0) {
1799
throw new Exception('Invalid path: ' + original, {loc: locInfo});
1800
} else if (part === '..') {
1801
depth++;
1802
depthString += '../';
1803
}
1804
} else {
1805
dig.push(part);
1806
}
1807
}
1808
1809
return new this.PathExpression(data, depth, dig, original, locInfo);
1810
}
1811
1812
__exports__.preparePath = preparePath;function prepareMustache(path, params, hash, open, strip, locInfo) {
1813
/*jshint -W040 */
1814
// Must use charAt to support IE pre-10
1815
var escapeFlag = open.charAt(3) || open.charAt(2),
1816
escaped = escapeFlag !== '{' && escapeFlag !== '&';
1817
1818
return new this.MustacheStatement(path, params, hash, escaped, strip, this.locInfo(locInfo));
1819
}
1820
1821
__exports__.prepareMustache = prepareMustache;function prepareRawBlock(openRawBlock, content, close, locInfo) {
1822
/*jshint -W040 */
1823
if (openRawBlock.path.original !== close) {
1824
var errorNode = {loc: openRawBlock.path.loc};
1825
1826
throw new Exception(openRawBlock.path.original + " doesn't match " + close, errorNode);
1827
}
1828
1829
locInfo = this.locInfo(locInfo);
1830
var program = new this.Program([content], null, {}, locInfo);
1831
1832
return new this.BlockStatement(
1833
openRawBlock.path, openRawBlock.params, openRawBlock.hash,
1834
program, undefined,
1835
{}, {}, {},
1836
locInfo);
1837
}
1838
1839
__exports__.prepareRawBlock = prepareRawBlock;function prepareBlock(openBlock, program, inverseAndProgram, close, inverted, locInfo) {
1840
/*jshint -W040 */
1841
// When we are chaining inverse calls, we will not have a close path
1842
if (close && close.path && openBlock.path.original !== close.path.original) {
1843
var errorNode = {loc: openBlock.path.loc};
1844
1845
throw new Exception(openBlock.path.original + ' doesn\'t match ' + close.path.original, errorNode);
1846
}
1847
1848
program.blockParams = openBlock.blockParams;
1849
1850
var inverse,
1851
inverseStrip;
1852
1853
if (inverseAndProgram) {
1854
if (inverseAndProgram.chain) {
1855
inverseAndProgram.program.body[0].closeStrip = close.strip;
1856
}
1857
1858
inverseStrip = inverseAndProgram.strip;
1859
inverse = inverseAndProgram.program;
1860
}
1861
1862
if (inverted) {
1863
inverted = inverse;
1864
inverse = program;
1865
program = inverted;
1866
}
1867
1868
return new this.BlockStatement(
1869
openBlock.path, openBlock.params, openBlock.hash,
1870
program, inverse,
1871
openBlock.strip, inverseStrip, close && close.strip,
1872
this.locInfo(locInfo));
1873
}
1874
1875
__exports__.prepareBlock = prepareBlock;
1876
});
1877
define(
1878
'handlebars/compiler/base',["./parser","./ast","./whitespace-control","./helpers","../utils","exports"],
1879
function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __exports__) {
1880
1881
var parser = __dependency1__["default"];
1882
var AST = __dependency2__["default"];
1883
var WhitespaceControl = __dependency3__["default"];
1884
var Helpers = __dependency4__;
1885
var extend = __dependency5__.extend;
1886
1887
__exports__.parser = parser;
1888
1889
var yy = {};
1890
extend(yy, Helpers, AST);
1891
1892
function parse(input, options) {
1893
// Just return if an already-compiled AST was passed in.
1894
if (input.type === 'Program') { return input; }
1895
1896
parser.yy = yy;
1897
1898
// Altering the shared object here, but this is ok as parser is a sync operation
1899
yy.locInfo = function(locInfo) {
1900
return new yy.SourceLocation(options && options.srcName, locInfo);
1901
};
1902
1903
var strip = new WhitespaceControl();
1904
return strip.accept(parser.parse(input));
1905
}
1906
1907
__exports__.parse = parse;
1908
});
1909
define(
1910
'handlebars/compiler/compiler',["../exception","../utils","./ast","exports"],
1911
function(__dependency1__, __dependency2__, __dependency3__, __exports__) {
1912
1913
var Exception = __dependency1__["default"];
1914
var isArray = __dependency2__.isArray;
1915
var indexOf = __dependency2__.indexOf;
1916
var AST = __dependency3__["default"];
1917
1918
var slice = [].slice;
1919
1920
1921
function Compiler() {}
1922
1923
__exports__.Compiler = Compiler;// the foundHelper register will disambiguate helper lookup from finding a
1924
// function in a context. This is necessary for mustache compatibility, which
1925
// requires that context functions in blocks are evaluated by blockHelperMissing,
1926
// and then proceed as if the resulting value was provided to blockHelperMissing.
1927
1928
Compiler.prototype = {
1929
compiler: Compiler,
1930
1931
equals: function(other) {
1932
var len = this.opcodes.length;
1933
if (other.opcodes.length !== len) {
1934
return false;
1935
}
1936
1937
for (var i = 0; i < len; i++) {
1938
var opcode = this.opcodes[i],
1939
otherOpcode = other.opcodes[i];
1940
if (opcode.opcode !== otherOpcode.opcode || !argEquals(opcode.args, otherOpcode.args)) {
1941
return false;
1942
}
1943
}
1944
1945
// We know that length is the same between the two arrays because they are directly tied
1946
// to the opcode behavior above.
1947
len = this.children.length;
1948
for (i = 0; i < len; i++) {
1949
if (!this.children[i].equals(other.children[i])) {
1950
return false;
1951
}
1952
}
1953
1954
return true;
1955
},
1956
1957
guid: 0,
1958
1959
compile: function(program, options) {
1960
this.sourceNode = [];
1961
this.opcodes = [];
1962
this.children = [];
1963
this.options = options;
1964
this.stringParams = options.stringParams;
1965
this.trackIds = options.trackIds;
1966
1967
options.blockParams = options.blockParams || [];
1968
1969
// These changes will propagate to the other compiler components
1970
var knownHelpers = options.knownHelpers;
1971
options.knownHelpers = {
1972
'helperMissing': true,
1973
'blockHelperMissing': true,
1974
'each': true,
1975
'if': true,
1976
'unless': true,
1977
'with': true,
1978
'log': true,
1979
'lookup': true
1980
};
1981
if (knownHelpers) {
1982
for (var name in knownHelpers) {
1983
options.knownHelpers[name] = knownHelpers[name];
1984
}
1985
}
1986
1987
return this.accept(program);
1988
},
1989
1990
compileProgram: function(program) {
1991
var result = new this.compiler().compile(program, this.options);
1992
var guid = this.guid++;
1993
1994
this.usePartial = this.usePartial || result.usePartial;
1995
1996
this.children[guid] = result;
1997
this.useDepths = this.useDepths || result.useDepths;
1998
1999
return guid;
2000
},
2001
2002
accept: function(node) {
2003
this.sourceNode.unshift(node);
2004
var ret = this[node.type](node);
2005
this.sourceNode.shift();
2006
return ret;
2007
},
2008
2009
Program: function(program) {
2010
this.options.blockParams.unshift(program.blockParams);
2011
2012
var body = program.body;
2013
for(var i=0, l=body.length; i<l; i++) {
2014
this.accept(body[i]);
2015
}
2016
2017
this.options.blockParams.shift();
2018
2019
this.isSimple = l === 1;
2020
this.blockParams = program.blockParams ? program.blockParams.length : 0;
2021
2022
return this;
2023
},
2024
2025
BlockStatement: function(block) {
2026
transformLiteralToPath(block);
2027
2028
var program = block.program,
2029
inverse = block.inverse;
2030
2031
program = program && this.compileProgram(program);
2032
inverse = inverse && this.compileProgram(inverse);
2033
2034
var type = this.classifySexpr(block);
2035
2036
if (type === 'helper') {
2037
this.helperSexpr(block, program, inverse);
2038
} else if (type === 'simple') {
2039
this.simpleSexpr(block);
2040
2041
// now that the simple mustache is resolved, we need to
2042
// evaluate it by executing `blockHelperMissing`
2043
this.opcode('pushProgram', program);
2044
this.opcode('pushProgram', inverse);
2045
this.opcode('emptyHash');
2046
this.opcode('blockValue', block.path.original);
2047
} else {
2048
this.ambiguousSexpr(block, program, inverse);
2049
2050
// now that the simple mustache is resolved, we need to
2051
// evaluate it by executing `blockHelperMissing`
2052
this.opcode('pushProgram', program);
2053
this.opcode('pushProgram', inverse);
2054
this.opcode('emptyHash');
2055
this.opcode('ambiguousBlockValue');
2056
}
2057
2058
this.opcode('append');
2059
},
2060
2061
PartialStatement: function(partial) {
2062
this.usePartial = true;
2063
2064
var params = partial.params;
2065
if (params.length > 1) {
2066
throw new Exception('Unsupported number of partial arguments: ' + params.length, partial);
2067
} else if (!params.length) {
2068
params.push({type: 'PathExpression', parts: [], depth: 0});
2069
}
2070
2071
var partialName = partial.name.original,
2072
isDynamic = partial.name.type === 'SubExpression';
2073
if (isDynamic) {
2074
this.accept(partial.name);
2075
}
2076
2077
this.setupFullMustacheParams(partial, undefined, undefined, true);
2078
2079
var indent = partial.indent || '';
2080
if (this.options.preventIndent && indent) {
2081
this.opcode('appendContent', indent);
2082
indent = '';
2083
}
2084
2085
this.opcode('invokePartial', isDynamic, partialName, indent);
2086
this.opcode('append');
2087
},
2088
2089
MustacheStatement: function(mustache) {
2090
this.SubExpression(mustache);
2091
2092
if(mustache.escaped && !this.options.noEscape) {
2093
this.opcode('appendEscaped');
2094
} else {
2095
this.opcode('append');
2096
}
2097
},
2098
2099
ContentStatement: function(content) {
2100
if (content.value) {
2101
this.opcode('appendContent', content.value);
2102
}
2103
},
2104
2105
CommentStatement: function() {},
2106
2107
SubExpression: function(sexpr) {
2108
transformLiteralToPath(sexpr);
2109
var type = this.classifySexpr(sexpr);
2110
2111
if (type === 'simple') {
2112
this.simpleSexpr(sexpr);
2113
} else if (type === 'helper') {
2114
this.helperSexpr(sexpr);
2115
} else {
2116
this.ambiguousSexpr(sexpr);
2117
}
2118
},
2119
ambiguousSexpr: function(sexpr, program, inverse) {
2120
var path = sexpr.path,
2121
name = path.parts[0],
2122
isBlock = program != null || inverse != null;
2123
2124
this.opcode('getContext', path.depth);
2125
2126
this.opcode('pushProgram', program);
2127
this.opcode('pushProgram', inverse);
2128
2129
this.accept(path);
2130
2131
this.opcode('invokeAmbiguous', name, isBlock);
2132
},
2133
2134
simpleSexpr: function(sexpr) {
2135
this.accept(sexpr.path);
2136
this.opcode('resolvePossibleLambda');
2137
},
2138
2139
helperSexpr: function(sexpr, program, inverse) {
2140
var params = this.setupFullMustacheParams(sexpr, program, inverse),
2141
path = sexpr.path,
2142
name = path.parts[0];
2143
2144
if (this.options.knownHelpers[name]) {
2145
this.opcode('invokeKnownHelper', params.length, name);
2146
} else if (this.options.knownHelpersOnly) {
2147
throw new Exception("You specified knownHelpersOnly, but used the unknown helper " + name, sexpr);
2148
} else {
2149
path.falsy = true;
2150
2151
this.accept(path);
2152
this.opcode('invokeHelper', params.length, path.original, AST.helpers.simpleId(path));
2153
}
2154
},
2155
2156
PathExpression: function(path) {
2157
this.addDepth(path.depth);
2158
this.opcode('getContext', path.depth);
2159
2160
var name = path.parts[0],
2161
scoped = AST.helpers.scopedId(path),
2162
blockParamId = !path.depth && !scoped && this.blockParamIndex(name);
2163
2164
if (blockParamId) {
2165
this.opcode('lookupBlockParam', blockParamId, path.parts);
2166
} else if (!name) {
2167
// Context reference, i.e. `{{foo .}}` or `{{foo ..}}`
2168
this.opcode('pushContext');
2169
} else if (path.data) {
2170
this.options.data = true;
2171
this.opcode('lookupData', path.depth, path.parts);
2172
} else {
2173
this.opcode('lookupOnContext', path.parts, path.falsy, scoped);
2174
}
2175
},
2176
2177
StringLiteral: function(string) {
2178
this.opcode('pushString', string.value);
2179
},
2180
2181
NumberLiteral: function(number) {
2182
this.opcode('pushLiteral', number.value);
2183
},
2184
2185
BooleanLiteral: function(bool) {
2186
this.opcode('pushLiteral', bool.value);
2187
},
2188
2189
Hash: function(hash) {
2190
var pairs = hash.pairs, i, l;
2191
2192
this.opcode('pushHash');
2193
2194
for (i=0, l=pairs.length; i<l; i++) {
2195
this.pushParam(pairs[i].value);
2196
}
2197
while (i--) {
2198
this.opcode('assignToHash', pairs[i].key);
2199
}
2200
this.opcode('popHash');
2201
},
2202
2203
// HELPERS
2204
opcode: function(name) {
2205
this.opcodes.push({ opcode: name, args: slice.call(arguments, 1), loc: this.sourceNode[0].loc });
2206
},
2207
2208
addDepth: function(depth) {
2209
if (!depth) {
2210
return;
2211
}
2212
2213
this.useDepths = true;
2214
},
2215
2216
classifySexpr: function(sexpr) {
2217
var isSimple = AST.helpers.simpleId(sexpr.path);
2218
2219
var isBlockParam = isSimple && !!this.blockParamIndex(sexpr.path.parts[0]);
2220
2221
// a mustache is an eligible helper if:
2222
// * its id is simple (a single part, not `this` or `..`)
2223
var isHelper = !isBlockParam && AST.helpers.helperExpression(sexpr);
2224
2225
// if a mustache is an eligible helper but not a definite
2226
// helper, it is ambiguous, and will be resolved in a later
2227
// pass or at runtime.
2228
var isEligible = !isBlockParam && (isHelper || isSimple);
2229
2230
var options = this.options;
2231
2232
// if ambiguous, we can possibly resolve the ambiguity now
2233
// An eligible helper is one that does not have a complex path, i.e. `this.foo`, `../foo` etc.
2234
if (isEligible && !isHelper) {
2235
var name = sexpr.path.parts[0];
2236
2237
if (options.knownHelpers[name]) {
2238
isHelper = true;
2239
} else if (options.knownHelpersOnly) {
2240
isEligible = false;
2241
}
2242
}
2243
2244
if (isHelper) { return 'helper'; }
2245
else if (isEligible) { return 'ambiguous'; }
2246
else { return 'simple'; }
2247
},
2248
2249
pushParams: function(params) {
2250
for(var i=0, l=params.length; i<l; i++) {
2251
this.pushParam(params[i]);
2252
}
2253
},
2254
2255
pushParam: function(val) {
2256
var value = val.value != null ? val.value : val.original || '';
2257
2258
if (this.stringParams) {
2259
if (value.replace) {
2260
value = value
2261
.replace(/^(\.?\.\/)*/g, '')
2262
.replace(/\//g, '.');
2263
}
2264
2265
if(val.depth) {
2266
this.addDepth(val.depth);
2267
}
2268
this.opcode('getContext', val.depth || 0);
2269
this.opcode('pushStringParam', value, val.type);
2270
2271
if (val.type === 'SubExpression') {
2272
// SubExpressions get evaluated and passed in
2273
// in string params mode.
2274
this.accept(val);
2275
}
2276
} else {
2277
if (this.trackIds) {
2278
var blockParamIndex;
2279
if (val.parts && !AST.helpers.scopedId(val) && !val.depth) {
2280
blockParamIndex = this.blockParamIndex(val.parts[0]);
2281
}
2282
if (blockParamIndex) {
2283
var blockParamChild = val.parts.slice(1).join('.');
2284
this.opcode('pushId', 'BlockParam', blockParamIndex, blockParamChild);
2285
} else {
2286
value = val.original || value;
2287
if (value.replace) {
2288
value = value
2289
.replace(/^\.\//g, '')
2290
.replace(/^\.$/g, '');
2291
}
2292
2293
this.opcode('pushId', val.type, value);
2294
}
2295
}
2296
this.accept(val);
2297
}
2298
},
2299
2300
setupFullMustacheParams: function(sexpr, program, inverse, omitEmpty) {
2301
var params = sexpr.params;
2302
this.pushParams(params);
2303
2304
this.opcode('pushProgram', program);
2305
this.opcode('pushProgram', inverse);
2306
2307
if (sexpr.hash) {
2308
this.accept(sexpr.hash);
2309
} else {
2310
this.opcode('emptyHash', omitEmpty);
2311
}
2312
2313
return params;
2314
},
2315
2316
blockParamIndex: function(name) {
2317
for (var depth = 0, len = this.options.blockParams.length; depth < len; depth++) {
2318
var blockParams = this.options.blockParams[depth],
2319
param = blockParams && indexOf(blockParams, name);
2320
if (blockParams && param >= 0) {
2321
return [depth, param];
2322
}
2323
}
2324
}
2325
};
2326
2327
function precompile(input, options, env) {
2328
if (input == null || (typeof input !== 'string' && input.type !== 'Program')) {
2329
throw new Exception("You must pass a string or Handlebars AST to Handlebars.precompile. You passed " + input);
2330
}
2331
2332
options = options || {};
2333
if (!('data' in options)) {
2334
options.data = true;
2335
}
2336
if (options.compat) {
2337
options.useDepths = true;
2338
}
2339
2340
var ast = env.parse(input, options);
2341
var environment = new env.Compiler().compile(ast, options);
2342
return new env.JavaScriptCompiler().compile(environment, options);
2343
}
2344
2345
__exports__.precompile = precompile;function compile(input, options, env) {
2346
if (input == null || (typeof input !== 'string' && input.type !== 'Program')) {
2347
throw new Exception("You must pass a string or Handlebars AST to Handlebars.compile. You passed " + input);
2348
}
2349
2350
options = options || {};
2351
2352
if (!('data' in options)) {
2353
options.data = true;
2354
}
2355
if (options.compat) {
2356
options.useDepths = true;
2357
}
2358
2359
var compiled;
2360
2361
function compileInput() {
2362
var ast = env.parse(input, options);
2363
var environment = new env.Compiler().compile(ast, options);
2364
var templateSpec = new env.JavaScriptCompiler().compile(environment, options, undefined, true);
2365
return env.template(templateSpec);
2366
}
2367
2368
// Template is only compiled on first use and cached after that point.
2369
var ret = function(context, options) {
2370
if (!compiled) {
2371
compiled = compileInput();
2372
}
2373
return compiled.call(this, context, options);
2374
};
2375
ret._setup = function(options) {
2376
if (!compiled) {
2377
compiled = compileInput();
2378
}
2379
return compiled._setup(options);
2380
};
2381
ret._child = function(i, data, blockParams, depths) {
2382
if (!compiled) {
2383
compiled = compileInput();
2384
}
2385
return compiled._child(i, data, blockParams, depths);
2386
};
2387
return ret;
2388
}
2389
2390
__exports__.compile = compile;function argEquals(a, b) {
2391
if (a === b) {
2392
return true;
2393
}
2394
2395
if (isArray(a) && isArray(b) && a.length === b.length) {
2396
for (var i = 0; i < a.length; i++) {
2397
if (!argEquals(a[i], b[i])) {
2398
return false;
2399
}
2400
}
2401
return true;
2402
}
2403
}
2404
2405
function transformLiteralToPath(sexpr) {
2406
if (!sexpr.path.parts) {
2407
var literal = sexpr.path;
2408
// Casting to string here to make false and 0 literal values play nicely with the rest
2409
// of the system.
2410
sexpr.path = new AST.PathExpression(false, 0, [literal.original+''], literal.original+'', literal.log);
2411
}
2412
}
2413
});
2414
define(
2415
'handlebars/compiler/code-gen',["../utils","exports"],
2416
function(__dependency1__, __exports__) {
2417
2418
var isArray = __dependency1__.isArray;
2419
2420
try {
2421
var SourceMap = require('source-map'),
2422
SourceNode = SourceMap.SourceNode;
2423
} catch (err) {
2424
/* istanbul ignore next: tested but not covered in istanbul due to dist build */
2425
SourceNode = function(line, column, srcFile, chunks) {
2426
this.src = '';
2427
if (chunks) {
2428
this.add(chunks);
2429
}
2430
};
2431
/* istanbul ignore next */
2432
SourceNode.prototype = {
2433
add: function(chunks) {
2434
if (isArray(chunks)) {
2435
chunks = chunks.join('');
2436
}
2437
this.src += chunks;
2438
},
2439
prepend: function(chunks) {
2440
if (isArray(chunks)) {
2441
chunks = chunks.join('');
2442
}
2443
this.src = chunks + this.src;
2444
},
2445
toStringWithSourceMap: function() {
2446
return {code: this.toString()};
2447
},
2448
toString: function() {
2449
return this.src;
2450
}
2451
};
2452
}
2453
2454
2455
function castChunk(chunk, codeGen, loc) {
2456
if (isArray(chunk)) {
2457
var ret = [];
2458
2459
for (var i = 0, len = chunk.length; i < len; i++) {
2460
ret.push(codeGen.wrap(chunk[i], loc));
2461
}
2462
return ret;
2463
} else if (typeof chunk === 'boolean' || typeof chunk === 'number') {
2464
// Handle primitives that the SourceNode will throw up on
2465
return chunk+'';
2466
}
2467
return chunk;
2468
}
2469
2470
2471
function CodeGen(srcFile) {
2472
this.srcFile = srcFile;
2473
this.source = [];
2474
}
2475
2476
CodeGen.prototype = {
2477
prepend: function(source, loc) {
2478
this.source.unshift(this.wrap(source, loc));
2479
},
2480
push: function(source, loc) {
2481
this.source.push(this.wrap(source, loc));
2482
},
2483
2484
merge: function() {
2485
var source = this.empty();
2486
this.each(function(line) {
2487
source.add([' ', line, '\n']);
2488
});
2489
return source;
2490
},
2491
2492
each: function(iter) {
2493
for (var i = 0, len = this.source.length; i < len; i++) {
2494
iter(this.source[i]);
2495
}
2496
},
2497
2498
empty: function(loc) {
2499
loc = loc || this.currentLocation || {start:{}};
2500
return new SourceNode(loc.start.line, loc.start.column, this.srcFile);
2501
},
2502
wrap: function(chunk, loc) {
2503
if (chunk instanceof SourceNode) {
2504
return chunk;
2505
}
2506
2507
loc = loc || this.currentLocation || {start:{}};
2508
chunk = castChunk(chunk, this, loc);
2509
2510
return new SourceNode(loc.start.line, loc.start.column, this.srcFile, chunk);
2511
},
2512
2513
functionCall: function(fn, type, params) {
2514
params = this.generateList(params);
2515
return this.wrap([fn, type ? '.' + type + '(' : '(', params, ')']);
2516
},
2517
2518
quotedString: function(str) {
2519
return '"' + (str + '')
2520
.replace(/\\/g, '\\\\')
2521
.replace(/"/g, '\\"')
2522
.replace(/\n/g, '\\n')
2523
.replace(/\r/g, '\\r')
2524
.replace(/\u2028/g, '\\u2028') // Per Ecma-262 7.3 + 7.8.4
2525
.replace(/\u2029/g, '\\u2029') + '"';
2526
},
2527
2528
objectLiteral: function(obj) {
2529
var pairs = [];
2530
2531
for (var key in obj) {
2532
if (obj.hasOwnProperty(key)) {
2533
var value = castChunk(obj[key], this);
2534
if (value !== 'undefined') {
2535
pairs.push([this.quotedString(key), ':', value]);
2536
}
2537
}
2538
}
2539
2540
var ret = this.generateList(pairs);
2541
ret.prepend('{');
2542
ret.add('}');
2543
return ret;
2544
},
2545
2546
2547
generateList: function(entries, loc) {
2548
var ret = this.empty(loc);
2549
2550
for (var i = 0, len = entries.length; i < len; i++) {
2551
if (i) {
2552
ret.add(',');
2553
}
2554
2555
ret.add(castChunk(entries[i], this, loc));
2556
}
2557
2558
return ret;
2559
},
2560
2561
generateArray: function(entries, loc) {
2562
var ret = this.generateList(entries, loc);
2563
ret.prepend('[');
2564
ret.add(']');
2565
2566
return ret;
2567
}
2568
};
2569
2570
__exports__["default"] = CodeGen;
2571
});
2572
define(
2573
'handlebars/compiler/javascript-compiler',["../base","../exception","../utils","./code-gen","exports"],
2574
function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __exports__) {
2575
2576
var COMPILER_REVISION = __dependency1__.COMPILER_REVISION;
2577
var REVISION_CHANGES = __dependency1__.REVISION_CHANGES;
2578
var Exception = __dependency2__["default"];
2579
var isArray = __dependency3__.isArray;
2580
var CodeGen = __dependency4__["default"];
2581
2582
function Literal(value) {
2583
this.value = value;
2584
}
2585
2586
function JavaScriptCompiler() {}
2587
2588
JavaScriptCompiler.prototype = {
2589
// PUBLIC API: You can override these methods in a subclass to provide
2590
// alternative compiled forms for name lookup and buffering semantics
2591
nameLookup: function(parent, name /* , type*/) {
2592
if (JavaScriptCompiler.isValidJavaScriptVariableName(name)) {
2593
return [parent, ".", name];
2594
} else {
2595
return [parent, "['", name, "']"];
2596
}
2597
},
2598
depthedLookup: function(name) {
2599
return [this.aliasable('this.lookup'), '(depths, "', name, '")'];
2600
},
2601
2602
compilerInfo: function() {
2603
var revision = COMPILER_REVISION,
2604
versions = REVISION_CHANGES[revision];
2605
return [revision, versions];
2606
},
2607
2608
appendToBuffer: function(source, location, explicit) {
2609
// Force a source as this simplifies the merge logic.
2610
if (!isArray(source)) {
2611
source = [source];
2612
}
2613
source = this.source.wrap(source, location);
2614
2615
if (this.environment.isSimple) {
2616
return ['return ', source, ';'];
2617
} else if (explicit) {
2618
// This is a case where the buffer operation occurs as a child of another
2619
// construct, generally braces. We have to explicitly output these buffer
2620
// operations to ensure that the emitted code goes in the correct location.
2621
return ['buffer += ', source, ';'];
2622
} else {
2623
source.appendToBuffer = true;
2624
return source;
2625
}
2626
},
2627
2628
initializeBuffer: function() {
2629
return this.quotedString("");
2630
},
2631
// END PUBLIC API
2632
2633
compile: function(environment, options, context, asObject) {
2634
this.environment = environment;
2635
this.options = options;
2636
this.stringParams = this.options.stringParams;
2637
this.trackIds = this.options.trackIds;
2638
this.precompile = !asObject;
2639
2640
this.name = this.environment.name;
2641
this.isChild = !!context;
2642
this.context = context || {
2643
programs: [],
2644
environments: []
2645
};
2646
2647
this.preamble();
2648
2649
this.stackSlot = 0;
2650
this.stackVars = [];
2651
this.aliases = {};
2652
this.registers = { list: [] };
2653
this.hashes = [];
2654
this.compileStack = [];
2655
this.inlineStack = [];
2656
this.blockParams = [];
2657
2658
this.compileChildren(environment, options);
2659
2660
this.useDepths = this.useDepths || environment.useDepths || this.options.compat;
2661
this.useBlockParams = this.useBlockParams || environment.useBlockParams;
2662
2663
var opcodes = environment.opcodes,
2664
opcode,
2665
firstLoc,
2666
i,
2667
l;
2668
2669
for (i = 0, l = opcodes.length; i < l; i++) {
2670
opcode = opcodes[i];
2671
2672
this.source.currentLocation = opcode.loc;
2673
firstLoc = firstLoc || opcode.loc;
2674
this[opcode.opcode].apply(this, opcode.args);
2675
}
2676
2677
// Flush any trailing content that might be pending.
2678
this.source.currentLocation = firstLoc;
2679
this.pushSource('');
2680
2681
/* istanbul ignore next */
2682
if (this.stackSlot || this.inlineStack.length || this.compileStack.length) {
2683
throw new Exception('Compile completed with content left on stack');
2684
}
2685
2686
var fn = this.createFunctionContext(asObject);
2687
if (!this.isChild) {
2688
var ret = {
2689
compiler: this.compilerInfo(),
2690
main: fn
2691
};
2692
var programs = this.context.programs;
2693
for (i = 0, l = programs.length; i < l; i++) {
2694
if (programs[i]) {
2695
ret[i] = programs[i];
2696
}
2697
}
2698
2699
if (this.environment.usePartial) {
2700
ret.usePartial = true;
2701
}
2702
if (this.options.data) {
2703
ret.useData = true;
2704
}
2705
if (this.useDepths) {
2706
ret.useDepths = true;
2707
}
2708
if (this.useBlockParams) {
2709
ret.useBlockParams = true;
2710
}
2711
if (this.options.compat) {
2712
ret.compat = true;
2713
}
2714
2715
if (!asObject) {
2716
ret.compiler = JSON.stringify(ret.compiler);
2717
2718
this.source.currentLocation = {start: {line: 1, column: 0}};
2719
ret = this.objectLiteral(ret);
2720
2721
if (options.srcName) {
2722
ret = ret.toStringWithSourceMap({file: options.destName});
2723
ret.map = ret.map && ret.map.toString();
2724
} else {
2725
ret = ret.toString();
2726
}
2727
} else {
2728
ret.compilerOptions = this.options;
2729
}
2730
2731
return ret;
2732
} else {
2733
return fn;
2734
}
2735
},
2736
2737
preamble: function() {
2738
// track the last context pushed into place to allow skipping the
2739
// getContext opcode when it would be a noop
2740
this.lastContext = 0;
2741
this.source = new CodeGen(this.options.srcName);
2742
},
2743
2744
createFunctionContext: function(asObject) {
2745
var varDeclarations = '';
2746
2747
var locals = this.stackVars.concat(this.registers.list);
2748
if(locals.length > 0) {
2749
varDeclarations += ", " + locals.join(", ");
2750
}
2751
2752
// Generate minimizer alias mappings
2753
//
2754
// When using true SourceNodes, this will update all references to the given alias
2755
// as the source nodes are reused in situ. For the non-source node compilation mode,
2756
// aliases will not be used, but this case is already being run on the client and
2757
// we aren't concern about minimizing the template size.
2758
var aliasCount = 0;
2759
for (var alias in this.aliases) {
2760
var node = this.aliases[alias];
2761
2762
if (this.aliases.hasOwnProperty(alias) && node.children && node.referenceCount > 1) {
2763
varDeclarations += ', alias' + (++aliasCount) + '=' + alias;
2764
node.children[0] = 'alias' + aliasCount;
2765
}
2766
}
2767
2768
var params = ["depth0", "helpers", "partials", "data"];
2769
2770
if (this.useBlockParams || this.useDepths) {
2771
params.push('blockParams');
2772
}
2773
if (this.useDepths) {
2774
params.push('depths');
2775
}
2776
2777
// Perform a second pass over the output to merge content when possible
2778
var source = this.mergeSource(varDeclarations);
2779
2780
if (asObject) {
2781
params.push(source);
2782
2783
return Function.apply(this, params);
2784
} else {
2785
return this.source.wrap(['function(', params.join(','), ') {\n ', source, '}']);
2786
}
2787
},
2788
mergeSource: function(varDeclarations) {
2789
var isSimple = this.environment.isSimple,
2790
appendOnly = !this.forceBuffer,
2791
appendFirst,
2792
2793
sourceSeen,
2794
bufferStart,
2795
bufferEnd;
2796
this.source.each(function(line) {
2797
if (line.appendToBuffer) {
2798
if (bufferStart) {
2799
line.prepend(' + ');
2800
} else {
2801
bufferStart = line;
2802
}
2803
bufferEnd = line;
2804
} else {
2805
if (bufferStart) {
2806
if (!sourceSeen) {
2807
appendFirst = true;
2808
} else {
2809
bufferStart.prepend('buffer += ');
2810
}
2811
bufferEnd.add(';');
2812
bufferStart = bufferEnd = undefined;
2813
}
2814
2815
sourceSeen = true;
2816
if (!isSimple) {
2817
appendOnly = false;
2818
}
2819
}
2820
});
2821
2822
2823
if (appendOnly) {
2824
if (bufferStart) {
2825
bufferStart.prepend('return ');
2826
bufferEnd.add(';');
2827
} else if (!sourceSeen) {
2828
this.source.push('return "";');
2829
}
2830
} else {
2831
varDeclarations += ", buffer = " + (appendFirst ? '' : this.initializeBuffer());
2832
2833
if (bufferStart) {
2834
bufferStart.prepend('return buffer + ');
2835
bufferEnd.add(';');
2836
} else {
2837
this.source.push('return buffer;');
2838
}
2839
}
2840
2841
if (varDeclarations) {
2842
this.source.prepend('var ' + varDeclarations.substring(2) + (appendFirst ? '' : ';\n'));
2843
}
2844
2845
return this.source.merge();
2846
},
2847
2848
// [blockValue]
2849
//
2850
// On stack, before: hash, inverse, program, value
2851
// On stack, after: return value of blockHelperMissing
2852
//
2853
// The purpose of this opcode is to take a block of the form
2854
// `{{#this.foo}}...{{/this.foo}}`, resolve the value of `foo`, and
2855
// replace it on the stack with the result of properly
2856
// invoking blockHelperMissing.
2857
blockValue: function(name) {
2858
var blockHelperMissing = this.aliasable('helpers.blockHelperMissing'),
2859
params = [this.contextName(0)];
2860
this.setupHelperArgs(name, 0, params);
2861
2862
var blockName = this.popStack();
2863
params.splice(1, 0, blockName);
2864
2865
this.push(this.source.functionCall(blockHelperMissing, 'call', params));
2866
},
2867
2868
// [ambiguousBlockValue]
2869
//
2870
// On stack, before: hash, inverse, program, value
2871
// Compiler value, before: lastHelper=value of last found helper, if any
2872
// On stack, after, if no lastHelper: same as [blockValue]
2873
// On stack, after, if lastHelper: value
2874
ambiguousBlockValue: function() {
2875
// We're being a bit cheeky and reusing the options value from the prior exec
2876
var blockHelperMissing = this.aliasable('helpers.blockHelperMissing'),
2877
params = [this.contextName(0)];
2878
this.setupHelperArgs('', 0, params, true);
2879
2880
this.flushInline();
2881
2882
var current = this.topStack();
2883
params.splice(1, 0, current);
2884
2885
this.pushSource([
2886
'if (!', this.lastHelper, ') { ',
2887
current, ' = ', this.source.functionCall(blockHelperMissing, 'call', params),
2888
'}']);
2889
},
2890
2891
// [appendContent]
2892
//
2893
// On stack, before: ...
2894
// On stack, after: ...
2895
//
2896
// Appends the string value of `content` to the current buffer
2897
appendContent: function(content) {
2898
if (this.pendingContent) {
2899
content = this.pendingContent + content;
2900
} else {
2901
this.pendingLocation = this.source.currentLocation;
2902
}
2903
2904
this.pendingContent = content;
2905
},
2906
2907
// [append]
2908
//
2909
// On stack, before: value, ...
2910
// On stack, after: ...
2911
//
2912
// Coerces `value` to a String and appends it to the current buffer.
2913
//
2914
// If `value` is truthy, or 0, it is coerced into a string and appended
2915
// Otherwise, the empty string is appended
2916
append: function() {
2917
if (this.isInline()) {
2918
this.replaceStack(function(current) {
2919
return [' != null ? ', current, ' : ""'];
2920
});
2921
2922
this.pushSource(this.appendToBuffer(this.popStack()));
2923
} else {
2924
var local = this.popStack();
2925
this.pushSource(['if (', local, ' != null) { ', this.appendToBuffer(local, undefined, true), ' }']);
2926
if (this.environment.isSimple) {
2927
this.pushSource(['else { ', this.appendToBuffer("''", undefined, true), ' }']);
2928
}
2929
}
2930
},
2931
2932
// [appendEscaped]
2933
//
2934
// On stack, before: value, ...
2935
// On stack, after: ...
2936
//
2937
// Escape `value` and append it to the buffer
2938
appendEscaped: function() {
2939
this.pushSource(this.appendToBuffer(
2940
[this.aliasable('this.escapeExpression'), '(', this.popStack(), ')']));
2941
},
2942
2943
// [getContext]
2944
//
2945
// On stack, before: ...
2946
// On stack, after: ...
2947
// Compiler value, after: lastContext=depth
2948
//
2949
// Set the value of the `lastContext` compiler value to the depth
2950
getContext: function(depth) {
2951
this.lastContext = depth;
2952
},
2953
2954
// [pushContext]
2955
//
2956
// On stack, before: ...
2957
// On stack, after: currentContext, ...
2958
//
2959
// Pushes the value of the current context onto the stack.
2960
pushContext: function() {
2961
this.pushStackLiteral(this.contextName(this.lastContext));
2962
},
2963
2964
// [lookupOnContext]
2965
//
2966
// On stack, before: ...
2967
// On stack, after: currentContext[name], ...
2968
//
2969
// Looks up the value of `name` on the current context and pushes
2970
// it onto the stack.
2971
lookupOnContext: function(parts, falsy, scoped) {
2972
var i = 0;
2973
2974
if (!scoped && this.options.compat && !this.lastContext) {
2975
// The depthed query is expected to handle the undefined logic for the root level that
2976
// is implemented below, so we evaluate that directly in compat mode
2977
this.push(this.depthedLookup(parts[i++]));
2978
} else {
2979
this.pushContext();
2980
}
2981
2982
this.resolvePath('context', parts, i, falsy);
2983
},
2984
2985
// [lookupBlockParam]
2986
//
2987
// On stack, before: ...
2988
// On stack, after: blockParam[name], ...
2989
//
2990
// Looks up the value of `parts` on the given block param and pushes
2991
// it onto the stack.
2992
lookupBlockParam: function(blockParamId, parts) {
2993
this.useBlockParams = true;
2994
2995
this.push(['blockParams[', blockParamId[0], '][', blockParamId[1], ']']);
2996
this.resolvePath('context', parts, 1);
2997
},
2998
2999
// [lookupData]
3000
//
3001
// On stack, before: ...
3002
// On stack, after: data, ...
3003
//
3004
// Push the data lookup operator
3005
lookupData: function(depth, parts) {
3006
/*jshint -W083 */
3007
if (!depth) {
3008
this.pushStackLiteral('data');
3009
} else {
3010
this.pushStackLiteral('this.data(data, ' + depth + ')');
3011
}
3012
3013
this.resolvePath('data', parts, 0, true);
3014
},
3015
3016
resolvePath: function(type, parts, i, falsy) {
3017
/*jshint -W083 */
3018
if (this.options.strict || this.options.assumeObjects) {
3019
this.push(strictLookup(this.options.strict, this, parts, type));
3020
return;
3021
}
3022
3023
var len = parts.length;
3024
for (; i < len; i++) {
3025
this.replaceStack(function(current) {
3026
var lookup = this.nameLookup(current, parts[i], type);
3027
// We want to ensure that zero and false are handled properly if the context (falsy flag)
3028
// needs to have the special handling for these values.
3029
if (!falsy) {
3030
return [' != null ? ', lookup, ' : ', current];
3031
} else {
3032
// Otherwise we can use generic falsy handling
3033
return [' && ', lookup];
3034
}
3035
});
3036
}
3037
},
3038
3039
// [resolvePossibleLambda]
3040
//
3041
// On stack, before: value, ...
3042
// On stack, after: resolved value, ...
3043
//
3044
// If the `value` is a lambda, replace it on the stack by
3045
// the return value of the lambda
3046
resolvePossibleLambda: function() {
3047
this.push([this.aliasable('this.lambda'), '(', this.popStack(), ', ', this.contextName(0), ')']);
3048
},
3049
3050
// [pushStringParam]
3051
//
3052
// On stack, before: ...
3053
// On stack, after: string, currentContext, ...
3054
//
3055
// This opcode is designed for use in string mode, which
3056
// provides the string value of a parameter along with its
3057
// depth rather than resolving it immediately.
3058
pushStringParam: function(string, type) {
3059
this.pushContext();
3060
this.pushString(type);
3061
3062
// If it's a subexpression, the string result
3063
// will be pushed after this opcode.
3064
if (type !== 'SubExpression') {
3065
if (typeof string === 'string') {
3066
this.pushString(string);
3067
} else {
3068
this.pushStackLiteral(string);
3069
}
3070
}
3071
},
3072
3073
emptyHash: function(omitEmpty) {
3074
if (this.trackIds) {
3075
this.push('{}'); // hashIds
3076
}
3077
if (this.stringParams) {
3078
this.push('{}'); // hashContexts
3079
this.push('{}'); // hashTypes
3080
}
3081
this.pushStackLiteral(omitEmpty ? 'undefined' : '{}');
3082
},
3083
pushHash: function() {
3084
if (this.hash) {
3085
this.hashes.push(this.hash);
3086
}
3087
this.hash = {values: [], types: [], contexts: [], ids: []};
3088
},
3089
popHash: function() {
3090
var hash = this.hash;
3091
this.hash = this.hashes.pop();
3092
3093
if (this.trackIds) {
3094
this.push(this.objectLiteral(hash.ids));
3095
}
3096
if (this.stringParams) {
3097
this.push(this.objectLiteral(hash.contexts));
3098
this.push(this.objectLiteral(hash.types));
3099
}
3100
3101
this.push(this.objectLiteral(hash.values));
3102
},
3103
3104
// [pushString]
3105
//
3106
// On stack, before: ...
3107
// On stack, after: quotedString(string), ...
3108
//
3109
// Push a quoted version of `string` onto the stack
3110
pushString: function(string) {
3111
this.pushStackLiteral(this.quotedString(string));
3112
},
3113
3114
// [pushLiteral]
3115
//
3116
// On stack, before: ...
3117
// On stack, after: value, ...
3118
//
3119
// Pushes a value onto the stack. This operation prevents
3120
// the compiler from creating a temporary variable to hold
3121
// it.
3122
pushLiteral: function(value) {
3123
this.pushStackLiteral(value);
3124
},
3125
3126
// [pushProgram]
3127
//
3128
// On stack, before: ...
3129
// On stack, after: program(guid), ...
3130
//
3131
// Push a program expression onto the stack. This takes
3132
// a compile-time guid and converts it into a runtime-accessible
3133
// expression.
3134
pushProgram: function(guid) {
3135
if (guid != null) {
3136
this.pushStackLiteral(this.programExpression(guid));
3137
} else {
3138
this.pushStackLiteral(null);
3139
}
3140
},
3141
3142
// [invokeHelper]
3143
//
3144
// On stack, before: hash, inverse, program, params..., ...
3145
// On stack, after: result of helper invocation
3146
//
3147
// Pops off the helper's parameters, invokes the helper,
3148
// and pushes the helper's return value onto the stack.
3149
//
3150
// If the helper is not found, `helperMissing` is called.
3151
invokeHelper: function(paramSize, name, isSimple) {
3152
var nonHelper = this.popStack();
3153
var helper = this.setupHelper(paramSize, name);
3154
var simple = isSimple ? [helper.name, ' || '] : '';
3155
3156
var lookup = ['('].concat(simple, nonHelper);
3157
if (!this.options.strict) {
3158
lookup.push(' || ', this.aliasable('helpers.helperMissing'));
3159
}
3160
lookup.push(')');
3161
3162
this.push(this.source.functionCall(lookup, 'call', helper.callParams));
3163
},
3164
3165
// [invokeKnownHelper]
3166
//
3167
// On stack, before: hash, inverse, program, params..., ...
3168
// On stack, after: result of helper invocation
3169
//
3170
// This operation is used when the helper is known to exist,
3171
// so a `helperMissing` fallback is not required.
3172
invokeKnownHelper: function(paramSize, name) {
3173
var helper = this.setupHelper(paramSize, name);
3174
this.push(this.source.functionCall(helper.name, 'call', helper.callParams));
3175
},
3176
3177
// [invokeAmbiguous]
3178
//
3179
// On stack, before: hash, inverse, program, params..., ...
3180
// On stack, after: result of disambiguation
3181
//
3182
// This operation is used when an expression like `{{foo}}`
3183
// is provided, but we don't know at compile-time whether it
3184
// is a helper or a path.
3185
//
3186
// This operation emits more code than the other options,
3187
// and can be avoided by passing the `knownHelpers` and
3188
// `knownHelpersOnly` flags at compile-time.
3189
invokeAmbiguous: function(name, helperCall) {
3190
this.useRegister('helper');
3191
3192
var nonHelper = this.popStack();
3193
3194
this.emptyHash();
3195
var helper = this.setupHelper(0, name, helperCall);
3196
3197
var helperName = this.lastHelper = this.nameLookup('helpers', name, 'helper');
3198
3199
var lookup = ['(', '(helper = ', helperName, ' || ', nonHelper, ')'];
3200
if (!this.options.strict) {
3201
lookup[0] = '(helper = ';
3202
lookup.push(
3203
' != null ? helper : ',
3204
this.aliasable('helpers.helperMissing')
3205
);
3206
}
3207
3208
this.push([
3209
'(', lookup,
3210
(helper.paramsInit ? ['),(', helper.paramsInit] : []), '),',
3211
'(typeof helper === ', this.aliasable('"function"'), ' ? ',
3212
this.source.functionCall('helper','call', helper.callParams), ' : helper))'
3213
]);
3214
},
3215
3216
// [invokePartial]
3217
//
3218
// On stack, before: context, ...
3219
// On stack after: result of partial invocation
3220
//
3221
// This operation pops off a context, invokes a partial with that context,
3222
// and pushes the result of the invocation back.
3223
invokePartial: function(isDynamic, name, indent) {
3224
var params = [],
3225
options = this.setupParams(name, 1, params, false);
3226
3227
if (isDynamic) {
3228
name = this.popStack();
3229
delete options.name;
3230
}
3231
3232
if (indent) {
3233
options.indent = JSON.stringify(indent);
3234
}
3235
options.helpers = 'helpers';
3236
options.partials = 'partials';
3237
3238
if (!isDynamic) {
3239
params.unshift(this.nameLookup('partials', name, 'partial'));
3240
} else {
3241
params.unshift(name);
3242
}
3243
3244
if (this.options.compat) {
3245
options.depths = 'depths';
3246
}
3247
options = this.objectLiteral(options);
3248
params.push(options);
3249
3250
this.push(this.source.functionCall('this.invokePartial', '', params));
3251
},
3252
3253
// [assignToHash]
3254
//
3255
// On stack, before: value, ..., hash, ...
3256
// On stack, after: ..., hash, ...
3257
//
3258
// Pops a value off the stack and assigns it to the current hash
3259
assignToHash: function(key) {
3260
var value = this.popStack(),
3261
context,
3262
type,
3263
id;
3264
3265
if (this.trackIds) {
3266
id = this.popStack();
3267
}
3268
if (this.stringParams) {
3269
type = this.popStack();
3270
context = this.popStack();
3271
}
3272
3273
var hash = this.hash;
3274
if (context) {
3275
hash.contexts[key] = context;
3276
}
3277
if (type) {
3278
hash.types[key] = type;
3279
}
3280
if (id) {
3281
hash.ids[key] = id;
3282
}
3283
hash.values[key] = value;
3284
},
3285
3286
pushId: function(type, name, child) {
3287
if (type === 'BlockParam') {
3288
this.pushStackLiteral(
3289
'blockParams[' + name[0] + '].path[' + name[1] + ']'
3290
+ (child ? ' + ' + JSON.stringify('.' + child) : ''));
3291
} else if (type === 'PathExpression') {
3292
this.pushString(name);
3293
} else if (type === 'SubExpression') {
3294
this.pushStackLiteral('true');
3295
} else {
3296
this.pushStackLiteral('null');
3297
}
3298
},
3299
3300
// HELPERS
3301
3302
compiler: JavaScriptCompiler,
3303
3304
compileChildren: function(environment, options) {
3305
var children = environment.children, child, compiler;
3306
3307
for(var i=0, l=children.length; i<l; i++) {
3308
child = children[i];
3309
compiler = new this.compiler();
3310
3311
var index = this.matchExistingProgram(child);
3312
3313
if (index == null) {
3314
this.context.programs.push(''); // Placeholder to prevent name conflicts for nested children
3315
index = this.context.programs.length;
3316
child.index = index;
3317
child.name = 'program' + index;
3318
this.context.programs[index] = compiler.compile(child, options, this.context, !this.precompile);
3319
this.context.environments[index] = child;
3320
3321
this.useDepths = this.useDepths || compiler.useDepths;
3322
this.useBlockParams = this.useBlockParams || compiler.useBlockParams;
3323
} else {
3324
child.index = index;
3325
child.name = 'program' + index;
3326
3327
this.useDepths = this.useDepths || child.useDepths;
3328
this.useBlockParams = this.useBlockParams || child.useBlockParams;
3329
}
3330
}
3331
},
3332
matchExistingProgram: function(child) {
3333
for (var i = 0, len = this.context.environments.length; i < len; i++) {
3334
var environment = this.context.environments[i];
3335
if (environment && environment.equals(child)) {
3336
return i;
3337
}
3338
}
3339
},
3340
3341
programExpression: function(guid) {
3342
var child = this.environment.children[guid],
3343
programParams = [child.index, 'data', child.blockParams];
3344
3345
if (this.useBlockParams || this.useDepths) {
3346
programParams.push('blockParams');
3347
}
3348
if (this.useDepths) {
3349
programParams.push('depths');
3350
}
3351
3352
return 'this.program(' + programParams.join(', ') + ')';
3353
},
3354
3355
useRegister: function(name) {
3356
if(!this.registers[name]) {
3357
this.registers[name] = true;
3358
this.registers.list.push(name);
3359
}
3360
},
3361
3362
push: function(expr) {
3363
if (!(expr instanceof Literal)) {
3364
expr = this.source.wrap(expr);
3365
}
3366
3367
this.inlineStack.push(expr);
3368
return expr;
3369
},
3370
3371
pushStackLiteral: function(item) {
3372
this.push(new Literal(item));
3373
},
3374
3375
pushSource: function(source) {
3376
if (this.pendingContent) {
3377
this.source.push(
3378
this.appendToBuffer(this.source.quotedString(this.pendingContent), this.pendingLocation));
3379
this.pendingContent = undefined;
3380
}
3381
3382
if (source) {
3383
this.source.push(source);
3384
}
3385
},
3386
3387
replaceStack: function(callback) {
3388
var prefix = ['('],
3389
stack,
3390
createdStack,
3391
usedLiteral;
3392
3393
/* istanbul ignore next */
3394
if (!this.isInline()) {
3395
throw new Exception('replaceStack on non-inline');
3396
}
3397
3398
// We want to merge the inline statement into the replacement statement via ','
3399
var top = this.popStack(true);
3400
3401
if (top instanceof Literal) {
3402
// Literals do not need to be inlined
3403
stack = [top.value];
3404
prefix = ['(', stack];
3405
usedLiteral = true;
3406
} else {
3407
// Get or create the current stack name for use by the inline
3408
createdStack = true;
3409
var name = this.incrStack();
3410
3411
prefix = ['((', this.push(name), ' = ', top, ')'];
3412
stack = this.topStack();
3413
}
3414
3415
var item = callback.call(this, stack);
3416
3417
if (!usedLiteral) {
3418
this.popStack();
3419
}
3420
if (createdStack) {
3421
this.stackSlot--;
3422
}
3423
this.push(prefix.concat(item, ')'));
3424
},
3425
3426
incrStack: function() {
3427
this.stackSlot++;
3428
if(this.stackSlot > this.stackVars.length) { this.stackVars.push("stack" + this.stackSlot); }
3429
return this.topStackName();
3430
},
3431
topStackName: function() {
3432
return "stack" + this.stackSlot;
3433
},
3434
flushInline: function() {
3435
var inlineStack = this.inlineStack;
3436
this.inlineStack = [];
3437
for (var i = 0, len = inlineStack.length; i < len; i++) {
3438
var entry = inlineStack[i];
3439
/* istanbul ignore if */
3440
if (entry instanceof Literal) {
3441
this.compileStack.push(entry);
3442
} else {
3443
var stack = this.incrStack();
3444
this.pushSource([stack, ' = ', entry, ';']);
3445
this.compileStack.push(stack);
3446
}
3447
}
3448
},
3449
isInline: function() {
3450
return this.inlineStack.length;
3451
},
3452
3453
popStack: function(wrapped) {
3454
var inline = this.isInline(),
3455
item = (inline ? this.inlineStack : this.compileStack).pop();
3456
3457
if (!wrapped && (item instanceof Literal)) {
3458
return item.value;
3459
} else {
3460
if (!inline) {
3461
/* istanbul ignore next */
3462
if (!this.stackSlot) {
3463
throw new Exception('Invalid stack pop');
3464
}
3465
this.stackSlot--;
3466
}
3467
return item;
3468
}
3469
},
3470
3471
topStack: function() {
3472
var stack = (this.isInline() ? this.inlineStack : this.compileStack),
3473
item = stack[stack.length - 1];
3474
3475
/* istanbul ignore if */
3476
if (item instanceof Literal) {
3477
return item.value;
3478
} else {
3479
return item;
3480
}
3481
},
3482
3483
contextName: function(context) {
3484
if (this.useDepths && context) {
3485
return 'depths[' + context + ']';
3486
} else {
3487
return 'depth' + context;
3488
}
3489
},
3490
3491
quotedString: function(str) {
3492
return this.source.quotedString(str);
3493
},
3494
3495
objectLiteral: function(obj) {
3496
return this.source.objectLiteral(obj);
3497
},
3498
3499
aliasable: function(name) {
3500
var ret = this.aliases[name];
3501
if (ret) {
3502
ret.referenceCount++;
3503
return ret;
3504
}
3505
3506
ret = this.aliases[name] = this.source.wrap(name);
3507
ret.aliasable = true;
3508
ret.referenceCount = 1;
3509
3510
return ret;
3511
},
3512
3513
setupHelper: function(paramSize, name, blockHelper) {
3514
var params = [],
3515
paramsInit = this.setupHelperArgs(name, paramSize, params, blockHelper);
3516
var foundHelper = this.nameLookup('helpers', name, 'helper');
3517
3518
return {
3519
params: params,
3520
paramsInit: paramsInit,
3521
name: foundHelper,
3522
callParams: [this.contextName(0)].concat(params)
3523
};
3524
},
3525
3526
setupParams: function(helper, paramSize, params) {
3527
var options = {}, contexts = [], types = [], ids = [], param;
3528
3529
options.name = this.quotedString(helper);
3530
options.hash = this.popStack();
3531
3532
if (this.trackIds) {
3533
options.hashIds = this.popStack();
3534
}
3535
if (this.stringParams) {
3536
options.hashTypes = this.popStack();
3537
options.hashContexts = this.popStack();
3538
}
3539
3540
var inverse = this.popStack(),
3541
program = this.popStack();
3542
3543
// Avoid setting fn and inverse if neither are set. This allows
3544
// helpers to do a check for `if (options.fn)`
3545
if (program || inverse) {
3546
options.fn = program || 'this.noop';
3547
options.inverse = inverse || 'this.noop';
3548
}
3549
3550
// The parameters go on to the stack in order (making sure that they are evaluated in order)
3551
// so we need to pop them off the stack in reverse order
3552
var i = paramSize;
3553
while (i--) {
3554
param = this.popStack();
3555
params[i] = param;
3556
3557
if (this.trackIds) {
3558
ids[i] = this.popStack();
3559
}
3560
if (this.stringParams) {
3561
types[i] = this.popStack();
3562
contexts[i] = this.popStack();
3563
}
3564
}
3565
3566
if (this.trackIds) {
3567
options.ids = this.source.generateArray(ids);
3568
}
3569
if (this.stringParams) {
3570
options.types = this.source.generateArray(types);
3571
options.contexts = this.source.generateArray(contexts);
3572
}
3573
3574
if (this.options.data) {
3575
options.data = 'data';
3576
}
3577
if (this.useBlockParams) {
3578
options.blockParams = 'blockParams';
3579
}
3580
return options;
3581
},
3582
3583
setupHelperArgs: function(helper, paramSize, params, useRegister) {
3584
var options = this.setupParams(helper, paramSize, params, true);
3585
options = this.objectLiteral(options);
3586
if (useRegister) {
3587
this.useRegister('options');
3588
params.push('options');
3589
return ['options=', options];
3590
} else {
3591
params.push(options);
3592
return '';
3593
}
3594
}
3595
};
3596
3597
3598
var reservedWords = (
3599
"break else new var" +
3600
" case finally return void" +
3601
" catch for switch while" +
3602
" continue function this with" +
3603
" default if throw" +
3604
" delete in try" +
3605
" do instanceof typeof" +
3606
" abstract enum int short" +
3607
" boolean export interface static" +
3608
" byte extends long super" +
3609
" char final native synchronized" +
3610
" class float package throws" +
3611
" const goto private transient" +
3612
" debugger implements protected volatile" +
3613
" double import public let yield await" +
3614
" null true false"
3615
).split(" ");
3616
3617
var compilerWords = JavaScriptCompiler.RESERVED_WORDS = {};
3618
3619
for(var i=0, l=reservedWords.length; i<l; i++) {
3620
compilerWords[reservedWords[i]] = true;
3621
}
3622
3623
JavaScriptCompiler.isValidJavaScriptVariableName = function(name) {
3624
return !JavaScriptCompiler.RESERVED_WORDS[name] && /^[a-zA-Z_$][0-9a-zA-Z_$]*$/.test(name);
3625
};
3626
3627
function strictLookup(requireTerminal, compiler, parts, type) {
3628
var stack = compiler.popStack();
3629
3630
var i = 0,
3631
len = parts.length;
3632
if (requireTerminal) {
3633
len--;
3634
}
3635
3636
for (; i < len; i++) {
3637
stack = compiler.nameLookup(stack, parts[i], type);
3638
}
3639
3640
if (requireTerminal) {
3641
return [compiler.aliasable('this.strict'), '(', stack, ', ', compiler.quotedString(parts[i]), ')'];
3642
} else {
3643
return stack;
3644
}
3645
}
3646
3647
__exports__["default"] = JavaScriptCompiler;
3648
});
3649
define(
3650
'handlebars',["./handlebars.runtime","./handlebars/compiler/ast","./handlebars/compiler/base","./handlebars/compiler/compiler","./handlebars/compiler/javascript-compiler","exports"],
3651
function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __exports__) {
3652
3653
/*globals Handlebars: true */
3654
var Handlebars = __dependency1__["default"];
3655
3656
// Compiler imports
3657
var AST = __dependency2__["default"];
3658
var Parser = __dependency3__.parser;
3659
var parse = __dependency3__.parse;
3660
var Compiler = __dependency4__.Compiler;
3661
var compile = __dependency4__.compile;
3662
var precompile = __dependency4__.precompile;
3663
var JavaScriptCompiler = __dependency5__["default"];
3664
3665
var _create = Handlebars.create;
3666
var create = function() {
3667
var hb = _create();
3668
3669
hb.compile = function(input, options) {
3670
return compile(input, options, hb);
3671
};
3672
hb.precompile = function (input, options) {
3673
return precompile(input, options, hb);
3674
};
3675
3676
hb.AST = AST;
3677
hb.Compiler = Compiler;
3678
hb.JavaScriptCompiler = JavaScriptCompiler;
3679
hb.Parser = Parser;
3680
hb.parse = parse;
3681
3682
return hb;
3683
};
3684
3685
Handlebars = create();
3686
Handlebars.create = create;
3687
3688
/*jshint -W040 */
3689
/* istanbul ignore next */
3690
var root = typeof global !== 'undefined' ? global : window,
3691
$Handlebars = root.Handlebars;
3692
/* istanbul ignore next */
3693
Handlebars.noConflict = function() {
3694
if (root.Handlebars === Handlebars) {
3695
root.Handlebars = $Handlebars;
3696
}
3697
};
3698
3699
Handlebars['default'] = Handlebars;
3700
3701
__exports__["default"] = Handlebars;
3702
});
3703
3704