diff --git a/NOTICE b/NOTICE index e2479553b..47de2415e 100644 --- a/NOTICE +++ b/NOTICE @@ -39,9 +39,12 @@ https://github.com/shutterstock/rickshaw Copyright 2011-2014 by Shutterstock Images, LLC See https://github.com/shutterstock/rickshaw/blob/master/LICENSE for license details -handlebars.js -Copyright 2011 by Yehuda Katz -See web/static/vendor/js/handlebars.js for license details +mustache.js +https://github.com/janl/mustache.js +Copyright 2009 Chris Wanstrath (Ruby) +Copyright 2010-2014 Jan Lehnardt (JavaScript) +Copyright 2010-2015 The mustache.js community +Licensed under the MIT License jQuery https://jquery.org diff --git a/web/ui/static/js/graph.js b/web/ui/static/js/graph.js index c44eb1f6b..2cbc9e1d0 100644 --- a/web/ui/static/js/graph.js +++ b/web/ui/static/js/graph.js @@ -3,8 +3,6 @@ var graphTemplate; var SECOND = 1000; -Handlebars.registerHelper('pathPrefix', function() { return PATH_PREFIX; }); - Prometheus.Graph = function(element, options, handleChange, handleRemove) { this.el = element; this.graphHTML = null; @@ -48,7 +46,9 @@ Prometheus.Graph.prototype.initialize = function() { // Draw graph controls and container from Handlebars template. - self.graphHTML = $(graphTemplate(self.options)); + var options = {'pathPrefix': PATH_PREFIX}; + jQuery.extend(options, self.options); + self.graphHTML = $(Mustache.render(graphTemplate, options)); self.el.append(self.graphHTML); // Get references to all the interesting elements in the graph container and @@ -822,7 +822,9 @@ function init() { $.ajax({ url: PATH_PREFIX + "/static/js/graph_template.handlebar", success: function(data) { - graphTemplate = Handlebars.compile(data); + + graphTemplate = data; + Mustache.parse(data); if (isDeprecatedGraphURL()) { redirectToMigratedURL(); } else { diff --git a/web/ui/static/vendor/js/handlebars.js b/web/ui/static/vendor/js/handlebars.js deleted file mode 100644 index 5db8e32d1..000000000 --- a/web/ui/static/vendor/js/handlebars.js +++ /dev/null @@ -1,2014 +0,0 @@ -/* -Copyright (C) 2011 by Yehuda Katz - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -*/ - -// lib/handlebars/base.js - -/*jshint eqnull:true*/ -this.Handlebars = {}; - -(function(Handlebars) { - -Handlebars.VERSION = "1.0.rc.2"; - -Handlebars.helpers = {}; -Handlebars.partials = {}; - -Handlebars.registerHelper = function(name, fn, inverse) { - if(inverse) { fn.not = inverse; } - this.helpers[name] = fn; -}; - -Handlebars.registerPartial = function(name, str) { - this.partials[name] = str; -}; - -Handlebars.registerHelper('helperMissing', function(arg) { - if(arguments.length === 2) { - return undefined; - } else { - throw new Error("Could not find property '" + arg + "'"); - } -}); - -var toString = Object.prototype.toString, functionType = "[object Function]"; - -Handlebars.registerHelper('blockHelperMissing', function(context, options) { - var inverse = options.inverse || function() {}, fn = options.fn; - - - var ret = ""; - var type = toString.call(context); - - if(type === functionType) { context = context.call(this); } - - if(context === true) { - return fn(this); - } else if(context === false || context == null) { - return inverse(this); - } else if(type === "[object Array]") { - if(context.length > 0) { - return Handlebars.helpers.each(context, options); - } else { - return inverse(this); - } - } else { - return fn(context); - } -}); - -Handlebars.K = function() {}; - -Handlebars.createFrame = Object.create || function(object) { - Handlebars.K.prototype = object; - var obj = new Handlebars.K(); - Handlebars.K.prototype = null; - return obj; -}; - -Handlebars.logger = { - DEBUG: 0, INFO: 1, WARN: 2, ERROR: 3, level: 3, - - methodMap: {0: 'debug', 1: 'info', 2: 'warn', 3: 'error'}, - - // can be overridden in the host environment - log: function(level, obj) { - if (Handlebars.logger.level <= level) { - var method = Handlebars.logger.methodMap[level]; - if (typeof console !== 'undefined' && console[method]) { - console[method].call(console, obj); - } - } - } -}; - -Handlebars.log = function(level, obj) { Handlebars.logger.log(level, obj); }; - -Handlebars.registerHelper('each', function(context, options) { - var fn = options.fn, inverse = options.inverse; - var i = 0, ret = "", data; - - if (options.data) { - data = Handlebars.createFrame(options.data); - } - - if(context && typeof context === 'object') { - if(context instanceof Array){ - for(var j = context.length; i 2) { - expected.push("'" + this.terminals_[p] + "'"); - } - if (this.lexer.showPosition) { - errStr = "Parse error on line " + (yylineno + 1) + ":\n" + this.lexer.showPosition() + "\nExpecting " + expected.join(", ") + ", got '" + (this.terminals_[symbol] || symbol) + "'"; - } else { - errStr = "Parse error on line " + (yylineno + 1) + ": Unexpected " + (symbol == 1?"end of input":"'" + (this.terminals_[symbol] || symbol) + "'"); - } - this.parseError(errStr, {text: this.lexer.match, token: this.terminals_[symbol] || symbol, line: this.lexer.yylineno, loc: yyloc, expected: expected}); - } - } - if (action[0] instanceof Array && action.length > 1) { - throw new Error("Parse Error: multiple actions possible at state: " + state + ", token: " + symbol); - } - switch (action[0]) { - case 1: - stack.push(symbol); - vstack.push(this.lexer.yytext); - lstack.push(this.lexer.yylloc); - stack.push(action[1]); - symbol = null; - if (!preErrorSymbol) { - yyleng = this.lexer.yyleng; - yytext = this.lexer.yytext; - yylineno = this.lexer.yylineno; - yyloc = this.lexer.yylloc; - if (recovering > 0) - recovering--; - } else { - symbol = preErrorSymbol; - preErrorSymbol = null; - } - break; - case 2: - len = this.productions_[action[1]][1]; - yyval.$ = vstack[vstack.length - len]; - 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}; - if (ranges) { - yyval._$.range = [lstack[lstack.length - (len || 1)].range[0], lstack[lstack.length - 1].range[1]]; - } - r = this.performAction.call(yyval, yytext, yyleng, yylineno, this.yy, action[1], vstack, lstack); - if (typeof r !== "undefined") { - return r; - } - if (len) { - stack = stack.slice(0, -1 * len * 2); - vstack = vstack.slice(0, -1 * len); - lstack = lstack.slice(0, -1 * len); - } - stack.push(this.productions_[action[1]][0]); - vstack.push(yyval.$); - lstack.push(yyval._$); - newState = table[stack[stack.length - 2]][stack[stack.length - 1]]; - stack.push(newState); - break; - case 3: - return true; - } - } - return true; -} -}; -/* Jison generated lexer */ -var lexer = (function(){ -var lexer = ({EOF:1, -parseError:function parseError(str, hash) { - if (this.yy.parser) { - this.yy.parser.parseError(str, hash); - } else { - throw new Error(str); - } - }, -setInput:function (input) { - this._input = input; - this._more = this._less = this.done = false; - this.yylineno = this.yyleng = 0; - this.yytext = this.matched = this.match = ''; - this.conditionStack = ['INITIAL']; - this.yylloc = {first_line:1,first_column:0,last_line:1,last_column:0}; - if (this.options.ranges) this.yylloc.range = [0,0]; - this.offset = 0; - return this; - }, -input:function () { - var ch = this._input[0]; - this.yytext += ch; - this.yyleng++; - this.offset++; - this.match += ch; - this.matched += ch; - var lines = ch.match(/(?:\r\n?|\n).*/g); - if (lines) { - this.yylineno++; - this.yylloc.last_line++; - } else { - this.yylloc.last_column++; - } - if (this.options.ranges) this.yylloc.range[1]++; - - this._input = this._input.slice(1); - return ch; - }, -unput:function (ch) { - var len = ch.length; - var lines = ch.split(/(?:\r\n?|\n)/g); - - this._input = ch + this._input; - this.yytext = this.yytext.substr(0, this.yytext.length-len-1); - //this.yyleng -= len; - this.offset -= len; - var oldLines = this.match.split(/(?:\r\n?|\n)/g); - this.match = this.match.substr(0, this.match.length-1); - this.matched = this.matched.substr(0, this.matched.length-1); - - if (lines.length-1) this.yylineno -= lines.length-1; - var r = this.yylloc.range; - - this.yylloc = {first_line: this.yylloc.first_line, - last_line: this.yylineno+1, - first_column: this.yylloc.first_column, - last_column: lines ? - (lines.length === oldLines.length ? this.yylloc.first_column : 0) + oldLines[oldLines.length - lines.length].length - lines[0].length: - this.yylloc.first_column - len - }; - - if (this.options.ranges) { - this.yylloc.range = [r[0], r[0] + this.yyleng - len]; - } - return this; - }, -more:function () { - this._more = true; - return this; - }, -less:function (n) { - this.unput(this.match.slice(n)); - }, -pastInput:function () { - var past = this.matched.substr(0, this.matched.length - this.match.length); - return (past.length > 20 ? '...':'') + past.substr(-20).replace(/\n/g, ""); - }, -upcomingInput:function () { - var next = this.match; - if (next.length < 20) { - next += this._input.substr(0, 20-next.length); - } - return (next.substr(0,20)+(next.length > 20 ? '...':'')).replace(/\n/g, ""); - }, -showPosition:function () { - var pre = this.pastInput(); - var c = new Array(pre.length + 1).join("-"); - return pre + this.upcomingInput() + "\n" + c+"^"; - }, -next:function () { - if (this.done) { - return this.EOF; - } - if (!this._input) this.done = true; - - var token, - match, - tempMatch, - index, - col, - lines; - if (!this._more) { - this.yytext = ''; - this.match = ''; - } - var rules = this._currentRules(); - for (var i=0;i < rules.length; i++) { - tempMatch = this._input.match(this.rules[rules[i]]); - if (tempMatch && (!match || tempMatch[0].length > match[0].length)) { - match = tempMatch; - index = i; - if (!this.options.flex) break; - } - } - if (match) { - lines = match[0].match(/(?:\r\n?|\n).*/g); - if (lines) this.yylineno += lines.length; - this.yylloc = {first_line: this.yylloc.last_line, - last_line: this.yylineno+1, - first_column: this.yylloc.last_column, - last_column: lines ? lines[lines.length-1].length-lines[lines.length-1].match(/\r?\n?/)[0].length : this.yylloc.last_column + match[0].length}; - this.yytext += match[0]; - this.match += match[0]; - this.matches = match; - this.yyleng = this.yytext.length; - if (this.options.ranges) { - this.yylloc.range = [this.offset, this.offset += this.yyleng]; - } - this._more = false; - this._input = this._input.slice(match[0].length); - this.matched += match[0]; - token = this.performAction.call(this, this.yy, this, rules[index],this.conditionStack[this.conditionStack.length-1]); - if (this.done && this._input) this.done = false; - if (token) return token; - else return; - } - if (this._input === "") { - return this.EOF; - } else { - return this.parseError('Lexical error on line '+(this.yylineno+1)+'. Unrecognized text.\n'+this.showPosition(), - {text: "", token: null, line: this.yylineno}); - } - }, -lex:function lex() { - var r = this.next(); - if (typeof r !== 'undefined') { - return r; - } else { - return this.lex(); - } - }, -begin:function begin(condition) { - this.conditionStack.push(condition); - }, -popState:function popState() { - return this.conditionStack.pop(); - }, -_currentRules:function _currentRules() { - return this.conditions[this.conditionStack[this.conditionStack.length-1]].rules; - }, -topState:function () { - return this.conditionStack[this.conditionStack.length-2]; - }, -pushState:function begin(condition) { - this.begin(condition); - }}); -lexer.options = {}; -lexer.performAction = function anonymous(yy,yy_,$avoiding_name_collisions,YY_START) { - -var YYSTATE=YY_START -switch($avoiding_name_collisions) { -case 0: - if(yy_.yytext.slice(-1) !== "\\") this.begin("mu"); - if(yy_.yytext.slice(-1) === "\\") yy_.yytext = yy_.yytext.substr(0,yy_.yyleng-1), this.begin("emu"); - if(yy_.yytext) return 14; - -break; -case 1: return 14; -break; -case 2: - if(yy_.yytext.slice(-1) !== "\\") this.popState(); - if(yy_.yytext.slice(-1) === "\\") yy_.yytext = yy_.yytext.substr(0,yy_.yyleng-1); - return 14; - -break; -case 3: yy_.yytext = yy_.yytext.substr(0, yy_.yyleng-4); this.popState(); return 15; -break; -case 4: this.begin("par"); return 24; -break; -case 5: return 16; -break; -case 6: return 20; -break; -case 7: return 19; -break; -case 8: return 19; -break; -case 9: return 23; -break; -case 10: return 23; -break; -case 11: this.popState(); this.begin('com'); -break; -case 12: yy_.yytext = yy_.yytext.substr(3,yy_.yyleng-5); this.popState(); return 15; -break; -case 13: return 22; -break; -case 14: return 36; -break; -case 15: return 35; -break; -case 16: return 35; -break; -case 17: return 39; -break; -case 18: /*ignore whitespace*/ -break; -case 19: this.popState(); return 18; -break; -case 20: this.popState(); return 18; -break; -case 21: yy_.yytext = yy_.yytext.substr(1,yy_.yyleng-2).replace(/\\"/g,'"'); return 30; -break; -case 22: yy_.yytext = yy_.yytext.substr(1,yy_.yyleng-2).replace(/\\'/g,"'"); return 30; -break; -case 23: yy_.yytext = yy_.yytext.substr(1); return 28; -break; -case 24: return 32; -break; -case 25: return 32; -break; -case 26: return 31; -break; -case 27: return 35; -break; -case 28: yy_.yytext = yy_.yytext.substr(1, yy_.yyleng-2); return 35; -break; -case 29: return 'INVALID'; -break; -case 30: /*ignore whitespace*/ -break; -case 31: this.popState(); return 37; -break; -case 32: return 5; -break; -} -}; -lexer.rules = [/^(?:[^\x00]*?(?=(\{\{)))/,/^(?:[^\x00]+)/,/^(?:[^\x00]{2,}?(?=(\{\{|$)))/,/^(?:[\s\S]*?--\}\})/,/^(?:\{\{>)/,/^(?:\{\{#)/,/^(?:\{\{\/)/,/^(?:\{\{\^)/,/^(?:\{\{\s*else\b)/,/^(?:\{\{\{)/,/^(?:\{\{&)/,/^(?:\{\{!--)/,/^(?:\{\{![\s\S]*?\}\})/,/^(?:\{\{)/,/^(?:=)/,/^(?:\.(?=[} ]))/,/^(?:\.\.)/,/^(?:[\/.])/,/^(?:\s+)/,/^(?:\}\}\})/,/^(?:\}\})/,/^(?:"(\\["]|[^"])*")/,/^(?:'(\\[']|[^'])*')/,/^(?:@[a-zA-Z]+)/,/^(?:true(?=[}\s]))/,/^(?:false(?=[}\s]))/,/^(?:[0-9]+(?=[}\s]))/,/^(?:[a-zA-Z0-9_$-]+(?=[=}\s\/.]))/,/^(?:\[[^\]]*\])/,/^(?:.)/,/^(?:\s+)/,/^(?:[a-zA-Z0-9_$-/]+)/,/^(?:$)/]; -lexer.conditions = {"mu":{"rules":[4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,32],"inclusive":false},"emu":{"rules":[2],"inclusive":false},"com":{"rules":[3],"inclusive":false},"par":{"rules":[30,31],"inclusive":false},"INITIAL":{"rules":[0,1,32],"inclusive":true}}; -return lexer;})() -parser.lexer = lexer; -function Parser () { this.yy = {}; }Parser.prototype = parser;parser.Parser = Parser; -return new Parser; -})();; -// lib/handlebars/compiler/base.js -Handlebars.Parser = handlebars; - -Handlebars.parse = function(string) { - Handlebars.Parser.yy = Handlebars.AST; - return Handlebars.Parser.parse(string); -}; - -Handlebars.print = function(ast) { - return new Handlebars.PrintVisitor().accept(ast); -};; -// lib/handlebars/compiler/ast.js -(function() { - - Handlebars.AST = {}; - - Handlebars.AST.ProgramNode = function(statements, inverse) { - this.type = "program"; - this.statements = statements; - if(inverse) { this.inverse = new Handlebars.AST.ProgramNode(inverse); } - }; - - Handlebars.AST.MustacheNode = function(rawParams, hash, unescaped) { - this.type = "mustache"; - this.escaped = !unescaped; - this.hash = hash; - - var id = this.id = rawParams[0]; - var params = this.params = rawParams.slice(1); - - // a mustache is an eligible helper if: - // * its id is simple (a single part, not `this` or `..`) - var eligibleHelper = this.eligibleHelper = id.isSimple; - - // a mustache is definitely a helper if: - // * it is an eligible helper, and - // * it has at least one parameter or hash segment - this.isHelper = eligibleHelper && (params.length || hash); - - // if a mustache is an eligible helper but not a definite - // helper, it is ambiguous, and will be resolved in a later - // pass or at runtime. - }; - - Handlebars.AST.PartialNode = function(partialName, context) { - this.type = "partial"; - this.partialName = partialName; - this.context = context; - }; - - var verifyMatch = function(open, close) { - if(open.original !== close.original) { - throw new Handlebars.Exception(open.original + " doesn't match " + close.original); - } - }; - - Handlebars.AST.BlockNode = function(mustache, program, inverse, close) { - verifyMatch(mustache.id, close); - this.type = "block"; - this.mustache = mustache; - this.program = program; - this.inverse = inverse; - - if (this.inverse && !this.program) { - this.isInverse = true; - } - }; - - Handlebars.AST.ContentNode = function(string) { - this.type = "content"; - this.string = string; - }; - - Handlebars.AST.HashNode = function(pairs) { - this.type = "hash"; - this.pairs = pairs; - }; - - Handlebars.AST.IdNode = function(parts) { - this.type = "ID"; - this.original = parts.join("."); - - var dig = [], depth = 0; - - for(var i=0,l=parts.length; i": ">", - '"': """, - "'": "'", - "`": "`" - }; - - var badChars = /[&<>"'`]/g; - var possible = /[&<>"'`]/; - - var escapeChar = function(chr) { - return escape[chr] || "&"; - }; - - Handlebars.Utils = { - escapeExpression: function(string) { - // don't escape SafeStrings, since they're already safe - if (string instanceof Handlebars.SafeString) { - return string.toString(); - } else if (string == null || string === false) { - return ""; - } - - if(!possible.test(string)) { return string; } - return string.replace(badChars, escapeChar); - }, - - isEmpty: function(value) { - if (!value && value !== 0) { - return true; - } else if(Object.prototype.toString.call(value) === "[object Array]" && value.length === 0) { - return true; - } else { - return false; - } - } - }; -})();; -// lib/handlebars/compiler/compiler.js - -/*jshint eqnull:true*/ -Handlebars.Compiler = function() {}; -Handlebars.JavaScriptCompiler = function() {}; - -(function(Compiler, JavaScriptCompiler) { - // the foundHelper register will disambiguate helper lookup from finding a - // function in a context. This is necessary for mustache compatibility, which - // requires that context functions in blocks are evaluated by blockHelperMissing, - // and then proceed as if the resulting value was provided to blockHelperMissing. - - Compiler.prototype = { - compiler: Compiler, - - disassemble: function() { - var opcodes = this.opcodes, opcode, out = [], params, param; - - for (var i=0, l=opcodes.length; i 0) { - this.source[1] = this.source[1] + ", " + locals.join(", "); - } - - // Generate minimizer alias mappings - if (!this.isChild) { - var aliases = []; - for (var alias in this.context.aliases) { - this.source[1] = this.source[1] + ', ' + alias + '=' + this.context.aliases[alias]; - } - } - - if (this.source[1]) { - this.source[1] = "var " + this.source[1].substring(2) + ";"; - } - - // Merge children - if (!this.isChild) { - this.source[1] += '\n' + this.context.programs.join('\n') + '\n'; - } - - if (!this.environment.isSimple) { - this.source.push("return buffer;"); - } - - var params = this.isChild ? ["depth0", "data"] : ["Handlebars", "depth0", "helpers", "partials", "data"]; - - for(var i=0, l=this.environment.depths.list.length; i this.stackVars.length) { this.stackVars.push("stack" + this.stackSlot); } - return "stack" + this.stackSlot; - }, - - popStack: function() { - var item = this.compileStack.pop(); - - if (item instanceof Literal) { - return item.value; - } else { - this.stackSlot--; - return item; - } - }, - - topStack: function() { - var item = this.compileStack[this.compileStack.length - 1]; - - if (item instanceof Literal) { - return item.value; - } else { - return item; - } - }, - - quotedString: function(str) { - return '"' + str - .replace(/\\/g, '\\\\') - .replace(/"/g, '\\"') - .replace(/\n/g, '\\n') - .replace(/\r/g, '\\r') + '"'; - }, - - setupHelper: function(paramSize, name) { - var params = []; - this.setupParams(paramSize, params); - var foundHelper = this.nameLookup('helpers', name, 'helper'); - - return { - params: params, - name: foundHelper, - callParams: ["depth0"].concat(params).join(", "), - helperMissingParams: ["depth0", this.quotedString(name)].concat(params).join(", ") - }; - }, - - // the params and contexts arguments are passed in arrays - // to fill in - setupParams: function(paramSize, params) { - var options = [], contexts = [], types = [], param, inverse, program; - - options.push("hash:" + this.popStack()); - - inverse = this.popStack(); - program = this.popStack(); - - // Avoid setting fn and inverse if neither are set. This allows - // helpers to do a check for `if (options.fn)` - if (program || inverse) { - if (!program) { - this.context.aliases.self = "this"; - program = "self.noop"; - } - - if (!inverse) { - this.context.aliases.self = "this"; - inverse = "self.noop"; - } - - options.push("inverse:" + inverse); - options.push("fn:" + program); - } - - for(var i=0; i":">",'"':""","'":"'","/":"/","`":"`","=":"="};function escapeHtml(string){return String(string).replace(/[&<>"'`=\/]/g,function fromEntityMap(s){return entityMap[s]})}var whiteRe=/\s*/;var spaceRe=/\s+/;var equalsRe=/\s*=/;var curlyRe=/\s*\}/;var tagRe=/#|\^|\/|>|\{|&|=|!/;function parseTemplate(template,tags){if(!template)return[];var sections=[];var tokens=[];var spaces=[];var hasTag=false;var nonSpace=false;function stripSpace(){if(hasTag&&!nonSpace){while(spaces.length)delete tokens[spaces.pop()]}else{spaces=[]}hasTag=false;nonSpace=false}var openingTagRe,closingTagRe,closingCurlyRe;function compileTags(tagsToCompile){if(typeof tagsToCompile==="string")tagsToCompile=tagsToCompile.split(spaceRe,2);if(!isArray(tagsToCompile)||tagsToCompile.length!==2)throw new Error("Invalid tags: "+tagsToCompile);openingTagRe=new RegExp(escapeRegExp(tagsToCompile[0])+"\\s*");closingTagRe=new RegExp("\\s*"+escapeRegExp(tagsToCompile[1]));closingCurlyRe=new RegExp("\\s*"+escapeRegExp("}"+tagsToCompile[1]))}compileTags(tags||mustache.tags);var scanner=new Scanner(template);var start,type,value,chr,token,openSection;while(!scanner.eos()){start=scanner.pos;value=scanner.scanUntil(openingTagRe);if(value){for(var i=0,valueLength=value.length;i0?sections[sections.length-1][4]:nestedTokens;break;default:collector.push(token)}}return nestedTokens}function Scanner(string){this.string=string;this.tail=string;this.pos=0}Scanner.prototype.eos=function eos(){return this.tail===""};Scanner.prototype.scan=function scan(re){var match=this.tail.match(re);if(!match||match.index!==0)return"";var string=match[0];this.tail=this.tail.substring(string.length);this.pos+=string.length;return string};Scanner.prototype.scanUntil=function scanUntil(re){var index=this.tail.search(re),match;switch(index){case-1:match=this.tail;this.tail="";break;case 0:match="";break;default:match=this.tail.substring(0,index);this.tail=this.tail.substring(index)}this.pos+=match.length;return match};function Context(view,parentContext){this.view=view;this.cache={".":this.view};this.parent=parentContext}Context.prototype.push=function push(view){return new Context(view,this)};Context.prototype.lookup=function lookup(name){var cache=this.cache;var value;if(cache.hasOwnProperty(name)){value=cache[name]}else{var context=this,names,index,lookupHit=false;while(context){if(name.indexOf(".")>0){value=context.view;names=name.split(".");index=0;while(value!=null&&index")value=this.renderPartial(token,context,partials,originalTemplate);else if(symbol==="&")value=this.unescapedValue(token,context);else if(symbol==="name")value=this.escapedValue(token,context);else if(symbol==="text")value=this.rawValue(token);if(value!==undefined)buffer+=value}return buffer};Writer.prototype.renderSection=function renderSection(token,context,partials,originalTemplate){var self=this;var buffer="";var value=context.lookup(token[1]);function subRender(template){return self.render(template,context,partials)}if(!value)return;if(isArray(value)){for(var j=0,valueLength=value.length;j - +