{"version":3,"sources":["spacebars-compiler/templatetag.js","spacebars-compiler/optimizer.js","spacebars-compiler/codegen.js","spacebars-compiler/compiler.js"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA,uB;;AAEA,iE;AACA,E;AACA,0C;AACA,E;AACA,2B;AACA,6B;AACA,8B;AACA,sC;AACA,gC;AACA,+B;AACA,gC;AACA,0B;AACA,kD;AACA,E;AACA,iE;AACA,E;AACA,yE;AACA,2E;AACA,oB;AACA,E;AACA,wE;AACA,sE;AACA,2E;AACA,uE;AACA,sC;AACA,E;AACA,qE;AACA,kB;AACA,E;AACA,qD;AACA,E;AACA,6E;AACA,yE;AACA,qD;AACA,mC;AACA,E;AACA,sE;AACA,sE;AACA,6B;;AAEA,4D;;AAEA,2D;AACA,+C;AACA,E;AACA,kD;AACA,wE;;AAEA,4C;AACA,oD;AACA,6C;AACA,E;;AAEA,yD;AACA,6D;AACA,mD;AACA,c;AACA,2B;AACA,0D;AACA,oD;AACA,sD;AACA,uD;AACA,gD;AACA,2D;AACA,2D;AACA,4D;AACA,E;;AAEA,Y;AACA,qB;AACA,sB;AACA,E;;AAEA,iE;AACA,qE;AACA,yE;AACA,6C;AACA,gD;AACA,gC;AACA,kC;AACA,qD;;AAEA,kC;AACA,gD;AACA,gB;;AAEA,8B;AACA,yC;AACA,4C;AACA,iB;AACA,kB;AACA,wB;AACA,8B;AACA,e;AACA,I;;AAEA,mC;AACA,0B;AACA,I;;AAEA,iD;AACA,qD;AACA,a;AACA,6B;AACA,wB;AACA,2D;AACA,yF;;AAEA,c;AACA,I;;AAEA,8B;AACA,sB;;AAEA,oE;AACA,a;AACA,mC;AACA,4D;AACA,2C;;AAEA,wB;AACA,iC;;AAEA,0D;AACA,0B;AACA,sD;AACA,iD;AACA,gB;AACA,iC;AACA,sC;AACA,S;;AAEA,+B;AACA,6B;AACA,S;;AAEA,iC;;AAEA,yB;AACA,wB;AACA,K;;AAEA,kB;AACA,4B;;AAEA,uB;AACA,qC;AACA,kB;AACA,6C;AACA,+B;AACA,uC;AACA,sD;AACA,2B;AACA,c;AACA,mD;AACA,4B;AACA,kC;AACA,6B;AACA,+B;AACA,kB;AACA,oI;AACA,W;AACA,gB;AACA,4B;AACA,S;AACA,O;;AAEA,+B;AACA,gB;AACA,c;AACA,K;;AAEA,oB;AACA,I;;AAEA,mD;AACA,sC;AACA,kD;AACA,iD;AACA,oC;AACA,0E;AACA,gB;AACA,qC;AACA,sB;AACA,Y;AACA,kB;AACA,K;AACA,I;;AAEA,0C;AACA,8C;AACA,sD;AACA,kB;AACA,6B;AACA,kE;AACA,+B;AACA,mD;AACA,I;;AAEA,kE;AACA,4D;AACA,kC;AACA,+B;AACA,e;AACA,qD;AACA,sC;AACA,mE;AACA,sC;AACA,gD;AACA,kC;AACA,oE;AACA,sB;AACA,0B;AACA,8B;AACA,mD;AACA,0C;AACA,c;AACA,iD;AACA,oC;AACA,O;AACA,Y;AACA,+D;AACA,K;AACA,I;;AAEA,W;;AAEA,8B;AACA,uB;AACA,I;;AAEA,kC;AACA,8B;AACA,I;;AAEA,uD;AACA,mC;AACA,0C;AACA,2C;AACA,+C;AACA,+C;AACA,2D;AACA,iD;AACA,qD;AACA,qD;AACA,uD;AACA,M;AACA,gC;;AAEA,4B;AACA,kB;;AAEA,gC;AACA,4C;AACA,iB;AACA,sC;AACA,0D;AACA,kC;AACA,sC;AACA,iB;AACA,gC;AACA,oC;AACA,qC;AACA,0B;AACA,2B;AACA,uB;AACA,+B;AACA,2B;AACA,uB;AACA,iC;AACA,+B;AACA,2C;AACA,U;AACA,2C;AACA,0B;AACA,kB;AACA,2B;AACA,kB;AACA,kB;AACA,8B;AACA,6B;AACA,gB;AACA,wC;AACA,4B;AACA,c;AACA,6B;AACA,gB;AACA,wC;AACA,2B;AACA,O;AACA,6B;AACA,gC;AACA,0B;AACA,c;AACA,uB;AACA,8E;AACA,O;AACA,4B;;AAEA,mC;AACA,0B;AACA,K;AACA,G;;AAEA,a;AACA,E;;AAEA,iF;AACA,4B;AACA,E;AACA,wE;AACA,wB;AACA,uC;AACA,6B;AACA,0C;AACA,yB;AACA,gB;AACA,E;;AAEA,0E;AACA,0E;AACA,+B;AACA,E;AACA,e;AACA,E;AACA,oE;AACA,E;AACA,sE;AACA,8D;AACA,E;AACA,2E;AACA,wC;AACA,E;AACA,yE;AACA,qE;AACA,gC;AACA,kC;AACA,qD;;AAEA,mD;AACA,kD;AACA,e;AACA,kB;;AAEA,qC;AACA,gB;;AAEA,gC;AACA,gB;;AAEA,6B;AACA,yC;;AAEA,mC;AACA,qD;;AAEA,yD;AACA,iD;AACA,+B;;AAEA,oC;AACA,2B;;AAEA,oE;AACA,uE;AACA,oE;AACA,gB;AACA,0C;;AAEA,wB;AACA,qC;AACA,0D;AACA,wC;AACA,gE;AACA,mE;AACA,wC;AACA,O;AACA,2B;AACA,qD;AACA,yC;AACA,0B;AACA,Q;AACA,qE;;AAEA,4C;AACA,yE;;AAEA,yD;AACA,qE;;AAEA,kC;AACA,mD;AACA,2E;;AAEA,8C;AACA,+D;;AAEA,4B;AACA,2C;AACA,K;;AAEA,wC;AACA,8C;AACA,qC;AACA,8B;AACA,yE;AACA,kC;AACA,O;AACA,Y;AACA,4B;AACA,uE;AACA,kC;AACA,K;AACA,G;;AAEA,6B;AACA,yB;AACA,+B;AACA,yB;;AAEA,gB;AACA,E;;AAEA,+C;AACA,qC;AACA,I;AACA,yE;AACA,kE;AACA,yE;AACA,2C;AACA,iB;AACA,mC;AACA,yD;AACA,6C;AACA,oD;AACA,sD;AACA,E;;AAEA,oE;AACA,mE;AACA,W;AACA,4C;;AAEA,+D;AACA,yB;AACA,2E;AACA,qE;AACA,wB;AACA,yH;AACA,K;AACA,G;;AAEA,gE;AACA,wD;AACA,2D;AACA,a;AACA,2C;AACA,2B;AACA,0B;AACA,oD;AACA,wD;AACA,sD;AACA,wD;AACA,0H;AACA,O;AACA,Y;AACA,qF;AACA,K;AACA,+D;AACA,qC;AACA,8N;AACA,K;AACA,iC;AACA,4L;AACA,K;AACA,G;;AAEA,E;;;;;;;;;;;;;;;;;;;AC/dA,yE;AACA,yB;;AAEA,iC;AACA,uC;AACA,E;;AAEA,mB;AACA,U;AACA,W;AACA,S;AACA,E;;AAEA,0E;AACA,yE;AACA,qE;AACA,0E;AACA,8E;AACA,E;AACA,yE;AACA,2E;AACA,sE;AACA,4E;AACA,qB;AACA,+C;AACA,wB;AACA,wC;AACA,6C;AACA,2C;AACA,2C;AACA,uC;AACA,0C;AACA,4C;AACA,4B;AACA,sC;AACA,gD;AACA,iC;AACA,4B;AACA,I;AACA,4B;AACA,8B;AACA,iC;AACA,yE;AACA,qB;AACA,8B;AACA,iD;AACA,uD;AACA,sE;AACA,8B;AACA,qC;AACA,2E;AACA,8E;AACA,wE;AACA,0B;AACA,8B;AACA,K;;AAEA,gC;AACA,6C;AACA,uD;AACA,iC;;AAEA,6D;AACA,+B;;AAEA,4B;AACA,I;AACA,qC;AACA,gB;AACA,wC;AACA,8D;AACA,6C;AACA,4E;AACA,mC;AACA,wB;AACA,oD;AACA,qC;AACA,O;AACA,K;AACA,4B;AACA,G;AACA,G;;AAEA,4C;AACA,iD;AACA,E;;AAEA,0B;AACA,kC;AACA,E;;AAEA,wD;AACA,qB;AACA,8C;AACA,4C;AACA,+C;AACA,mB;;AAEA,oE;AACA,uB;AACA,G;AACA,G;;AAEA,kE;AACA,+D;AACA,iD;AACA,uB;AACA,mB;AACA,wB;AACA,sB;AACA,sB;AACA,gC;AACA,kD;AACA,8C;AACA,0B;AACA,sD;AACA,oE;AACA,Y;AACA,mB;AACA,K;AACA,I;AACA,4B;AACA,gD;AACA,8C;AACA,wB;AACA,sD;AACA,gE;AACA,Y;AACA,iB;AACA,K;AACA,I;AACA,sC;AACA,2D;AACA,qE;AACA,I;AACA,qC;AACA,iB;AACA,G;AACA,G;;AAEA,qD;AACA,oD;AACA,0B;AACA,gC;AACA,oB;AACA,4C;AACA,0B;AACA,uC;AACA,4B;AACA,4B;AACA,gE;AACA,+D;AACA,mE;AACA,2D;AACA,yB;AACA,+C;AACA,0D;AACA,S;AACA,c;AACA,0B;AACA,O;AACA,K;AACA,kB;AACA,G;AACA,G;;AAEA,wE;AACA,kC;AACA,mD;AACA,yB;AACA,4B;AACA,yB;AACA,yD;AACA,kB;AACA,Y;AACA,iB;AACA,K;AACA,G;AACA,G;;AAEA,8C;AACA,6C;AACA,gD;AACA,+C;AACA,c;AACA,E;;;;;;;;;;;;;;;;;;;ACzLA,+D;AACA,mC;;AAEA,qE;AACA,kE;AACA,yC;AACA,yD;;AAEA,oE;AACA,mB;AACA,2B;AACA,2B;AACA,sB;AACA,E;;;AAGA,kE;AACA,oE;AACA,W;AACA,6B;AACA,+D;AACA,kE;AACA,qC;AACA,8C;AACA,wC;;AAEA,8D;AACA,kE;AACA,6C;AACA,kC;;AAEA,sE;AACA,E;;AAEA,8D;AACA,iD;AACA,E;AACA,qE;AACA,kE;AACA,mB;AACA,oD;AACA,oD;AACA,+C;AACA,E;;AAEA,wC;AACA,iB;AACA,oB;AACA,iE;AACA,sC;AACA,E;;AAEA,6B;AACA,sC;AACA,oB;AACA,wE;AACA,yD;AACA,qE;AACA,0D;AACA,kE;AACA,mB;AACA,Y;AACA,2D;AACA,4D;AACA,oC;AACA,mD;AACA,S;AACA,4E;AACA,mE;AACA,oD;AACA,qD;AACA,qE;AACA,oD;AACA,S;AACA,yC;AACA,wE;AACA,4B;;AAEA,uC;AACA,0D;AACA,oC;AACA,Y;AACA,wD;AACA,8E;;AAEA,qF;AACA,uC;AACA,8B;AACA,gF;AACA,gC;AACA,qE;;AAEA,oD;AACA,2E;AACA,iC;AACA,kD;AACA,qE;AACA,wC;AACA,0D;AACA,6E;;AAEA,kD;AACA,+B;AACA,4C;;AAEA,qC;AACA,4E;;AAEA,gB;AACA,wE;AACA,gC;AACA,iC;AACA,0E;AACA,qB;AACA,W;;AAEA,iE;AACA,6C;AACA,gE;AACA,qD;AACA,wE;;AAEA,uC;AACA,wB;AACA,sC;AACA,4B;AACA,4C;AACA,W;;AAEA,2B;AACA,oE;;AAEA,yE;AACA,sE;AACA,mE;AACA,oE;AACA,0E;AACA,0E;AACA,oE;AACA,yB;AACA,yB;AACA,6E;AACA,mC;AACA,W;;AAEA,sE;AACA,6D;AACA,wE;AACA,uE;AACA,mF;AACA,qC;AACA,W;;AAEA,kD;AACA,S;AACA,yC;AACA,yB;AACA,c;AACA,kE;AACA,qE;AACA,qE;AACA,O;AACA,K;AACA,I;;AAEA,+C;AACA,I;AACA,6D;AACA,sD;AACA,I;AACA,gE;AACA,I;AACA,a;AACA,I;AACA,qE;AACA,mE;AACA,oE;AACA,iC;AACA,sC;AACA,oD;AACA,uE;AACA,0E;AACA,4E;AACA,qC;AACA,gE;AACA,2B;AACA,oD;AACA,2D;AACA,0B;AACA,kE;AACA,iD;AACA,4C;AACA,K;;AAEA,wD;AACA,gC;AACA,yD;AACA,sC;AACA,kE;;AAEA,0B;AACA,6C;AACA,sE;AACA,K;;AAEA,gB;AACA,I;;AAEA,+D;AACA,mE;AACA,I;AACA,iE;AACA,4D;AACA,mC;AACA,oB;;AAEA,yB;AACA,0B;;AAEA,gB;AACA,sB;AACA,kB;AACA,kB;AACA,mB;AACA,gB;AACA,iD;AACA,Y;AACA,gB;AACA,2C;AACA,Y;AACA,Y;AACA,uB;AACA,yD;AACA,K;;AAEA,mB;AACA,I;;AAEA,wE;AACA,uE;AACA,qC;AACA,wD;AACA,oB;;AAEA,0C;AACA,iD;AACA,gD;;AAEA,qD;AACA,uD;AACA,I;;AAEA,oD;AACA,iB;AACA,2C;AACA,oB;;AAEA,0C;AACA,gC;;AAEA,0B;AACA,oC;AACA,8C;;AAEA,2B;AACA,gE;AACA,gC;AACA,iC;AACA,c;AACA,8B;AACA,4B;AACA,2B;AACA,O;AACA,O;;AAEA,sD;AACA,iB;AACA,0B;AACA,mE;AACA,K;;AAEA,gB;AACA,I;;AAEA,oC;AACA,8C;AACA,I;;AAEA,6C;AACA,oB;;AAEA,4B;;AAEA,wB;AACA,wB;AACA,kB;AACA,sC;AACA,2D;AACA,yB;AACA,mC;AACA,4B;AACA,gF;AACA,S;AACA,kD;AACA,uC;AACA,wD;AACA,Q;AACA,uE;AACA,2C;AACA,mD;AACA,mC;AACA,qC;AACA,4E;AACA,Y;AACA,8D;AACA,wB;AACA,oE;AACA,0D;AACA,K;;AAEA,0D;AACA,G;;AAEA,G;;;;;;;;;;;;;;;;;;;;AClUA,4C;;AAEA,qC;AACA,U;AACA,sD;;AAEA,c;AACA,E;;AAEA,uD;AACA,4C;AACA,kD;AACA,E;;AAEA,2E;AACA,4C;AACA,6B;AACA,6C;;AAEA,gE;AACA,0D;AACA,4D;AACA,kE;AACA,6D;AACA,yB;AACA,gC;AACA,kE;;AAEA,gD;AACA,K;;AAEA,wE;AACA,I;AACA,qC;AACA,+C;AACA,oD;;AAEA,2D;AACA,gF;AACA,I;AACA,+C;AACA,iC;AACA,mC;AACA,kC;;AAEA,2B;AACA,sE;AACA,sE;AACA,wD;AACA,uE;AACA,4E;AACA,iD;AACA,oE;AACA,K;AACA,kB;AACA,G;AACA,G;;AAEA,2D;AACA,sD;AACA,wB;AACA,mD;AACA,2C;;AAEA,uB;;AAEA,4D;AACA,6B;AACA,4E;AACA,0B;AACA,4C;AACA,G;;AAEA,8C;AACA,qD;AACA,qC;;AAEA,+B;AACA,6B;AACA,gC;AACA,G;AACA,oB;AACA,gC;AACA,iB;;AAEA,2C;;AAEA,c;AACA,E;;AAEA,+C;AACA,8D;AACA,kD;AACA,W;AACA,yB;AACA,sB;AACA,wB;AACA,iC;AACA,kC;AACA,iC;AACA,6B;AACA,+E;AACA,gC;AACA,sC;AACA,kB;AACA,U;AACA,2C;AACA,gB;AACA,G;AACA,E","file":"/packages/spacebars-compiler.js","sourcesContent":["SpacebarsCompiler = {};\n\n// A TemplateTag is the result of parsing a single `{{...}}` tag.\n//\n// The `.type` of a TemplateTag is one of:\n//\n// - `\"DOUBLE\"` - `{{foo}}`\n// - `\"TRIPLE\"` - `{{{foo}}}`\n// - `\"COMMENT\"` - `{{! foo}}`\n// - `\"BLOCKCOMMENT\" - `{{!-- foo--}}`\n// - `\"INCLUSION\"` - `{{> foo}}`\n// - `\"BLOCKOPEN\"` - `{{#foo}}`\n// - `\"BLOCKCLOSE\"` - `{{/foo}}`\n// - `\"ELSE\"` - `{{else}}`\n// - `\"ESCAPE\"` - `{{|`, `{{{|`, `{{{{|` and so on\n//\n// Besides `type`, the mandatory properties of a TemplateTag are:\n//\n// - `path` - An array of one or more strings. The path of `{{foo.bar}}`\n// is `[\"foo\", \"bar\"]`. Applies to DOUBLE, TRIPLE, INCLUSION, BLOCKOPEN,\n// and BLOCKCLOSE.\n//\n// - `args` - An array of zero or more argument specs. An argument spec\n// is a two or three element array, consisting of a type, value, and\n// optional keyword name. For example, the `args` of `{{foo \"bar\" x=3}}`\n// are `[[\"STRING\", \"bar\"], [\"NUMBER\", 3, \"x\"]]`. Applies to DOUBLE,\n// TRIPLE, INCLUSION, and BLOCKOPEN.\n//\n// - `value` - A string of the comment's text. Applies to COMMENT and\n// BLOCKCOMMENT.\n//\n// These additional are typically set during parsing:\n//\n// - `position` - The HTMLTools.TEMPLATE_TAG_POSITION specifying at what sort\n// of site the TemplateTag was encountered (e.g. at element level or as\n// part of an attribute value). Its absence implies\n// TEMPLATE_TAG_POSITION.ELEMENT.\n//\n// - `content` and `elseContent` - When a BLOCKOPEN tag's contents are\n// parsed, they are put here. `elseContent` will only be present if\n// an `{{else}}` was found.\n\nvar TEMPLATE_TAG_POSITION = HTMLTools.TEMPLATE_TAG_POSITION;\n\nTemplateTag = SpacebarsCompiler.TemplateTag = function () {\n HTMLTools.TemplateTag.apply(this, arguments);\n};\nTemplateTag.prototype = new HTMLTools.TemplateTag;\nTemplateTag.prototype.constructorName = 'SpacebarsCompiler.TemplateTag';\n\nvar makeStacheTagStartRegex = function (r) {\n return new RegExp(r.source + /(?![{>!#/])/.source,\n r.ignoreCase ? 'i' : '');\n};\n\n// \"starts\" regexes are used to see what type of template\n// tag the parser is looking at. They must match a non-empty\n// result, but not the interesting part of the tag.\nvar starts = {\n ESCAPE: /^\\{\\{(?=\\{*\\|)/,\n ELSE: makeStacheTagStartRegex(/^\\{\\{\\s*else(?=[\\s}])/i),\n DOUBLE: makeStacheTagStartRegex(/^\\{\\{\\s*(?!\\s)/),\n TRIPLE: makeStacheTagStartRegex(/^\\{\\{\\{\\s*(?!\\s)/),\n BLOCKCOMMENT: makeStacheTagStartRegex(/^\\{\\{\\s*!--/),\n COMMENT: makeStacheTagStartRegex(/^\\{\\{\\s*!/),\n INCLUSION: makeStacheTagStartRegex(/^\\{\\{\\s*>\\s*(?!\\s)/),\n BLOCKOPEN: makeStacheTagStartRegex(/^\\{\\{\\s*#\\s*(?!\\s)/),\n BLOCKCLOSE: makeStacheTagStartRegex(/^\\{\\{\\s*\\/\\s*(?!\\s)/)\n};\n\nvar ends = {\n DOUBLE: /^\\s*\\}\\}/,\n TRIPLE: /^\\s*\\}\\}\\}/\n};\n\n// Parse a tag from the provided scanner or string. If the input\n// doesn't start with `{{`, returns null. Otherwise, either succeeds\n// and returns a SpacebarsCompiler.TemplateTag, or throws an error (using\n// `scanner.fatal` if a scanner is provided).\nTemplateTag.parse = function (scannerOrString) {\n var scanner = scannerOrString;\n if (typeof scanner === 'string')\n scanner = new HTMLTools.Scanner(scannerOrString);\n\n if (! (scanner.peek() === '{' &&\n (scanner.rest()).slice(0, 2) === '{{'))\n return null;\n\n var run = function (regex) {\n // regex is assumed to start with `^`\n var result = regex.exec(scanner.rest());\n if (! result)\n return null;\n var ret = result[0];\n scanner.pos += ret.length;\n return ret;\n };\n\n var advance = function (amount) {\n scanner.pos += amount;\n };\n\n var scanIdentifier = function (isFirstInPath) {\n var id = BlazeTools.parseIdentifierName(scanner);\n if (! id)\n expected('IDENTIFIER');\n if (isFirstInPath &&\n (id === 'null' || id === 'true' || id === 'false'))\n scanner.fatal(\"Can't use null, true, or false, as an identifier at start of path\");\n\n return id;\n };\n\n var scanPath = function () {\n var segments = [];\n\n // handle initial `.`, `..`, `./`, `../`, `../..`, `../../`, etc\n var dots;\n if ((dots = run(/^[\\.\\/]+/))) {\n var ancestorStr = '.'; // eg `../../..` maps to `....`\n var endsWithSlash = /\\/$/.test(dots);\n\n if (endsWithSlash)\n dots = dots.slice(0, -1);\n\n _.each(dots.split('/'), function(dotClause, index) {\n if (index === 0) {\n if (dotClause !== '.' && dotClause !== '..')\n expected(\"`.`, `..`, `./` or `../`\");\n } else {\n if (dotClause !== '..')\n expected(\"`..` or `../`\");\n }\n\n if (dotClause === '..')\n ancestorStr += '.';\n });\n\n segments.push(ancestorStr);\n\n if (!endsWithSlash)\n return segments;\n }\n\n while (true) {\n // scan a path segment\n\n if (run(/^\\[/)) {\n var seg = run(/^[\\s\\S]*?\\]/);\n if (! seg)\n error(\"Unterminated path segment\");\n seg = seg.slice(0, -1);\n if (! seg && ! segments.length)\n error(\"Path can't start with empty string\");\n segments.push(seg);\n } else {\n var id = scanIdentifier(! segments.length);\n if (id === 'this') {\n if (! segments.length) {\n // initial `this`\n segments.push('.');\n } else {\n error(\"Can only use `this` at the beginning of a path.\\nInstead of `foo.this` or `../this`, just write `foo` or `..`.\");\n }\n } else {\n segments.push(id);\n }\n }\n\n var sep = run(/^[\\.\\/]/);\n if (! sep)\n break;\n }\n\n return segments;\n };\n\n // scan the keyword portion of a keyword argument\n // (the \"foo\" portion in \"foo=bar\").\n // Result is either the keyword matched, or null\n // if we're not at a keyword argument position.\n var scanArgKeyword = function () {\n var match = /^([^\\{\\}\\(\\)\\>#=\\s\"'\\[\\]]+)\\s*=\\s*/.exec(scanner.rest());\n if (match) {\n scanner.pos += match[0].length;\n return match[1];\n } else {\n return null;\n }\n };\n\n // scan an argument; succeeds or errors.\n // Result is an array of two or three items:\n // type , value, and (indicating a keyword argument)\n // keyword name.\n var scanArg = function () {\n var keyword = scanArgKeyword(); // null if not parsing a kwarg\n var value = scanArgValue();\n return keyword ? value.concat(keyword) : value;\n };\n\n // scan an argument value (for keyword or positional arguments);\n // succeeds or errors. Result is an array of type, value.\n var scanArgValue = function () {\n var startPos = scanner.pos;\n var result;\n if ((result = BlazeTools.parseNumber(scanner))) {\n return ['NUMBER', result.value];\n } else if ((result = BlazeTools.parseStringLiteral(scanner))) {\n return ['STRING', result.value];\n } else if (/^[\\.\\[]/.test(scanner.peek())) {\n return ['PATH', scanPath()];\n } else if ((result = BlazeTools.parseIdentifierName(scanner))) {\n var id = result;\n if (id === 'null') {\n return ['NULL', null];\n } else if (id === 'true' || id === 'false') {\n return ['BOOLEAN', id === 'true'];\n } else {\n scanner.pos = startPos; // unconsume `id`\n return ['PATH', scanPath()];\n }\n } else {\n expected('identifier, number, string, boolean, or null');\n }\n };\n\n var type;\n\n var error = function (msg) {\n scanner.fatal(msg);\n };\n\n var expected = function (what) {\n error('Expected ' + what);\n };\n\n // must do ESCAPE first, immediately followed by ELSE\n // order of others doesn't matter\n if (run(starts.ESCAPE)) type = 'ESCAPE';\n else if (run(starts.ELSE)) type = 'ELSE';\n else if (run(starts.DOUBLE)) type = 'DOUBLE';\n else if (run(starts.TRIPLE)) type = 'TRIPLE';\n else if (run(starts.BLOCKCOMMENT)) type = 'BLOCKCOMMENT';\n else if (run(starts.COMMENT)) type = 'COMMENT';\n else if (run(starts.INCLUSION)) type = 'INCLUSION';\n else if (run(starts.BLOCKOPEN)) type = 'BLOCKOPEN';\n else if (run(starts.BLOCKCLOSE)) type = 'BLOCKCLOSE';\n else\n error('Unknown stache tag');\n\n var tag = new TemplateTag;\n tag.type = type;\n\n if (type === 'BLOCKCOMMENT') {\n var result = run(/^[\\s\\S]*?--\\s*?\\}\\}/);\n if (! result)\n error(\"Unclosed block comment\");\n tag.value = result.slice(0, result.lastIndexOf('--'));\n } else if (type === 'COMMENT') {\n var result = run(/^[\\s\\S]*?\\}\\}/);\n if (! result)\n error(\"Unclosed comment\");\n tag.value = result.slice(0, -2);\n } else if (type === 'BLOCKCLOSE') {\n tag.path = scanPath();\n if (! run(ends.DOUBLE))\n expected('`}}`');\n } else if (type === 'ELSE') {\n if (! run(ends.DOUBLE))\n expected('`}}`');\n } else if (type === 'ESCAPE') {\n var result = run(/^\\{*\\|/);\n tag.value = '{{' + result.slice(0, -1);\n } else {\n // DOUBLE, TRIPLE, BLOCKOPEN, INCLUSION\n tag.path = scanPath();\n tag.args = [];\n var foundKwArg = false;\n while (true) {\n run(/^\\s*/);\n if (type === 'TRIPLE') {\n if (run(ends.TRIPLE))\n break;\n else if (scanner.peek() === '}')\n expected('`}}}`');\n } else {\n if (run(ends.DOUBLE))\n break;\n else if (scanner.peek() === '}')\n expected('`}}`');\n }\n var newArg = scanArg();\n if (newArg.length === 3) {\n foundKwArg = true;\n } else {\n if (foundKwArg)\n error(\"Can't have a non-keyword argument after a keyword argument\");\n }\n tag.args.push(newArg);\n\n if (run(/^(?=[\\s}])/) !== '')\n expected('space');\n }\n }\n\n return tag;\n};\n\n// Returns a SpacebarsCompiler.TemplateTag parsed from `scanner`, leaving scanner\n// at its original position.\n//\n// An error will still be thrown if there is not a valid template tag at\n// the current position.\nTemplateTag.peek = function (scanner) {\n var startPos = scanner.pos;\n var result = TemplateTag.parse(scanner);\n scanner.pos = startPos;\n return result;\n};\n\n// Like `TemplateTag.parse`, but in the case of blocks, parse the complete\n// `{{#foo}}...{{/foo}}` with `content` and possible `elseContent`, rather\n// than just the BLOCKOPEN tag.\n//\n// In addition:\n//\n// - Throws an error if `{{else}}` or `{{/foo}}` tag is encountered.\n//\n// - Returns `null` for a COMMENT. (This case is distinguishable from\n// parsing no tag by the fact that the scanner is advanced.)\n//\n// - Takes an HTMLTools.TEMPLATE_TAG_POSITION `position` and sets it as the\n// TemplateTag's `.position` property.\n//\n// - Validates the tag's well-formedness and legality at in its position.\nTemplateTag.parseCompleteTag = function (scannerOrString, position) {\n var scanner = scannerOrString;\n if (typeof scanner === 'string')\n scanner = new HTMLTools.Scanner(scannerOrString);\n\n var startPos = scanner.pos; // for error messages\n var result = TemplateTag.parse(scannerOrString);\n if (! result)\n return result;\n\n if (result.type === 'BLOCKCOMMENT')\n return null;\n\n if (result.type === 'COMMENT')\n return null;\n\n if (result.type === 'ELSE')\n scanner.fatal(\"Unexpected {{else}}\");\n\n if (result.type === 'BLOCKCLOSE')\n scanner.fatal(\"Unexpected closing template tag\");\n\n position = (position || TEMPLATE_TAG_POSITION.ELEMENT);\n if (position !== TEMPLATE_TAG_POSITION.ELEMENT)\n result.position = position;\n\n if (result.type === 'BLOCKOPEN') {\n // parse block contents\n\n // Construct a string version of `.path` for comparing start and\n // end tags. For example, `foo/[0]` was parsed into `[\"foo\", \"0\"]`\n // and now becomes `foo,0`. This form may also show up in error\n // messages.\n var blockName = result.path.join(',');\n\n var textMode = null;\n if (blockName === 'markdown' ||\n position === TEMPLATE_TAG_POSITION.IN_RAWTEXT) {\n textMode = HTML.TEXTMODE.STRING;\n } else if (position === TEMPLATE_TAG_POSITION.IN_RCDATA ||\n position === TEMPLATE_TAG_POSITION.IN_ATTRIBUTE) {\n textMode = HTML.TEXTMODE.RCDATA;\n }\n var parserOptions = {\n getTemplateTag: TemplateTag.parseCompleteTag,\n shouldStop: isAtBlockCloseOrElse,\n textMode: textMode\n };\n result.content = HTMLTools.parseFragment(scanner, parserOptions);\n\n if (scanner.rest().slice(0, 2) !== '{{')\n scanner.fatal(\"Expected {{else}} or block close for \" + blockName);\n\n var lastPos = scanner.pos; // save for error messages\n var tmplTag = TemplateTag.parse(scanner); // {{else}} or {{/foo}}\n\n if (tmplTag.type === 'ELSE') {\n // parse {{else}} and content up to close tag\n result.elseContent = HTMLTools.parseFragment(scanner, parserOptions);\n\n if (scanner.rest().slice(0, 2) !== '{{')\n scanner.fatal(\"Expected block close for \" + blockName);\n\n lastPos = scanner.pos;\n tmplTag = TemplateTag.parse(scanner);\n }\n\n if (tmplTag.type === 'BLOCKCLOSE') {\n var blockName2 = tmplTag.path.join(',');\n if (blockName !== blockName2) {\n scanner.pos = lastPos;\n scanner.fatal('Expected tag to close ' + blockName + ', found ' +\n blockName2);\n }\n } else {\n scanner.pos = lastPos;\n scanner.fatal('Expected tag to close ' + blockName + ', found ' +\n tmplTag.type);\n }\n }\n\n var finalPos = scanner.pos;\n scanner.pos = startPos;\n validateTag(result, scanner);\n scanner.pos = finalPos;\n\n return result;\n};\n\nvar isAtBlockCloseOrElse = function (scanner) {\n // Detect `{{else}}` or `{{/foo}}`.\n //\n // We do as much work ourselves before deferring to `TemplateTag.peek`,\n // for efficiency (we're called for every input token) and to be\n // less obtrusive, because `TemplateTag.peek` will throw an error if it\n // sees `{{` followed by a malformed tag.\n var rest, type;\n return (scanner.peek() === '{' &&\n (rest = scanner.rest()).slice(0, 2) === '{{' &&\n /^\\{\\{\\s*(\\/|else\\b)/.test(rest) &&\n (type = TemplateTag.peek(scanner).type) &&\n (type === 'BLOCKCLOSE' || type === 'ELSE'));\n};\n\n// Validate that `templateTag` is correctly formed and legal for its\n// HTML position. Use `scanner` to report errors. On success, does\n// nothing.\nvar validateTag = function (ttag, scanner) {\n\n if (ttag.type === 'INCLUSION' || ttag.type === 'BLOCKOPEN') {\n var args = ttag.args;\n if (args.length > 1 && args[0].length === 2 && args[0][0] !== 'PATH') {\n // we have a positional argument that is not a PATH followed by\n // other arguments\n scanner.fatal(\"First argument must be a function, to be called on the rest of the arguments; found \" + args[0][0]);\n }\n }\n\n var position = ttag.position || TEMPLATE_TAG_POSITION.ELEMENT;\n if (position === TEMPLATE_TAG_POSITION.IN_ATTRIBUTE) {\n if (ttag.type === 'DOUBLE' || ttag.type === 'ESCAPE') {\n return;\n } else if (ttag.type === 'BLOCKOPEN') {\n var path = ttag.path;\n var path0 = path[0];\n if (! (path.length === 1 && (path0 === 'if' ||\n path0 === 'unless' ||\n path0 === 'with' ||\n path0 === 'each'))) {\n scanner.fatal(\"Custom block helpers are not allowed in an HTML attribute, only built-in ones like #each and #if\");\n }\n } else {\n scanner.fatal(ttag.type + \" template tag is not allowed in an HTML attribute\");\n }\n } else if (position === TEMPLATE_TAG_POSITION.IN_START_TAG) {\n if (! (ttag.type === 'DOUBLE')) {\n scanner.fatal(\"Reactive HTML attributes must either have a constant name or consist of a single {{helper}} providing a dictionary of names and values. A template tag of type \" + ttag.type + \" is not allowed here.\");\n }\n if (scanner.peek() === '=') {\n scanner.fatal(\"Template tags are not allowed in attribute names, only in attribute values or in the form of a single {{helper}} that evaluates to a dictionary of name=value pairs.\");\n }\n }\n\n};\n","// Optimize parts of an HTMLjs tree into raw HTML strings when they don't\n// contain template tags.\n\nvar constant = function (value) {\n return function () { return value; };\n};\n\nvar OPTIMIZABLE = {\n NONE: 0,\n PARTS: 1,\n FULL: 2\n};\n\n// We can only turn content into an HTML string if it contains no template\n// tags and no \"tricky\" HTML tags. If we can optimize the entire content\n// into a string, we return OPTIMIZABLE.FULL. If the we are given an\n// unoptimizable node, we return OPTIMIZABLE.NONE. If we are given a tree\n// that contains an unoptimizable node somewhere, we return OPTIMIZABLE.PARTS.\n//\n// For example, we always create SVG elements programmatically, since SVG\n// doesn't have innerHTML. If we are given an SVG element, we return NONE.\n// However, if we are given a big tree that contains SVG somewhere, we\n// return PARTS so that the optimizer can descend into the tree and optimize\n// other parts of it.\nvar CanOptimizeVisitor = HTML.Visitor.extend();\nCanOptimizeVisitor.def({\n visitNull: constant(OPTIMIZABLE.FULL),\n visitPrimitive: constant(OPTIMIZABLE.FULL),\n visitComment: constant(OPTIMIZABLE.FULL),\n visitCharRef: constant(OPTIMIZABLE.FULL),\n visitRaw: constant(OPTIMIZABLE.FULL),\n visitObject: constant(OPTIMIZABLE.NONE),\n visitFunction: constant(OPTIMIZABLE.NONE),\n visitArray: function (x) {\n for (var i = 0; i < x.length; i++)\n if (this.visit(x[i]) !== OPTIMIZABLE.FULL)\n return OPTIMIZABLE.PARTS;\n return OPTIMIZABLE.FULL;\n },\n visitTag: function (tag) {\n var tagName = tag.tagName;\n if (tagName === 'textarea') {\n // optimizing into a TEXTAREA's RCDATA would require being a little\n // more clever.\n return OPTIMIZABLE.NONE;\n } else if (! (HTML.isKnownElement(tagName) &&\n ! HTML.isKnownSVGElement(tagName))) {\n // foreign elements like SVG can't be stringified for innerHTML.\n return OPTIMIZABLE.NONE;\n } else if (tagName === 'table') {\n // Avoid ever producing HTML containing `