github.com/enmand/kubernetes@v1.2.0-alpha.0/third_party/swagger-ui/lib/handlebars-1.0.0.js (about)

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