vendor: 21,320 bytes, lines 1-750
1/*! 2 * Copyright 2011 Twitter, Inc. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16 17 18var Hogan = {}; 19 20(function (Hogan) { 21 Hogan.Template = function (codeObj, text, compiler, options) { 22 codeObj = codeObj || {}; 23 this.r = codeObj.code || this.r; 24 this.c = compiler; 25 this.options = options || {}; 26 this.text = text || ''; 27 this.partials = codeObj.partials || {}; 28 this.subs = codeObj.subs || {}; 29 this.buf = ''; 30 } 31 32 Hogan.Template.prototype = { 33 // render: replaced by generated code. 34 r: function (context, partials, indent) { return ''; }, 35 36 // variable escaping 37 v: hoganEscape, 38 39 // triple stache 40 t: coerceToString, 41 42 render: function render(context, partials, indent) { 43 return this.ri([context], partials || {}, indent); 44 }, 45 46 // render internal -- a hook for overrides that catches partials too 47 ri: function (context, partials, indent) { 48 return this.r(context, partials, indent); 49 }, 50 51 // ensurePartial 52 ep: function(symbol, partials) { 53 var partial = this.partials[symbol]; 54 55 // check to see that if we've instantiated this partial before 56 var template = partials[partial.name]; 57 if (partial.instance && partial.base == template) { 58 return partial.instance; 59 } 60 61 if (typeof template == 'string') { 62 if (!this.c) { 63 throw new Error("No compiler available."); 64 } 65 template = this.c.compile(template, this.options); 66 } 67 68 if (!template) { 69 return null; 70 } 71 72 // We use this to check whether the partials dictionary has changed 73 this.partials[symbol].base = template; 74 75 if (partial.subs) { 76 // Make sure we consider parent template now 77 if (!partials.stackText) partials.stackText = {}; 78 for (key in partial.subs) { 79 if (!partials.stackText[key]) { 80 partials.stackText[key] = (this.activeSub !== undefined && partials.stackText[this.activeSub]) ? partials.stackText[this.activeSub] : this.text; 81 } 82 } 83 template = createSpecializedPartial(template, partial.subs, partial.partials, 84 this.stackSubs, this.stackPartials, partials.stackText); 85 } 86 this.partials[symbol].instance = template; 87 88 return template; 89 }, 90 91 // tries to find a partial in the current scope and render it 92 rp: function(symbol, context, partials, indent) { 93 var partial = this.ep(symbol, partials); 94 if (!partial) { 95 return ''; 96 } 97 98 return partial.ri(context, partials, indent); 99 }, 100 101 // render a section 102 rs: function(context, partials, section) { 103 var tail = context[context.length - 1]; 104 105 if (!isArray(tail)) { 106 section(context, partials, this); 107 return; 108 } 109 110 for (var i = 0; i < tail.length; i++) { 111 context.push(tail[i]); 112 section(context, partials, this); 113 context.pop(); 114 } 115 }, 116 117 // maybe start a section 118 s: function(val, ctx, partials, inverted, start, end, tags) { 119 var pass; 120 121 if (isArray(val) && val.length === 0) { 122 return false; 123 } 124 125 if (typeof val == 'function') { 126 val = this.ms(val, ctx, partials, inverted, start, end, tags); 127 } 128 129 pass = !!val; 130 131 if (!inverted && pass && ctx) { 132 ctx.push((typeof val == 'object') ? val : ctx[ctx.length - 1]); 133 } 134 135 return pass; 136 }, 137 138 // find values with dotted names 139 d: function(key, ctx, partials, returnFound) { 140 var found, 141 names = key.split('.'), 142 val = this.f(names[0], ctx, partials, returnFound), 143 doModelGet = this.options.modelGet, 144 cx = null; 145 146 if (key === '.' && isArray(ctx[ctx.length - 2])) { 147 val = ctx[ctx.length - 1]; 148 } else { 149 for (var i = 1; i < names.length; i++) { 150 found = findInScope(names[i], val, doModelGet); 151 if (found != null) { 152 cx = val; 153 val = found; 154 } else { 155 val = ''; 156 } 157 } 158 } 159 160 if (returnFound && !val) { 161 return false; 162 } 163 164 if (!returnFound && typeof val == 'function') { 165 ctx.push(cx); 166 val = this.mv(val, ctx, partials); 167 ctx.pop(); 168 } 169 170 return val; 171 }, 172 173 // find values with normal names 174 f: function(key, ctx, partials, returnFound) { 175 var val = false, 176 v = null, 177 found = false, 178 doModelGet = this.options.modelGet; 179 180 for (var i = ctx.length - 1; i >= 0; i--) { 181 v = ctx[i]; 182 val = findInScope(key, v, doModelGet); 183 if (val != null) { 184 found = true; 185 break; 186 } 187 } 188 189 if (!found) { 190 return (returnFound) ? false : ""; 191 } 192 193 if (!returnFound && typeof val == 'function') { 194 val = this.mv(val, ctx, partials); 195 } 196 197 return val; 198 }, 199 200 // higher order templates 201 ls: function(func, cx, partials, text, tags) { 202 var oldTags = this.options.delimiters; 203 204 this.options.delimiters = tags; 205 this.b(this.ct(coerceToString(func.call(cx, text)), cx, partials)); 206 this.options.delimiters = oldTags; 207 208 return false; 209 }, 210 211 // compile text 212 ct: function(text, cx, partials) { 213 if (this.options.disableLambda) { 214 throw new Error('Lambda features disabled.'); 215 } 216 return this.c.compile(text, this.options).render(cx, partials); 217 }, 218 219 // template result buffering 220 b: function(s) { this.buf += s; }, 221 222 fl: function() { var r = this.buf; this.buf = ''; return r; }, 223 224 // method replace section 225 ms: function(func, ctx, partials, inverted, start, end, tags) { 226 var textSource, 227 cx = ctx[ctx.length - 1], 228 result = func.call(cx); 229 230 if (typeof result == 'function') { 231 if (inverted) { 232 return true; 233 } else { 234 textSource = (this.activeSub && this.subsText && this.subsText[this.activeSub]) ? this.subsText[this.activeSub] : this.text; 235 return this.ls(result, cx, partials, textSource.substring(start, end), tags); 236 } 237 } 238 239 return result; 240 }, 241 242 // method replace variable 243 mv: function(func, ctx, partials) { 244 var cx = ctx[ctx.length - 1]; 245 var result = func.call(cx); 246 247 if (typeof result == 'function') { 248 return this.ct(coerceToString(result.call(cx)), cx, partials); 249 } 250 251 return result; 252 }, 253 254 sub: function(name, context, partials, indent) { 255 var f = this.subs[name]; 256 if (f) { 257 this.activeSub = name; 258 f(context, partials, this, indent); 259 this.activeSub = false; 260 } 261 } 262 263 }; 264 265 //Find a key in an object 266 function findInScope(key, scope, doModelGet) { 267 var val, checkVal; 268 269 if (scope && typeof scope == 'object') { 270 271 if (scope[key] != null) { 272 val = scope[key]; 273 274 // try lookup with get for backbone or similar model data 275 } else if (doModelGet && scope.get && typeof scope.get == 'function') { 276 val = scope.get(key); 277 } 278 } 279 280 return val; 281 } 282 283 function createSpecializedPartial(instance, subs, partials, stackSubs, stackPartials, stackText) { 284 function PartialTemplate() {}; 285 PartialTemplate.prototype = instance; 286 function Substitutions() {}; 287 Substitutions.prototype = instance.subs; 288 var key; 289 var partial = new PartialTemplate(); 290 partial.subs = new Substitutions(); 291 partial.subsText = {}; //hehe. substext. 292 partial.buf = ''; 293 294 stackSubs = stackSubs || {}; 295 partial.stackSubs = stackSubs; 296 partial.subsText = stackText; 297 for (key in subs) { 298 if (!stackSubs[key]) stackSubs[key] = subs[key]; 299 } 300 for (key in stackSubs) { 301 partial.subs[key] = stackSubs[key]; 302 } 303 304 stackPartials = stackPartials || {}; 305 partial.stackPartials = stackPartials; 306 for (key in partials) { 307 if (!stackPartials[key]) stackPartials[key] = partials[key]; 308 } 309 for (key in stackPartials) { 310 partial.partials[key] = stackPartials[key]; 311 } 312 313 return partial; 314 } 315 316 var rAmp = /&/g, 317 rLt = /</g, 318 rGt = />/g, 319 rApos = /\'/g, 320 rQuot = /\"/g, 321 hChars = /[&<>\"\']/; 322 323 function coerceToString(val) { 324 return String((val === null || val === undefined) ? '' : val); 325 } 326 327 function hoganEscape(str) { 328 str = coerceToString(str); 329 return hChars.test(str) ? 330 str 331 .replace(rAmp, '&') 332 .replace(rLt, '<') 333 .replace(rGt, '>') 334 .replace(rApos, ''') 335 .replace(rQuot, '"') : 336 str; 337 } 338 339 var isArray = Array.isArray || function(a) { 340 return Object.prototype.toString.call(a) === '[object Array]'; 341 }; 342 343})(typeof exports !== 'undefined' ? exports : Hogan); 344 345 346 347(function (Hogan) { 348 // Setup regex assignments 349 // remove whitespace according to Mustache spec 350 var rIsWhitespace = /\S/, 351 rQuot = /\"/g, 352 rNewline = /\n/g, 353 rCr = /\r/g, 354 rSlash = /\\/g; 355 356 Hogan.tags = { 357 '#': 1, '^': 2, '<': 3, '$': 4, 358 '/': 5, '!': 6, '>': 7, '=': 8, '_v': 9, 359 '{': 10, '&': 11, '_t': 12 360 }; 361 362 Hogan.scan = function scan(text, delimiters) { 363 var len = text.length, 364 IN_TEXT = 0, 365 IN_TAG_TYPE = 1, 366 IN_TAG = 2, 367 state = IN_TEXT, 368 tagType = null, 369 tag = null, 370 buf = '', 371 tokens = [], 372 seenTag = false, 373 i = 0, 374 lineStart = 0, 375 otag = '{{', 376 ctag = '}}'; 377 378 function addBuf() { 379 if (buf.length > 0) { 380 tokens.push({tag: '_t', text: new String(buf)}); 381 buf = ''; 382 } 383 } 384 385 function lineIsWhitespace() { 386 var isAllWhitespace = true; 387 for (var j = lineStart; j < tokens.length; j++) { 388 isAllWhitespace = 389 (Hogan.tags[tokens[j].tag] < Hogan.tags['_v']) || 390 (tokens[j].tag == '_t' && tokens[j].text.match(rIsWhitespace) === null); 391 if (!isAllWhitespace) { 392 return false; 393 } 394 } 395 396 return isAllWhitespace; 397 } 398 399 function filterLine(haveSeenTag, noNewLine) { 400 addBuf(); 401 402 if (haveSeenTag && lineIsWhitespace()) { 403 for (var j = lineStart, next; j < tokens.length; j++) { 404 if (tokens[j].text) { 405 if ((next = tokens[j+1]) && next.tag == '>') { 406 // set indent to token value 407 next.indent = tokens[j].text.toString() 408 } 409 tokens.splice(j, 1); 410 } 411 } 412 } else if (!noNewLine) { 413 tokens.push({tag:'\n'}); 414 } 415 416 seenTag = false; 417 lineStart = tokens.length; 418 } 419 420 function changeDelimiters(text, index) { 421 var close = '=' + ctag, 422 closeIndex = text.indexOf(close, index), 423 delimiters = trim( 424 text.substring(text.indexOf('=', index) + 1, closeIndex) 425 ).split(' '); 426 427 otag = delimiters[0]; 428 ctag = delimiters[delimiters.length - 1]; 429 430 return closeIndex + close.length - 1; 431 } 432 433 if (delimiters) { 434 delimiters = delimiters.split(' '); 435 otag = delimiters[0]; 436 ctag = delimiters[1]; 437 } 438 439 for (i = 0; i < len; i++) { 440 if (state == IN_TEXT) { 441 if (tagChange(otag, text, i)) { 442 --i; 443 addBuf(); 444 state = IN_TAG_TYPE; 445 } else { 446 if (text.charAt(i) == '\n') { 447 filterLine(seenTag); 448 } else { 449 buf += text.charAt(i); 450 } 451 } 452 } else if (state == IN_TAG_TYPE) { 453 i += otag.length - 1; 454 tag = Hogan.tags[text.charAt(i + 1)]; 455 tagType = tag ? text.charAt(i + 1) : '_v'; 456 if (tagType == '=') { 457 i = changeDelimiters(text, i); 458 state = IN_TEXT; 459 } else { 460 if (tag) { 461 i++; 462 } 463 state = IN_TAG; 464 } 465 seenTag = i; 466 } else { 467 if (tagChange(ctag, text, i)) { 468 tokens.push({tag: tagType, n: trim(buf), otag: otag, ctag: ctag, 469 i: (tagType == '/') ? seenTag - otag.length : i + ctag.length}); 470 buf = ''; 471 i += ctag.length - 1; 472 state = IN_TEXT; 473 if (tagType == '{') { 474 if (ctag == '}}') { 475 i++; 476 } else { 477 cleanTripleStache(tokens[tokens.length - 1]); 478 } 479 } 480 } else { 481 buf += text.charAt(i); 482 } 483 } 484 } 485 486 filterLine(seenTag, true); 487 488 return tokens; 489 } 490 491 function cleanTripleStache(token) { 492 if (token.n.substr(token.n.length - 1) === '}') { 493 token.n = token.n.substring(0, token.n.length - 1); 494 } 495 } 496 497 function trim(s) { 498 if (s.trim) { 499 return s.trim(); 500 } 501 502 return s.replace(/^\s*|\s*$/g, ''); 503 } 504 505 function tagChange(tag, text, index) { 506 if (text.charAt(index) != tag.charAt(0)) { 507 return false; 508 } 509 510 for (var i = 1, l = tag.length; i < l; i++) { 511 if (text.charAt(index + i) != tag.charAt(i)) { 512 return false; 513 } 514 } 515 516 return true; 517 } 518 519 // the tags allowed inside super templates 520 var allowedInSuper = {'_t': true, '\n': true, '$': true, '/': true}; 521 522 function buildTree(tokens, kind, stack, customTags) { 523 var instructions = [], 524 opener = null, 525 tail = null, 526 token = null; 527 528 tail = stack[stack.length - 1]; 529 530 while (tokens.length > 0) { 531 token = tokens.shift(); 532 533 if (tail && tail.tag == '<' && !(token.tag in allowedInSuper)) { 534 throw new Error('Illegal content in < super tag.'); 535 } 536 537 if (Hogan.tags[token.tag] <= Hogan.tags['$'] || isOpener(token, customTags)) { 538 stack.push(token); 539 token.nodes = buildTree(tokens, token.tag, stack, customTags); 540 } else if (token.tag == '/') { 541 if (stack.length === 0) { 542 throw new Error('Closing tag without opener: /' + token.n); 543 } 544 opener = stack.pop(); 545 if (token.n != opener.n && !isCloser(token.n, opener.n, customTags)) { 546 throw new Error('Nesting error: ' + opener.n + ' vs. ' + token.n); 547 } 548 opener.end = token.i; 549 return instructions; 550 } else if (token.tag == '\n') { 551 token.last = (tokens.length == 0) || (tokens[0].tag == '\n'); 552 } 553 554 instructions.push(token); 555 } 556 557 if (stack.length > 0) { 558 throw new Error('missing closing tag: ' + stack.pop().n); 559 } 560 561 return instructions; 562 } 563 564 function isOpener(token, tags) { 565 for (var i = 0, l = tags.length; i < l; i++) { 566 if (tags[i].o == token.n) { 567 token.tag = '#'; 568 return true; 569 } 570 } 571 } 572 573 function isCloser(close, open, tags) { 574 for (var i = 0, l = tags.length; i < l; i++) { 575 if (tags[i].c == close && tags[i].o == open) { 576 return true; 577 } 578 } 579 } 580 581 function stringifySubstitutions(obj) { 582 var items = []; 583 for (var key in obj) { 584 items.push('"' + esc(key) + '": function(c,p,t,i) {' + obj[key] + '}'); 585 } 586 return "{ " + items.join(",") + " }"; 587 } 588 589 function stringifyPartials(codeObj) { 590 var partials = []; 591 for (var key in codeObj.partials) { 592 partials.push('"' + esc(key) + '":{name:"' + esc(codeObj.partials[key].name) + '", ' + stringifyPartials(codeObj.partials[key]) + "}"); 593 } 594 return "partials: {" + partials.join(",") + "}, subs: " + stringifySubstitutions(codeObj.subs); 595 } 596 597 Hogan.stringify = function(codeObj, text, options) { 598 return "{code: function (c,p,i) { " + Hogan.wrapMain(codeObj.code) + " }," + stringifyPartials(codeObj) + "}"; 599 } 600 601 var serialNo = 0; 602 Hogan.generate = function(tree, text, options) { 603 serialNo = 0; 604 var context = { code: '', subs: {}, partials: {} }; 605 Hogan.walk(tree, context); 606 607 if (options.asString) { 608 return this.stringify(context, text, options); 609 } 610 611 return this.makeTemplate(context, text, options); 612 } 613 614 Hogan.wrapMain = function(code) { 615 return 'var t=this;t.b(i=i||"");' + code + 'return t.fl();'; 616 } 617 618 Hogan.template = Hogan.Template; 619 620 Hogan.makeTemplate = function(codeObj, text, options) { 621 var template = this.makePartials(codeObj); 622 template.code = new Function('c', 'p', 'i', this.wrapMain(codeObj.code)); 623 return new this.template(template, text, this, options); 624 } 625 626 Hogan.makePartials = function(codeObj) { 627 var key, template = {subs: {}, partials: codeObj.partials, name: codeObj.name}; 628 for (key in template.partials) { 629 template.partials[key] = this.makePartials(template.partials[key]); 630 } 631 for (key in codeObj.subs) { 632 template.subs[key] = new Function('c', 'p', 't', 'i', codeObj.subs[key]); 633 } 634 return template; 635 } 636 637 function esc(s) { 638 return s.replace(rSlash, '\\\\') 639 .replace(rQuot, '\\\"') 640 .replace(rNewline, '\\n') 641 .replace(rCr, '\\r'); 642 } 643 644 function chooseMethod(s) { 645 return (~s.indexOf('.')) ? 'd' : 'f'; 646 } 647 648 function createPartial(node, context) { 649 var prefix = "<" + (context.prefix || ""); 650 var sym = prefix + node.n + serialNo++; 651 context.partials[sym] = {name: node.n, partials: {}}; 652 context.code += 't.b(t.rp("' + esc(sym) + '",c,p,"' + (node.indent || '') + '"));'; 653 return sym; 654 } 655 656 Hogan.codegen = { 657 '#': function(node, context) { 658 context.code += 'if(t.s(t.' + chooseMethod(node.n) + '("' + esc(node.n) + '",c,p,1),' + 659 'c,p,0,' + node.i + ',' + node.end + ',"' + node.otag + " " + node.ctag + '")){' + 660 't.rs(c,p,' + 'function(c,p,t){'; 661 Hogan.walk(node.nodes, context); 662 context.code += '});c.pop();}'; 663 }, 664 665 '^': function(node, context) { 666 context.code += 'if(!t.s(t.' + chooseMethod(node.n) + '("' + esc(node.n) + '",c,p,1),c,p,1,0,0,"")){'; 667 Hogan.walk(node.nodes, context); 668 context.code += '};'; 669 }, 670 671 '>': createPartial, 672 '<': function(node, context) { 673 var ctx = {partials: {}, code: '', subs: {}, inPartial: true}; 674 Hogan.walk(node.nodes, ctx); 675 var template = context.partials[createPartial(node, context)]; 676 template.subs = ctx.subs; 677 template.partials = ctx.partials; 678 }, 679 680 '$': function(node, context) { 681 var ctx = {subs: {}, code: '', partials: context.partials, prefix: node.n}; 682 Hogan.walk(node.nodes, ctx); 683 context.subs[node.n] = ctx.code; 684 if (!context.inPartial) { 685 context.code += 't.sub("' + esc(node.n) + '",c,p,i);'; 686 } 687 }, 688 689 '\n': function(node, context) { 690 context.code += write('"\\n"' + (node.last ? '' : ' + i')); 691 }, 692 693 '_v': function(node, context) { 694 context.code += 't.b(t.v(t.' + chooseMethod(node.n) + '("' + esc(node.n) + '",c,p,0)));'; 695 }, 696 697 '_t': function(node, context) { 698 context.code += write('"' + esc(node.text) + '"'); 699 }, 700 701 '{': tripleStache, 702 703 '&': tripleStache 704 } 705 706 function tripleStache(node, context) { 707 context.code += 't.b(t.t(t.' + chooseMethod(node.n) + '("' + esc(node.n) + '",c,p,0)));'; 708 } 709 710 function write(s) { 711 return 't.b(' + s + ');'; 712 } 713 714 Hogan.walk = function(nodelist, context) { 715 var func; 716 for (var i = 0, l = nodelist.length; i < l; i++) { 717 func = Hogan.codegen[nodelist[i].tag]; 718 func && func(nodelist[i], context); 719 } 720 return context; 721 } 722 723 Hogan.parse = function(tokens, text, options) { 724 options = options || {}; 725 return buildTree(tokens, '', [], options.sectionTags || []); 726 } 727 728 Hogan.cache = {}; 729 730 Hogan.cacheKey = function(text, options) { 731 return [text, !!options.asString, !!options.disableLambda, options.delimiters, !!options.modelGet].join('||'); 732 } 733 734 Hogan.compile = function(text, options) { 735 options = options || {}; 736 var key = Hogan.cacheKey(text, options); 737 var template = this.cache[key]; 738 739 if (template) { 740 var partials = template.partials; 741 for (var name in partials) { 742 delete partials[name].instance; 743 } 744 return template; 745 } 746 747 template = this.generate(this.parse(this.scan(text, options.delimiters), text, options), text, options); 748 return this.cache[key] = template; 749 } 750})(typeof exports !== 'undefined' ? exports : Hogan);
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.