From 4d54eaf8b51633250847c75c5113c5f2961a691e Mon Sep 17 00:00:00 2001 From: opi Date: Tue, 11 Feb 2014 12:46:03 +0100 Subject: [PATCH] Use Handlebars instead of Mustache as templating engine. --- index.html | 4 +- js/app.js | 2 +- js/vendor/handlebars-v1.3.0.js | 2746 ++++++++++++++++++++++++++++++++ js/vendor/mustache.js | 536 ------- js/vendor/sammy.handlebars.js | 133 ++ js/vendor/sammy.mustache.js | 126 -- 6 files changed, 2882 insertions(+), 665 deletions(-) create mode 100644 js/vendor/handlebars-v1.3.0.js delete mode 100644 js/vendor/mustache.js create mode 100644 js/vendor/sammy.handlebars.js delete mode 100644 js/vendor/sammy.mustache.js diff --git a/index.html b/index.html index 042003d1..8d77e9b9 100644 --- a/index.html +++ b/index.html @@ -43,9 +43,9 @@ - + - + diff --git a/js/app.js b/js/app.js index b17ee338..2c7b7655 100644 --- a/js/app.js +++ b/js/app.js @@ -5,7 +5,7 @@ app = Sammy('#main', function (sam) { * */ // Plugins - sam.use('Mustache', 'ms'); + sam.use('Handlebars', 'ms'); // Look for supported type of storage to use var storageType; diff --git a/js/vendor/handlebars-v1.3.0.js b/js/vendor/handlebars-v1.3.0.js new file mode 100644 index 00000000..bec7085c --- /dev/null +++ b/js/vendor/handlebars-v1.3.0.js @@ -0,0 +1,2746 @@ +/*! + + handlebars v1.3.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. + +@license +*/ +/* exported Handlebars */ +var Handlebars = (function() { +// handlebars/safe-string.js +var __module4__ = (function() { + "use strict"; + var __exports__; + // Build out our basic SafeString type + function SafeString(string) { + this.string = string; + } + + SafeString.prototype.toString = function() { + return "" + this.string; + }; + + __exports__ = SafeString; + return __exports__; +})(); + +// handlebars/utils.js +var __module3__ = (function(__dependency1__) { + "use strict"; + var __exports__ = {}; + /*jshint -W004 */ + var SafeString = __dependency1__; + + var escape = { + "&": "&", + "<": "<", + ">": ">", + '"': """, + "'": "'", + "`": "`" + }; + + var badChars = /[&<>"'`]/g; + var possible = /[&<>"'`]/; + + function escapeChar(chr) { + return escape[chr] || "&"; + } + + function extend(obj, value) { + for(var key in value) { + if(Object.prototype.hasOwnProperty.call(value, key)) { + obj[key] = value[key]; + } + } + } + + __exports__.extend = extend;var toString = Object.prototype.toString; + __exports__.toString = toString; + // Sourced from lodash + // https://github.com/bestiejs/lodash/blob/master/LICENSE.txt + var isFunction = function(value) { + return typeof value === 'function'; + }; + // fallback for older versions of Chrome and Safari + if (isFunction(/x/)) { + isFunction = function(value) { + return typeof value === 'function' && toString.call(value) === '[object Function]'; + }; + } + var isFunction; + __exports__.isFunction = isFunction; + var isArray = Array.isArray || function(value) { + return (value && typeof value === 'object') ? toString.call(value) === '[object Array]' : false; + }; + __exports__.isArray = isArray; + + function escapeExpression(string) { + // don't escape SafeStrings, since they're already safe + if (string instanceof SafeString) { + return string.toString(); + } else if (!string && string !== 0) { + return ""; + } + + // Force a string conversion as this will be done by the append regardless and + // the regex test will do this transparently behind the scenes, causing issues if + // an object's to string has escaped characters in it. + string = "" + string; + + if(!possible.test(string)) { return string; } + return string.replace(badChars, escapeChar); + } + + __exports__.escapeExpression = escapeExpression;function isEmpty(value) { + if (!value && value !== 0) { + return true; + } else if (isArray(value) && value.length === 0) { + return true; + } else { + return false; + } + } + + __exports__.isEmpty = isEmpty; + return __exports__; +})(__module4__); + +// handlebars/exception.js +var __module5__ = (function() { + "use strict"; + var __exports__; + + var errorProps = ['description', 'fileName', 'lineNumber', 'message', 'name', 'number', 'stack']; + + function Exception(message, node) { + var line; + if (node && node.firstLine) { + line = node.firstLine; + + message += ' - ' + line + ':' + node.firstColumn; + } + + var tmp = Error.prototype.constructor.call(this, message); + + // Unfortunately errors are not enumerable in Chrome (at least), so `for prop in tmp` doesn't work. + for (var idx = 0; idx < errorProps.length; idx++) { + this[errorProps[idx]] = tmp[errorProps[idx]]; + } + + if (line) { + this.lineNumber = line; + this.column = node.firstColumn; + } + } + + Exception.prototype = new Error(); + + __exports__ = Exception; + return __exports__; +})(); + +// handlebars/base.js +var __module2__ = (function(__dependency1__, __dependency2__) { + "use strict"; + var __exports__ = {}; + var Utils = __dependency1__; + var Exception = __dependency2__; + + var VERSION = "1.3.0"; + __exports__.VERSION = VERSION;var COMPILER_REVISION = 4; + __exports__.COMPILER_REVISION = COMPILER_REVISION; + var REVISION_CHANGES = { + 1: '<= 1.0.rc.2', // 1.0.rc.2 is actually rev2 but doesn't report it + 2: '== 1.0.0-rc.3', + 3: '== 1.0.0-rc.4', + 4: '>= 1.0.0' + }; + __exports__.REVISION_CHANGES = REVISION_CHANGES; + var isArray = Utils.isArray, + isFunction = Utils.isFunction, + toString = Utils.toString, + objectType = '[object Object]'; + + function HandlebarsEnvironment(helpers, partials) { + this.helpers = helpers || {}; + this.partials = partials || {}; + + registerDefaultHelpers(this); + } + + __exports__.HandlebarsEnvironment = HandlebarsEnvironment;HandlebarsEnvironment.prototype = { + constructor: HandlebarsEnvironment, + + logger: logger, + log: log, + + registerHelper: function(name, fn, inverse) { + if (toString.call(name) === objectType) { + if (inverse || fn) { throw new Exception('Arg not supported with multiple helpers'); } + Utils.extend(this.helpers, name); + } else { + if (inverse) { fn.not = inverse; } + this.helpers[name] = fn; + } + }, + + registerPartial: function(name, str) { + if (toString.call(name) === objectType) { + Utils.extend(this.partials, name); + } else { + this.partials[name] = str; + } + } + }; + + function registerDefaultHelpers(instance) { + instance.registerHelper('helperMissing', function(arg) { + if(arguments.length === 2) { + return undefined; + } else { + throw new Exception("Missing helper: '" + arg + "'"); + } + }); + + instance.registerHelper('blockHelperMissing', function(context, options) { + var inverse = options.inverse || function() {}, fn = options.fn; + + if (isFunction(context)) { context = context.call(this); } + + if(context === true) { + return fn(this); + } else if(context === false || context == null) { + return inverse(this); + } else if (isArray(context)) { + if(context.length > 0) { + return instance.helpers.each(context, options); + } else { + return inverse(this); + } + } else { + return fn(context); + } + }); + + instance.registerHelper('each', function(context, options) { + var fn = options.fn, inverse = options.inverse; + var i = 0, ret = "", data; + + if (isFunction(context)) { context = context.call(this); } + + if (options.data) { + data = createFrame(options.data); + } + + if(context && typeof context === 'object') { + if (isArray(context)) { + for(var j = context.length; i 0) { + throw new Exception("Invalid path: " + original, this); + } else if (part === "..") { + depth++; + } else { + this.isScoped = true; + } + } else { + dig.push(part); + } + } + + this.original = original; + this.parts = dig; + this.string = dig.join('.'); + this.depth = depth; + + // an ID is simple if it only has one part, and that part is not + // `..` or `this`. + this.isSimple = parts.length === 1 && !this.isScoped && depth === 0; + + this.stringModeValue = this.string; + }, + + PartialNameNode: function(name, locInfo) { + LocationInfo.call(this, locInfo); + this.type = "PARTIAL_NAME"; + this.name = name.original; + }, + + DataNode: function(id, locInfo) { + LocationInfo.call(this, locInfo); + this.type = "DATA"; + this.id = id; + }, + + StringNode: function(string, locInfo) { + LocationInfo.call(this, locInfo); + this.type = "STRING"; + this.original = + this.string = + this.stringModeValue = string; + }, + + IntegerNode: function(integer, locInfo) { + LocationInfo.call(this, locInfo); + this.type = "INTEGER"; + this.original = + this.integer = integer; + this.stringModeValue = Number(integer); + }, + + BooleanNode: function(bool, locInfo) { + LocationInfo.call(this, locInfo); + this.type = "BOOLEAN"; + this.bool = bool; + this.stringModeValue = bool === "true"; + }, + + CommentNode: function(comment, locInfo) { + LocationInfo.call(this, locInfo); + this.type = "comment"; + this.comment = comment; + } + }; + + // Must be exported as an object rather than the root of the module as the jison lexer + // most modify the object to operate properly. + __exports__ = AST; + return __exports__; +})(__module5__); + +// handlebars/compiler/parser.js +var __module9__ = (function() { + "use strict"; + var __exports__; + /* jshint ignore:start */ + /* Jison generated parser */ + var handlebars = (function(){ + var parser = {trace: function trace() { }, + yy: {}, + symbols_: {"error":2,"root":3,"statements":4,"EOF":5,"program":6,"simpleInverse":7,"statement":8,"openInverse":9,"closeBlock":10,"openBlock":11,"mustache":12,"partial":13,"CONTENT":14,"COMMENT":15,"OPEN_BLOCK":16,"sexpr":17,"CLOSE":18,"OPEN_INVERSE":19,"OPEN_ENDBLOCK":20,"path":21,"OPEN":22,"OPEN_UNESCAPED":23,"CLOSE_UNESCAPED":24,"OPEN_PARTIAL":25,"partialName":26,"partial_option0":27,"sexpr_repetition0":28,"sexpr_option0":29,"dataName":30,"param":31,"STRING":32,"INTEGER":33,"BOOLEAN":34,"OPEN_SEXPR":35,"CLOSE_SEXPR":36,"hash":37,"hash_repetition_plus0":38,"hashSegment":39,"ID":40,"EQUALS":41,"DATA":42,"pathSegments":43,"SEP":44,"$accept":0,"$end":1}, + terminals_: {2:"error",5:"EOF",14:"CONTENT",15:"COMMENT",16:"OPEN_BLOCK",18:"CLOSE",19:"OPEN_INVERSE",20:"OPEN_ENDBLOCK",22:"OPEN",23:"OPEN_UNESCAPED",24:"CLOSE_UNESCAPED",25:"OPEN_PARTIAL",32:"STRING",33:"INTEGER",34:"BOOLEAN",35:"OPEN_SEXPR",36:"CLOSE_SEXPR",40:"ID",41:"EQUALS",42:"DATA",44:"SEP"}, + productions_: [0,[3,2],[3,1],[6,2],[6,3],[6,2],[6,1],[6,1],[6,0],[4,1],[4,2],[8,3],[8,3],[8,1],[8,1],[8,1],[8,1],[11,3],[9,3],[10,3],[12,3],[12,3],[13,4],[7,2],[17,3],[17,1],[31,1],[31,1],[31,1],[31,1],[31,1],[31,3],[37,1],[39,3],[26,1],[26,1],[26,1],[30,2],[21,1],[43,3],[43,1],[27,0],[27,1],[28,0],[28,2],[29,0],[29,1],[38,1],[38,2]], + performAction: function anonymous(yytext,yyleng,yylineno,yy,yystate,$$,_$) { + + var $0 = $$.length - 1; + switch (yystate) { + case 1: return new yy.ProgramNode($$[$0-1], this._$); + break; + case 2: return new yy.ProgramNode([], this._$); + break; + case 3:this.$ = new yy.ProgramNode([], $$[$0-1], $$[$0], this._$); + break; + case 4:this.$ = new yy.ProgramNode($$[$0-2], $$[$0-1], $$[$0], this._$); + break; + case 5:this.$ = new yy.ProgramNode($$[$0-1], $$[$0], [], this._$); + break; + case 6:this.$ = new yy.ProgramNode($$[$0], this._$); + break; + case 7:this.$ = new yy.ProgramNode([], this._$); + break; + case 8:this.$ = new yy.ProgramNode([], this._$); + break; + case 9:this.$ = [$$[$0]]; + break; + case 10: $$[$0-1].push($$[$0]); this.$ = $$[$0-1]; + break; + case 11:this.$ = new yy.BlockNode($$[$0-2], $$[$0-1].inverse, $$[$0-1], $$[$0], this._$); + break; + case 12:this.$ = new yy.BlockNode($$[$0-2], $$[$0-1], $$[$0-1].inverse, $$[$0], this._$); + break; + case 13:this.$ = $$[$0]; + break; + case 14:this.$ = $$[$0]; + break; + case 15:this.$ = new yy.ContentNode($$[$0], this._$); + break; + case 16:this.$ = new yy.CommentNode($$[$0], this._$); + break; + case 17:this.$ = new yy.MustacheNode($$[$0-1], null, $$[$0-2], stripFlags($$[$0-2], $$[$0]), this._$); + break; + case 18:this.$ = new yy.MustacheNode($$[$0-1], null, $$[$0-2], stripFlags($$[$0-2], $$[$0]), this._$); + break; + case 19:this.$ = {path: $$[$0-1], strip: stripFlags($$[$0-2], $$[$0])}; + break; + case 20:this.$ = new yy.MustacheNode($$[$0-1], null, $$[$0-2], stripFlags($$[$0-2], $$[$0]), this._$); + break; + case 21:this.$ = new yy.MustacheNode($$[$0-1], null, $$[$0-2], stripFlags($$[$0-2], $$[$0]), this._$); + break; + case 22:this.$ = new yy.PartialNode($$[$0-2], $$[$0-1], stripFlags($$[$0-3], $$[$0]), this._$); + break; + case 23:this.$ = stripFlags($$[$0-1], $$[$0]); + break; + case 24:this.$ = new yy.SexprNode([$$[$0-2]].concat($$[$0-1]), $$[$0], this._$); + break; + case 25:this.$ = new yy.SexprNode([$$[$0]], null, this._$); + break; + case 26:this.$ = $$[$0]; + break; + case 27:this.$ = new yy.StringNode($$[$0], this._$); + break; + case 28:this.$ = new yy.IntegerNode($$[$0], this._$); + break; + case 29:this.$ = new yy.BooleanNode($$[$0], this._$); + break; + case 30:this.$ = $$[$0]; + break; + case 31:$$[$0-1].isHelper = true; this.$ = $$[$0-1]; + break; + case 32:this.$ = new yy.HashNode($$[$0], this._$); + break; + case 33:this.$ = [$$[$0-2], $$[$0]]; + break; + case 34:this.$ = new yy.PartialNameNode($$[$0], this._$); + break; + case 35:this.$ = new yy.PartialNameNode(new yy.StringNode($$[$0], this._$), this._$); + break; + case 36:this.$ = new yy.PartialNameNode(new yy.IntegerNode($$[$0], this._$)); + break; + case 37:this.$ = new yy.DataNode($$[$0], this._$); + break; + case 38:this.$ = new yy.IdNode($$[$0], this._$); + break; + case 39: $$[$0-2].push({part: $$[$0], separator: $$[$0-1]}); this.$ = $$[$0-2]; + break; + case 40:this.$ = [{part: $$[$0]}]; + break; + case 43:this.$ = []; + break; + case 44:$$[$0-1].push($$[$0]); + break; + case 47:this.$ = [$$[$0]]; + break; + case 48:$$[$0-1].push($$[$0]); + break; + } + }, + table: [{3:1,4:2,5:[1,3],8:4,9:5,11:6,12:7,13:8,14:[1,9],15:[1,10],16:[1,12],19:[1,11],22:[1,13],23:[1,14],25:[1,15]},{1:[3]},{5:[1,16],8:17,9:5,11:6,12:7,13:8,14:[1,9],15:[1,10],16:[1,12],19:[1,11],22:[1,13],23:[1,14],25:[1,15]},{1:[2,2]},{5:[2,9],14:[2,9],15:[2,9],16:[2,9],19:[2,9],20:[2,9],22:[2,9],23:[2,9],25:[2,9]},{4:20,6:18,7:19,8:4,9:5,11:6,12:7,13:8,14:[1,9],15:[1,10],16:[1,12],19:[1,21],20:[2,8],22:[1,13],23:[1,14],25:[1,15]},{4:20,6:22,7:19,8:4,9:5,11:6,12:7,13:8,14:[1,9],15:[1,10],16:[1,12],19:[1,21],20:[2,8],22:[1,13],23:[1,14],25:[1,15]},{5:[2,13],14:[2,13],15:[2,13],16:[2,13],19:[2,13],20:[2,13],22:[2,13],23:[2,13],25:[2,13]},{5:[2,14],14:[2,14],15:[2,14],16:[2,14],19:[2,14],20:[2,14],22:[2,14],23:[2,14],25:[2,14]},{5:[2,15],14:[2,15],15:[2,15],16:[2,15],19:[2,15],20:[2,15],22:[2,15],23:[2,15],25:[2,15]},{5:[2,16],14:[2,16],15:[2,16],16:[2,16],19:[2,16],20:[2,16],22:[2,16],23:[2,16],25:[2,16]},{17:23,21:24,30:25,40:[1,28],42:[1,27],43:26},{17:29,21:24,30:25,40:[1,28],42:[1,27],43:26},{17:30,21:24,30:25,40:[1,28],42:[1,27],43:26},{17:31,21:24,30:25,40:[1,28],42:[1,27],43:26},{21:33,26:32,32:[1,34],33:[1,35],40:[1,28],43:26},{1:[2,1]},{5:[2,10],14:[2,10],15:[2,10],16:[2,10],19:[2,10],20:[2,10],22:[2,10],23:[2,10],25:[2,10]},{10:36,20:[1,37]},{4:38,8:4,9:5,11:6,12:7,13:8,14:[1,9],15:[1,10],16:[1,12],19:[1,11],20:[2,7],22:[1,13],23:[1,14],25:[1,15]},{7:39,8:17,9:5,11:6,12:7,13:8,14:[1,9],15:[1,10],16:[1,12],19:[1,21],20:[2,6],22:[1,13],23:[1,14],25:[1,15]},{17:23,18:[1,40],21:24,30:25,40:[1,28],42:[1,27],43:26},{10:41,20:[1,37]},{18:[1,42]},{18:[2,43],24:[2,43],28:43,32:[2,43],33:[2,43],34:[2,43],35:[2,43],36:[2,43],40:[2,43],42:[2,43]},{18:[2,25],24:[2,25],36:[2,25]},{18:[2,38],24:[2,38],32:[2,38],33:[2,38],34:[2,38],35:[2,38],36:[2,38],40:[2,38],42:[2,38],44:[1,44]},{21:45,40:[1,28],43:26},{18:[2,40],24:[2,40],32:[2,40],33:[2,40],34:[2,40],35:[2,40],36:[2,40],40:[2,40],42:[2,40],44:[2,40]},{18:[1,46]},{18:[1,47]},{24:[1,48]},{18:[2,41],21:50,27:49,40:[1,28],43:26},{18:[2,34],40:[2,34]},{18:[2,35],40:[2,35]},{18:[2,36],40:[2,36]},{5:[2,11],14:[2,11],15:[2,11],16:[2,11],19:[2,11],20:[2,11],22:[2,11],23:[2,11],25:[2,11]},{21:51,40:[1,28],43:26},{8:17,9:5,11:6,12:7,13:8,14:[1,9],15:[1,10],16:[1,12],19:[1,11],20:[2,3],22:[1,13],23:[1,14],25:[1,15]},{4:52,8:4,9:5,11:6,12:7,13:8,14:[1,9],15:[1,10],16:[1,12],19:[1,11],20:[2,5],22:[1,13],23:[1,14],25:[1,15]},{14:[2,23],15:[2,23],16:[2,23],19:[2,23],20:[2,23],22:[2,23],23:[2,23],25:[2,23]},{5:[2,12],14:[2,12],15:[2,12],16:[2,12],19:[2,12],20:[2,12],22:[2,12],23:[2,12],25:[2,12]},{14:[2,18],15:[2,18],16:[2,18],19:[2,18],20:[2,18],22:[2,18],23:[2,18],25:[2,18]},{18:[2,45],21:56,24:[2,45],29:53,30:60,31:54,32:[1,57],33:[1,58],34:[1,59],35:[1,61],36:[2,45],37:55,38:62,39:63,40:[1,64],42:[1,27],43:26},{40:[1,65]},{18:[2,37],24:[2,37],32:[2,37],33:[2,37],34:[2,37],35:[2,37],36:[2,37],40:[2,37],42:[2,37]},{14:[2,17],15:[2,17],16:[2,17],19:[2,17],20:[2,17],22:[2,17],23:[2,17],25:[2,17]},{5:[2,20],14:[2,20],15:[2,20],16:[2,20],19:[2,20],20:[2,20],22:[2,20],23:[2,20],25:[2,20]},{5:[2,21],14:[2,21],15:[2,21],16:[2,21],19:[2,21],20:[2,21],22:[2,21],23:[2,21],25:[2,21]},{18:[1,66]},{18:[2,42]},{18:[1,67]},{8:17,9:5,11:6,12:7,13:8,14:[1,9],15:[1,10],16:[1,12],19:[1,11],20:[2,4],22:[1,13],23:[1,14],25:[1,15]},{18:[2,24],24:[2,24],36:[2,24]},{18:[2,44],24:[2,44],32:[2,44],33:[2,44],34:[2,44],35:[2,44],36:[2,44],40:[2,44],42:[2,44]},{18:[2,46],24:[2,46],36:[2,46]},{18:[2,26],24:[2,26],32:[2,26],33:[2,26],34:[2,26],35:[2,26],36:[2,26],40:[2,26],42:[2,26]},{18:[2,27],24:[2,27],32:[2,27],33:[2,27],34:[2,27],35:[2,27],36:[2,27],40:[2,27],42:[2,27]},{18:[2,28],24:[2,28],32:[2,28],33:[2,28],34:[2,28],35:[2,28],36:[2,28],40:[2,28],42:[2,28]},{18:[2,29],24:[2,29],32:[2,29],33:[2,29],34:[2,29],35:[2,29],36:[2,29],40:[2,29],42:[2,29]},{18:[2,30],24:[2,30],32:[2,30],33:[2,30],34:[2,30],35:[2,30],36:[2,30],40:[2,30],42:[2,30]},{17:68,21:24,30:25,40:[1,28],42:[1,27],43:26},{18:[2,32],24:[2,32],36:[2,32],39:69,40:[1,70]},{18:[2,47],24:[2,47],36:[2,47],40:[2,47]},{18:[2,40],24:[2,40],32:[2,40],33:[2,40],34:[2,40],35:[2,40],36:[2,40],40:[2,40],41:[1,71],42:[2,40],44:[2,40]},{18:[2,39],24:[2,39],32:[2,39],33:[2,39],34:[2,39],35:[2,39],36:[2,39],40:[2,39],42:[2,39],44:[2,39]},{5:[2,22],14:[2,22],15:[2,22],16:[2,22],19:[2,22],20:[2,22],22:[2,22],23:[2,22],25:[2,22]},{5:[2,19],14:[2,19],15:[2,19],16:[2,19],19:[2,19],20:[2,19],22:[2,19],23:[2,19],25:[2,19]},{36:[1,72]},{18:[2,48],24:[2,48],36:[2,48],40:[2,48]},{41:[1,71]},{21:56,30:60,31:73,32:[1,57],33:[1,58],34:[1,59],35:[1,61],40:[1,28],42:[1,27],43:26},{18:[2,31],24:[2,31],32:[2,31],33:[2,31],34:[2,31],35:[2,31],36:[2,31],40:[2,31],42:[2,31]},{18:[2,33],24:[2,33],36:[2,33],40:[2,33]}], + defaultActions: {3:[2,2],16:[2,1],50:[2,42]}, + parseError: function parseError(str, hash) { + throw new Error(str); + }, + parse: function parse(input) { + var self = this, stack = [0], vstack = [null], lstack = [], table = this.table, yytext = "", yylineno = 0, yyleng = 0, recovering = 0, TERROR = 2, EOF = 1; + this.lexer.setInput(input); + this.lexer.yy = this.yy; + this.yy.lexer = this.lexer; + this.yy.parser = this; + if (typeof this.lexer.yylloc == "undefined") + this.lexer.yylloc = {}; + var yyloc = this.lexer.yylloc; + lstack.push(yyloc); + var ranges = this.lexer.options && this.lexer.options.ranges; + if (typeof this.yy.parseError === "function") + this.parseError = this.yy.parseError; + function popStack(n) { + stack.length = stack.length - 2 * n; + vstack.length = vstack.length - n; + lstack.length = lstack.length - n; + } + function lex() { + var token; + token = self.lexer.lex() || 1; + if (typeof token !== "number") { + token = self.symbols_[token] || token; + } + return token; + } + var symbol, preErrorSymbol, state, action, a, r, yyval = {}, p, len, newState, expected; + while (true) { + state = stack[stack.length - 1]; + if (this.defaultActions[state]) { + action = this.defaultActions[state]; + } else { + if (symbol === null || typeof symbol == "undefined") { + symbol = lex(); + } + action = table[state] && table[state][symbol]; + } + if (typeof action === "undefined" || !action.length || !action[0]) { + var errStr = ""; + if (!recovering) { + expected = []; + for (p in table[state]) + if (this.terminals_[p] && p > 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; + } + }; + + + function stripFlags(open, close) { + return { + left: open.charAt(2) === '~', + right: close.charAt(0) === '~' || close.charAt(1) === '~' + }; + } + + /* 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) { + + + function strip(start, end) { + return yy_.yytext = yy_.yytext.substr(start, yy_.yyleng-end); + } + + + var YYSTATE=YY_START + switch($avoiding_name_collisions) { + case 0: + if(yy_.yytext.slice(-2) === "\\\\") { + strip(0,1); + this.begin("mu"); + } else if(yy_.yytext.slice(-1) === "\\") { + strip(0,1); + this.begin("emu"); + } else { + this.begin("mu"); + } + if(yy_.yytext) return 14; + + break; + case 1:return 14; + break; + case 2: + this.popState(); + return 14; + + break; + case 3:strip(0,4); this.popState(); return 15; + break; + case 4:return 35; + break; + case 5:return 36; + break; + case 6:return 25; + break; + case 7:return 16; + break; + case 8:return 20; + break; + case 9:return 19; + break; + case 10:return 19; + break; + case 11:return 23; + break; + case 12:return 22; + break; + case 13:this.popState(); this.begin('com'); + break; + case 14:strip(3,5); this.popState(); return 15; + break; + case 15:return 22; + break; + case 16:return 41; + break; + case 17:return 40; + break; + case 18:return 40; + break; + case 19:return 44; + break; + case 20:// ignore whitespace + break; + case 21:this.popState(); return 24; + break; + case 22:this.popState(); return 18; + break; + case 23:yy_.yytext = strip(1,2).replace(/\\"/g,'"'); return 32; + break; + case 24:yy_.yytext = strip(1,2).replace(/\\'/g,"'"); return 32; + break; + case 25:return 42; + break; + case 26:return 34; + break; + case 27:return 34; + break; + case 28:return 33; + break; + case 29:return 40; + break; + case 30:yy_.yytext = strip(1,2); return 40; + break; + case 31:return 'INVALID'; + break; + case 32:return 5; + break; + } + }; + lexer.rules = [/^(?:[^\x00]*?(?=(\{\{)))/,/^(?:[^\x00]+)/,/^(?:[^\x00]{2,}?(?=(\{\{|\\\{\{|\\\\\{\{|$)))/,/^(?:[\s\S]*?--\}\})/,/^(?:\()/,/^(?:\))/,/^(?:\{\{(~)?>)/,/^(?:\{\{(~)?#)/,/^(?:\{\{(~)?\/)/,/^(?:\{\{(~)?\^)/,/^(?:\{\{(~)?\s*else\b)/,/^(?:\{\{(~)?\{)/,/^(?:\{\{(~)?&)/,/^(?:\{\{!--)/,/^(?:\{\{![\s\S]*?\}\})/,/^(?:\{\{(~)?)/,/^(?:=)/,/^(?:\.\.)/,/^(?:\.(?=([=~}\s\/.)])))/,/^(?:[\/.])/,/^(?:\s+)/,/^(?:\}(~)?\}\})/,/^(?:(~)?\}\})/,/^(?:"(\\["]|[^"])*")/,/^(?:'(\\[']|[^'])*')/,/^(?:@)/,/^(?:true(?=([~}\s)])))/,/^(?:false(?=([~}\s)])))/,/^(?:-?[0-9]+(?=([~}\s)])))/,/^(?:([^\s!"#%-,\.\/;->@\[-\^`\{-~]+(?=([=~}\s\/.)]))))/,/^(?:\[[^\]]*\])/,/^(?:.)/,/^(?:$)/]; + lexer.conditions = {"mu":{"rules":[4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32],"inclusive":false},"emu":{"rules":[2],"inclusive":false},"com":{"rules":[3],"inclusive":false},"INITIAL":{"rules":[0,1,32],"inclusive":true}}; + return lexer;})() + parser.lexer = lexer; + function Parser () { this.yy = {}; }Parser.prototype = parser;parser.Parser = Parser; + return new Parser; + })();__exports__ = handlebars; + /* jshint ignore:end */ + return __exports__; +})(); + +// handlebars/compiler/base.js +var __module8__ = (function(__dependency1__, __dependency2__) { + "use strict"; + var __exports__ = {}; + var parser = __dependency1__; + var AST = __dependency2__; + + __exports__.parser = parser; + + function parse(input) { + // Just return if an already-compile AST was passed in. + if(input.constructor === AST.ProgramNode) { return input; } + + parser.yy = AST; + return parser.parse(input); + } + + __exports__.parse = parse; + return __exports__; +})(__module9__, __module7__); + +// handlebars/compiler/compiler.js +var __module10__ = (function(__dependency1__) { + "use strict"; + var __exports__ = {}; + var Exception = __dependency1__; + + function Compiler() {} + + __exports__.Compiler = Compiler;// 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) { + for (var alias in this.context.aliases) { + if (this.context.aliases.hasOwnProperty(alias)) { + 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.pushSource("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 this.topStackName(); + }, + topStackName: function() { + return "stack" + this.stackSlot; + }, + flushInline: function() { + var inlineStack = this.inlineStack; + if (inlineStack.length) { + this.inlineStack = []; + for (var i = 0, len = inlineStack.length; i < len; i++) { + var entry = inlineStack[i]; + if (entry instanceof Literal) { + this.compileStack.push(entry); + } else { + this.pushStack(entry); + } + } + } + }, + isInline: function() { + return this.inlineStack.length; + }, + + popStack: function(wrapped) { + var inline = this.isInline(), + item = (inline ? this.inlineStack : this.compileStack).pop(); + + if (!wrapped && (item instanceof Literal)) { + return item.value; + } else { + if (!inline) { + if (!this.stackSlot) { + throw new Exception('Invalid stack pop'); + } + this.stackSlot--; + } + return item; + } + }, + + topStack: function(wrapped) { + var stack = (this.isInline() ? this.inlineStack : this.compileStack), + item = stack[stack.length - 1]; + + if (!wrapped && (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') + .replace(/\u2028/g, '\\u2028') // Per Ecma-262 7.3 + 7.8.4 + .replace(/\u2029/g, '\\u2029') + '"'; + }, + + setupHelper: function(paramSize, name, missingParams) { + var params = [], + paramsInit = this.setupParams(paramSize, params, missingParams); + var foundHelper = this.nameLookup('helpers', name, 'helper'); + + return { + params: params, + paramsInit: paramsInit, + name: foundHelper, + callParams: ["depth0"].concat(params).join(", "), + helperMissingParams: missingParams && ["depth0", this.quotedString(name)].concat(params).join(", ") + }; + }, + + setupOptions: function(paramSize, params) { + var options = [], contexts = [], types = [], param, inverse, program; + + options.push("hash:" + this.popStack()); + + if (this.options.stringParams) { + options.push("hashTypes:" + this.popStack()); + options.push("hashContexts:" + 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 - } - } -}(this, function (mustache) { - - var whiteRe = /\s*/; - var spaceRe = /\s+/; - var nonSpaceRe = /\S/; - var eqRe = /\s*=/; - var curlyRe = /\s*\}/; - var tagRe = /#|\^|\/|>|\{|&|=|!/; - - // Workaround for https://issues.apache.org/jira/browse/COUCHDB-577 - // See https://github.com/janl/mustache.js/issues/189 - var RegExp_test = RegExp.prototype.test; - function testRegExp(re, string) { - return RegExp_test.call(re, string); - } - - function isWhitespace(string) { - return !testRegExp(nonSpaceRe, string); - } - - var Object_toString = Object.prototype.toString; - var isArray = Array.isArray || function (obj) { - return Object_toString.call(obj) === '[object Array]'; - }; - - function escapeRegExp(string) { - return string.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&"); - } - - var entityMap = { - "&": "&", - "<": "<", - ">": ">", - '"': '"', - "'": ''', - "/": '/' - }; - - function escapeHtml(string) { - return String(string).replace(/[&<>"'\/]/g, function (s) { - return entityMap[s]; - }); - } - - function Scanner(string) { - this.string = string; - this.tail = string; - this.pos = 0; - } - - /** - * Returns `true` if the tail is empty (end of string). - */ - Scanner.prototype.eos = function () { - return this.tail === ""; - }; - - /** - * Tries to match the given regular expression at the current position. - * Returns the matched text if it can match, the empty string otherwise. - */ - Scanner.prototype.scan = function (re) { - var match = this.tail.match(re); - - if (match && match.index === 0) { - this.tail = this.tail.substring(match[0].length); - this.pos += match[0].length; - return match[0]; - } - - return ""; - }; - - /** - * Skips all text until the given regular expression can be matched. Returns - * the skipped string, which is the entire tail if no match can be made. - */ - Scanner.prototype.scanUntil = function (re) { - var match, pos = this.tail.search(re); - - switch (pos) { - case -1: - match = this.tail; - this.pos += this.tail.length; - this.tail = ""; - break; - case 0: - match = ""; - break; - default: - match = this.tail.substring(0, pos); - this.tail = this.tail.substring(pos); - this.pos += pos; - } - - return match; - }; - - function Context(view, parent) { - this.view = view || {}; - this.parent = parent; - this._cache = {}; - } - - Context.make = function (view) { - return (view instanceof Context) ? view : new Context(view); - }; - - Context.prototype.push = function (view) { - return new Context(view, this); - }; - - Context.prototype.lookup = function (name) { - var value = this._cache[name]; - - if (!value) { - if (name == '.') { - value = this.view; - } else { - var context = this; - - while (context) { - if (name.indexOf('.') > 0) { - value = context.view; - var names = name.split('.'), i = 0; - while (value && i < names.length) { - value = value[names[i++]]; - } - } else { - value = context.view[name]; - } - - if (value != null) break; - - context = context.parent; - } - } - - this._cache[name] = value; - } - - if (typeof value === 'function') value = value.call(this.view); - - return value; - }; - - function Writer() { - this.clearCache(); - } - - Writer.prototype.clearCache = function () { - this._cache = {}; - this._partialCache = {}; - }; - - Writer.prototype.compile = function (template, tags) { - var fn = this._cache[template]; - - if (!fn) { - var tokens = mustache.parse(template, tags); - fn = this._cache[template] = this.compileTokens(tokens, template); - } - - return fn; - }; - - Writer.prototype.compilePartial = function (name, template, tags) { - var fn = this.compile(template, tags); - this._partialCache[name] = fn; - return fn; - }; - - Writer.prototype.getPartial = function (name) { - if (!(name in this._partialCache) && this._loadPartial) { - this.compilePartial(name, this._loadPartial(name)); - } - - return this._partialCache[name]; - }; - - Writer.prototype.compileTokens = function (tokens, template) { - var self = this; - return function (view, partials) { - if (partials) { - if (typeof partials === 'function') { - self._loadPartial = partials; - } else { - for (var name in partials) { - self.compilePartial(name, partials[name]); - } - } - } - - return renderTokens(tokens, self, Context.make(view), template); - }; - }; - - Writer.prototype.render = function (template, view, partials) { - return this.compile(template)(view, partials); - }; - - /** - * Low-level function that renders the given `tokens` using the given `writer` - * and `context`. The `template` string is only needed for templates that use - * higher-order sections to extract the portion of the original template that - * was contained in that section. - */ - function renderTokens(tokens, writer, context, template) { - var buffer = ''; - - var token, tokenValue, value; - for (var i = 0, len = tokens.length; i < len; ++i) { - token = tokens[i]; - tokenValue = token[1]; - - switch (token[0]) { - case '#': - value = context.lookup(tokenValue); - - if (typeof value === 'object') { - if (isArray(value)) { - for (var j = 0, jlen = value.length; j < jlen; ++j) { - buffer += renderTokens(token[4], writer, context.push(value[j]), template); - } - } else if (value) { - buffer += renderTokens(token[4], writer, context.push(value), template); - } - } else if (typeof value === 'function') { - var text = template == null ? null : template.slice(token[3], token[5]); - value = value.call(context.view, text, function (template) { - return writer.render(template, context); - }); - if (value != null) buffer += value; - } else if (value) { - buffer += renderTokens(token[4], writer, context, template); - } - - break; - case '^': - value = context.lookup(tokenValue); - - // Use JavaScript's definition of falsy. Include empty arrays. - // See https://github.com/janl/mustache.js/issues/186 - if (!value || (isArray(value) && value.length === 0)) { - buffer += renderTokens(token[4], writer, context, template); - } - - break; - case '>': - value = writer.getPartial(tokenValue); - if (typeof value === 'function') buffer += value(context); - break; - case '&': - value = context.lookup(tokenValue); - if (value != null) buffer += value; - break; - case 'name': - value = context.lookup(tokenValue); - if (value != null) buffer += mustache.escape(value); - break; - case 'text': - buffer += tokenValue; - break; - } - } - - return buffer; - } - - /** - * Forms the given array of `tokens` into a nested tree structure where - * tokens that represent a section have two additional items: 1) an array of - * all tokens that appear in that section and 2) the index in the original - * template that represents the end of that section. - */ - function nestTokens(tokens) { - var tree = []; - var collector = tree; - var sections = []; - - var token; - for (var i = 0, len = tokens.length; i < len; ++i) { - token = tokens[i]; - switch (token[0]) { - case '#': - case '^': - sections.push(token); - collector.push(token); - collector = token[4] = []; - break; - case '/': - var section = sections.pop(); - section[5] = token[2]; - collector = sections.length > 0 ? sections[sections.length - 1][4] : tree; - break; - default: - collector.push(token); - } - } - - return tree; - } - - /** - * Combines the values of consecutive text tokens in the given `tokens` array - * to a single token. - */ - function squashTokens(tokens) { - var squashedTokens = []; - - var token, lastToken; - for (var i = 0, len = tokens.length; i < len; ++i) { - token = tokens[i]; - if (token) { - if (token[0] === 'text' && lastToken && lastToken[0] === 'text') { - lastToken[1] += token[1]; - lastToken[3] = token[3]; - } else { - lastToken = token; - squashedTokens.push(token); - } - } - } - - return squashedTokens; - } - - function escapeTags(tags) { - return [ - new RegExp(escapeRegExp(tags[0]) + "\\s*"), - new RegExp("\\s*" + escapeRegExp(tags[1])) - ]; - } - - /** - * Breaks up the given `template` string into a tree of token objects. If - * `tags` is given here it must be an array with two string values: the - * opening and closing tags used in the template (e.g. ["<%", "%>"]). Of - * course, the default is to use mustaches (i.e. Mustache.tags). - */ - function parseTemplate(template, tags) { - template = template || ''; - tags = tags || mustache.tags; - - if (typeof tags === 'string') tags = tags.split(spaceRe); - if (tags.length !== 2) throw new Error('Invalid tags: ' + tags.join(', ')); - - var tagRes = escapeTags(tags); - var scanner = new Scanner(template); - - var sections = []; // Stack to hold section tokens - var tokens = []; // Buffer to hold the tokens - var spaces = []; // Indices of whitespace tokens on the current line - var hasTag = false; // Is there a {{tag}} on the current line? - var nonSpace = false; // Is there a non-space char on the current line? - - // Strips all whitespace tokens array for the current line - // if there was a {{#tag}} on it and otherwise only space. - function stripSpace() { - if (hasTag && !nonSpace) { - while (spaces.length) { - delete tokens[spaces.pop()]; - } - } else { - spaces = []; - } - - hasTag = false; - nonSpace = false; - } - - var start, type, value, chr, token; - while (!scanner.eos()) { - start = scanner.pos; - - // Match any text between tags. - value = scanner.scanUntil(tagRes[0]); - if (value) { - for (var i = 0, len = value.length; i < len; ++i) { - chr = value.charAt(i); - - if (isWhitespace(chr)) { - spaces.push(tokens.length); - } else { - nonSpace = true; - } - - tokens.push(['text', chr, start, start + 1]); - start += 1; - - // Check for whitespace on the current line. - if (chr == '\n') stripSpace(); - } - } - - // Match the opening tag. - if (!scanner.scan(tagRes[0])) break; - hasTag = true; - - // Get the tag type. - type = scanner.scan(tagRe) || 'name'; - scanner.scan(whiteRe); - - // Get the tag value. - if (type === '=') { - value = scanner.scanUntil(eqRe); - scanner.scan(eqRe); - scanner.scanUntil(tagRes[1]); - } else if (type === '{') { - value = scanner.scanUntil(new RegExp('\\s*' + escapeRegExp('}' + tags[1]))); - scanner.scan(curlyRe); - scanner.scanUntil(tagRes[1]); - type = '&'; - } else { - value = scanner.scanUntil(tagRes[1]); - } - - // Match the closing tag. - if (!scanner.scan(tagRes[1])) throw new Error('Unclosed tag at ' + scanner.pos); - - token = [type, value, start, scanner.pos]; - tokens.push(token); - - if (type === '#' || type === '^') { - sections.push(token); - } else if (type === '/') { - // Check section nesting. - if (sections.length === 0) throw new Error('Unopened section "' + value + '" at ' + start); - var openSection = sections.pop(); - if (openSection[1] !== value) throw new Error('Unclosed section "' + openSection[1] + '" at ' + start); - } else if (type === 'name' || type === '{' || type === '&') { - nonSpace = true; - } else if (type === '=') { - // Set the tags for the next time around. - tags = value.split(spaceRe); - if (tags.length !== 2) throw new Error('Invalid tags at ' + start + ': ' + tags.join(', ')); - tagRes = escapeTags(tags); - } - } - - // Make sure there are no open sections when we're done. - var openSection = sections.pop(); - if (openSection) throw new Error('Unclosed section "' + openSection[1] + '" at ' + scanner.pos); - - tokens = squashTokens(tokens); - - return nestTokens(tokens); - } - - mustache.name = "mustache.js"; - mustache.version = "0.7.2"; - mustache.tags = ["{{", "}}"]; - - mustache.Scanner = Scanner; - mustache.Context = Context; - mustache.Writer = Writer; - - mustache.parse = parseTemplate; - - // Export the escaping function so that the user may override it. - // See https://github.com/janl/mustache.js/issues/244 - mustache.escape = escapeHtml; - - // All Mustache.* functions use this writer. - var defaultWriter = new Writer(); - - /** - * Clears all cached templates and partials in the default writer. - */ - mustache.clearCache = function () { - return defaultWriter.clearCache(); - }; - - /** - * Compiles the given `template` to a reusable function using the default - * writer. - */ - mustache.compile = function (template, tags) { - return defaultWriter.compile(template, tags); - }; - - /** - * Compiles the partial with the given `name` and `template` to a reusable - * function using the default writer. - */ - mustache.compilePartial = function (name, template, tags) { - return defaultWriter.compilePartial(name, template, tags); - }; - - /** - * Compiles the given array of tokens (the output of a parse) to a reusable - * function using the default writer. - */ - mustache.compileTokens = function (tokens, template) { - return defaultWriter.compileTokens(tokens, template); - }; - - /** - * Renders the `template` with the given `view` and `partials` using the - * default writer. - */ - mustache.render = function (template, view, partials) { - return defaultWriter.render(template, view, partials); - }; - - // This is here for backwards compatibility with 0.4.x. - mustache.to_html = function (template, view, partials, send) { - var result = mustache.render(template, view, partials); - - if (typeof send === "function") { - send(result); - } else { - return result; - } - }; - -})); diff --git a/js/vendor/sammy.handlebars.js b/js/vendor/sammy.handlebars.js new file mode 100644 index 00000000..c94a2aa6 --- /dev/null +++ b/js/vendor/sammy.handlebars.js @@ -0,0 +1,133 @@ +(function (factory) { + if (typeof define === 'function' && define.amd) { + define(['jquery', 'sammy', 'handlebars'], factory); + } else { + (window.Sammy = window.Sammy || {}).Handlebars = factory(window.jQuery, window.Sammy); + } +}(function ($, Sammy, Handlebars) { + // version 1.0.0 has no support for AMD but upwards does, this way we support both. + Handlebars = Handlebars || window.Handlebars; + + // Sammy.Handlebars provides a quick way of using Handlebars templates in your app. + // + // Note: As of Sammy 0.7 Handlebars itself is not included in the source. Please download and + // include handlebars.js before Sammy.Handlebars. + // + // Handlebars.js is an extension to the Mustache templating language created by Chris Wanstrath. Handlebars.js + // and Mustache are both logicless templating languages that keep the view and the code separated like + // we all know they should be. + // + // By default using Sammy.Handlbars in your app adds the handlebars() method to the EventContext + // prototype. However, just like Sammy.Template you can change the default name of the method + // by passing a second argument (e.g. you could use the hbr() as the method alias so that all the template + // files could be in the form file.hbr instead of file.handlebars) + // + // ### Example #1 + // + // The template (mytemplate.hb): + // + //

{{title}}

+ // + // Hey, {{name}}! Welcome to Handlebars! + // + // The app: + // + // var app = $.sammy(function() { + // // include the plugin and alias handlebars() to hb() + // this.use('Handlebars', 'hb'); + // + // this.get('#/hello/:name', function() { + // // set local vars + // this.title = 'Hello!' + // this.name = this.params.name; + // // render the template and pass it through handlebars + // this.partial('mytemplate.hb'); + // }); + // }); + // + // $(function() { + // app.run() + // }); + // + // If I go to #/hello/AQ in the browser, Sammy will render this to the body: + // + //

Hello!

+ // + // Hey, AQ! Welcome to Handlebars! + // + // + // ### Example #2 - Handlebars partials + // + // The template (mytemplate.hb) + // + // Hey, {{name}}! {{>hello_friend}} + // + // + // The partial (mypartial.hb) + // + // Say hello to your friend {{friend}}! + // + // The app: + // + // var app = $.sammy(function() { + // // include the plugin and alias handlebars() to hb() + // this.use('Handlebars', 'hb'); + // + // this.get('#/hello/:name/to/:friend', function(context) { + // // fetch handlebars-partial first + // this.load('mypartial.hb') + // .then(function(partial) { + // // set local vars + // context.partials = {hello_friend: partial}; + // context.name = context.params.name; + // context.friend = context.params.friend; + // + // // render the template and pass it through handlebars + // context.partial('mytemplate.hb'); + // }); + // }); + // }); + // + // $(function() { + // app.run() + // }); + // + // If I go to #/hello/AQ/to/dP in the browser, Sammy will render this to the body: + // + // Hey, AQ! Say hello to your friend dP! + // + // Note: You dont have to include the handlebars.js file on top of the plugin as the plugin + // includes the full source. + // + Sammy.Handlebars = function(app, method_alias) { + var handlebars_cache = {}; + // *Helper* Uses handlebars.js to parse a template and interpolate and work with the passed data + // + // ### Arguments + // + // * `template` A String template. + // * `data` An Object containing the replacement values for the template. + // data is extended with the EventContext allowing you to call its methods within the template. + // + var handlebars = function(template, data, partials, name) { + // use name for caching + if (typeof name == 'undefined') { name = template; } + var fn = handlebars_cache[name]; + if (!fn) { + fn = handlebars_cache[name] = Handlebars.compile(template); + } + + data = $.extend({}, this, data); + partials = $.extend({}, data.partials, partials); + + return fn(data, {"partials":partials}); + }; + + // set the default method name/extension + if (!method_alias) { method_alias = 'handlebars'; } + app.helper(method_alias, handlebars); + }; + + return Sammy.Handlebars; + +})); \ No newline at end of file diff --git a/js/vendor/sammy.mustache.js b/js/vendor/sammy.mustache.js deleted file mode 100644 index 1f5ff091..00000000 --- a/js/vendor/sammy.mustache.js +++ /dev/null @@ -1,126 +0,0 @@ -(function (factory) { - if (typeof define === 'function' && define.amd) { - define(['jquery', 'sammy', 'mustache'], factory); - } else { - (window.Sammy = window.Sammy || {}).Mustache = factory(window.jQuery, window.Sammy, window.Mustache); - } -}(function ($, Sammy, Mustache) { - - // Sammy.Mustache provides a quick way of using mustache style templates in your app. - // The plugin wraps the awesome mustache.js lib created and maintained by Jan Lehnardt - // at http://github.com/janl/mustache.js - // - // Note: As of Sammy 0.7 the Mustache lib is not included in the templates source. Please download - // mustache.js and include it before Sammy.Mustache. - // - // Mustache is a clever templating system that relys on double brackets {{}} for interpolation. - // For full details on syntax check out the original Ruby implementation created by Chris Wanstrath at - // http://github.com/defunkt/mustache - // - // By default using Sammy.Mustache in your app adds the mustache() method to the EventContext - // prototype. However, just like Sammy.Template you can change the default name of the method - // by passing a second argument (e.g. you could use the ms() as the method alias so that all the template - // files could be in the form file.ms instead of file.mustache) - // - // ### Example #1 - // - // The template (mytemplate.ms): - // - //

{{title}}

- // - // Hey, {{name}}! Welcome to Mustache! - // - // The app: - // - // var app = $.sammy(function() { - // // include the plugin and alias mustache() to ms() - // this.use('Mustache', 'ms'); - // - // this.get('#/hello/:name', function() { - // // set local vars - // this.title = 'Hello!' - // this.name = this.params.name; - // // render the template and pass it through mustache - // this.partial('mytemplate.ms'); - // }); - // }); - // - // $(function() { - // app.run() - // }); - // - // If I go to #/hello/AQ in the browser, Sammy will render this to the body: - // - //

Hello!

- // - // Hey, AQ! Welcome to Mustache! - // - // - // ### Example #2 - Mustache partials - // - // The template (mytemplate.ms) - // - // Hey, {{name}}! {{>hello_friend}} - // - // - // The partial (mypartial.ms) - // - // Say hello to your friend {{friend}}! - // - // The app: - // - // var app = $.sammy(function() { - // // include the plugin and alias mustache() to ms() - // this.use('Mustache', 'ms'); - // - // this.get('#/hello/:name/to/:friend', function(context) { - // // fetch mustache-partial first - // this.load('mypartial.ms') - // .then(function(partial) { - // // set local vars - // context.partials = {hello_friend: partial}; - // context.name = context.params.name; - // context.friend = context.params.friend; - // - // // render the template and pass it through mustache - // context.partial('mytemplate.ms'); - // }); - // }); - // }); - // - // $(function() { - // app.run() - // }); - // - // If I go to #/hello/AQ/to/dP in the browser, Sammy will render this to the body: - // - // Hey, AQ! Say hello to your friend dP! - // - // Note: You need to include the mustache.js file before this plugin. - // - Sammy.Mustache = function(app, method_alias) { - - // *Helper* Uses Mustache.js to parse a template and interpolate and work with the passed data - // - // ### Arguments - // - // * `template` A String template. {{}} Tags are evaluated and interpolated by Mustache.js - // * `data` An Object containing the replacement values for the template. - // data is extended with the EventContext allowing you to call its methods within the template. - // * `partials` An Object containing one or more partials (String templates - // that are called from the main template). - // - var mustache = function(template, data, partials) { - data = $.extend({}, this, data); - partials = $.extend({}, data.partials, partials); - return Mustache.to_html(template, data, partials); - }; - - // set the default method name/extension - if (!method_alias) { method_alias = 'mustache'; } - app.helper(method_alias, mustache); - }; - - return Sammy.Mustache; - -}));