Make the analysis page more useful
[WebKit-https.git] / Websites / perf.webkit.org / public / v2 / js / handlebars.js
1 /*!
2
3  handlebars v1.3.0
4
5 Copyright (C) 2011 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 /* exported Handlebars */
28 var Handlebars = (function() {
29 // handlebars/safe-string.js
30 var __module4__ = (function() {
31   "use strict";
32   var __exports__;
33   // Build out our basic SafeString type
34   function SafeString(string) {
35     this.string = string;
36   }
37
38   SafeString.prototype.toString = function() {
39     return "" + this.string;
40   };
41
42   __exports__ = SafeString;
43   return __exports__;
44 })();
45
46 // handlebars/utils.js
47 var __module3__ = (function(__dependency1__) {
48   "use strict";
49   var __exports__ = {};
50   /*jshint -W004 */
51   var SafeString = __dependency1__;
52
53   var escape = {
54     "&": "&",
55     "<": "&lt;",
56     ">": "&gt;",
57     '"': "&quot;",
58     "'": "&#x27;",
59     "`": "&#x60;"
60   };
61
62   var badChars = /[&<>"'`]/g;
63   var possible = /[&<>"'`]/;
64
65   function escapeChar(chr) {
66     return escape[chr] || "&amp;";
67   }
68
69   function extend(obj, value) {
70     for(var key in value) {
71       if(Object.prototype.hasOwnProperty.call(value, key)) {
72         obj[key] = value[key];
73       }
74     }
75   }
76
77   __exports__.extend = extend;var toString = Object.prototype.toString;
78   __exports__.toString = toString;
79   // Sourced from lodash
80   // https://github.com/bestiejs/lodash/blob/master/LICENSE.txt
81   var isFunction = function(value) {
82     return typeof value === 'function';
83   };
84   // fallback for older versions of Chrome and Safari
85   if (isFunction(/x/)) {
86     isFunction = function(value) {
87       return typeof value === 'function' && toString.call(value) === '[object Function]';
88     };
89   }
90   var isFunction;
91   __exports__.isFunction = isFunction;
92   var isArray = Array.isArray || function(value) {
93     return (value && typeof value === 'object') ? toString.call(value) === '[object Array]' : false;
94   };
95   __exports__.isArray = isArray;
96
97   function escapeExpression(string) {
98     // don't escape SafeStrings, since they're already safe
99     if (string instanceof SafeString) {
100       return string.toString();
101     } else if (!string && string !== 0) {
102       return "";
103     }
104
105     // Force a string conversion as this will be done by the append regardless and
106     // the regex test will do this transparently behind the scenes, causing issues if
107     // an object's to string has escaped characters in it.
108     string = "" + string;
109
110     if(!possible.test(string)) { return string; }
111     return string.replace(badChars, escapeChar);
112   }
113
114   __exports__.escapeExpression = escapeExpression;function isEmpty(value) {
115     if (!value && value !== 0) {
116       return true;
117     } else if (isArray(value) && value.length === 0) {
118       return true;
119     } else {
120       return false;
121     }
122   }
123
124   __exports__.isEmpty = isEmpty;
125   return __exports__;
126 })(__module4__);
127
128 // handlebars/exception.js
129 var __module5__ = (function() {
130   "use strict";
131   var __exports__;
132
133   var errorProps = ['description', 'fileName', 'lineNumber', 'message', 'name', 'number', 'stack'];
134
135   function Exception(message, node) {
136     var line;
137     if (node && node.firstLine) {
138       line = node.firstLine;
139
140       message += ' - ' + line + ':' + node.firstColumn;
141     }
142
143     var tmp = Error.prototype.constructor.call(this, message);
144
145     // Unfortunately errors are not enumerable in Chrome (at least), so `for prop in tmp` doesn't work.
146     for (var idx = 0; idx < errorProps.length; idx++) {
147       this[errorProps[idx]] = tmp[errorProps[idx]];
148     }
149
150     if (line) {
151       this.lineNumber = line;
152       this.column = node.firstColumn;
153     }
154   }
155
156   Exception.prototype = new Error();
157
158   __exports__ = Exception;
159   return __exports__;
160 })();
161
162 // handlebars/base.js
163 var __module2__ = (function(__dependency1__, __dependency2__) {
164   "use strict";
165   var __exports__ = {};
166   var Utils = __dependency1__;
167   var Exception = __dependency2__;
168
169   var VERSION = "1.3.0";
170   __exports__.VERSION = VERSION;var COMPILER_REVISION = 4;
171   __exports__.COMPILER_REVISION = COMPILER_REVISION;
172   var REVISION_CHANGES = {
173     1: '<= 1.0.rc.2', // 1.0.rc.2 is actually rev2 but doesn't report it
174     2: '== 1.0.0-rc.3',
175     3: '== 1.0.0-rc.4',
176     4: '>= 1.0.0'
177   };
178   __exports__.REVISION_CHANGES = REVISION_CHANGES;
179   var isArray = Utils.isArray,
180       isFunction = Utils.isFunction,
181       toString = Utils.toString,
182       objectType = '[object Object]';
183
184   function HandlebarsEnvironment(helpers, partials) {
185     this.helpers = helpers || {};
186     this.partials = partials || {};
187
188     registerDefaultHelpers(this);
189   }
190
191   __exports__.HandlebarsEnvironment = HandlebarsEnvironment;HandlebarsEnvironment.prototype = {
192     constructor: HandlebarsEnvironment,
193
194     logger: logger,
195     log: log,
196
197     registerHelper: function(name, fn, inverse) {
198       if (toString.call(name) === objectType) {
199         if (inverse || fn) { throw new Exception('Arg not supported with multiple helpers'); }
200         Utils.extend(this.helpers, name);
201       } else {
202         if (inverse) { fn.not = inverse; }
203         this.helpers[name] = fn;
204       }
205     },
206
207     registerPartial: function(name, str) {
208       if (toString.call(name) === objectType) {
209         Utils.extend(this.partials,  name);
210       } else {
211         this.partials[name] = str;
212       }
213     }
214   };
215
216   function registerDefaultHelpers(instance) {
217     instance.registerHelper('helperMissing', function(arg) {
218       if(arguments.length === 2) {
219         return undefined;
220       } else {
221         throw new Exception("Missing helper: '" + arg + "'");
222       }
223     });
224
225     instance.registerHelper('blockHelperMissing', function(context, options) {
226       var inverse = options.inverse || function() {}, fn = options.fn;
227
228       if (isFunction(context)) { context = context.call(this); }
229
230       if(context === true) {
231         return fn(this);
232       } else if(context === false || context == null) {
233         return inverse(this);
234       } else if (isArray(context)) {
235         if(context.length > 0) {
236           return instance.helpers.each(context, options);
237         } else {
238           return inverse(this);
239         }
240       } else {
241         return fn(context);
242       }
243     });
244
245     instance.registerHelper('each', function(context, options) {
246       var fn = options.fn, inverse = options.inverse;
247       var i = 0, ret = "", data;
248
249       if (isFunction(context)) { context = context.call(this); }
250
251       if (options.data) {
252         data = createFrame(options.data);
253       }
254
255       if(context && typeof context === 'object') {
256         if (isArray(context)) {
257           for(var j = context.length; i<j; i++) {
258             if (data) {
259               data.index = i;
260               data.first = (i === 0);
261               data.last  = (i === (context.length-1));
262             }
263             ret = ret + fn(context[i], { data: data });
264           }
265         } else {
266           for(var key in context) {
267             if(context.hasOwnProperty(key)) {
268               if(data) { 
269                 data.key = key; 
270                 data.index = i;
271                 data.first = (i === 0);
272               }
273               ret = ret + fn(context[key], {data: data});
274               i++;
275             }
276           }
277         }
278       }
279
280       if(i === 0){
281         ret = inverse(this);
282       }
283
284       return ret;
285     });
286
287     instance.registerHelper('if', function(conditional, options) {
288       if (isFunction(conditional)) { conditional = conditional.call(this); }
289
290       // Default behavior is to render the positive path if the value is truthy and not empty.
291       // The `includeZero` option may be set to treat the condtional as purely not empty based on the
292       // behavior of isEmpty. Effectively this determines if 0 is handled by the positive path or negative.
293       if ((!options.hash.includeZero && !conditional) || Utils.isEmpty(conditional)) {
294         return options.inverse(this);
295       } else {
296         return options.fn(this);
297       }
298     });
299
300     instance.registerHelper('unless', function(conditional, options) {
301       return instance.helpers['if'].call(this, conditional, {fn: options.inverse, inverse: options.fn, hash: options.hash});
302     });
303
304     instance.registerHelper('with', function(context, options) {
305       if (isFunction(context)) { context = context.call(this); }
306
307       if (!Utils.isEmpty(context)) return options.fn(context);
308     });
309
310     instance.registerHelper('log', function(context, options) {
311       var level = options.data && options.data.level != null ? parseInt(options.data.level, 10) : 1;
312       instance.log(level, context);
313     });
314   }
315
316   var logger = {
317     methodMap: { 0: 'debug', 1: 'info', 2: 'warn', 3: 'error' },
318
319     // State enum
320     DEBUG: 0,
321     INFO: 1,
322     WARN: 2,
323     ERROR: 3,
324     level: 3,
325
326     // can be overridden in the host environment
327     log: function(level, obj) {
328       if (logger.level <= level) {
329         var method = logger.methodMap[level];
330         if (typeof console !== 'undefined' && console[method]) {
331           console[method].call(console, obj);
332         }
333       }
334     }
335   };
336   __exports__.logger = logger;
337   function log(level, obj) { logger.log(level, obj); }
338
339   __exports__.log = log;var createFrame = function(object) {
340     var obj = {};
341     Utils.extend(obj, object);
342     return obj;
343   };
344   __exports__.createFrame = createFrame;
345   return __exports__;
346 })(__module3__, __module5__);
347
348 // handlebars/runtime.js
349 var __module6__ = (function(__dependency1__, __dependency2__, __dependency3__) {
350   "use strict";
351   var __exports__ = {};
352   var Utils = __dependency1__;
353   var Exception = __dependency2__;
354   var COMPILER_REVISION = __dependency3__.COMPILER_REVISION;
355   var REVISION_CHANGES = __dependency3__.REVISION_CHANGES;
356
357   function checkRevision(compilerInfo) {
358     var compilerRevision = compilerInfo && compilerInfo[0] || 1,
359         currentRevision = COMPILER_REVISION;
360
361     if (compilerRevision !== currentRevision) {
362       if (compilerRevision < currentRevision) {
363         var runtimeVersions = REVISION_CHANGES[currentRevision],
364             compilerVersions = REVISION_CHANGES[compilerRevision];
365         throw new Exception("Template was precompiled with an older version of Handlebars than the current runtime. "+
366               "Please update your precompiler to a newer version ("+runtimeVersions+") or downgrade your runtime to an older version ("+compilerVersions+").");
367       } else {
368         // Use the embedded version info since the runtime doesn't know about this revision yet
369         throw new Exception("Template was precompiled with a newer version of Handlebars than the current runtime. "+
370               "Please update your runtime to a newer version ("+compilerInfo[1]+").");
371       }
372     }
373   }
374
375   __exports__.checkRevision = checkRevision;// TODO: Remove this line and break up compilePartial
376
377   function template(templateSpec, env) {
378     if (!env) {
379       throw new Exception("No environment passed to template");
380     }
381
382     // Note: Using env.VM references rather than local var references throughout this section to allow
383     // for external users to override these as psuedo-supported APIs.
384     var invokePartialWrapper = function(partial, name, context, helpers, partials, data) {
385       var result = env.VM.invokePartial.apply(this, arguments);
386       if (result != null) { return result; }
387
388       if (env.compile) {
389         var options = { helpers: helpers, partials: partials, data: data };
390         partials[name] = env.compile(partial, { data: data !== undefined }, env);
391         return partials[name](context, options);
392       } else {
393         throw new Exception("The partial " + name + " could not be compiled when running in runtime-only mode");
394       }
395     };
396
397     // Just add water
398     var container = {
399       escapeExpression: Utils.escapeExpression,
400       invokePartial: invokePartialWrapper,
401       programs: [],
402       program: function(i, fn, data) {
403         var programWrapper = this.programs[i];
404         if(data) {
405           programWrapper = program(i, fn, data);
406         } else if (!programWrapper) {
407           programWrapper = this.programs[i] = program(i, fn);
408         }
409         return programWrapper;
410       },
411       merge: function(param, common) {
412         var ret = param || common;
413
414         if (param && common && (param !== common)) {
415           ret = {};
416           Utils.extend(ret, common);
417           Utils.extend(ret, param);
418         }
419         return ret;
420       },
421       programWithDepth: env.VM.programWithDepth,
422       noop: env.VM.noop,
423       compilerInfo: null
424     };
425
426     return function(context, options) {
427       options = options || {};
428       var namespace = options.partial ? options : env,
429           helpers,
430           partials;
431
432       if (!options.partial) {
433         helpers = options.helpers;
434         partials = options.partials;
435       }
436       var result = templateSpec.call(
437             container,
438             namespace, context,
439             helpers,
440             partials,
441             options.data);
442
443       if (!options.partial) {
444         env.VM.checkRevision(container.compilerInfo);
445       }
446
447       return result;
448     };
449   }
450
451   __exports__.template = template;function programWithDepth(i, fn, data /*, $depth */) {
452     var args = Array.prototype.slice.call(arguments, 3);
453
454     var prog = function(context, options) {
455       options = options || {};
456
457       return fn.apply(this, [context, options.data || data].concat(args));
458     };
459     prog.program = i;
460     prog.depth = args.length;
461     return prog;
462   }
463
464   __exports__.programWithDepth = programWithDepth;function program(i, fn, data) {
465     var prog = function(context, options) {
466       options = options || {};
467
468       return fn(context, options.data || data);
469     };
470     prog.program = i;
471     prog.depth = 0;
472     return prog;
473   }
474
475   __exports__.program = program;function invokePartial(partial, name, context, helpers, partials, data) {
476     var options = { partial: true, helpers: helpers, partials: partials, data: data };
477
478     if(partial === undefined) {
479       throw new Exception("The partial " + name + " could not be found");
480     } else if(partial instanceof Function) {
481       return partial(context, options);
482     }
483   }
484
485   __exports__.invokePartial = invokePartial;function noop() { return ""; }
486
487   __exports__.noop = noop;
488   return __exports__;
489 })(__module3__, __module5__, __module2__);
490
491 // handlebars.runtime.js
492 var __module1__ = (function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__) {
493   "use strict";
494   var __exports__;
495   /*globals Handlebars: true */
496   var base = __dependency1__;
497
498   // Each of these augment the Handlebars object. No need to setup here.
499   // (This is done to easily share code between commonjs and browse envs)
500   var SafeString = __dependency2__;
501   var Exception = __dependency3__;
502   var Utils = __dependency4__;
503   var runtime = __dependency5__;
504
505   // For compatibility and usage outside of module systems, make the Handlebars object a namespace
506   var create = function() {
507     var hb = new base.HandlebarsEnvironment();
508
509     Utils.extend(hb, base);
510     hb.SafeString = SafeString;
511     hb.Exception = Exception;
512     hb.Utils = Utils;
513
514     hb.VM = runtime;
515     hb.template = function(spec) {
516       return runtime.template(spec, hb);
517     };
518
519     return hb;
520   };
521
522   var Handlebars = create();
523   Handlebars.create = create;
524
525   __exports__ = Handlebars;
526   return __exports__;
527 })(__module2__, __module4__, __module5__, __module3__, __module6__);
528
529 // handlebars/compiler/ast.js
530 var __module7__ = (function(__dependency1__) {
531   "use strict";
532   var __exports__;
533   var Exception = __dependency1__;
534
535   function LocationInfo(locInfo){
536     locInfo = locInfo || {};
537     this.firstLine   = locInfo.first_line;
538     this.firstColumn = locInfo.first_column;
539     this.lastColumn  = locInfo.last_column;
540     this.lastLine    = locInfo.last_line;
541   }
542
543   var AST = {
544     ProgramNode: function(statements, inverseStrip, inverse, locInfo) {
545       var inverseLocationInfo, firstInverseNode;
546       if (arguments.length === 3) {
547         locInfo = inverse;
548         inverse = null;
549       } else if (arguments.length === 2) {
550         locInfo = inverseStrip;
551         inverseStrip = null;
552       }
553
554       LocationInfo.call(this, locInfo);
555       this.type = "program";
556       this.statements = statements;
557       this.strip = {};
558
559       if(inverse) {
560         firstInverseNode = inverse[0];
561         if (firstInverseNode) {
562           inverseLocationInfo = {
563             first_line: firstInverseNode.firstLine,
564             last_line: firstInverseNode.lastLine,
565             last_column: firstInverseNode.lastColumn,
566             first_column: firstInverseNode.firstColumn
567           };
568           this.inverse = new AST.ProgramNode(inverse, inverseStrip, inverseLocationInfo);
569         } else {
570           this.inverse = new AST.ProgramNode(inverse, inverseStrip);
571         }
572         this.strip.right = inverseStrip.left;
573       } else if (inverseStrip) {
574         this.strip.left = inverseStrip.right;
575       }
576     },
577
578     MustacheNode: function(rawParams, hash, open, strip, locInfo) {
579       LocationInfo.call(this, locInfo);
580       this.type = "mustache";
581       this.strip = strip;
582
583       // Open may be a string parsed from the parser or a passed boolean flag
584       if (open != null && open.charAt) {
585         // Must use charAt to support IE pre-10
586         var escapeFlag = open.charAt(3) || open.charAt(2);
587         this.escaped = escapeFlag !== '{' && escapeFlag !== '&';
588       } else {
589         this.escaped = !!open;
590       }
591
592       if (rawParams instanceof AST.SexprNode) {
593         this.sexpr = rawParams;
594       } else {
595         // Support old AST API
596         this.sexpr = new AST.SexprNode(rawParams, hash);
597       }
598
599       this.sexpr.isRoot = true;
600
601       // Support old AST API that stored this info in MustacheNode
602       this.id = this.sexpr.id;
603       this.params = this.sexpr.params;
604       this.hash = this.sexpr.hash;
605       this.eligibleHelper = this.sexpr.eligibleHelper;
606       this.isHelper = this.sexpr.isHelper;
607     },
608
609     SexprNode: function(rawParams, hash, locInfo) {
610       LocationInfo.call(this, locInfo);
611
612       this.type = "sexpr";
613       this.hash = hash;
614
615       var id = this.id = rawParams[0];
616       var params = this.params = rawParams.slice(1);
617
618       // a mustache is an eligible helper if:
619       // * its id is simple (a single part, not `this` or `..`)
620       var eligibleHelper = this.eligibleHelper = id.isSimple;
621
622       // a mustache is definitely a helper if:
623       // * it is an eligible helper, and
624       // * it has at least one parameter or hash segment
625       this.isHelper = eligibleHelper && (params.length || hash);
626
627       // if a mustache is an eligible helper but not a definite
628       // helper, it is ambiguous, and will be resolved in a later
629       // pass or at runtime.
630     },
631
632     PartialNode: function(partialName, context, strip, locInfo) {
633       LocationInfo.call(this, locInfo);
634       this.type         = "partial";
635       this.partialName  = partialName;
636       this.context      = context;
637       this.strip = strip;
638     },
639
640     BlockNode: function(mustache, program, inverse, close, locInfo) {
641       LocationInfo.call(this, locInfo);
642
643       if(mustache.sexpr.id.original !== close.path.original) {
644         throw new Exception(mustache.sexpr.id.original + " doesn't match " + close.path.original, this);
645       }
646
647       this.type = 'block';
648       this.mustache = mustache;
649       this.program  = program;
650       this.inverse  = inverse;
651
652       this.strip = {
653         left: mustache.strip.left,
654         right: close.strip.right
655       };
656
657       (program || inverse).strip.left = mustache.strip.right;
658       (inverse || program).strip.right = close.strip.left;
659
660       if (inverse && !program) {
661         this.isInverse = true;
662       }
663     },
664
665     ContentNode: function(string, locInfo) {
666       LocationInfo.call(this, locInfo);
667       this.type = "content";
668       this.string = string;
669     },
670
671     HashNode: function(pairs, locInfo) {
672       LocationInfo.call(this, locInfo);
673       this.type = "hash";
674       this.pairs = pairs;
675     },
676
677     IdNode: function(parts, locInfo) {
678       LocationInfo.call(this, locInfo);
679       this.type = "ID";
680
681       var original = "",
682           dig = [],
683           depth = 0;
684
685       for(var i=0,l=parts.length; i<l; i++) {
686         var part = parts[i].part;
687         original += (parts[i].separator || '') + part;
688
689         if (part === ".." || part === "." || part === "this") {
690           if (dig.length > 0) {
691             throw new Exception("Invalid path: " + original, this);
692           } else if (part === "..") {
693             depth++;
694           } else {
695             this.isScoped = true;
696           }
697         } else {
698           dig.push(part);
699         }
700       }
701
702       this.original = original;
703       this.parts    = dig;
704       this.string   = dig.join('.');
705       this.depth    = depth;
706
707       // an ID is simple if it only has one part, and that part is not
708       // `..` or `this`.
709       this.isSimple = parts.length === 1 && !this.isScoped && depth === 0;
710
711       this.stringModeValue = this.string;
712     },
713
714     PartialNameNode: function(name, locInfo) {
715       LocationInfo.call(this, locInfo);
716       this.type = "PARTIAL_NAME";
717       this.name = name.original;
718     },
719
720     DataNode: function(id, locInfo) {
721       LocationInfo.call(this, locInfo);
722       this.type = "DATA";
723       this.id = id;
724     },
725
726     StringNode: function(string, locInfo) {
727       LocationInfo.call(this, locInfo);
728       this.type = "STRING";
729       this.original =
730         this.string =
731         this.stringModeValue = string;
732     },
733
734     IntegerNode: function(integer, locInfo) {
735       LocationInfo.call(this, locInfo);
736       this.type = "INTEGER";
737       this.original =
738         this.integer = integer;
739       this.stringModeValue = Number(integer);
740     },
741
742     BooleanNode: function(bool, locInfo) {
743       LocationInfo.call(this, locInfo);
744       this.type = "BOOLEAN";
745       this.bool = bool;
746       this.stringModeValue = bool === "true";
747     },
748
749     CommentNode: function(comment, locInfo) {
750       LocationInfo.call(this, locInfo);
751       this.type = "comment";
752       this.comment = comment;
753     }
754   };
755
756   // Must be exported as an object rather than the root of the module as the jison lexer
757   // most modify the object to operate properly.
758   __exports__ = AST;
759   return __exports__;
760 })(__module5__);
761
762 // handlebars/compiler/parser.js
763 var __module9__ = (function() {
764   "use strict";
765   var __exports__;
766   /* jshint ignore:start */
767   /* Jison generated parser */
768   var handlebars = (function(){
769   var parser = {trace: function trace() { },
770   yy: {},
771   symbols_: {"error":2,"root":3,"statements":4,"EOF":5,"program":6,"simpleInverse":7,"statement":8,"openInverse":9,"closeBlock":10,"openBlock":11,"mustache":12,"partial":13,"CONTENT":14,"COMMENT":15,"OPEN_BLOCK":16,"sexpr":17,"CLOSE":18,"OPEN_INVERSE":19,"OPEN_ENDBLOCK":20,"path":21,"OPEN":22,"OPEN_UNESCAPED":23,"CLOSE_UNESCAPED":24,"OPEN_PARTIAL":25,"partialName":26,"partial_option0":27,"sexpr_repetition0":28,"sexpr_option0":29,"dataName":30,"param":31,"STRING":32,"INTEGER":33,"BOOLEAN":34,"OPEN_SEXPR":35,"CLOSE_SEXPR":36,"hash":37,"hash_repetition_plus0":38,"hashSegment":39,"ID":40,"EQUALS":41,"DATA":42,"pathSegments":43,"SEP":44,"$accept":0,"$end":1},
772   terminals_: {2:"error",5:"EOF",14:"CONTENT",15:"COMMENT",16:"OPEN_BLOCK",18:"CLOSE",19:"OPEN_INVERSE",20:"OPEN_ENDBLOCK",22:"OPEN",23:"OPEN_UNESCAPED",24:"CLOSE_UNESCAPED",25:"OPEN_PARTIAL",32:"STRING",33:"INTEGER",34:"BOOLEAN",35:"OPEN_SEXPR",36:"CLOSE_SEXPR",40:"ID",41:"EQUALS",42:"DATA",44:"SEP"},
773   productions_: [0,[3,2],[3,1],[6,2],[6,3],[6,2],[6,1],[6,1],[6,0],[4,1],[4,2],[8,3],[8,3],[8,1],[8,1],[8,1],[8,1],[11,3],[9,3],[10,3],[12,3],[12,3],[13,4],[7,2],[17,3],[17,1],[31,1],[31,1],[31,1],[31,1],[31,1],[31,3],[37,1],[39,3],[26,1],[26,1],[26,1],[30,2],[21,1],[43,3],[43,1],[27,0],[27,1],[28,0],[28,2],[29,0],[29,1],[38,1],[38,2]],
774   performAction: function anonymous(yytext,yyleng,yylineno,yy,yystate,$$,_$) {
775
776   var $0 = $$.length - 1;
777   switch (yystate) {
778   case 1: return new yy.ProgramNode($$[$0-1], this._$); 
779   break;
780   case 2: return new yy.ProgramNode([], this._$); 
781   break;
782   case 3:this.$ = new yy.ProgramNode([], $$[$0-1], $$[$0], this._$);
783   break;
784   case 4:this.$ = new yy.ProgramNode($$[$0-2], $$[$0-1], $$[$0], this._$);
785   break;
786   case 5:this.$ = new yy.ProgramNode($$[$0-1], $$[$0], [], this._$);
787   break;
788   case 6:this.$ = new yy.ProgramNode($$[$0], this._$);
789   break;
790   case 7:this.$ = new yy.ProgramNode([], this._$);
791   break;
792   case 8:this.$ = new yy.ProgramNode([], this._$);
793   break;
794   case 9:this.$ = [$$[$0]];
795   break;
796   case 10: $$[$0-1].push($$[$0]); this.$ = $$[$0-1]; 
797   break;
798   case 11:this.$ = new yy.BlockNode($$[$0-2], $$[$0-1].inverse, $$[$0-1], $$[$0], this._$);
799   break;
800   case 12:this.$ = new yy.BlockNode($$[$0-2], $$[$0-1], $$[$0-1].inverse, $$[$0], this._$);
801   break;
802   case 13:this.$ = $$[$0];
803   break;
804   case 14:this.$ = $$[$0];
805   break;
806   case 15:this.$ = new yy.ContentNode($$[$0], this._$);
807   break;
808   case 16:this.$ = new yy.CommentNode($$[$0], this._$);
809   break;
810   case 17:this.$ = new yy.MustacheNode($$[$0-1], null, $$[$0-2], stripFlags($$[$0-2], $$[$0]), this._$);
811   break;
812   case 18:this.$ = new yy.MustacheNode($$[$0-1], null, $$[$0-2], stripFlags($$[$0-2], $$[$0]), this._$);
813   break;
814   case 19:this.$ = {path: $$[$0-1], strip: stripFlags($$[$0-2], $$[$0])};
815   break;
816   case 20:this.$ = new yy.MustacheNode($$[$0-1], null, $$[$0-2], stripFlags($$[$0-2], $$[$0]), this._$);
817   break;
818   case 21:this.$ = new yy.MustacheNode($$[$0-1], null, $$[$0-2], stripFlags($$[$0-2], $$[$0]), this._$);
819   break;
820   case 22:this.$ = new yy.PartialNode($$[$0-2], $$[$0-1], stripFlags($$[$0-3], $$[$0]), this._$);
821   break;
822   case 23:this.$ = stripFlags($$[$0-1], $$[$0]);
823   break;
824   case 24:this.$ = new yy.SexprNode([$$[$0-2]].concat($$[$0-1]), $$[$0], this._$);
825   break;
826   case 25:this.$ = new yy.SexprNode([$$[$0]], null, this._$);
827   break;
828   case 26:this.$ = $$[$0];
829   break;
830   case 27:this.$ = new yy.StringNode($$[$0], this._$);
831   break;
832   case 28:this.$ = new yy.IntegerNode($$[$0], this._$);
833   break;
834   case 29:this.$ = new yy.BooleanNode($$[$0], this._$);
835   break;
836   case 30:this.$ = $$[$0];
837   break;
838   case 31:$$[$0-1].isHelper = true; this.$ = $$[$0-1];
839   break;
840   case 32:this.$ = new yy.HashNode($$[$0], this._$);
841   break;
842   case 33:this.$ = [$$[$0-2], $$[$0]];
843   break;
844   case 34:this.$ = new yy.PartialNameNode($$[$0], this._$);
845   break;
846   case 35:this.$ = new yy.PartialNameNode(new yy.StringNode($$[$0], this._$), this._$);
847   break;
848   case 36:this.$ = new yy.PartialNameNode(new yy.IntegerNode($$[$0], this._$));
849   break;
850   case 37:this.$ = new yy.DataNode($$[$0], this._$);
851   break;
852   case 38:this.$ = new yy.IdNode($$[$0], this._$);
853   break;
854   case 39: $$[$0-2].push({part: $$[$0], separator: $$[$0-1]}); this.$ = $$[$0-2]; 
855   break;
856   case 40:this.$ = [{part: $$[$0]}];
857   break;
858   case 43:this.$ = [];
859   break;
860   case 44:$$[$0-1].push($$[$0]);
861   break;
862   case 47:this.$ = [$$[$0]];
863   break;
864   case 48:$$[$0-1].push($$[$0]);
865   break;
866   }
867   },
868   table: [{3:1,4:2,5:[1,3],8:4,9:5,11:6,12:7,13:8,14:[1,9],15:[1,10],16:[1,12],19:[1,11],22:[1,13],23:[1,14],25:[1,15]},{1:[3]},{5:[1,16],8:17,9:5,11:6,12:7,13:8,14:[1,9],15:[1,10],16:[1,12],19:[1,11],22:[1,13],23:[1,14],25:[1,15]},{1:[2,2]},{5:[2,9],14:[2,9],15:[2,9],16:[2,9],19:[2,9],20:[2,9],22:[2,9],23:[2,9],25:[2,9]},{4:20,6:18,7:19,8:4,9:5,11:6,12:7,13:8,14:[1,9],15:[1,10],16:[1,12],19:[1,21],20:[2,8],22:[1,13],23:[1,14],25:[1,15]},{4:20,6:22,7:19,8:4,9:5,11:6,12:7,13:8,14:[1,9],15:[1,10],16:[1,12],19:[1,21],20:[2,8],22:[1,13],23:[1,14],25:[1,15]},{5:[2,13],14:[2,13],15:[2,13],16:[2,13],19:[2,13],20:[2,13],22:[2,13],23:[2,13],25:[2,13]},{5:[2,14],14:[2,14],15:[2,14],16:[2,14],19:[2,14],20:[2,14],22:[2,14],23:[2,14],25:[2,14]},{5:[2,15],14:[2,15],15:[2,15],16:[2,15],19:[2,15],20:[2,15],22:[2,15],23:[2,15],25:[2,15]},{5:[2,16],14:[2,16],15:[2,16],16:[2,16],19:[2,16],20:[2,16],22:[2,16],23:[2,16],25:[2,16]},{17:23,21:24,30:25,40:[1,28],42:[1,27],43:26},{17:29,21:24,30:25,40:[1,28],42:[1,27],43:26},{17:30,21:24,30:25,40:[1,28],42:[1,27],43:26},{17:31,21:24,30:25,40:[1,28],42:[1,27],43:26},{21:33,26:32,32:[1,34],33:[1,35],40:[1,28],43:26},{1:[2,1]},{5:[2,10],14:[2,10],15:[2,10],16:[2,10],19:[2,10],20:[2,10],22:[2,10],23:[2,10],25:[2,10]},{10:36,20:[1,37]},{4:38,8:4,9:5,11:6,12:7,13:8,14:[1,9],15:[1,10],16:[1,12],19:[1,11],20:[2,7],22:[1,13],23:[1,14],25:[1,15]},{7:39,8:17,9:5,11:6,12:7,13:8,14:[1,9],15:[1,10],16:[1,12],19:[1,21],20:[2,6],22:[1,13],23:[1,14],25:[1,15]},{17:23,18:[1,40],21:24,30:25,40:[1,28],42:[1,27],43:26},{10:41,20:[1,37]},{18:[1,42]},{18:[2,43],24:[2,43],28:43,32:[2,43],33:[2,43],34:[2,43],35:[2,43],36:[2,43],40:[2,43],42:[2,43]},{18:[2,25],24:[2,25],36:[2,25]},{18:[2,38],24:[2,38],32:[2,38],33:[2,38],34:[2,38],35:[2,38],36:[2,38],40:[2,38],42:[2,38],44:[1,44]},{21:45,40:[1,28],43:26},{18:[2,40],24:[2,40],32:[2,40],33:[2,40],34:[2,40],35:[2,40],36:[2,40],40:[2,40],42:[2,40],44:[2,40]},{18:[1,46]},{18:[1,47]},{24:[1,48]},{18:[2,41],21:50,27:49,40:[1,28],43:26},{18:[2,34],40:[2,34]},{18:[2,35],40:[2,35]},{18:[2,36],40:[2,36]},{5:[2,11],14:[2,11],15:[2,11],16:[2,11],19:[2,11],20:[2,11],22:[2,11],23:[2,11],25:[2,11]},{21:51,40:[1,28],43:26},{8:17,9:5,11:6,12:7,13:8,14:[1,9],15:[1,10],16:[1,12],19:[1,11],20:[2,3],22:[1,13],23:[1,14],25:[1,15]},{4:52,8:4,9:5,11:6,12:7,13:8,14:[1,9],15:[1,10],16:[1,12],19:[1,11],20:[2,5],22:[1,13],23:[1,14],25:[1,15]},{14:[2,23],15:[2,23],16:[2,23],19:[2,23],20:[2,23],22:[2,23],23:[2,23],25:[2,23]},{5:[2,12],14:[2,12],15:[2,12],16:[2,12],19:[2,12],20:[2,12],22:[2,12],23:[2,12],25:[2,12]},{14:[2,18],15:[2,18],16:[2,18],19:[2,18],20:[2,18],22:[2,18],23:[2,18],25:[2,18]},{18:[2,45],21:56,24:[2,45],29:53,30:60,31:54,32:[1,57],33:[1,58],34:[1,59],35:[1,61],36:[2,45],37:55,38:62,39:63,40:[1,64],42:[1,27],43:26},{40:[1,65]},{18:[2,37],24:[2,37],32:[2,37],33:[2,37],34:[2,37],35:[2,37],36:[2,37],40:[2,37],42:[2,37]},{14:[2,17],15:[2,17],16:[2,17],19:[2,17],20:[2,17],22:[2,17],23:[2,17],25:[2,17]},{5:[2,20],14:[2,20],15:[2,20],16:[2,20],19:[2,20],20:[2,20],22:[2,20],23:[2,20],25:[2,20]},{5:[2,21],14:[2,21],15:[2,21],16:[2,21],19:[2,21],20:[2,21],22:[2,21],23:[2,21],25:[2,21]},{18:[1,66]},{18:[2,42]},{18:[1,67]},{8:17,9:5,11:6,12:7,13:8,14:[1,9],15:[1,10],16:[1,12],19:[1,11],20:[2,4],22:[1,13],23:[1,14],25:[1,15]},{18:[2,24],24:[2,24],36:[2,24]},{18:[2,44],24:[2,44],32:[2,44],33:[2,44],34:[2,44],35:[2,44],36:[2,44],40:[2,44],42:[2,44]},{18:[2,46],24:[2,46],36:[2,46]},{18:[2,26],24:[2,26],32:[2,26],33:[2,26],34:[2,26],35:[2,26],36:[2,26],40:[2,26],42:[2,26]},{18:[2,27],24:[2,27],32:[2,27],33:[2,27],34:[2,27],35:[2,27],36:[2,27],40:[2,27],42:[2,27]},{18:[2,28],24:[2,28],32:[2,28],33:[2,28],34:[2,28],35:[2,28],36:[2,28],40:[2,28],42:[2,28]},{18:[2,29],24:[2,29],32:[2,29],33:[2,29],34:[2,29],35:[2,29],36:[2,29],40:[2,29],42:[2,29]},{18:[2,30],24:[2,30],32:[2,30],33:[2,30],34:[2,30],35:[2,30],36:[2,30],40:[2,30],42:[2,30]},{17:68,21:24,30:25,40:[1,28],42:[1,27],43:26},{18:[2,32],24:[2,32],36:[2,32],39:69,40:[1,70]},{18:[2,47],24:[2,47],36:[2,47],40:[2,47]},{18:[2,40],24:[2,40],32:[2,40],33:[2,40],34:[2,40],35:[2,40],36:[2,40],40:[2,40],41:[1,71],42:[2,40],44:[2,40]},{18:[2,39],24:[2,39],32:[2,39],33:[2,39],34:[2,39],35:[2,39],36:[2,39],40:[2,39],42:[2,39],44:[2,39]},{5:[2,22],14:[2,22],15:[2,22],16:[2,22],19:[2,22],20:[2,22],22:[2,22],23:[2,22],25:[2,22]},{5:[2,19],14:[2,19],15:[2,19],16:[2,19],19:[2,19],20:[2,19],22:[2,19],23:[2,19],25:[2,19]},{36:[1,72]},{18:[2,48],24:[2,48],36:[2,48],40:[2,48]},{41:[1,71]},{21:56,30:60,31:73,32:[1,57],33:[1,58],34:[1,59],35:[1,61],40:[1,28],42:[1,27],43:26},{18:[2,31],24:[2,31],32:[2,31],33:[2,31],34:[2,31],35:[2,31],36:[2,31],40:[2,31],42:[2,31]},{18:[2,33],24:[2,33],36:[2,33],40:[2,33]}],
869   defaultActions: {3:[2,2],16:[2,1],50:[2,42]},
870   parseError: function parseError(str, hash) {
871       throw new Error(str);
872   },
873   parse: function parse(input) {
874       var self = this, stack = [0], vstack = [null], lstack = [], table = this.table, yytext = "", yylineno = 0, yyleng = 0, recovering = 0, TERROR = 2, EOF = 1;
875       this.lexer.setInput(input);
876       this.lexer.yy = this.yy;
877       this.yy.lexer = this.lexer;
878       this.yy.parser = this;
879       if (typeof this.lexer.yylloc == "undefined")
880           this.lexer.yylloc = {};
881       var yyloc = this.lexer.yylloc;
882       lstack.push(yyloc);
883       var ranges = this.lexer.options && this.lexer.options.ranges;
884       if (typeof this.yy.parseError === "function")
885           this.parseError = this.yy.parseError;
886       function popStack(n) {
887           stack.length = stack.length - 2 * n;
888           vstack.length = vstack.length - n;
889           lstack.length = lstack.length - n;
890       }
891       function lex() {
892           var token;
893           token = self.lexer.lex() || 1;
894           if (typeof token !== "number") {
895               token = self.symbols_[token] || token;
896           }
897           return token;
898       }
899       var symbol, preErrorSymbol, state, action, a, r, yyval = {}, p, len, newState, expected;
900       while (true) {
901           state = stack[stack.length - 1];
902           if (this.defaultActions[state]) {
903               action = this.defaultActions[state];
904           } else {
905               if (symbol === null || typeof symbol == "undefined") {
906                   symbol = lex();
907               }
908               action = table[state] && table[state][symbol];
909           }
910           if (typeof action === "undefined" || !action.length || !action[0]) {
911               var errStr = "";
912               if (!recovering) {
913                   expected = [];
914                   for (p in table[state])
915                       if (this.terminals_[p] && p > 2) {
916                           expected.push("'" + this.terminals_[p] + "'");
917                       }
918                   if (this.lexer.showPosition) {
919                       errStr = "Parse error on line " + (yylineno + 1) + ":\n" + this.lexer.showPosition() + "\nExpecting " + expected.join(", ") + ", got '" + (this.terminals_[symbol] || symbol) + "'";
920                   } else {
921                       errStr = "Parse error on line " + (yylineno + 1) + ": Unexpected " + (symbol == 1?"end of input":"'" + (this.terminals_[symbol] || symbol) + "'");
922                   }
923                   this.parseError(errStr, {text: this.lexer.match, token: this.terminals_[symbol] || symbol, line: this.lexer.yylineno, loc: yyloc, expected: expected});
924               }
925           }
926           if (action[0] instanceof Array && action.length > 1) {
927               throw new Error("Parse Error: multiple actions possible at state: " + state + ", token: " + symbol);
928           }
929           switch (action[0]) {
930           case 1:
931               stack.push(symbol);
932               vstack.push(this.lexer.yytext);
933               lstack.push(this.lexer.yylloc);
934               stack.push(action[1]);
935               symbol = null;
936               if (!preErrorSymbol) {
937                   yyleng = this.lexer.yyleng;
938                   yytext = this.lexer.yytext;
939                   yylineno = this.lexer.yylineno;
940                   yyloc = this.lexer.yylloc;
941                   if (recovering > 0)
942                       recovering--;
943               } else {
944                   symbol = preErrorSymbol;
945                   preErrorSymbol = null;
946               }
947               break;
948           case 2:
949               len = this.productions_[action[1]][1];
950               yyval.$ = vstack[vstack.length - len];
951               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};
952               if (ranges) {
953                   yyval._$.range = [lstack[lstack.length - (len || 1)].range[0], lstack[lstack.length - 1].range[1]];
954               }
955               r = this.performAction.call(yyval, yytext, yyleng, yylineno, this.yy, action[1], vstack, lstack);
956               if (typeof r !== "undefined") {
957                   return r;
958               }
959               if (len) {
960                   stack = stack.slice(0, -1 * len * 2);
961                   vstack = vstack.slice(0, -1 * len);
962                   lstack = lstack.slice(0, -1 * len);
963               }
964               stack.push(this.productions_[action[1]][0]);
965               vstack.push(yyval.$);
966               lstack.push(yyval._$);
967               newState = table[stack[stack.length - 2]][stack[stack.length - 1]];
968               stack.push(newState);
969               break;
970           case 3:
971               return true;
972           }
973       }
974       return true;
975   }
976   };
977
978
979   function stripFlags(open, close) {
980     return {
981       left: open.charAt(2) === '~',
982       right: close.charAt(0) === '~' || close.charAt(1) === '~'
983     };
984   }
985
986   /* Jison generated lexer */
987   var lexer = (function(){
988   var lexer = ({EOF:1,
989   parseError:function parseError(str, hash) {
990           if (this.yy.parser) {
991               this.yy.parser.parseError(str, hash);
992           } else {
993               throw new Error(str);
994           }
995       },
996   setInput:function (input) {
997           this._input = input;
998           this._more = this._less = this.done = false;
999           this.yylineno = this.yyleng = 0;
1000           this.yytext = this.matched = this.match = '';
1001           this.conditionStack = ['INITIAL'];
1002           this.yylloc = {first_line:1,first_column:0,last_line:1,last_column:0};
1003           if (this.options.ranges) this.yylloc.range = [0,0];
1004           this.offset = 0;
1005           return this;
1006       },
1007   input:function () {
1008           var ch = this._input[0];
1009           this.yytext += ch;
1010           this.yyleng++;
1011           this.offset++;
1012           this.match += ch;
1013           this.matched += ch;
1014           var lines = ch.match(/(?:\r\n?|\n).*/g);
1015           if (lines) {
1016               this.yylineno++;
1017               this.yylloc.last_line++;
1018           } else {
1019               this.yylloc.last_column++;
1020           }
1021           if (this.options.ranges) this.yylloc.range[1]++;
1022
1023           this._input = this._input.slice(1);
1024           return ch;
1025       },
1026   unput:function (ch) {
1027           var len = ch.length;
1028           var lines = ch.split(/(?:\r\n?|\n)/g);
1029
1030           this._input = ch + this._input;
1031           this.yytext = this.yytext.substr(0, this.yytext.length-len-1);
1032           //this.yyleng -= len;
1033           this.offset -= len;
1034           var oldLines = this.match.split(/(?:\r\n?|\n)/g);
1035           this.match = this.match.substr(0, this.match.length-1);
1036           this.matched = this.matched.substr(0, this.matched.length-1);
1037
1038           if (lines.length-1) this.yylineno -= lines.length-1;
1039           var r = this.yylloc.range;
1040
1041           this.yylloc = {first_line: this.yylloc.first_line,
1042             last_line: this.yylineno+1,
1043             first_column: this.yylloc.first_column,
1044             last_column: lines ?
1045                 (lines.length === oldLines.length ? this.yylloc.first_column : 0) + oldLines[oldLines.length - lines.length].length - lines[0].length:
1046                 this.yylloc.first_column - len
1047             };
1048
1049           if (this.options.ranges) {
1050               this.yylloc.range = [r[0], r[0] + this.yyleng - len];
1051           }
1052           return this;
1053       },
1054   more:function () {
1055           this._more = true;
1056           return this;
1057       },
1058   less:function (n) {
1059           this.unput(this.match.slice(n));
1060       },
1061   pastInput:function () {
1062           var past = this.matched.substr(0, this.matched.length - this.match.length);
1063           return (past.length > 20 ? '...':'') + past.substr(-20).replace(/\n/g, "");
1064       },
1065   upcomingInput:function () {
1066           var next = this.match;
1067           if (next.length < 20) {
1068               next += this._input.substr(0, 20-next.length);
1069           }
1070           return (next.substr(0,20)+(next.length > 20 ? '...':'')).replace(/\n/g, "");
1071       },
1072   showPosition:function () {
1073           var pre = this.pastInput();
1074           var c = new Array(pre.length + 1).join("-");
1075           return pre + this.upcomingInput() + "\n" + c+"^";
1076       },
1077   next:function () {
1078           if (this.done) {
1079               return this.EOF;
1080           }
1081           if (!this._input) this.done = true;
1082
1083           var token,
1084               match,
1085               tempMatch,
1086               index,
1087               col,
1088               lines;
1089           if (!this._more) {
1090               this.yytext = '';
1091               this.match = '';
1092           }
1093           var rules = this._currentRules();
1094           for (var i=0;i < rules.length; i++) {
1095               tempMatch = this._input.match(this.rules[rules[i]]);
1096               if (tempMatch && (!match || tempMatch[0].length > match[0].length)) {
1097                   match = tempMatch;
1098                   index = i;
1099                   if (!this.options.flex) break;
1100               }
1101           }
1102           if (match) {
1103               lines = match[0].match(/(?:\r\n?|\n).*/g);
1104               if (lines) this.yylineno += lines.length;
1105               this.yylloc = {first_line: this.yylloc.last_line,
1106                              last_line: this.yylineno+1,
1107                              first_column: this.yylloc.last_column,
1108                              last_column: lines ? lines[lines.length-1].length-lines[lines.length-1].match(/\r?\n?/)[0].length : this.yylloc.last_column + match[0].length};
1109               this.yytext += match[0];
1110               this.match += match[0];
1111               this.matches = match;
1112               this.yyleng = this.yytext.length;
1113               if (this.options.ranges) {
1114                   this.yylloc.range = [this.offset, this.offset += this.yyleng];
1115               }
1116               this._more = false;
1117               this._input = this._input.slice(match[0].length);
1118               this.matched += match[0];
1119               token = this.performAction.call(this, this.yy, this, rules[index],this.conditionStack[this.conditionStack.length-1]);
1120               if (this.done && this._input) this.done = false;
1121               if (token) return token;
1122               else return;
1123           }
1124           if (this._input === "") {
1125               return this.EOF;
1126           } else {
1127               return this.parseError('Lexical error on line '+(this.yylineno+1)+'. Unrecognized text.\n'+this.showPosition(),
1128                       {text: "", token: null, line: this.yylineno});
1129           }
1130       },
1131   lex:function lex() {
1132           var r = this.next();
1133           if (typeof r !== 'undefined') {
1134               return r;
1135           } else {
1136               return this.lex();
1137           }
1138       },
1139   begin:function begin(condition) {
1140           this.conditionStack.push(condition);
1141       },
1142   popState:function popState() {
1143           return this.conditionStack.pop();
1144       },
1145   _currentRules:function _currentRules() {
1146           return this.conditions[this.conditionStack[this.conditionStack.length-1]].rules;
1147       },
1148   topState:function () {
1149           return this.conditionStack[this.conditionStack.length-2];
1150       },
1151   pushState:function begin(condition) {
1152           this.begin(condition);
1153       }});
1154   lexer.options = {};
1155   lexer.performAction = function anonymous(yy,yy_,$avoiding_name_collisions,YY_START) {
1156
1157
1158   function strip(start, end) {
1159     return yy_.yytext = yy_.yytext.substr(start, yy_.yyleng-end);
1160   }
1161
1162
1163   var YYSTATE=YY_START
1164   switch($avoiding_name_collisions) {
1165   case 0:
1166                                      if(yy_.yytext.slice(-2) === "\\\\") {
1167                                        strip(0,1);
1168                                        this.begin("mu");
1169                                      } else if(yy_.yytext.slice(-1) === "\\") {
1170                                        strip(0,1);
1171                                        this.begin("emu");
1172                                      } else {
1173                                        this.begin("mu");
1174                                      }
1175                                      if(yy_.yytext) return 14;
1176                                    
1177   break;
1178   case 1:return 14;
1179   break;
1180   case 2:
1181                                      this.popState();
1182                                      return 14;
1183                                    
1184   break;
1185   case 3:strip(0,4); this.popState(); return 15;
1186   break;
1187   case 4:return 35;
1188   break;
1189   case 5:return 36;
1190   break;
1191   case 6:return 25;
1192   break;
1193   case 7:return 16;
1194   break;
1195   case 8:return 20;
1196   break;
1197   case 9:return 19;
1198   break;
1199   case 10:return 19;
1200   break;
1201   case 11:return 23;
1202   break;
1203   case 12:return 22;
1204   break;
1205   case 13:this.popState(); this.begin('com');
1206   break;
1207   case 14:strip(3,5); this.popState(); return 15;
1208   break;
1209   case 15:return 22;
1210   break;
1211   case 16:return 41;
1212   break;
1213   case 17:return 40;
1214   break;
1215   case 18:return 40;
1216   break;
1217   case 19:return 44;
1218   break;
1219   case 20:// ignore whitespace
1220   break;
1221   case 21:this.popState(); return 24;
1222   break;
1223   case 22:this.popState(); return 18;
1224   break;
1225   case 23:yy_.yytext = strip(1,2).replace(/\\"/g,'"'); return 32;
1226   break;
1227   case 24:yy_.yytext = strip(1,2).replace(/\\'/g,"'"); return 32;
1228   break;
1229   case 25:return 42;
1230   break;
1231   case 26:return 34;
1232   break;
1233   case 27:return 34;
1234   break;
1235   case 28:return 33;
1236   break;
1237   case 29:return 40;
1238   break;
1239   case 30:yy_.yytext = strip(1,2); return 40;
1240   break;
1241   case 31:return 'INVALID';
1242   break;
1243   case 32:return 5;
1244   break;
1245   }
1246   };
1247   lexer.rules = [/^(?:[^\x00]*?(?=(\{\{)))/,/^(?:[^\x00]+)/,/^(?:[^\x00]{2,}?(?=(\{\{|\\\{\{|\\\\\{\{|$)))/,/^(?:[\s\S]*?--\}\})/,/^(?:\()/,/^(?:\))/,/^(?:\{\{(~)?>)/,/^(?:\{\{(~)?#)/,/^(?:\{\{(~)?\/)/,/^(?:\{\{(~)?\^)/,/^(?:\{\{(~)?\s*else\b)/,/^(?:\{\{(~)?\{)/,/^(?:\{\{(~)?&)/,/^(?:\{\{!--)/,/^(?:\{\{![\s\S]*?\}\})/,/^(?:\{\{(~)?)/,/^(?:=)/,/^(?:\.\.)/,/^(?:\.(?=([=~}\s\/.)])))/,/^(?:[\/.])/,/^(?:\s+)/,/^(?:\}(~)?\}\})/,/^(?:(~)?\}\})/,/^(?:"(\\["]|[^"])*")/,/^(?:'(\\[']|[^'])*')/,/^(?:@)/,/^(?:true(?=([~}\s)])))/,/^(?:false(?=([~}\s)])))/,/^(?:-?[0-9]+(?=([~}\s)])))/,/^(?:([^\s!"#%-,\.\/;->@\[-\^`\{-~]+(?=([=~}\s\/.)]))))/,/^(?:\[[^\]]*\])/,/^(?:.)/,/^(?:$)/];
1248   lexer.conditions = {"mu":{"rules":[4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32],"inclusive":false},"emu":{"rules":[2],"inclusive":false},"com":{"rules":[3],"inclusive":false},"INITIAL":{"rules":[0,1,32],"inclusive":true}};
1249   return lexer;})()
1250   parser.lexer = lexer;
1251   function Parser () { this.yy = {}; }Parser.prototype = parser;parser.Parser = Parser;
1252   return new Parser;
1253   })();__exports__ = handlebars;
1254   /* jshint ignore:end */
1255   return __exports__;
1256 })();
1257
1258 // handlebars/compiler/base.js
1259 var __module8__ = (function(__dependency1__, __dependency2__) {
1260   "use strict";
1261   var __exports__ = {};
1262   var parser = __dependency1__;
1263   var AST = __dependency2__;
1264
1265   __exports__.parser = parser;
1266
1267   function parse(input) {
1268     // Just return if an already-compile AST was passed in.
1269     if(input.constructor === AST.ProgramNode) { return input; }
1270
1271     parser.yy = AST;
1272     return parser.parse(input);
1273   }
1274
1275   __exports__.parse = parse;
1276   return __exports__;
1277 })(__module9__, __module7__);
1278
1279 // handlebars/compiler/compiler.js
1280 var __module10__ = (function(__dependency1__) {
1281   "use strict";
1282   var __exports__ = {};
1283   var Exception = __dependency1__;
1284
1285   function Compiler() {}
1286
1287   __exports__.Compiler = Compiler;// the foundHelper register will disambiguate helper lookup from finding a
1288   // function in a context. This is necessary for mustache compatibility, which
1289   // requires that context functions in blocks are evaluated by blockHelperMissing,
1290   // and then proceed as if the resulting value was provided to blockHelperMissing.
1291
1292   Compiler.prototype = {
1293     compiler: Compiler,
1294
1295     disassemble: function() {
1296       var opcodes = this.opcodes, opcode, out = [], params, param;
1297
1298       for (var i=0, l=opcodes.length; i<l; i++) {
1299         opcode = opcodes[i];
1300
1301         if (opcode.opcode === 'DECLARE') {
1302           out.push("DECLARE " + opcode.name + "=" + opcode.value);
1303         } else {
1304           params = [];
1305           for (var j=0; j<opcode.args.length; j++) {
1306             param = opcode.args[j];
1307             if (typeof param === "string") {
1308               param = "\"" + param.replace("\n", "\\n") + "\"";
1309             }
1310             params.push(param);
1311           }
1312           out.push(opcode.opcode + " " + params.join(" "));
1313         }
1314       }
1315
1316       return out.join("\n");
1317     },
1318
1319     equals: function(other) {
1320       var len = this.opcodes.length;
1321       if (other.opcodes.length !== len) {
1322         return false;
1323       }
1324
1325       for (var i = 0; i < len; i++) {
1326         var opcode = this.opcodes[i],
1327             otherOpcode = other.opcodes[i];
1328         if (opcode.opcode !== otherOpcode.opcode || opcode.args.length !== otherOpcode.args.length) {
1329           return false;
1330         }
1331         for (var j = 0; j < opcode.args.length; j++) {
1332           if (opcode.args[j] !== otherOpcode.args[j]) {
1333             return false;
1334           }
1335         }
1336       }
1337
1338       len = this.children.length;
1339       if (other.children.length !== len) {
1340         return false;
1341       }
1342       for (i = 0; i < len; i++) {
1343         if (!this.children[i].equals(other.children[i])) {
1344           return false;
1345         }
1346       }
1347
1348       return true;
1349     },
1350
1351     guid: 0,
1352
1353     compile: function(program, options) {
1354       this.opcodes = [];
1355       this.children = [];
1356       this.depths = {list: []};
1357       this.options = options;
1358
1359       // These changes will propagate to the other compiler components
1360       var knownHelpers = this.options.knownHelpers;
1361       this.options.knownHelpers = {
1362         'helperMissing': true,
1363         'blockHelperMissing': true,
1364         'each': true,
1365         'if': true,
1366         'unless': true,
1367         'with': true,
1368         'log': true
1369       };
1370       if (knownHelpers) {
1371         for (var name in knownHelpers) {
1372           this.options.knownHelpers[name] = knownHelpers[name];
1373         }
1374       }
1375
1376       return this.accept(program);
1377     },
1378
1379     accept: function(node) {
1380       var strip = node.strip || {},
1381           ret;
1382       if (strip.left) {
1383         this.opcode('strip');
1384       }
1385
1386       ret = this[node.type](node);
1387
1388       if (strip.right) {
1389         this.opcode('strip');
1390       }
1391
1392       return ret;
1393     },
1394
1395     program: function(program) {
1396       var statements = program.statements;
1397
1398       for(var i=0, l=statements.length; i<l; i++) {
1399         this.accept(statements[i]);
1400       }
1401       this.isSimple = l === 1;
1402
1403       this.depths.list = this.depths.list.sort(function(a, b) {
1404         return a - b;
1405       });
1406
1407       return this;
1408     },
1409
1410     compileProgram: function(program) {
1411       var result = new this.compiler().compile(program, this.options);
1412       var guid = this.guid++, depth;
1413
1414       this.usePartial = this.usePartial || result.usePartial;
1415
1416       this.children[guid] = result;
1417
1418       for(var i=0, l=result.depths.list.length; i<l; i++) {
1419         depth = result.depths.list[i];
1420
1421         if(depth < 2) { continue; }
1422         else { this.addDepth(depth - 1); }
1423       }
1424
1425       return guid;
1426     },
1427
1428     block: function(block) {
1429       var mustache = block.mustache,
1430           program = block.program,
1431           inverse = block.inverse;
1432
1433       if (program) {
1434         program = this.compileProgram(program);
1435       }
1436
1437       if (inverse) {
1438         inverse = this.compileProgram(inverse);
1439       }
1440
1441       var sexpr = mustache.sexpr;
1442       var type = this.classifySexpr(sexpr);
1443
1444       if (type === "helper") {
1445         this.helperSexpr(sexpr, program, inverse);
1446       } else if (type === "simple") {
1447         this.simpleSexpr(sexpr);
1448
1449         // now that the simple mustache is resolved, we need to
1450         // evaluate it by executing `blockHelperMissing`
1451         this.opcode('pushProgram', program);
1452         this.opcode('pushProgram', inverse);
1453         this.opcode('emptyHash');
1454         this.opcode('blockValue');
1455       } else {
1456         this.ambiguousSexpr(sexpr, program, inverse);
1457
1458         // now that the simple mustache is resolved, we need to
1459         // evaluate it by executing `blockHelperMissing`
1460         this.opcode('pushProgram', program);
1461         this.opcode('pushProgram', inverse);
1462         this.opcode('emptyHash');
1463         this.opcode('ambiguousBlockValue');
1464       }
1465
1466       this.opcode('append');
1467     },
1468
1469     hash: function(hash) {
1470       var pairs = hash.pairs, pair, val;
1471
1472       this.opcode('pushHash');
1473
1474       for(var i=0, l=pairs.length; i<l; i++) {
1475         pair = pairs[i];
1476         val  = pair[1];
1477
1478         if (this.options.stringParams) {
1479           if(val.depth) {
1480             this.addDepth(val.depth);
1481           }
1482           this.opcode('getContext', val.depth || 0);
1483           this.opcode('pushStringParam', val.stringModeValue, val.type);
1484
1485           if (val.type === 'sexpr') {
1486             // Subexpressions get evaluated and passed in
1487             // in string params mode.
1488             this.sexpr(val);
1489           }
1490         } else {
1491           this.accept(val);
1492         }
1493
1494         this.opcode('assignToHash', pair[0]);
1495       }
1496       this.opcode('popHash');
1497     },
1498
1499     partial: function(partial) {
1500       var partialName = partial.partialName;
1501       this.usePartial = true;
1502
1503       if(partial.context) {
1504         this.ID(partial.context);
1505       } else {
1506         this.opcode('push', 'depth0');
1507       }
1508
1509       this.opcode('invokePartial', partialName.name);
1510       this.opcode('append');
1511     },
1512
1513     content: function(content) {
1514       this.opcode('appendContent', content.string);
1515     },
1516
1517     mustache: function(mustache) {
1518       this.sexpr(mustache.sexpr);
1519
1520       if(mustache.escaped && !this.options.noEscape) {
1521         this.opcode('appendEscaped');
1522       } else {
1523         this.opcode('append');
1524       }
1525     },
1526
1527     ambiguousSexpr: function(sexpr, program, inverse) {
1528       var id = sexpr.id,
1529           name = id.parts[0],
1530           isBlock = program != null || inverse != null;
1531
1532       this.opcode('getContext', id.depth);
1533
1534       this.opcode('pushProgram', program);
1535       this.opcode('pushProgram', inverse);
1536
1537       this.opcode('invokeAmbiguous', name, isBlock);
1538     },
1539
1540     simpleSexpr: function(sexpr) {
1541       var id = sexpr.id;
1542
1543       if (id.type === 'DATA') {
1544         this.DATA(id);
1545       } else if (id.parts.length) {
1546         this.ID(id);
1547       } else {
1548         // Simplified ID for `this`
1549         this.addDepth(id.depth);
1550         this.opcode('getContext', id.depth);
1551         this.opcode('pushContext');
1552       }
1553
1554       this.opcode('resolvePossibleLambda');
1555     },
1556
1557     helperSexpr: function(sexpr, program, inverse) {
1558       var params = this.setupFullMustacheParams(sexpr, program, inverse),
1559           name = sexpr.id.parts[0];
1560
1561       if (this.options.knownHelpers[name]) {
1562         this.opcode('invokeKnownHelper', params.length, name);
1563       } else if (this.options.knownHelpersOnly) {
1564         throw new Exception("You specified knownHelpersOnly, but used the unknown helper " + name, sexpr);
1565       } else {
1566         this.opcode('invokeHelper', params.length, name, sexpr.isRoot);
1567       }
1568     },
1569
1570     sexpr: function(sexpr) {
1571       var type = this.classifySexpr(sexpr);
1572
1573       if (type === "simple") {
1574         this.simpleSexpr(sexpr);
1575       } else if (type === "helper") {
1576         this.helperSexpr(sexpr);
1577       } else {
1578         this.ambiguousSexpr(sexpr);
1579       }
1580     },
1581
1582     ID: function(id) {
1583       this.addDepth(id.depth);
1584       this.opcode('getContext', id.depth);
1585
1586       var name = id.parts[0];
1587       if (!name) {
1588         this.opcode('pushContext');
1589       } else {
1590         this.opcode('lookupOnContext', id.parts[0]);
1591       }
1592
1593       for(var i=1, l=id.parts.length; i<l; i++) {
1594         this.opcode('lookup', id.parts[i]);
1595       }
1596     },
1597
1598     DATA: function(data) {
1599       this.options.data = true;
1600       if (data.id.isScoped || data.id.depth) {
1601         throw new Exception('Scoped data references are not supported: ' + data.original, data);
1602       }
1603
1604       this.opcode('lookupData');
1605       var parts = data.id.parts;
1606       for(var i=0, l=parts.length; i<l; i++) {
1607         this.opcode('lookup', parts[i]);
1608       }
1609     },
1610
1611     STRING: function(string) {
1612       this.opcode('pushString', string.string);
1613     },
1614
1615     INTEGER: function(integer) {
1616       this.opcode('pushLiteral', integer.integer);
1617     },
1618
1619     BOOLEAN: function(bool) {
1620       this.opcode('pushLiteral', bool.bool);
1621     },
1622
1623     comment: function() {},
1624
1625     // HELPERS
1626     opcode: function(name) {
1627       this.opcodes.push({ opcode: name, args: [].slice.call(arguments, 1) });
1628     },
1629
1630     declare: function(name, value) {
1631       this.opcodes.push({ opcode: 'DECLARE', name: name, value: value });
1632     },
1633
1634     addDepth: function(depth) {
1635       if(depth === 0) { return; }
1636
1637       if(!this.depths[depth]) {
1638         this.depths[depth] = true;
1639         this.depths.list.push(depth);
1640       }
1641     },
1642
1643     classifySexpr: function(sexpr) {
1644       var isHelper   = sexpr.isHelper;
1645       var isEligible = sexpr.eligibleHelper;
1646       var options    = this.options;
1647
1648       // if ambiguous, we can possibly resolve the ambiguity now
1649       if (isEligible && !isHelper) {
1650         var name = sexpr.id.parts[0];
1651
1652         if (options.knownHelpers[name]) {
1653           isHelper = true;
1654         } else if (options.knownHelpersOnly) {
1655           isEligible = false;
1656         }
1657       }
1658
1659       if (isHelper) { return "helper"; }
1660       else if (isEligible) { return "ambiguous"; }
1661       else { return "simple"; }
1662     },
1663
1664     pushParams: function(params) {
1665       var i = params.length, param;
1666
1667       while(i--) {
1668         param = params[i];
1669
1670         if(this.options.stringParams) {
1671           if(param.depth) {
1672             this.addDepth(param.depth);
1673           }
1674
1675           this.opcode('getContext', param.depth || 0);
1676           this.opcode('pushStringParam', param.stringModeValue, param.type);
1677
1678           if (param.type === 'sexpr') {
1679             // Subexpressions get evaluated and passed in
1680             // in string params mode.
1681             this.sexpr(param);
1682           }
1683         } else {
1684           this[param.type](param);
1685         }
1686       }
1687     },
1688
1689     setupFullMustacheParams: function(sexpr, program, inverse) {
1690       var params = sexpr.params;
1691       this.pushParams(params);
1692
1693       this.opcode('pushProgram', program);
1694       this.opcode('pushProgram', inverse);
1695
1696       if (sexpr.hash) {
1697         this.hash(sexpr.hash);
1698       } else {
1699         this.opcode('emptyHash');
1700       }
1701
1702       return params;
1703     }
1704   };
1705
1706   function precompile(input, options, env) {
1707     if (input == null || (typeof input !== 'string' && input.constructor !== env.AST.ProgramNode)) {
1708       throw new Exception("You must pass a string or Handlebars AST to Handlebars.precompile. You passed " + input);
1709     }
1710
1711     options = options || {};
1712     if (!('data' in options)) {
1713       options.data = true;
1714     }
1715
1716     var ast = env.parse(input);
1717     var environment = new env.Compiler().compile(ast, options);
1718     return new env.JavaScriptCompiler().compile(environment, options);
1719   }
1720
1721   __exports__.precompile = precompile;function compile(input, options, env) {
1722     if (input == null || (typeof input !== 'string' && input.constructor !== env.AST.ProgramNode)) {
1723       throw new Exception("You must pass a string or Handlebars AST to Handlebars.compile. You passed " + input);
1724     }
1725
1726     options = options || {};
1727
1728     if (!('data' in options)) {
1729       options.data = true;
1730     }
1731
1732     var compiled;
1733
1734     function compileInput() {
1735       var ast = env.parse(input);
1736       var environment = new env.Compiler().compile(ast, options);
1737       var templateSpec = new env.JavaScriptCompiler().compile(environment, options, undefined, true);
1738       return env.template(templateSpec);
1739     }
1740
1741     // Template is only compiled on first use and cached after that point.
1742     return function(context, options) {
1743       if (!compiled) {
1744         compiled = compileInput();
1745       }
1746       return compiled.call(this, context, options);
1747     };
1748   }
1749
1750   __exports__.compile = compile;
1751   return __exports__;
1752 })(__module5__);
1753
1754 // handlebars/compiler/javascript-compiler.js
1755 var __module11__ = (function(__dependency1__, __dependency2__) {
1756   "use strict";
1757   var __exports__;
1758   var COMPILER_REVISION = __dependency1__.COMPILER_REVISION;
1759   var REVISION_CHANGES = __dependency1__.REVISION_CHANGES;
1760   var log = __dependency1__.log;
1761   var Exception = __dependency2__;
1762
1763   function Literal(value) {
1764     this.value = value;
1765   }
1766
1767   function JavaScriptCompiler() {}
1768
1769   JavaScriptCompiler.prototype = {
1770     // PUBLIC API: You can override these methods in a subclass to provide
1771     // alternative compiled forms for name lookup and buffering semantics
1772     nameLookup: function(parent, name /* , type*/) {
1773       var wrap,
1774           ret;
1775       if (parent.indexOf('depth') === 0) {
1776         wrap = true;
1777       }
1778
1779       if (/^[0-9]+$/.test(name)) {
1780         ret = parent + "[" + name + "]";
1781       } else if (JavaScriptCompiler.isValidJavaScriptVariableName(name)) {
1782         ret = parent + "." + name;
1783       }
1784       else {
1785         ret = parent + "['" + name + "']";
1786       }
1787
1788       if (wrap) {
1789         return '(' + parent + ' && ' + ret + ')';
1790       } else {
1791         return ret;
1792       }
1793     },
1794
1795     compilerInfo: function() {
1796       var revision = COMPILER_REVISION,
1797           versions = REVISION_CHANGES[revision];
1798       return "this.compilerInfo = ["+revision+",'"+versions+"'];\n";
1799     },
1800
1801     appendToBuffer: function(string) {
1802       if (this.environment.isSimple) {
1803         return "return " + string + ";";
1804       } else {
1805         return {
1806           appendToBuffer: true,
1807           content: string,
1808           toString: function() { return "buffer += " + string + ";"; }
1809         };
1810       }
1811     },
1812
1813     initializeBuffer: function() {
1814       return this.quotedString("");
1815     },
1816
1817     namespace: "Handlebars",
1818     // END PUBLIC API
1819
1820     compile: function(environment, options, context, asObject) {
1821       this.environment = environment;
1822       this.options = options || {};
1823
1824       log('debug', this.environment.disassemble() + "\n\n");
1825
1826       this.name = this.environment.name;
1827       this.isChild = !!context;
1828       this.context = context || {
1829         programs: [],
1830         environments: [],
1831         aliases: { }
1832       };
1833
1834       this.preamble();
1835
1836       this.stackSlot = 0;
1837       this.stackVars = [];
1838       this.registers = { list: [] };
1839       this.hashes = [];
1840       this.compileStack = [];
1841       this.inlineStack = [];
1842
1843       this.compileChildren(environment, options);
1844
1845       var opcodes = environment.opcodes, opcode;
1846
1847       this.i = 0;
1848
1849       for(var l=opcodes.length; this.i<l; this.i++) {
1850         opcode = opcodes[this.i];
1851
1852         if(opcode.opcode === 'DECLARE') {
1853           this[opcode.name] = opcode.value;
1854         } else {
1855           this[opcode.opcode].apply(this, opcode.args);
1856         }
1857
1858         // Reset the stripNext flag if it was not set by this operation.
1859         if (opcode.opcode !== this.stripNext) {
1860           this.stripNext = false;
1861         }
1862       }
1863
1864       // Flush any trailing content that might be pending.
1865       this.pushSource('');
1866
1867       if (this.stackSlot || this.inlineStack.length || this.compileStack.length) {
1868         throw new Exception('Compile completed with content left on stack');
1869       }
1870
1871       return this.createFunctionContext(asObject);
1872     },
1873
1874     preamble: function() {
1875       var out = [];
1876
1877       if (!this.isChild) {
1878         var namespace = this.namespace;
1879
1880         var copies = "helpers = this.merge(helpers, " + namespace + ".helpers);";
1881         if (this.environment.usePartial) { copies = copies + " partials = this.merge(partials, " + namespace + ".partials);"; }
1882         if (this.options.data) { copies = copies + " data = data || {};"; }
1883         out.push(copies);
1884       } else {
1885         out.push('');
1886       }
1887
1888       if (!this.environment.isSimple) {
1889         out.push(", buffer = " + this.initializeBuffer());
1890       } else {
1891         out.push("");
1892       }
1893
1894       // track the last context pushed into place to allow skipping the
1895       // getContext opcode when it would be a noop
1896       this.lastContext = 0;
1897       this.source = out;
1898     },
1899
1900     createFunctionContext: function(asObject) {
1901       var locals = this.stackVars.concat(this.registers.list);
1902
1903       if(locals.length > 0) {
1904         this.source[1] = this.source[1] + ", " + locals.join(", ");
1905       }
1906
1907       // Generate minimizer alias mappings
1908       if (!this.isChild) {
1909         for (var alias in this.context.aliases) {
1910           if (this.context.aliases.hasOwnProperty(alias)) {
1911             this.source[1] = this.source[1] + ', ' + alias + '=' + this.context.aliases[alias];
1912           }
1913         }
1914       }
1915
1916       if (this.source[1]) {
1917         this.source[1] = "var " + this.source[1].substring(2) + ";";
1918       }
1919
1920       // Merge children
1921       if (!this.isChild) {
1922         this.source[1] += '\n' + this.context.programs.join('\n') + '\n';
1923       }
1924
1925       if (!this.environment.isSimple) {
1926         this.pushSource("return buffer;");
1927       }
1928
1929       var params = this.isChild ? ["depth0", "data"] : ["Handlebars", "depth0", "helpers", "partials", "data"];
1930
1931       for(var i=0, l=this.environment.depths.list.length; i<l; i++) {
1932         params.push("depth" + this.environment.depths.list[i]);
1933       }
1934
1935       // Perform a second pass over the output to merge content when possible
1936       var source = this.mergeSource();
1937
1938       if (!this.isChild) {
1939         source = this.compilerInfo()+source;
1940       }
1941
1942       if (asObject) {
1943         params.push(source);
1944
1945         return Function.apply(this, params);
1946       } else {
1947         var functionSource = 'function ' + (this.name || '') + '(' + params.join(',') + ') {\n  ' + source + '}';
1948         log('debug', functionSource + "\n\n");
1949         return functionSource;
1950       }
1951     },
1952     mergeSource: function() {
1953       // WARN: We are not handling the case where buffer is still populated as the source should
1954       // not have buffer append operations as their final action.
1955       var source = '',
1956           buffer;
1957       for (var i = 0, len = this.source.length; i < len; i++) {
1958         var line = this.source[i];
1959         if (line.appendToBuffer) {
1960           if (buffer) {
1961             buffer = buffer + '\n    + ' + line.content;
1962           } else {
1963             buffer = line.content;
1964           }
1965         } else {
1966           if (buffer) {
1967             source += 'buffer += ' + buffer + ';\n  ';
1968             buffer = undefined;
1969           }
1970           source += line + '\n  ';
1971         }
1972       }
1973       return source;
1974     },
1975
1976     // [blockValue]
1977     //
1978     // On stack, before: hash, inverse, program, value
1979     // On stack, after: return value of blockHelperMissing
1980     //
1981     // The purpose of this opcode is to take a block of the form
1982     // `{{#foo}}...{{/foo}}`, resolve the value of `foo`, and
1983     // replace it on the stack with the result of properly
1984     // invoking blockHelperMissing.
1985     blockValue: function() {
1986       this.context.aliases.blockHelperMissing = 'helpers.blockHelperMissing';
1987
1988       var params = ["depth0"];
1989       this.setupParams(0, params);
1990
1991       this.replaceStack(function(current) {
1992         params.splice(1, 0, current);
1993         return "blockHelperMissing.call(" + params.join(", ") + ")";
1994       });
1995     },
1996
1997     // [ambiguousBlockValue]
1998     //
1999     // On stack, before: hash, inverse, program, value
2000     // Compiler value, before: lastHelper=value of last found helper, if any
2001     // On stack, after, if no lastHelper: same as [blockValue]
2002     // On stack, after, if lastHelper: value
2003     ambiguousBlockValue: function() {
2004       this.context.aliases.blockHelperMissing = 'helpers.blockHelperMissing';
2005
2006       var params = ["depth0"];
2007       this.setupParams(0, params);
2008
2009       var current = this.topStack();
2010       params.splice(1, 0, current);
2011
2012       this.pushSource("if (!" + this.lastHelper + ") { " + current + " = blockHelperMissing.call(" + params.join(", ") + "); }");
2013     },
2014
2015     // [appendContent]
2016     //
2017     // On stack, before: ...
2018     // On stack, after: ...
2019     //
2020     // Appends the string value of `content` to the current buffer
2021     appendContent: function(content) {
2022       if (this.pendingContent) {
2023         content = this.pendingContent + content;
2024       }
2025       if (this.stripNext) {
2026         content = content.replace(/^\s+/, '');
2027       }
2028
2029       this.pendingContent = content;
2030     },
2031
2032     // [strip]
2033     //
2034     // On stack, before: ...
2035     // On stack, after: ...
2036     //
2037     // Removes any trailing whitespace from the prior content node and flags
2038     // the next operation for stripping if it is a content node.
2039     strip: function() {
2040       if (this.pendingContent) {
2041         this.pendingContent = this.pendingContent.replace(/\s+$/, '');
2042       }
2043       this.stripNext = 'strip';
2044     },
2045
2046     // [append]
2047     //
2048     // On stack, before: value, ...
2049     // On stack, after: ...
2050     //
2051     // Coerces `value` to a String and appends it to the current buffer.
2052     //
2053     // If `value` is truthy, or 0, it is coerced into a string and appended
2054     // Otherwise, the empty string is appended
2055     append: function() {
2056       // Force anything that is inlined onto the stack so we don't have duplication
2057       // when we examine local
2058       this.flushInline();
2059       var local = this.popStack();
2060       this.pushSource("if(" + local + " || " + local + " === 0) { " + this.appendToBuffer(local) + " }");
2061       if (this.environment.isSimple) {
2062         this.pushSource("else { " + this.appendToBuffer("''") + " }");
2063       }
2064     },
2065
2066     // [appendEscaped]
2067     //
2068     // On stack, before: value, ...
2069     // On stack, after: ...
2070     //
2071     // Escape `value` and append it to the buffer
2072     appendEscaped: function() {
2073       this.context.aliases.escapeExpression = 'this.escapeExpression';
2074
2075       this.pushSource(this.appendToBuffer("escapeExpression(" + this.popStack() + ")"));
2076     },
2077
2078     // [getContext]
2079     //
2080     // On stack, before: ...
2081     // On stack, after: ...
2082     // Compiler value, after: lastContext=depth
2083     //
2084     // Set the value of the `lastContext` compiler value to the depth
2085     getContext: function(depth) {
2086       if(this.lastContext !== depth) {
2087         this.lastContext = depth;
2088       }
2089     },
2090
2091     // [lookupOnContext]
2092     //
2093     // On stack, before: ...
2094     // On stack, after: currentContext[name], ...
2095     //
2096     // Looks up the value of `name` on the current context and pushes
2097     // it onto the stack.
2098     lookupOnContext: function(name) {
2099       this.push(this.nameLookup('depth' + this.lastContext, name, 'context'));
2100     },
2101
2102     // [pushContext]
2103     //
2104     // On stack, before: ...
2105     // On stack, after: currentContext, ...
2106     //
2107     // Pushes the value of the current context onto the stack.
2108     pushContext: function() {
2109       this.pushStackLiteral('depth' + this.lastContext);
2110     },
2111
2112     // [resolvePossibleLambda]
2113     //
2114     // On stack, before: value, ...
2115     // On stack, after: resolved value, ...
2116     //
2117     // If the `value` is a lambda, replace it on the stack by
2118     // the return value of the lambda
2119     resolvePossibleLambda: function() {
2120       this.context.aliases.functionType = '"function"';
2121
2122       this.replaceStack(function(current) {
2123         return "typeof " + current + " === functionType ? " + current + ".apply(depth0) : " + current;
2124       });
2125     },
2126
2127     // [lookup]
2128     //
2129     // On stack, before: value, ...
2130     // On stack, after: value[name], ...
2131     //
2132     // Replace the value on the stack with the result of looking
2133     // up `name` on `value`
2134     lookup: function(name) {
2135       this.replaceStack(function(current) {
2136         return current + " == null || " + current + " === false ? " + current + " : " + this.nameLookup(current, name, 'context');
2137       });
2138     },
2139
2140     // [lookupData]
2141     //
2142     // On stack, before: ...
2143     // On stack, after: data, ...
2144     //
2145     // Push the data lookup operator
2146     lookupData: function() {
2147       this.pushStackLiteral('data');
2148     },
2149
2150     // [pushStringParam]
2151     //
2152     // On stack, before: ...
2153     // On stack, after: string, currentContext, ...
2154     //
2155     // This opcode is designed for use in string mode, which
2156     // provides the string value of a parameter along with its
2157     // depth rather than resolving it immediately.
2158     pushStringParam: function(string, type) {
2159       this.pushStackLiteral('depth' + this.lastContext);
2160
2161       this.pushString(type);
2162
2163       // If it's a subexpression, the string result
2164       // will be pushed after this opcode.
2165       if (type !== 'sexpr') {
2166         if (typeof string === 'string') {
2167           this.pushString(string);
2168         } else {
2169           this.pushStackLiteral(string);
2170         }
2171       }
2172     },
2173
2174     emptyHash: function() {
2175       this.pushStackLiteral('{}');
2176
2177       if (this.options.stringParams) {
2178         this.push('{}'); // hashContexts
2179         this.push('{}'); // hashTypes
2180       }
2181     },
2182     pushHash: function() {
2183       if (this.hash) {
2184         this.hashes.push(this.hash);
2185       }
2186       this.hash = {values: [], types: [], contexts: []};
2187     },
2188     popHash: function() {
2189       var hash = this.hash;
2190       this.hash = this.hashes.pop();
2191
2192       if (this.options.stringParams) {
2193         this.push('{' + hash.contexts.join(',') + '}');
2194         this.push('{' + hash.types.join(',') + '}');
2195       }
2196
2197       this.push('{\n    ' + hash.values.join(',\n    ') + '\n  }');
2198     },
2199
2200     // [pushString]
2201     //
2202     // On stack, before: ...
2203     // On stack, after: quotedString(string), ...
2204     //
2205     // Push a quoted version of `string` onto the stack
2206     pushString: function(string) {
2207       this.pushStackLiteral(this.quotedString(string));
2208     },
2209
2210     // [push]
2211     //
2212     // On stack, before: ...
2213     // On stack, after: expr, ...
2214     //
2215     // Push an expression onto the stack
2216     push: function(expr) {
2217       this.inlineStack.push(expr);
2218       return expr;
2219     },
2220
2221     // [pushLiteral]
2222     //
2223     // On stack, before: ...
2224     // On stack, after: value, ...
2225     //
2226     // Pushes a value onto the stack. This operation prevents
2227     // the compiler from creating a temporary variable to hold
2228     // it.
2229     pushLiteral: function(value) {
2230       this.pushStackLiteral(value);
2231     },
2232
2233     // [pushProgram]
2234     //
2235     // On stack, before: ...
2236     // On stack, after: program(guid), ...
2237     //
2238     // Push a program expression onto the stack. This takes
2239     // a compile-time guid and converts it into a runtime-accessible
2240     // expression.
2241     pushProgram: function(guid) {
2242       if (guid != null) {
2243         this.pushStackLiteral(this.programExpression(guid));
2244       } else {
2245         this.pushStackLiteral(null);
2246       }
2247     },
2248
2249     // [invokeHelper]
2250     //
2251     // On stack, before: hash, inverse, program, params..., ...
2252     // On stack, after: result of helper invocation
2253     //
2254     // Pops off the helper's parameters, invokes the helper,
2255     // and pushes the helper's return value onto the stack.
2256     //
2257     // If the helper is not found, `helperMissing` is called.
2258     invokeHelper: function(paramSize, name, isRoot) {
2259       this.context.aliases.helperMissing = 'helpers.helperMissing';
2260       this.useRegister('helper');
2261
2262       var helper = this.lastHelper = this.setupHelper(paramSize, name, true);
2263       var nonHelper = this.nameLookup('depth' + this.lastContext, name, 'context');
2264
2265       var lookup = 'helper = ' + helper.name + ' || ' + nonHelper;
2266       if (helper.paramsInit) {
2267         lookup += ',' + helper.paramsInit;
2268       }
2269
2270       this.push(
2271         '('
2272           + lookup
2273           + ',helper '
2274             + '? helper.call(' + helper.callParams + ') '
2275             + ': helperMissing.call(' + helper.helperMissingParams + '))');
2276
2277       // Always flush subexpressions. This is both to prevent the compounding size issue that
2278       // occurs when the code has to be duplicated for inlining and also to prevent errors
2279       // due to the incorrect options object being passed due to the shared register.
2280       if (!isRoot) {
2281         this.flushInline();
2282       }
2283     },
2284
2285     // [invokeKnownHelper]
2286     //
2287     // On stack, before: hash, inverse, program, params..., ...
2288     // On stack, after: result of helper invocation
2289     //
2290     // This operation is used when the helper is known to exist,
2291     // so a `helperMissing` fallback is not required.
2292     invokeKnownHelper: function(paramSize, name) {
2293       var helper = this.setupHelper(paramSize, name);
2294       this.push(helper.name + ".call(" + helper.callParams + ")");
2295     },
2296
2297     // [invokeAmbiguous]
2298     //
2299     // On stack, before: hash, inverse, program, params..., ...
2300     // On stack, after: result of disambiguation
2301     //
2302     // This operation is used when an expression like `{{foo}}`
2303     // is provided, but we don't know at compile-time whether it
2304     // is a helper or a path.
2305     //
2306     // This operation emits more code than the other options,
2307     // and can be avoided by passing the `knownHelpers` and
2308     // `knownHelpersOnly` flags at compile-time.
2309     invokeAmbiguous: function(name, helperCall) {
2310       this.context.aliases.functionType = '"function"';
2311       this.useRegister('helper');
2312
2313       this.emptyHash();
2314       var helper = this.setupHelper(0, name, helperCall);
2315
2316       var helperName = this.lastHelper = this.nameLookup('helpers', name, 'helper');
2317
2318       var nonHelper = this.nameLookup('depth' + this.lastContext, name, 'context');
2319       var nextStack = this.nextStack();
2320
2321       if (helper.paramsInit) {
2322         this.pushSource(helper.paramsInit);
2323       }
2324       this.pushSource('if (helper = ' + helperName + ') { ' + nextStack + ' = helper.call(' + helper.callParams + '); }');
2325       this.pushSource('else { helper = ' + nonHelper + '; ' + nextStack + ' = typeof helper === functionType ? helper.call(' + helper.callParams + ') : helper; }');
2326     },
2327
2328     // [invokePartial]
2329     //
2330     // On stack, before: context, ...
2331     // On stack after: result of partial invocation
2332     //
2333     // This operation pops off a context, invokes a partial with that context,
2334     // and pushes the result of the invocation back.
2335     invokePartial: function(name) {
2336       var params = [this.nameLookup('partials', name, 'partial'), "'" + name + "'", this.popStack(), "helpers", "partials"];
2337
2338       if (this.options.data) {
2339         params.push("data");
2340       }
2341
2342       this.context.aliases.self = "this";
2343       this.push("self.invokePartial(" + params.join(", ") + ")");
2344     },
2345
2346     // [assignToHash]
2347     //
2348     // On stack, before: value, hash, ...
2349     // On stack, after: hash, ...
2350     //
2351     // Pops a value and hash off the stack, assigns `hash[key] = value`
2352     // and pushes the hash back onto the stack.
2353     assignToHash: function(key) {
2354       var value = this.popStack(),
2355           context,
2356           type;
2357
2358       if (this.options.stringParams) {
2359         type = this.popStack();
2360         context = this.popStack();
2361       }
2362
2363       var hash = this.hash;
2364       if (context) {
2365         hash.contexts.push("'" + key + "': " + context);
2366       }
2367       if (type) {
2368         hash.types.push("'" + key + "': " + type);
2369       }
2370       hash.values.push("'" + key + "': (" + value + ")");
2371     },
2372
2373     // HELPERS
2374
2375     compiler: JavaScriptCompiler,
2376
2377     compileChildren: function(environment, options) {
2378       var children = environment.children, child, compiler;
2379
2380       for(var i=0, l=children.length; i<l; i++) {
2381         child = children[i];
2382         compiler = new this.compiler();
2383
2384         var index = this.matchExistingProgram(child);
2385
2386         if (index == null) {
2387           this.context.programs.push('');     // Placeholder to prevent name conflicts for nested children
2388           index = this.context.programs.length;
2389           child.index = index;
2390           child.name = 'program' + index;
2391           this.context.programs[index] = compiler.compile(child, options, this.context);
2392           this.context.environments[index] = child;
2393         } else {
2394           child.index = index;
2395           child.name = 'program' + index;
2396         }
2397       }
2398     },
2399     matchExistingProgram: function(child) {
2400       for (var i = 0, len = this.context.environments.length; i < len; i++) {
2401         var environment = this.context.environments[i];
2402         if (environment && environment.equals(child)) {
2403           return i;
2404         }
2405       }
2406     },
2407
2408     programExpression: function(guid) {
2409       this.context.aliases.self = "this";
2410
2411       if(guid == null) {
2412         return "self.noop";
2413       }
2414
2415       var child = this.environment.children[guid],
2416           depths = child.depths.list, depth;
2417
2418       var programParams = [child.index, child.name, "data"];
2419
2420       for(var i=0, l = depths.length; i<l; i++) {
2421         depth = depths[i];
2422
2423         if(depth === 1) { programParams.push("depth0"); }
2424         else { programParams.push("depth" + (depth - 1)); }
2425       }
2426
2427       return (depths.length === 0 ? "self.program(" : "self.programWithDepth(") + programParams.join(", ") + ")";
2428     },
2429
2430     register: function(name, val) {
2431       this.useRegister(name);
2432       this.pushSource(name + " = " + val + ";");
2433     },
2434
2435     useRegister: function(name) {
2436       if(!this.registers[name]) {
2437         this.registers[name] = true;
2438         this.registers.list.push(name);
2439       }
2440     },
2441
2442     pushStackLiteral: function(item) {
2443       return this.push(new Literal(item));
2444     },
2445
2446     pushSource: function(source) {
2447       if (this.pendingContent) {
2448         this.source.push(this.appendToBuffer(this.quotedString(this.pendingContent)));
2449         this.pendingContent = undefined;
2450       }
2451
2452       if (source) {
2453         this.source.push(source);
2454       }
2455     },
2456
2457     pushStack: function(item) {
2458       this.flushInline();
2459
2460       var stack = this.incrStack();
2461       if (item) {
2462         this.pushSource(stack + " = " + item + ";");
2463       }
2464       this.compileStack.push(stack);
2465       return stack;
2466     },
2467
2468     replaceStack: function(callback) {
2469       var prefix = '',
2470           inline = this.isInline(),
2471           stack,
2472           createdStack,
2473           usedLiteral;
2474
2475       // If we are currently inline then we want to merge the inline statement into the
2476       // replacement statement via ','
2477       if (inline) {
2478         var top = this.popStack(true);
2479
2480         if (top instanceof Literal) {
2481           // Literals do not need to be inlined
2482           stack = top.value;
2483           usedLiteral = true;
2484         } else {
2485           // Get or create the current stack name for use by the inline
2486           createdStack = !this.stackSlot;
2487           var name = !createdStack ? this.topStackName() : this.incrStack();
2488
2489           prefix = '(' + this.push(name) + ' = ' + top + '),';
2490           stack = this.topStack();
2491         }
2492       } else {
2493         stack = this.topStack();
2494       }
2495
2496       var item = callback.call(this, stack);
2497
2498       if (inline) {
2499         if (!usedLiteral) {
2500           this.popStack();
2501         }
2502         if (createdStack) {
2503           this.stackSlot--;
2504         }
2505         this.push('(' + prefix + item + ')');
2506       } else {
2507         // Prevent modification of the context depth variable. Through replaceStack
2508         if (!/^stack/.test(stack)) {
2509           stack = this.nextStack();
2510         }
2511
2512         this.pushSource(stack + " = (" + prefix + item + ");");
2513       }
2514       return stack;
2515     },
2516
2517     nextStack: function() {
2518       return this.pushStack();
2519     },
2520
2521     incrStack: function() {
2522       this.stackSlot++;
2523       if(this.stackSlot > this.stackVars.length) { this.stackVars.push("stack" + this.stackSlot); }
2524       return this.topStackName();
2525     },
2526     topStackName: function() {
2527       return "stack" + this.stackSlot;
2528     },
2529     flushInline: function() {
2530       var inlineStack = this.inlineStack;
2531       if (inlineStack.length) {
2532         this.inlineStack = [];
2533         for (var i = 0, len = inlineStack.length; i < len; i++) {
2534           var entry = inlineStack[i];
2535           if (entry instanceof Literal) {
2536             this.compileStack.push(entry);
2537           } else {
2538             this.pushStack(entry);
2539           }
2540         }
2541       }
2542     },
2543     isInline: function() {
2544       return this.inlineStack.length;
2545     },
2546
2547     popStack: function(wrapped) {
2548       var inline = this.isInline(),
2549           item = (inline ? this.inlineStack : this.compileStack).pop();
2550
2551       if (!wrapped && (item instanceof Literal)) {
2552         return item.value;
2553       } else {
2554         if (!inline) {
2555           if (!this.stackSlot) {
2556             throw new Exception('Invalid stack pop');
2557           }
2558           this.stackSlot--;
2559         }
2560         return item;
2561       }
2562     },
2563
2564     topStack: function(wrapped) {
2565       var stack = (this.isInline() ? this.inlineStack : this.compileStack),
2566           item = stack[stack.length - 1];
2567
2568       if (!wrapped && (item instanceof Literal)) {
2569         return item.value;
2570       } else {
2571         return item;
2572       }
2573     },
2574
2575     quotedString: function(str) {
2576       return '"' + str
2577         .replace(/\\/g, '\\\\')
2578         .replace(/"/g, '\\"')
2579         .replace(/\n/g, '\\n')
2580         .replace(/\r/g, '\\r')
2581         .replace(/\u2028/g, '\\u2028')   // Per Ecma-262 7.3 + 7.8.4
2582         .replace(/\u2029/g, '\\u2029') + '"';
2583     },
2584
2585     setupHelper: function(paramSize, name, missingParams) {
2586       var params = [],
2587           paramsInit = this.setupParams(paramSize, params, missingParams);
2588       var foundHelper = this.nameLookup('helpers', name, 'helper');
2589
2590       return {
2591         params: params,
2592         paramsInit: paramsInit,
2593         name: foundHelper,
2594         callParams: ["depth0"].concat(params).join(", "),
2595         helperMissingParams: missingParams && ["depth0", this.quotedString(name)].concat(params).join(", ")
2596       };
2597     },
2598
2599     setupOptions: function(paramSize, params) {
2600       var options = [], contexts = [], types = [], param, inverse, program;
2601
2602       options.push("hash:" + this.popStack());
2603
2604       if (this.options.stringParams) {
2605         options.push("hashTypes:" + this.popStack());
2606         options.push("hashContexts:" + this.popStack());
2607       }
2608
2609       inverse = this.popStack();
2610       program = this.popStack();
2611
2612       // Avoid setting fn and inverse if neither are set. This allows
2613       // helpers to do a check for `if (options.fn)`
2614       if (program || inverse) {
2615         if (!program) {
2616           this.context.aliases.self = "this";
2617           program = "self.noop";
2618         }
2619
2620         if (!inverse) {
2621           this.context.aliases.self = "this";
2622           inverse = "self.noop";
2623         }
2624
2625         options.push("inverse:" + inverse);
2626         options.push("fn:" + program);
2627       }
2628
2629       for(var i=0; i<paramSize; i++) {
2630         param = this.popStack();
2631         params.push(param);
2632
2633         if(this.options.stringParams) {
2634           types.push(this.popStack());
2635           contexts.push(this.popStack());
2636         }
2637       }
2638
2639       if (this.options.stringParams) {
2640         options.push("contexts:[" + contexts.join(",") + "]");
2641         options.push("types:[" + types.join(",") + "]");
2642       }
2643
2644       if(this.options.data) {
2645         options.push("data:data");
2646       }
2647
2648       return options;
2649     },
2650
2651     // the params and contexts arguments are passed in arrays
2652     // to fill in
2653     setupParams: function(paramSize, params, useRegister) {
2654       var options = '{' + this.setupOptions(paramSize, params).join(',') + '}';
2655
2656       if (useRegister) {
2657         this.useRegister('options');
2658         params.push('options');
2659         return 'options=' + options;
2660       } else {
2661         params.push(options);
2662         return '';
2663       }
2664     }
2665   };
2666
2667   var reservedWords = (
2668     "break else new var" +
2669     " case finally return void" +
2670     " catch for switch while" +
2671     " continue function this with" +
2672     " default if throw" +
2673     " delete in try" +
2674     " do instanceof typeof" +
2675     " abstract enum int short" +
2676     " boolean export interface static" +
2677     " byte extends long super" +
2678     " char final native synchronized" +
2679     " class float package throws" +
2680     " const goto private transient" +
2681     " debugger implements protected volatile" +
2682     " double import public let yield"
2683   ).split(" ");
2684
2685   var compilerWords = JavaScriptCompiler.RESERVED_WORDS = {};
2686
2687   for(var i=0, l=reservedWords.length; i<l; i++) {
2688     compilerWords[reservedWords[i]] = true;
2689   }
2690
2691   JavaScriptCompiler.isValidJavaScriptVariableName = function(name) {
2692     if(!JavaScriptCompiler.RESERVED_WORDS[name] && /^[a-zA-Z_$][0-9a-zA-Z_$]*$/.test(name)) {
2693       return true;
2694     }
2695     return false;
2696   };
2697
2698   __exports__ = JavaScriptCompiler;
2699   return __exports__;
2700 })(__module2__, __module5__);
2701
2702 // handlebars.js
2703 var __module0__ = (function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__) {
2704   "use strict";
2705   var __exports__;
2706   /*globals Handlebars: true */
2707   var Handlebars = __dependency1__;
2708
2709   // Compiler imports
2710   var AST = __dependency2__;
2711   var Parser = __dependency3__.parser;
2712   var parse = __dependency3__.parse;
2713   var Compiler = __dependency4__.Compiler;
2714   var compile = __dependency4__.compile;
2715   var precompile = __dependency4__.precompile;
2716   var JavaScriptCompiler = __dependency5__;
2717
2718   var _create = Handlebars.create;
2719   var create = function() {
2720     var hb = _create();
2721
2722     hb.compile = function(input, options) {
2723       return compile(input, options, hb);
2724     };
2725     hb.precompile = function (input, options) {
2726       return precompile(input, options, hb);
2727     };
2728
2729     hb.AST = AST;
2730     hb.Compiler = Compiler;
2731     hb.JavaScriptCompiler = JavaScriptCompiler;
2732     hb.Parser = Parser;
2733     hb.parse = parse;
2734
2735     return hb;
2736   };
2737
2738   Handlebars = create();
2739   Handlebars.create = create;
2740
2741   __exports__ = Handlebars;
2742   return __exports__;
2743 })(__module1__, __module7__, __module8__, __module10__, __module11__);
2744
2745   return __module0__;
2746 })();