vendor/assets/javascripts/handlebars.js in handlebars_assets-0.18 vs vendor/assets/javascripts/handlebars.js in handlebars_assets-0.19
- old
+ new
@@ -1,8 +1,8 @@
/*!
- handlebars v2.0.0
+ handlebars v3.0.0
Copyright (C) 2011-2014 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
@@ -23,43 +23,28 @@
THE SOFTWARE.
@license
*/
/* exported Handlebars */
+if (!window) {
+ var window = {};
+}
+
(function (root, factory) {
if (typeof define === 'function' && define.amd) {
define([], factory);
} else if (typeof exports === 'object') {
module.exports = factory();
} else {
- root.Handlebars = root.Handlebars || factory();
+ root.Handlebars = factory();
}
}(this, 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__) {
+var __module3__ = (function() {
"use strict";
var __exports__ = {};
/*jshint -W004 */
- var SafeString = __dependency1__;
-
var escape = {
"&": "&",
"<": "<",
">": ">",
'"': """,
@@ -105,15 +90,25 @@
/* istanbul ignore next */
var isArray = Array.isArray || function(value) {
return (value && typeof value === 'object') ? toString.call(value) === '[object Array]' : false;
};
__exports__.isArray = isArray;
+ // Older IE versions do not directly support indexOf so we must implement our own, sadly.
+ function indexOf(array, value) {
+ for (var i = 0, len = array.length; i < len; i++) {
+ if (array[i] === value) {
+ return i;
+ }
+ }
+ return -1;
+ }
+ __exports__.indexOf = indexOf;
function escapeExpression(string) {
// don't escape SafeStrings, since they're already safe
- if (string instanceof SafeString) {
- return string.toString();
+ if (string && string.toHTML) {
+ return string.toHTML();
} else if (string == null) {
return "";
} else if (!string) {
return string + '';
}
@@ -135,43 +130,51 @@
} else {
return false;
}
}
- __exports__.isEmpty = isEmpty;function appendContextPath(contextPath, id) {
+ __exports__.isEmpty = isEmpty;function blockParams(params, ids) {
+ params.path = ids;
+ return params;
+ }
+
+ __exports__.blockParams = blockParams;function appendContextPath(contextPath, id) {
return (contextPath ? contextPath + '.' : '') + id;
}
__exports__.appendContextPath = appendContextPath;
return __exports__;
-})(__module4__);
+})();
// handlebars/exception.js
-var __module5__ = (function() {
+var __module4__ = (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;
+ var loc = node && node.loc,
+ line,
+ column;
+ if (loc) {
+ line = loc.start.line;
+ column = loc.start.column;
- message += ' - ' + line + ':' + node.firstColumn;
+ message += ' - ' + line + ':' + column;
}
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) {
+ if (loc) {
this.lineNumber = line;
- this.column = node.firstColumn;
+ this.column = column;
}
}
Exception.prototype = new Error();
@@ -184,11 +187,11 @@
"use strict";
var __exports__ = {};
var Utils = __dependency1__;
var Exception = __dependency2__;
- var VERSION = "2.0.0";
+ var VERSION = "3.0.0";
__exports__.VERSION = VERSION;var COMPILER_REVISION = 6;
__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',
@@ -230,10 +233,13 @@
registerPartial: function(name, partial) {
if (toString.call(name) === objectType) {
Utils.extend(this.partials, name);
} else {
+ if (typeof partial === 'undefined') {
+ throw new Exception('Attempting to register a partial as undefined');
+ }
this.partials[name] = partial;
}
},
unregisterPartial: function(name) {
delete this.partials[name];
@@ -297,40 +303,51 @@
if (options.data) {
data = createFrame(options.data);
}
+ function execIteration(key, i, last) {
+ if (data) {
+ data.key = key;
+ data.index = i;
+ data.first = i === 0;
+ data.last = !!last;
+
+ if (contextPath) {
+ data.contextPath = contextPath + key;
+ }
+ }
+
+ ret = ret + fn(context[key], {
+ data: data,
+ blockParams: Utils.blockParams([context[key], key], [contextPath + key, null])
+ });
+ }
+
if(context && typeof context === 'object') {
if (isArray(context)) {
for(var j = context.length; i<j; i++) {
- if (data) {
- data.index = i;
- data.first = (i === 0);
- data.last = (i === (context.length-1));
-
- if (contextPath) {
- data.contextPath = contextPath + i;
- }
- }
- ret = ret + fn(context[i], { data: data });
+ execIteration(i, i, i === context.length-1);
}
} else {
+ var priorKey;
+
for(var key in context) {
if(context.hasOwnProperty(key)) {
- if(data) {
- data.key = key;
- data.index = i;
- data.first = (i === 0);
-
- if (contextPath) {
- data.contextPath = contextPath + key;
- }
+ // We're running the iterations one step out of sync so we can detect
+ // the last iteration without have to scan the object twice and create
+ // an itermediate keys array.
+ if (priorKey) {
+ execIteration(priorKey, i-1);
}
- ret = ret + fn(context[key], {data: data});
+ priorKey = key;
i++;
}
}
+ if (priorKey) {
+ execIteration(priorKey, i-1, true);
+ }
}
}
if(i === 0){
ret = inverse(this);
@@ -390,19 +407,17 @@
// State enum
DEBUG: 0,
INFO: 1,
WARN: 2,
ERROR: 3,
- level: 3,
+ level: 1,
- // can be overridden in the host environment
+ // Can be overridden in the host environment
log: function(level, message) {
- if (logger.level <= level) {
+ if (typeof console !== 'undefined' && logger.level <= level) {
var method = logger.methodMap[level];
- if (typeof console !== 'undefined' && console[method]) {
- console[method].call(console, message);
- }
+ (console[method] || console.log).call(console, message);
}
}
};
__exports__.logger = logger;
var log = logger.log;
@@ -412,12 +427,29 @@
frame._parent = object;
return frame;
};
__exports__.createFrame = createFrame;
return __exports__;
-})(__module3__, __module5__);
+})(__module3__, __module4__);
+// handlebars/safe-string.js
+var __module5__ = (function() {
+ "use strict";
+ var __exports__;
+ // Build out our basic SafeString type
+ function SafeString(string) {
+ this.string = string;
+ }
+
+ SafeString.prototype.toString = SafeString.prototype.toHTML = function() {
+ return "" + this.string;
+ };
+
+ __exports__ = SafeString;
+ return __exports__;
+})();
+
// handlebars/runtime.js
var __module6__ = (function(__dependency1__, __dependency2__, __dependency3__) {
"use strict";
var __exports__ = {};
var Utils = __dependency1__;
@@ -457,42 +489,48 @@
// Note: Using env.VM references rather than local var references throughout this section to allow
// for external users to override these as psuedo-supported APIs.
env.VM.checkRevision(templateSpec.compiler);
- var invokePartialWrapper = function(partial, indent, name, context, hash, helpers, partials, data, depths) {
- if (hash) {
- context = Utils.extend({}, context, hash);
+ var invokePartialWrapper = function(partial, context, options) {
+ if (options.hash) {
+ context = Utils.extend({}, context, options.hash);
}
- var result = env.VM.invokePartial.call(this, partial, name, context, helpers, partials, data, depths);
+ partial = env.VM.resolvePartial.call(this, partial, context, options);
+ var result = env.VM.invokePartial.call(this, partial, context, options);
if (result == null && env.compile) {
- var options = { helpers: helpers, partials: partials, data: data, depths: depths };
- partials[name] = env.compile(partial, { data: data !== undefined, compat: templateSpec.compat }, env);
- result = partials[name](context, options);
+ options.partials[options.name] = env.compile(partial, templateSpec.compilerOptions, env);
+ result = options.partials[options.name](context, options);
}
if (result != null) {
- if (indent) {
+ if (options.indent) {
var lines = result.split('\n');
for (var i = 0, l = lines.length; i < l; i++) {
if (!lines[i] && i + 1 === l) {
break;
}
- lines[i] = indent + lines[i];
+ lines[i] = options.indent + lines[i];
}
result = lines.join('\n');
}
return result;
} else {
- throw new Exception("The partial " + name + " could not be compiled when running in runtime-only mode");
+ throw new Exception("The partial " + options.name + " could not be compiled when running in runtime-only mode");
}
};
// Just add water
var container = {
+ strict: function(obj, name) {
+ if (!(name in obj)) {
+ throw new Exception('"' + name + '" not defined in ' + obj);
+ }
+ return obj[name];
+ },
lookup: function(depths, name) {
var len = depths.length;
for (var i = 0; i < len; i++) {
if (depths[i] && depths[i][name] != null) {
return depths[i][name];
@@ -509,15 +547,15 @@
fn: function(i) {
return templateSpec[i];
},
programs: [],
- program: function(i, data, depths) {
+ program: function(i, data, declaredBlockParams, blockParams, depths) {
var programWrapper = this.programs[i],
fn = this.fn(i);
- if (data || depths) {
- programWrapper = program(this, i, fn, data, depths);
+ if (data || depths || blockParams || declaredBlockParams) {
+ programWrapper = program(this, i, fn, data, declaredBlockParams, blockParams, depths);
} else if (!programWrapper) {
programWrapper = this.programs[i] = program(this, i, fn);
}
return programWrapper;
},
@@ -548,16 +586,17 @@
ret._setup(options);
if (!options.partial && templateSpec.useData) {
data = initData(context, data);
}
- var depths;
+ var depths,
+ blockParams = templateSpec.useBlockParams ? [] : undefined;
if (templateSpec.useDepths) {
depths = options.depths ? [context].concat(options.depths) : [context];
}
- return templateSpec.main.call(container, context, container.helpers, container.partials, data, depths);
+ return templateSpec.main.call(container, context, container.helpers, container.partials, data, blockParams, depths);
};
ret.isTop = true;
ret._setup = function(options) {
if (!options.partial) {
@@ -570,36 +609,56 @@
container.helpers = options.helpers;
container.partials = options.partials;
}
};
- ret._child = function(i, data, depths) {
+ ret._child = function(i, data, blockParams, depths) {
+ if (templateSpec.useBlockParams && !blockParams) {
+ throw new Exception('must pass block params');
+ }
if (templateSpec.useDepths && !depths) {
throw new Exception('must pass parent depths');
}
- return program(container, i, templateSpec[i], data, depths);
+ return program(container, i, templateSpec[i], data, 0, blockParams, depths);
};
return ret;
}
- __exports__.template = template;function program(container, i, fn, data, depths) {
+ __exports__.template = template;function program(container, i, fn, data, declaredBlockParams, blockParams, depths) {
var prog = function(context, options) {
options = options || {};
- return fn.call(container, context, container.helpers, container.partials, options.data || data, depths && [context].concat(depths));
+ return fn.call(container,
+ context,
+ container.helpers, container.partials,
+ options.data || data,
+ blockParams && [options.blockParams].concat(blockParams),
+ depths && [context].concat(depths));
};
prog.program = i;
prog.depth = depths ? depths.length : 0;
+ prog.blockParams = declaredBlockParams || 0;
return prog;
}
- __exports__.program = program;function invokePartial(partial, name, context, helpers, partials, data, depths) {
- var options = { partial: true, helpers: helpers, partials: partials, data: data, depths: depths };
+ __exports__.program = program;function resolvePartial(partial, context, options) {
+ if (!partial) {
+ partial = options.partials[options.name];
+ } else if (!partial.call && !options.name) {
+ // This is a dynamic partial that returned a string
+ options.name = partial;
+ partial = options.partials[partial];
+ }
+ return partial;
+ }
+ __exports__.resolvePartial = resolvePartial;function invokePartial(partial, context, options) {
+ options.partial = true;
+
if(partial === undefined) {
- throw new Exception("The partial " + name + " could not be found");
+ throw new Exception("The partial " + options.name + " could not be found");
} else if(partial instanceof Function) {
return partial(context, options);
}
}
@@ -611,11 +670,11 @@
data.root = context;
}
return data;
}
return __exports__;
-})(__module3__, __module5__, __module2__);
+})(__module3__, __module4__, __module2__);
// handlebars.runtime.js
var __module1__ = (function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__) {
"use strict";
var __exports__;
@@ -648,235 +707,174 @@
};
var Handlebars = create();
Handlebars.create = create;
+ /*jshint -W040 */
+ /* istanbul ignore next */
+ var root = typeof global !== 'undefined' ? global : window,
+ $Handlebars = root.Handlebars;
+ /* istanbul ignore next */
+ Handlebars.noConflict = function() {
+ if (root.Handlebars === Handlebars) {
+ root.Handlebars = $Handlebars;
+ }
+ };
+
Handlebars['default'] = Handlebars;
__exports__ = Handlebars;
return __exports__;
-})(__module2__, __module4__, __module5__, __module3__, __module6__);
+})(__module2__, __module5__, __module4__, __module3__, __module6__);
// handlebars/compiler/ast.js
-var __module7__ = (function(__dependency1__) {
+var __module7__ = (function() {
"use strict";
var __exports__;
- var Exception = __dependency1__;
-
- function LocationInfo(locInfo) {
- locInfo = locInfo || {};
- this.firstLine = locInfo.first_line;
- this.firstColumn = locInfo.first_column;
- this.lastColumn = locInfo.last_column;
- this.lastLine = locInfo.last_line;
- }
-
var AST = {
- ProgramNode: function(statements, strip, locInfo) {
- LocationInfo.call(this, locInfo);
- this.type = "program";
- this.statements = statements;
- this.strip = strip;
- },
+ Program: function(statements, blockParams, strip, locInfo) {
+ this.loc = locInfo;
+ this.type = 'Program';
+ this.body = statements;
- MustacheNode: function(rawParams, hash, open, strip, locInfo) {
- LocationInfo.call(this, locInfo);
- this.type = "mustache";
+ this.blockParams = blockParams;
this.strip = strip;
-
- // Open may be a string parsed from the parser or a passed boolean flag
- if (open != null && open.charAt) {
- // Must use charAt to support IE pre-10
- var escapeFlag = open.charAt(3) || open.charAt(2);
- this.escaped = escapeFlag !== '{' && escapeFlag !== '&';
- } else {
- this.escaped = !!open;
- }
-
- if (rawParams instanceof AST.SexprNode) {
- this.sexpr = rawParams;
- } else {
- // Support old AST API
- this.sexpr = new AST.SexprNode(rawParams, hash);
- }
-
- // Support old AST API that stored this info in MustacheNode
- this.id = this.sexpr.id;
- this.params = this.sexpr.params;
- this.hash = this.sexpr.hash;
- this.eligibleHelper = this.sexpr.eligibleHelper;
- this.isHelper = this.sexpr.isHelper;
},
- SexprNode: function(rawParams, hash, locInfo) {
- LocationInfo.call(this, locInfo);
+ MustacheStatement: function(path, params, hash, escaped, strip, locInfo) {
+ this.loc = locInfo;
+ this.type = 'MustacheStatement';
- this.type = "sexpr";
+ this.path = path;
+ this.params = params || [];
this.hash = hash;
+ this.escaped = escaped;
- var id = this.id = rawParams[0];
- var params = this.params = rawParams.slice(1);
-
- // a mustache is definitely a helper if:
- // * it is an eligible helper, and
- // * it has at least one parameter or hash segment
- this.isHelper = !!(params.length || hash);
-
- // a mustache is an eligible helper if:
- // * its id is simple (a single part, not `this` or `..`)
- this.eligibleHelper = this.isHelper || id.isSimple;
-
- // 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.
- },
-
- PartialNode: function(partialName, context, hash, strip, locInfo) {
- LocationInfo.call(this, locInfo);
- this.type = "partial";
- this.partialName = partialName;
- this.context = context;
- this.hash = hash;
this.strip = strip;
-
- this.strip.inlineStandalone = true;
},
- BlockNode: function(mustache, program, inverse, strip, locInfo) {
- LocationInfo.call(this, locInfo);
+ BlockStatement: function(path, params, hash, program, inverse, openStrip, inverseStrip, closeStrip, locInfo) {
+ this.loc = locInfo;
+ this.type = 'BlockStatement';
- this.type = 'block';
- this.mustache = mustache;
+ this.path = path;
+ this.params = params || [];
+ this.hash = hash;
this.program = program;
this.inverse = inverse;
- this.strip = strip;
- if (inverse && !program) {
- this.isInverse = true;
- }
+ this.openStrip = openStrip;
+ this.inverseStrip = inverseStrip;
+ this.closeStrip = closeStrip;
},
- RawBlockNode: function(mustache, content, close, locInfo) {
- LocationInfo.call(this, locInfo);
+ PartialStatement: function(name, params, hash, strip, locInfo) {
+ this.loc = locInfo;
+ this.type = 'PartialStatement';
- if (mustache.sexpr.id.original !== close) {
- throw new Exception(mustache.sexpr.id.original + " doesn't match " + close, this);
- }
+ this.name = name;
+ this.params = params || [];
+ this.hash = hash;
- content = new AST.ContentNode(content, locInfo);
-
- this.type = 'block';
- this.mustache = mustache;
- this.program = new AST.ProgramNode([content], {}, locInfo);
+ this.indent = '';
+ this.strip = strip;
},
- ContentNode: function(string, locInfo) {
- LocationInfo.call(this, locInfo);
- this.type = "content";
- this.original = this.string = string;
+ ContentStatement: function(string, locInfo) {
+ this.loc = locInfo;
+ this.type = 'ContentStatement';
+ this.original = this.value = string;
},
- HashNode: function(pairs, locInfo) {
- LocationInfo.call(this, locInfo);
- this.type = "hash";
- this.pairs = pairs;
+ CommentStatement: function(comment, strip, locInfo) {
+ this.loc = locInfo;
+ this.type = 'CommentStatement';
+ this.value = comment;
+
+ this.strip = strip;
},
- IdNode: function(parts, locInfo) {
- LocationInfo.call(this, locInfo);
- this.type = "ID";
+ SubExpression: function(path, params, hash, locInfo) {
+ this.loc = locInfo;
- var original = "",
- dig = [],
- depth = 0,
- depthString = '';
+ this.type = 'SubExpression';
+ this.path = path;
+ this.params = params || [];
+ this.hash = hash;
+ },
- for(var i=0,l=parts.length; i<l; i++) {
- var part = parts[i].part;
- original += (parts[i].separator || '') + part;
+ PathExpression: function(data, depth, parts, original, locInfo) {
+ this.loc = locInfo;
+ this.type = 'PathExpression';
- if (part === ".." || part === "." || part === "this") {
- if (dig.length > 0) {
- throw new Exception("Invalid path: " + original, this);
- } else if (part === "..") {
- depth++;
- depthString += '../';
- } else {
- this.isScoped = true;
- }
- } else {
- dig.push(part);
- }
- }
-
+ this.data = data;
this.original = original;
- this.parts = dig;
- this.string = dig.join('.');
+ this.parts = parts;
this.depth = depth;
- this.idName = depthString + this.string;
-
- // 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;
+ StringLiteral: function(string, locInfo) {
+ this.loc = locInfo;
+ this.type = 'StringLiteral';
+ this.original =
+ this.value = string;
},
- DataNode: function(id, locInfo) {
- LocationInfo.call(this, locInfo);
- this.type = "DATA";
- this.id = id;
- this.stringModeValue = id.stringModeValue;
- this.idName = '@' + id.stringModeValue;
- },
-
- StringNode: function(string, locInfo) {
- LocationInfo.call(this, locInfo);
- this.type = "STRING";
+ NumberLiteral: function(number, locInfo) {
+ this.loc = locInfo;
+ this.type = 'NumberLiteral';
this.original =
- this.string =
- this.stringModeValue = string;
+ this.value = Number(number);
},
- NumberNode: function(number, locInfo) {
- LocationInfo.call(this, locInfo);
- this.type = "NUMBER";
+ BooleanLiteral: function(bool, locInfo) {
+ this.loc = locInfo;
+ this.type = 'BooleanLiteral';
this.original =
- this.number = number;
- this.stringModeValue = Number(number);
+ this.value = bool === 'true';
},
- BooleanNode: function(bool, locInfo) {
- LocationInfo.call(this, locInfo);
- this.type = "BOOLEAN";
- this.bool = bool;
- this.stringModeValue = bool === "true";
+ Hash: function(pairs, locInfo) {
+ this.loc = locInfo;
+ this.type = 'Hash';
+ this.pairs = pairs;
},
+ HashPair: function(key, value, locInfo) {
+ this.loc = locInfo;
+ this.type = 'HashPair';
+ this.key = key;
+ this.value = value;
+ },
- CommentNode: function(comment, locInfo) {
- LocationInfo.call(this, locInfo);
- this.type = "comment";
- this.comment = comment;
+ // Public API used to evaluate derived attributes regarding AST nodes
+ helpers: {
+ // a mustache is definitely a helper if:
+ // * it is an eligible helper, and
+ // * it has at least one parameter or hash segment
+ // TODO: Make these public utility methods
+ helperExpression: function(node) {
+ return !!(node.type === 'SubExpression' || node.params.length || node.hash);
+ },
- this.strip = {
- inlineStandalone: true
- };
+ scopedId: function(path) {
+ return (/^\.|this\b/).test(path.original);
+ },
+
+ // an ID is simple if it only has one part, and that part is not
+ // `..` or `this`.
+ simpleId: function(path) {
+ return path.parts.length === 1 && !AST.helpers.scopedId(path) && !path.depth;
+ }
}
};
// Must be exported as an object rather than the root of the module as the jison lexer
- // most modify the object to operate properly.
+ // must modify the object to operate properly.
__exports__ = AST;
return __exports__;
-})(__module5__);
+})();
// handlebars/compiler/parser.js
var __module9__ = (function() {
"use strict";
var __exports__;
@@ -884,107 +882,151 @@
/* istanbul ignore next */
/* Jison generated parser */
var handlebars = (function(){
var parser = {trace: function trace() { },
yy: {},
- symbols_: {"error":2,"root":3,"program":4,"EOF":5,"program_repetition0":6,"statement":7,"mustache":8,"block":9,"rawBlock":10,"partial":11,"CONTENT":12,"COMMENT":13,"openRawBlock":14,"END_RAW_BLOCK":15,"OPEN_RAW_BLOCK":16,"sexpr":17,"CLOSE_RAW_BLOCK":18,"openBlock":19,"block_option0":20,"closeBlock":21,"openInverse":22,"block_option1":23,"OPEN_BLOCK":24,"CLOSE":25,"OPEN_INVERSE":26,"inverseAndProgram":27,"INVERSE":28,"OPEN_ENDBLOCK":29,"path":30,"OPEN":31,"OPEN_UNESCAPED":32,"CLOSE_UNESCAPED":33,"OPEN_PARTIAL":34,"partialName":35,"param":36,"partial_option0":37,"partial_option1":38,"sexpr_repetition0":39,"sexpr_option0":40,"dataName":41,"STRING":42,"NUMBER":43,"BOOLEAN":44,"OPEN_SEXPR":45,"CLOSE_SEXPR":46,"hash":47,"hash_repetition_plus0":48,"hashSegment":49,"ID":50,"EQUALS":51,"DATA":52,"pathSegments":53,"SEP":54,"$accept":0,"$end":1},
- terminals_: {2:"error",5:"EOF",12:"CONTENT",13:"COMMENT",15:"END_RAW_BLOCK",16:"OPEN_RAW_BLOCK",18:"CLOSE_RAW_BLOCK",24:"OPEN_BLOCK",25:"CLOSE",26:"OPEN_INVERSE",28:"INVERSE",29:"OPEN_ENDBLOCK",31:"OPEN",32:"OPEN_UNESCAPED",33:"CLOSE_UNESCAPED",34:"OPEN_PARTIAL",42:"STRING",43:"NUMBER",44:"BOOLEAN",45:"OPEN_SEXPR",46:"CLOSE_SEXPR",50:"ID",51:"EQUALS",52:"DATA",54:"SEP"},
- productions_: [0,[3,2],[4,1],[7,1],[7,1],[7,1],[7,1],[7,1],[7,1],[10,3],[14,3],[9,4],[9,4],[19,3],[22,3],[27,2],[21,3],[8,3],[8,3],[11,5],[11,4],[17,3],[17,1],[36,1],[36,1],[36,1],[36,1],[36,1],[36,3],[47,1],[49,3],[35,1],[35,1],[35,1],[41,2],[30,1],[53,3],[53,1],[6,0],[6,2],[20,0],[20,1],[23,0],[23,1],[37,0],[37,1],[38,0],[38,1],[39,0],[39,2],[40,0],[40,1],[48,1],[48,2]],
+ symbols_: {"error":2,"root":3,"program":4,"EOF":5,"program_repetition0":6,"statement":7,"mustache":8,"block":9,"rawBlock":10,"partial":11,"content":12,"COMMENT":13,"CONTENT":14,"openRawBlock":15,"END_RAW_BLOCK":16,"OPEN_RAW_BLOCK":17,"helperName":18,"openRawBlock_repetition0":19,"openRawBlock_option0":20,"CLOSE_RAW_BLOCK":21,"openBlock":22,"block_option0":23,"closeBlock":24,"openInverse":25,"block_option1":26,"OPEN_BLOCK":27,"openBlock_repetition0":28,"openBlock_option0":29,"openBlock_option1":30,"CLOSE":31,"OPEN_INVERSE":32,"openInverse_repetition0":33,"openInverse_option0":34,"openInverse_option1":35,"openInverseChain":36,"OPEN_INVERSE_CHAIN":37,"openInverseChain_repetition0":38,"openInverseChain_option0":39,"openInverseChain_option1":40,"inverseAndProgram":41,"INVERSE":42,"inverseChain":43,"inverseChain_option0":44,"OPEN_ENDBLOCK":45,"OPEN":46,"mustache_repetition0":47,"mustache_option0":48,"OPEN_UNESCAPED":49,"mustache_repetition1":50,"mustache_option1":51,"CLOSE_UNESCAPED":52,"OPEN_PARTIAL":53,"partialName":54,"partial_repetition0":55,"partial_option0":56,"param":57,"sexpr":58,"OPEN_SEXPR":59,"sexpr_repetition0":60,"sexpr_option0":61,"CLOSE_SEXPR":62,"hash":63,"hash_repetition_plus0":64,"hashSegment":65,"ID":66,"EQUALS":67,"blockParams":68,"OPEN_BLOCK_PARAMS":69,"blockParams_repetition_plus0":70,"CLOSE_BLOCK_PARAMS":71,"path":72,"dataName":73,"STRING":74,"NUMBER":75,"BOOLEAN":76,"DATA":77,"pathSegments":78,"SEP":79,"$accept":0,"$end":1},
+ terminals_: {2:"error",5:"EOF",13:"COMMENT",14:"CONTENT",16:"END_RAW_BLOCK",17:"OPEN_RAW_BLOCK",21:"CLOSE_RAW_BLOCK",27:"OPEN_BLOCK",31:"CLOSE",32:"OPEN_INVERSE",37:"OPEN_INVERSE_CHAIN",42:"INVERSE",45:"OPEN_ENDBLOCK",46:"OPEN",49:"OPEN_UNESCAPED",52:"CLOSE_UNESCAPED",53:"OPEN_PARTIAL",59:"OPEN_SEXPR",62:"CLOSE_SEXPR",66:"ID",67:"EQUALS",69:"OPEN_BLOCK_PARAMS",71:"CLOSE_BLOCK_PARAMS",74:"STRING",75:"NUMBER",76:"BOOLEAN",77:"DATA",79:"SEP"},
+ productions_: [0,[3,2],[4,1],[7,1],[7,1],[7,1],[7,1],[7,1],[7,1],[12,1],[10,3],[15,5],[9,4],[9,4],[22,6],[25,6],[36,6],[41,2],[43,3],[43,1],[24,3],[8,5],[8,5],[11,5],[57,1],[57,1],[58,5],[63,1],[65,3],[68,3],[18,1],[18,1],[18,1],[18,1],[18,1],[54,1],[54,1],[73,2],[72,1],[78,3],[78,1],[6,0],[6,2],[19,0],[19,2],[20,0],[20,1],[23,0],[23,1],[26,0],[26,1],[28,0],[28,2],[29,0],[29,1],[30,0],[30,1],[33,0],[33,2],[34,0],[34,1],[35,0],[35,1],[38,0],[38,2],[39,0],[39,1],[40,0],[40,1],[44,0],[44,1],[47,0],[47,2],[48,0],[48,1],[50,0],[50,2],[51,0],[51,1],[55,0],[55,2],[56,0],[56,1],[60,0],[60,2],[61,0],[61,1],[64,1],[64,2],[70,1],[70,2]],
performAction: function anonymous(yytext,yyleng,yylineno,yy,yystate,$$,_$) {
var $0 = $$.length - 1;
switch (yystate) {
- case 1: yy.prepareProgram($$[$0-1].statements, true); return $$[$0-1];
+ case 1: return $$[$0-1];
break;
- case 2:this.$ = new yy.ProgramNode(yy.prepareProgram($$[$0]), {}, this._$);
+ case 2:this.$ = new yy.Program($$[$0], null, {}, yy.locInfo(this._$));
break;
case 3:this.$ = $$[$0];
break;
case 4:this.$ = $$[$0];
break;
case 5:this.$ = $$[$0];
break;
case 6:this.$ = $$[$0];
break;
- case 7:this.$ = new yy.ContentNode($$[$0], this._$);
+ case 7:this.$ = $$[$0];
break;
- case 8:this.$ = new yy.CommentNode($$[$0], this._$);
+ case 8:this.$ = new yy.CommentStatement(yy.stripComment($$[$0]), yy.stripFlags($$[$0], $$[$0]), yy.locInfo(this._$));
break;
- case 9:this.$ = new yy.RawBlockNode($$[$0-2], $$[$0-1], $$[$0], this._$);
+ case 9:this.$ = new yy.ContentStatement($$[$0], yy.locInfo(this._$));
break;
- case 10:this.$ = new yy.MustacheNode($$[$0-1], null, '', '', this._$);
+ case 10:this.$ = yy.prepareRawBlock($$[$0-2], $$[$0-1], $$[$0], this._$);
break;
- case 11:this.$ = yy.prepareBlock($$[$0-3], $$[$0-2], $$[$0-1], $$[$0], false, this._$);
+ case 11:this.$ = { path: $$[$0-3], params: $$[$0-2], hash: $$[$0-1] };
break;
- case 12:this.$ = yy.prepareBlock($$[$0-3], $$[$0-2], $$[$0-1], $$[$0], true, this._$);
+ case 12:this.$ = yy.prepareBlock($$[$0-3], $$[$0-2], $$[$0-1], $$[$0], false, this._$);
break;
- case 13:this.$ = new yy.MustacheNode($$[$0-1], null, $$[$0-2], yy.stripFlags($$[$0-2], $$[$0]), this._$);
+ case 13:this.$ = yy.prepareBlock($$[$0-3], $$[$0-2], $$[$0-1], $$[$0], true, this._$);
break;
- case 14:this.$ = new yy.MustacheNode($$[$0-1], null, $$[$0-2], yy.stripFlags($$[$0-2], $$[$0]), this._$);
+ case 14:this.$ = { path: $$[$0-4], params: $$[$0-3], hash: $$[$0-2], blockParams: $$[$0-1], strip: yy.stripFlags($$[$0-5], $$[$0]) };
break;
- case 15:this.$ = { strip: yy.stripFlags($$[$0-1], $$[$0-1]), program: $$[$0] };
+ case 15:this.$ = { path: $$[$0-4], params: $$[$0-3], hash: $$[$0-2], blockParams: $$[$0-1], strip: yy.stripFlags($$[$0-5], $$[$0]) };
break;
- case 16:this.$ = {path: $$[$0-1], strip: yy.stripFlags($$[$0-2], $$[$0])};
+ case 16:this.$ = { path: $$[$0-4], params: $$[$0-3], hash: $$[$0-2], blockParams: $$[$0-1], strip: yy.stripFlags($$[$0-5], $$[$0]) };
break;
- case 17:this.$ = new yy.MustacheNode($$[$0-1], null, $$[$0-2], yy.stripFlags($$[$0-2], $$[$0]), this._$);
+ case 17:this.$ = { strip: yy.stripFlags($$[$0-1], $$[$0-1]), program: $$[$0] };
break;
- case 18:this.$ = new yy.MustacheNode($$[$0-1], null, $$[$0-2], yy.stripFlags($$[$0-2], $$[$0]), this._$);
+ case 18:
+ var inverse = yy.prepareBlock($$[$0-2], $$[$0-1], $$[$0], $$[$0], false, this._$),
+ program = new yy.Program([inverse], null, {}, yy.locInfo(this._$));
+ program.chained = true;
+
+ this.$ = { strip: $$[$0-2].strip, program: program, chain: true };
+
break;
- case 19:this.$ = new yy.PartialNode($$[$0-3], $$[$0-2], $$[$0-1], yy.stripFlags($$[$0-4], $$[$0]), this._$);
+ case 19:this.$ = $$[$0];
break;
- case 20:this.$ = new yy.PartialNode($$[$0-2], undefined, $$[$0-1], yy.stripFlags($$[$0-3], $$[$0]), this._$);
+ case 20:this.$ = {path: $$[$0-1], strip: yy.stripFlags($$[$0-2], $$[$0])};
break;
- case 21:this.$ = new yy.SexprNode([$$[$0-2]].concat($$[$0-1]), $$[$0], this._$);
+ case 21:this.$ = yy.prepareMustache($$[$0-3], $$[$0-2], $$[$0-1], $$[$0-4], yy.stripFlags($$[$0-4], $$[$0]), this._$);
break;
- case 22:this.$ = new yy.SexprNode([$$[$0]], null, this._$);
+ case 22:this.$ = yy.prepareMustache($$[$0-3], $$[$0-2], $$[$0-1], $$[$0-4], yy.stripFlags($$[$0-4], $$[$0]), this._$);
break;
- case 23:this.$ = $$[$0];
+ case 23:this.$ = new yy.PartialStatement($$[$0-3], $$[$0-2], $$[$0-1], yy.stripFlags($$[$0-4], $$[$0]), yy.locInfo(this._$));
break;
- case 24:this.$ = new yy.StringNode($$[$0], this._$);
+ case 24:this.$ = $$[$0];
break;
- case 25:this.$ = new yy.NumberNode($$[$0], this._$);
+ case 25:this.$ = $$[$0];
break;
- case 26:this.$ = new yy.BooleanNode($$[$0], this._$);
+ case 26:this.$ = new yy.SubExpression($$[$0-3], $$[$0-2], $$[$0-1], yy.locInfo(this._$));
break;
- case 27:this.$ = $$[$0];
+ case 27:this.$ = new yy.Hash($$[$0], yy.locInfo(this._$));
break;
- case 28:$$[$0-1].isHelper = true; this.$ = $$[$0-1];
+ case 28:this.$ = new yy.HashPair($$[$0-2], $$[$0], yy.locInfo(this._$));
break;
- case 29:this.$ = new yy.HashNode($$[$0], this._$);
+ case 29:this.$ = $$[$0-1];
break;
- case 30:this.$ = [$$[$0-2], $$[$0]];
+ case 30:this.$ = $$[$0];
break;
- case 31:this.$ = new yy.PartialNameNode($$[$0], this._$);
+ case 31:this.$ = $$[$0];
break;
- case 32:this.$ = new yy.PartialNameNode(new yy.StringNode($$[$0], this._$), this._$);
+ case 32:this.$ = new yy.StringLiteral($$[$0], yy.locInfo(this._$));
break;
- case 33:this.$ = new yy.PartialNameNode(new yy.NumberNode($$[$0], this._$));
+ case 33:this.$ = new yy.NumberLiteral($$[$0], yy.locInfo(this._$));
break;
- case 34:this.$ = new yy.DataNode($$[$0], this._$);
+ case 34:this.$ = new yy.BooleanLiteral($$[$0], yy.locInfo(this._$));
break;
- case 35:this.$ = new yy.IdNode($$[$0], this._$);
+ case 35:this.$ = $$[$0];
break;
- case 36: $$[$0-2].push({part: $$[$0], separator: $$[$0-1]}); this.$ = $$[$0-2];
+ case 36:this.$ = $$[$0];
break;
- case 37:this.$ = [{part: $$[$0]}];
+ case 37:this.$ = yy.preparePath(true, $$[$0], this._$);
break;
- case 38:this.$ = [];
+ case 38:this.$ = yy.preparePath(false, $$[$0], this._$);
break;
- case 39:$$[$0-1].push($$[$0]);
+ case 39: $$[$0-2].push({part: $$[$0], separator: $$[$0-1]}); this.$ = $$[$0-2];
break;
- case 48:this.$ = [];
+ case 40:this.$ = [{part: $$[$0]}];
break;
- case 49:$$[$0-1].push($$[$0]);
+ case 41:this.$ = [];
break;
- case 52:this.$ = [$$[$0]];
+ case 42:$$[$0-1].push($$[$0]);
break;
- case 53:$$[$0-1].push($$[$0]);
+ case 43:this.$ = [];
break;
+ case 44:$$[$0-1].push($$[$0]);
+ break;
+ case 51:this.$ = [];
+ break;
+ case 52:$$[$0-1].push($$[$0]);
+ break;
+ case 57:this.$ = [];
+ break;
+ case 58:$$[$0-1].push($$[$0]);
+ break;
+ case 63:this.$ = [];
+ break;
+ case 64:$$[$0-1].push($$[$0]);
+ break;
+ case 71:this.$ = [];
+ break;
+ case 72:$$[$0-1].push($$[$0]);
+ break;
+ case 75:this.$ = [];
+ break;
+ case 76:$$[$0-1].push($$[$0]);
+ break;
+ case 79:this.$ = [];
+ break;
+ case 80:$$[$0-1].push($$[$0]);
+ break;
+ case 83:this.$ = [];
+ break;
+ case 84:$$[$0-1].push($$[$0]);
+ break;
+ case 87:this.$ = [$$[$0]];
+ break;
+ case 88:$$[$0-1].push($$[$0]);
+ break;
+ case 89:this.$ = [$$[$0]];
+ break;
+ case 90:$$[$0-1].push($$[$0]);
+ break;
}
},
- table: [{3:1,4:2,5:[2,38],6:3,12:[2,38],13:[2,38],16:[2,38],24:[2,38],26:[2,38],31:[2,38],32:[2,38],34:[2,38]},{1:[3]},{5:[1,4]},{5:[2,2],7:5,8:6,9:7,10:8,11:9,12:[1,10],13:[1,11],14:16,16:[1,20],19:14,22:15,24:[1,18],26:[1,19],28:[2,2],29:[2,2],31:[1,12],32:[1,13],34:[1,17]},{1:[2,1]},{5:[2,39],12:[2,39],13:[2,39],16:[2,39],24:[2,39],26:[2,39],28:[2,39],29:[2,39],31:[2,39],32:[2,39],34:[2,39]},{5:[2,3],12:[2,3],13:[2,3],16:[2,3],24:[2,3],26:[2,3],28:[2,3],29:[2,3],31:[2,3],32:[2,3],34:[2,3]},{5:[2,4],12:[2,4],13:[2,4],16:[2,4],24:[2,4],26:[2,4],28:[2,4],29:[2,4],31:[2,4],32:[2,4],34:[2,4]},{5:[2,5],12:[2,5],13:[2,5],16:[2,5],24:[2,5],26:[2,5],28:[2,5],29:[2,5],31:[2,5],32:[2,5],34:[2,5]},{5:[2,6],12:[2,6],13:[2,6],16:[2,6],24:[2,6],26:[2,6],28:[2,6],29:[2,6],31:[2,6],32:[2,6],34:[2,6]},{5:[2,7],12:[2,7],13:[2,7],16:[2,7],24:[2,7],26:[2,7],28:[2,7],29:[2,7],31:[2,7],32:[2,7],34:[2,7]},{5:[2,8],12:[2,8],13:[2,8],16:[2,8],24:[2,8],26:[2,8],28:[2,8],29:[2,8],31:[2,8],32:[2,8],34:[2,8]},{17:21,30:22,41:23,50:[1,26],52:[1,25],53:24},{17:27,30:22,41:23,50:[1,26],52:[1,25],53:24},{4:28,6:3,12:[2,38],13:[2,38],16:[2,38],24:[2,38],26:[2,38],28:[2,38],29:[2,38],31:[2,38],32:[2,38],34:[2,38]},{4:29,6:3,12:[2,38],13:[2,38],16:[2,38],24:[2,38],26:[2,38],28:[2,38],29:[2,38],31:[2,38],32:[2,38],34:[2,38]},{12:[1,30]},{30:32,35:31,42:[1,33],43:[1,34],50:[1,26],53:24},{17:35,30:22,41:23,50:[1,26],52:[1,25],53:24},{17:36,30:22,41:23,50:[1,26],52:[1,25],53:24},{17:37,30:22,41:23,50:[1,26],52:[1,25],53:24},{25:[1,38]},{18:[2,48],25:[2,48],33:[2,48],39:39,42:[2,48],43:[2,48],44:[2,48],45:[2,48],46:[2,48],50:[2,48],52:[2,48]},{18:[2,22],25:[2,22],33:[2,22],46:[2,22]},{18:[2,35],25:[2,35],33:[2,35],42:[2,35],43:[2,35],44:[2,35],45:[2,35],46:[2,35],50:[2,35],52:[2,35],54:[1,40]},{30:41,50:[1,26],53:24},{18:[2,37],25:[2,37],33:[2,37],42:[2,37],43:[2,37],44:[2,37],45:[2,37],46:[2,37],50:[2,37],52:[2,37],54:[2,37]},{33:[1,42]},{20:43,27:44,28:[1,45],29:[2,40]},{23:46,27:47,28:[1,45],29:[2,42]},{15:[1,48]},{25:[2,46],30:51,36:49,38:50,41:55,42:[1,52],43:[1,53],44:[1,54],45:[1,56],47:57,48:58,49:60,50:[1,59],52:[1,25],53:24},{25:[2,31],42:[2,31],43:[2,31],44:[2,31],45:[2,31],50:[2,31],52:[2,31]},{25:[2,32],42:[2,32],43:[2,32],44:[2,32],45:[2,32],50:[2,32],52:[2,32]},{25:[2,33],42:[2,33],43:[2,33],44:[2,33],45:[2,33],50:[2,33],52:[2,33]},{25:[1,61]},{25:[1,62]},{18:[1,63]},{5:[2,17],12:[2,17],13:[2,17],16:[2,17],24:[2,17],26:[2,17],28:[2,17],29:[2,17],31:[2,17],32:[2,17],34:[2,17]},{18:[2,50],25:[2,50],30:51,33:[2,50],36:65,40:64,41:55,42:[1,52],43:[1,53],44:[1,54],45:[1,56],46:[2,50],47:66,48:58,49:60,50:[1,59],52:[1,25],53:24},{50:[1,67]},{18:[2,34],25:[2,34],33:[2,34],42:[2,34],43:[2,34],44:[2,34],45:[2,34],46:[2,34],50:[2,34],52:[2,34]},{5:[2,18],12:[2,18],13:[2,18],16:[2,18],24:[2,18],26:[2,18],28:[2,18],29:[2,18],31:[2,18],32:[2,18],34:[2,18]},{21:68,29:[1,69]},{29:[2,41]},{4:70,6:3,12:[2,38],13:[2,38],16:[2,38],24:[2,38],26:[2,38],29:[2,38],31:[2,38],32:[2,38],34:[2,38]},{21:71,29:[1,69]},{29:[2,43]},{5:[2,9],12:[2,9],13:[2,9],16:[2,9],24:[2,9],26:[2,9],28:[2,9],29:[2,9],31:[2,9],32:[2,9],34:[2,9]},{25:[2,44],37:72,47:73,48:58,49:60,50:[1,74]},{25:[1,75]},{18:[2,23],25:[2,23],33:[2,23],42:[2,23],43:[2,23],44:[2,23],45:[2,23],46:[2,23],50:[2,23],52:[2,23]},{18:[2,24],25:[2,24],33:[2,24],42:[2,24],43:[2,24],44:[2,24],45:[2,24],46:[2,24],50:[2,24],52:[2,24]},{18:[2,25],25:[2,25],33:[2,25],42:[2,25],43:[2,25],44:[2,25],45:[2,25],46:[2,25],50:[2,25],52:[2,25]},{18:[2,26],25:[2,26],33:[2,26],42:[2,26],43:[2,26],44:[2,26],45:[2,26],46:[2,26],50:[2,26],52:[2,26]},{18:[2,27],25:[2,27],33:[2,27],42:[2,27],43:[2,27],44:[2,27],45:[2,27],46:[2,27],50:[2,27],52:[2,27]},{17:76,30:22,41:23,50:[1,26],52:[1,25],53:24},{25:[2,47]},{18:[2,29],25:[2,29],33:[2,29],46:[2,29],49:77,50:[1,74]},{18:[2,37],25:[2,37],33:[2,37],42:[2,37],43:[2,37],44:[2,37],45:[2,37],46:[2,37],50:[2,37],51:[1,78],52:[2,37],54:[2,37]},{18:[2,52],25:[2,52],33:[2,52],46:[2,52],50:[2,52]},{12:[2,13],13:[2,13],16:[2,13],24:[2,13],26:[2,13],28:[2,13],29:[2,13],31:[2,13],32:[2,13],34:[2,13]},{12:[2,14],13:[2,14],16:[2,14],24:[2,14],26:[2,14],28:[2,14],29:[2,14],31:[2,14],32:[2,14],34:[2,14]},{12:[2,10]},{18:[2,21],25:[2,21],33:[2,21],46:[2,21]},{18:[2,49],25:[2,49],33:[2,49],42:[2,49],43:[2,49],44:[2,49],45:[2,49],46:[2,49],50:[2,49],52:[2,49]},{18:[2,51],25:[2,51],33:[2,51],46:[2,51]},{18:[2,36],25:[2,36],33:[2,36],42:[2,36],43:[2,36],44:[2,36],45:[2,36],46:[2,36],50:[2,36],52:[2,36],54:[2,36]},{5:[2,11],12:[2,11],13:[2,11],16:[2,11],24:[2,11],26:[2,11],28:[2,11],29:[2,11],31:[2,11],32:[2,11],34:[2,11]},{30:79,50:[1,26],53:24},{29:[2,15]},{5:[2,12],12:[2,12],13:[2,12],16:[2,12],24:[2,12],26:[2,12],28:[2,12],29:[2,12],31:[2,12],32:[2,12],34:[2,12]},{25:[1,80]},{25:[2,45]},{51:[1,78]},{5:[2,20],12:[2,20],13:[2,20],16:[2,20],24:[2,20],26:[2,20],28:[2,20],29:[2,20],31:[2,20],32:[2,20],34:[2,20]},{46:[1,81]},{18:[2,53],25:[2,53],33:[2,53],46:[2,53],50:[2,53]},{30:51,36:82,41:55,42:[1,52],43:[1,53],44:[1,54],45:[1,56],50:[1,26],52:[1,25],53:24},{25:[1,83]},{5:[2,19],12:[2,19],13:[2,19],16:[2,19],24:[2,19],26:[2,19],28:[2,19],29:[2,19],31:[2,19],32:[2,19],34:[2,19]},{18:[2,28],25:[2,28],33:[2,28],42:[2,28],43:[2,28],44:[2,28],45:[2,28],46:[2,28],50:[2,28],52:[2,28]},{18:[2,30],25:[2,30],33:[2,30],46:[2,30],50:[2,30]},{5:[2,16],12:[2,16],13:[2,16],16:[2,16],24:[2,16],26:[2,16],28:[2,16],29:[2,16],31:[2,16],32:[2,16],34:[2,16]}],
- defaultActions: {4:[2,1],44:[2,41],47:[2,43],57:[2,47],63:[2,10],70:[2,15],73:[2,45]},
+ table: [{3:1,4:2,5:[2,41],6:3,13:[2,41],14:[2,41],17:[2,41],27:[2,41],32:[2,41],46:[2,41],49:[2,41],53:[2,41]},{1:[3]},{5:[1,4]},{5:[2,2],7:5,8:6,9:7,10:8,11:9,12:10,13:[1,11],14:[1,18],15:16,17:[1,21],22:14,25:15,27:[1,19],32:[1,20],37:[2,2],42:[2,2],45:[2,2],46:[1,12],49:[1,13],53:[1,17]},{1:[2,1]},{5:[2,42],13:[2,42],14:[2,42],17:[2,42],27:[2,42],32:[2,42],37:[2,42],42:[2,42],45:[2,42],46:[2,42],49:[2,42],53:[2,42]},{5:[2,3],13:[2,3],14:[2,3],17:[2,3],27:[2,3],32:[2,3],37:[2,3],42:[2,3],45:[2,3],46:[2,3],49:[2,3],53:[2,3]},{5:[2,4],13:[2,4],14:[2,4],17:[2,4],27:[2,4],32:[2,4],37:[2,4],42:[2,4],45:[2,4],46:[2,4],49:[2,4],53:[2,4]},{5:[2,5],13:[2,5],14:[2,5],17:[2,5],27:[2,5],32:[2,5],37:[2,5],42:[2,5],45:[2,5],46:[2,5],49:[2,5],53:[2,5]},{5:[2,6],13:[2,6],14:[2,6],17:[2,6],27:[2,6],32:[2,6],37:[2,6],42:[2,6],45:[2,6],46:[2,6],49:[2,6],53:[2,6]},{5:[2,7],13:[2,7],14:[2,7],17:[2,7],27:[2,7],32:[2,7],37:[2,7],42:[2,7],45:[2,7],46:[2,7],49:[2,7],53:[2,7]},{5:[2,8],13:[2,8],14:[2,8],17:[2,8],27:[2,8],32:[2,8],37:[2,8],42:[2,8],45:[2,8],46:[2,8],49:[2,8],53:[2,8]},{18:22,66:[1,30],72:23,73:24,74:[1,25],75:[1,26],76:[1,27],77:[1,29],78:28},{18:31,66:[1,30],72:23,73:24,74:[1,25],75:[1,26],76:[1,27],77:[1,29],78:28},{4:32,6:3,13:[2,41],14:[2,41],17:[2,41],27:[2,41],32:[2,41],37:[2,41],42:[2,41],45:[2,41],46:[2,41],49:[2,41],53:[2,41]},{4:33,6:3,13:[2,41],14:[2,41],17:[2,41],27:[2,41],32:[2,41],42:[2,41],45:[2,41],46:[2,41],49:[2,41],53:[2,41]},{12:34,14:[1,18]},{18:36,54:35,58:37,59:[1,38],66:[1,30],72:23,73:24,74:[1,25],75:[1,26],76:[1,27],77:[1,29],78:28},{5:[2,9],13:[2,9],14:[2,9],16:[2,9],17:[2,9],27:[2,9],32:[2,9],37:[2,9],42:[2,9],45:[2,9],46:[2,9],49:[2,9],53:[2,9]},{18:39,66:[1,30],72:23,73:24,74:[1,25],75:[1,26],76:[1,27],77:[1,29],78:28},{18:40,66:[1,30],72:23,73:24,74:[1,25],75:[1,26],76:[1,27],77:[1,29],78:28},{18:41,66:[1,30],72:23,73:24,74:[1,25],75:[1,26],76:[1,27],77:[1,29],78:28},{31:[2,71],47:42,59:[2,71],66:[2,71],74:[2,71],75:[2,71],76:[2,71],77:[2,71]},{21:[2,30],31:[2,30],52:[2,30],59:[2,30],62:[2,30],66:[2,30],69:[2,30],74:[2,30],75:[2,30],76:[2,30],77:[2,30]},{21:[2,31],31:[2,31],52:[2,31],59:[2,31],62:[2,31],66:[2,31],69:[2,31],74:[2,31],75:[2,31],76:[2,31],77:[2,31]},{21:[2,32],31:[2,32],52:[2,32],59:[2,32],62:[2,32],66:[2,32],69:[2,32],74:[2,32],75:[2,32],76:[2,32],77:[2,32]},{21:[2,33],31:[2,33],52:[2,33],59:[2,33],62:[2,33],66:[2,33],69:[2,33],74:[2,33],75:[2,33],76:[2,33],77:[2,33]},{21:[2,34],31:[2,34],52:[2,34],59:[2,34],62:[2,34],66:[2,34],69:[2,34],74:[2,34],75:[2,34],76:[2,34],77:[2,34]},{21:[2,38],31:[2,38],52:[2,38],59:[2,38],62:[2,38],66:[2,38],69:[2,38],74:[2,38],75:[2,38],76:[2,38],77:[2,38],79:[1,43]},{66:[1,30],78:44},{21:[2,40],31:[2,40],52:[2,40],59:[2,40],62:[2,40],66:[2,40],69:[2,40],74:[2,40],75:[2,40],76:[2,40],77:[2,40],79:[2,40]},{50:45,52:[2,75],59:[2,75],66:[2,75],74:[2,75],75:[2,75],76:[2,75],77:[2,75]},{23:46,36:48,37:[1,50],41:49,42:[1,51],43:47,45:[2,47]},{26:52,41:53,42:[1,51],45:[2,49]},{16:[1,54]},{31:[2,79],55:55,59:[2,79],66:[2,79],74:[2,79],75:[2,79],76:[2,79],77:[2,79]},{31:[2,35],59:[2,35],66:[2,35],74:[2,35],75:[2,35],76:[2,35],77:[2,35]},{31:[2,36],59:[2,36],66:[2,36],74:[2,36],75:[2,36],76:[2,36],77:[2,36]},{18:56,66:[1,30],72:23,73:24,74:[1,25],75:[1,26],76:[1,27],77:[1,29],78:28},{28:57,31:[2,51],59:[2,51],66:[2,51],69:[2,51],74:[2,51],75:[2,51],76:[2,51],77:[2,51]},{31:[2,57],33:58,59:[2,57],66:[2,57],69:[2,57],74:[2,57],75:[2,57],76:[2,57],77:[2,57]},{19:59,21:[2,43],59:[2,43],66:[2,43],74:[2,43],75:[2,43],76:[2,43],77:[2,43]},{18:63,31:[2,73],48:60,57:61,58:64,59:[1,38],63:62,64:65,65:66,66:[1,67],72:23,73:24,74:[1,25],75:[1,26],76:[1,27],77:[1,29],78:28},{66:[1,68]},{21:[2,37],31:[2,37],52:[2,37],59:[2,37],62:[2,37],66:[2,37],69:[2,37],74:[2,37],75:[2,37],76:[2,37],77:[2,37],79:[1,43]},{18:63,51:69,52:[2,77],57:70,58:64,59:[1,38],63:71,64:65,65:66,66:[1,67],72:23,73:24,74:[1,25],75:[1,26],76:[1,27],77:[1,29],78:28},{24:72,45:[1,73]},{45:[2,48]},{4:74,6:3,13:[2,41],14:[2,41],17:[2,41],27:[2,41],32:[2,41],37:[2,41],42:[2,41],45:[2,41],46:[2,41],49:[2,41],53:[2,41]},{45:[2,19]},{18:75,66:[1,30],72:23,73:24,74:[1,25],75:[1,26],76:[1,27],77:[1,29],78:28},{4:76,6:3,13:[2,41],14:[2,41],17:[2,41],27:[2,41],32:[2,41],45:[2,41],46:[2,41],49:[2,41],53:[2,41]},{24:77,45:[1,73]},{45:[2,50]},{5:[2,10],13:[2,10],14:[2,10],17:[2,10],27:[2,10],32:[2,10],37:[2,10],42:[2,10],45:[2,10],46:[2,10],49:[2,10],53:[2,10]},{18:63,31:[2,81],56:78,57:79,58:64,59:[1,38],63:80,64:65,65:66,66:[1,67],72:23,73:24,74:[1,25],75:[1,26],76:[1,27],77:[1,29],78:28},{59:[2,83],60:81,62:[2,83],66:[2,83],74:[2,83],75:[2,83],76:[2,83],77:[2,83]},{18:63,29:82,31:[2,53],57:83,58:64,59:[1,38],63:84,64:65,65:66,66:[1,67],69:[2,53],72:23,73:24,74:[1,25],75:[1,26],76:[1,27],77:[1,29],78:28},{18:63,31:[2,59],34:85,57:86,58:64,59:[1,38],63:87,64:65,65:66,66:[1,67],69:[2,59],72:23,73:24,74:[1,25],75:[1,26],76:[1,27],77:[1,29],78:28},{18:63,20:88,21:[2,45],57:89,58:64,59:[1,38],63:90,64:65,65:66,66:[1,67],72:23,73:24,74:[1,25],75:[1,26],76:[1,27],77:[1,29],78:28},{31:[1,91]},{31:[2,72],59:[2,72],66:[2,72],74:[2,72],75:[2,72],76:[2,72],77:[2,72]},{31:[2,74]},{21:[2,24],31:[2,24],52:[2,24],59:[2,24],62:[2,24],66:[2,24],69:[2,24],74:[2,24],75:[2,24],76:[2,24],77:[2,24]},{21:[2,25],31:[2,25],52:[2,25],59:[2,25],62:[2,25],66:[2,25],69:[2,25],74:[2,25],75:[2,25],76:[2,25],77:[2,25]},{21:[2,27],31:[2,27],52:[2,27],62:[2,27],65:92,66:[1,93],69:[2,27]},{21:[2,87],31:[2,87],52:[2,87],62:[2,87],66:[2,87],69:[2,87]},{21:[2,40],31:[2,40],52:[2,40],59:[2,40],62:[2,40],66:[2,40],67:[1,94],69:[2,40],74:[2,40],75:[2,40],76:[2,40],77:[2,40],79:[2,40]},{21:[2,39],31:[2,39],52:[2,39],59:[2,39],62:[2,39],66:[2,39],69:[2,39],74:[2,39],75:[2,39],76:[2,39],77:[2,39],79:[2,39]},{52:[1,95]},{52:[2,76],59:[2,76],66:[2,76],74:[2,76],75:[2,76],76:[2,76],77:[2,76]},{52:[2,78]},{5:[2,12],13:[2,12],14:[2,12],17:[2,12],27:[2,12],32:[2,12],37:[2,12],42:[2,12],45:[2,12],46:[2,12],49:[2,12],53:[2,12]},{18:96,66:[1,30],72:23,73:24,74:[1,25],75:[1,26],76:[1,27],77:[1,29],78:28},{36:48,37:[1,50],41:49,42:[1,51],43:98,44:97,45:[2,69]},{31:[2,63],38:99,59:[2,63],66:[2,63],69:[2,63],74:[2,63],75:[2,63],76:[2,63],77:[2,63]},{45:[2,17]},{5:[2,13],13:[2,13],14:[2,13],17:[2,13],27:[2,13],32:[2,13],37:[2,13],42:[2,13],45:[2,13],46:[2,13],49:[2,13],53:[2,13]},{31:[1,100]},{31:[2,80],59:[2,80],66:[2,80],74:[2,80],75:[2,80],76:[2,80],77:[2,80]},{31:[2,82]},{18:63,57:102,58:64,59:[1,38],61:101,62:[2,85],63:103,64:65,65:66,66:[1,67],72:23,73:24,74:[1,25],75:[1,26],76:[1,27],77:[1,29],78:28},{30:104,31:[2,55],68:105,69:[1,106]},{31:[2,52],59:[2,52],66:[2,52],69:[2,52],74:[2,52],75:[2,52],76:[2,52],77:[2,52]},{31:[2,54],69:[2,54]},{31:[2,61],35:107,68:108,69:[1,106]},{31:[2,58],59:[2,58],66:[2,58],69:[2,58],74:[2,58],75:[2,58],76:[2,58],77:[2,58]},{31:[2,60],69:[2,60]},{21:[1,109]},{21:[2,44],59:[2,44],66:[2,44],74:[2,44],75:[2,44],76:[2,44],77:[2,44]},{21:[2,46]},{5:[2,21],13:[2,21],14:[2,21],17:[2,21],27:[2,21],32:[2,21],37:[2,21],42:[2,21],45:[2,21],46:[2,21],49:[2,21],53:[2,21]},{21:[2,88],31:[2,88],52:[2,88],62:[2,88],66:[2,88],69:[2,88]},{67:[1,94]},{18:63,57:110,58:64,59:[1,38],66:[1,30],72:23,73:24,74:[1,25],75:[1,26],76:[1,27],77:[1,29],78:28},{5:[2,22],13:[2,22],14:[2,22],17:[2,22],27:[2,22],32:[2,22],37:[2,22],42:[2,22],45:[2,22],46:[2,22],49:[2,22],53:[2,22]},{31:[1,111]},{45:[2,18]},{45:[2,70]},{18:63,31:[2,65],39:112,57:113,58:64,59:[1,38],63:114,64:65,65:66,66:[1,67],69:[2,65],72:23,73:24,74:[1,25],75:[1,26],76:[1,27],77:[1,29],78:28},{5:[2,23],13:[2,23],14:[2,23],17:[2,23],27:[2,23],32:[2,23],37:[2,23],42:[2,23],45:[2,23],46:[2,23],49:[2,23],53:[2,23]},{62:[1,115]},{59:[2,84],62:[2,84],66:[2,84],74:[2,84],75:[2,84],76:[2,84],77:[2,84]},{62:[2,86]},{31:[1,116]},{31:[2,56]},{66:[1,118],70:117},{31:[1,119]},{31:[2,62]},{14:[2,11]},{21:[2,28],31:[2,28],52:[2,28],62:[2,28],66:[2,28],69:[2,28]},{5:[2,20],13:[2,20],14:[2,20],17:[2,20],27:[2,20],32:[2,20],37:[2,20],42:[2,20],45:[2,20],46:[2,20],49:[2,20],53:[2,20]},{31:[2,67],40:120,68:121,69:[1,106]},{31:[2,64],59:[2,64],66:[2,64],69:[2,64],74:[2,64],75:[2,64],76:[2,64],77:[2,64]},{31:[2,66],69:[2,66]},{21:[2,26],31:[2,26],52:[2,26],59:[2,26],62:[2,26],66:[2,26],69:[2,26],74:[2,26],75:[2,26],76:[2,26],77:[2,26]},{13:[2,14],14:[2,14],17:[2,14],27:[2,14],32:[2,14],37:[2,14],42:[2,14],45:[2,14],46:[2,14],49:[2,14],53:[2,14]},{66:[1,123],71:[1,122]},{66:[2,89],71:[2,89]},{13:[2,15],14:[2,15],17:[2,15],27:[2,15],32:[2,15],42:[2,15],45:[2,15],46:[2,15],49:[2,15],53:[2,15]},{31:[1,124]},{31:[2,68]},{31:[2,29]},{66:[2,90],71:[2,90]},{13:[2,16],14:[2,16],17:[2,16],27:[2,16],32:[2,16],37:[2,16],42:[2,16],45:[2,16],46:[2,16],49:[2,16],53:[2,16]}],
+ defaultActions: {4:[2,1],47:[2,48],49:[2,19],53:[2,50],62:[2,74],71:[2,78],76:[2,17],80:[2,82],90:[2,46],97:[2,18],98:[2,70],103:[2,86],105:[2,56],108:[2,62],109:[2,11],121:[2,68],122:[2,29]},
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;
@@ -1277,262 +1319,428 @@
strip(0,1);
this.begin("emu");
} else {
this.begin("mu");
}
- if(yy_.yytext) return 12;
-
+ if(yy_.yytext) return 14;
+
break;
- case 1:return 12;
+ case 1:return 14;
break;
case 2:
this.popState();
- return 12;
-
+ return 14;
+
break;
case 3:
yy_.yytext = yy_.yytext.substr(5, yy_.yyleng-9);
this.popState();
- return 15;
-
+ return 16;
+
break;
- case 4: return 12;
+ case 4: return 14;
break;
- case 5:strip(0,4); this.popState(); return 13;
+ case 5:
+ this.popState();
+ return 13;
+
break;
- case 6:return 45;
+ case 6:return 59;
break;
- case 7:return 46;
+ case 7:return 62;
break;
- case 8: return 16;
+ case 8: return 17;
break;
case 9:
this.popState();
this.begin('raw');
- return 18;
-
+ return 21;
+
break;
- case 10:return 34;
+ case 10:return 53;
break;
- case 11:return 24;
+ case 11:return 27;
break;
- case 12:return 29;
+ case 12:return 45;
break;
- case 13:this.popState(); return 28;
+ case 13:this.popState(); return 42;
break;
- case 14:this.popState(); return 28;
+ case 14:this.popState(); return 42;
break;
- case 15:return 26;
+ case 15:return 32;
break;
- case 16:return 26;
+ case 16:return 37;
break;
- case 17:return 32;
+ case 17:return 49;
break;
- case 18:return 31;
+ case 18:return 46;
break;
- case 19:this.popState(); this.begin('com');
+ case 19:
+ this.unput(yy_.yytext);
+ this.popState();
+ this.begin('com');
+
break;
- case 20:strip(3,5); this.popState(); return 13;
+ case 20:
+ this.popState();
+ return 13;
+
break;
- case 21:return 31;
+ case 21:return 46;
break;
- case 22:return 51;
+ case 22:return 67;
break;
- case 23:return 50;
+ case 23:return 66;
break;
- case 24:return 50;
+ case 24:return 66;
break;
- case 25:return 54;
+ case 25:return 79;
break;
case 26:// ignore whitespace
break;
- case 27:this.popState(); return 33;
+ case 27:this.popState(); return 52;
break;
- case 28:this.popState(); return 25;
+ case 28:this.popState(); return 31;
break;
- case 29:yy_.yytext = strip(1,2).replace(/\\"/g,'"'); return 42;
+ case 29:yy_.yytext = strip(1,2).replace(/\\"/g,'"'); return 74;
break;
- case 30:yy_.yytext = strip(1,2).replace(/\\'/g,"'"); return 42;
+ case 30:yy_.yytext = strip(1,2).replace(/\\'/g,"'"); return 74;
break;
- case 31:return 52;
+ case 31:return 77;
break;
- case 32:return 44;
+ case 32:return 76;
break;
- case 33:return 44;
+ case 33:return 76;
break;
- case 34:return 43;
+ case 34:return 75;
break;
- case 35:return 50;
+ case 35:return 69;
break;
- case 36:yy_.yytext = strip(1,2); return 50;
+ case 36:return 71;
break;
- case 37:return 'INVALID';
+ case 37:return 66;
break;
- case 38:return 5;
+ case 38:yy_.yytext = strip(1,2); return 66;
break;
+ case 39:return 'INVALID';
+ break;
+ case 40:return 5;
+ break;
}
};
- lexer.rules = [/^(?:[^\x00]*?(?=(\{\{)))/,/^(?:[^\x00]+)/,/^(?:[^\x00]{2,}?(?=(\{\{|\\\{\{|\\\\\{\{|$)))/,/^(?:\{\{\{\{\/[^\s!"#%-,\.\/;->@\[-\^`\{-~]+(?=[=}\s\/.])\}\}\}\})/,/^(?:[^\x00]*?(?=(\{\{\{\{\/)))/,/^(?:[\s\S]*?--\}\})/,/^(?:\()/,/^(?:\))/,/^(?:\{\{\{\{)/,/^(?:\}\}\}\})/,/^(?:\{\{(~)?>)/,/^(?:\{\{(~)?#)/,/^(?:\{\{(~)?\/)/,/^(?:\{\{(~)?\^\s*(~)?\}\})/,/^(?:\{\{(~)?\s*else\s*(~)?\}\})/,/^(?:\{\{(~)?\^)/,/^(?:\{\{(~)?\s*else\b)/,/^(?:\{\{(~)?\{)/,/^(?:\{\{(~)?&)/,/^(?:\{\{!--)/,/^(?:\{\{![\s\S]*?\}\})/,/^(?:\{\{(~)?)/,/^(?:=)/,/^(?:\.\.)/,/^(?:\.(?=([=~}\s\/.)])))/,/^(?:[\/.])/,/^(?:\s+)/,/^(?:\}(~)?\}\})/,/^(?:(~)?\}\})/,/^(?:"(\\["]|[^"])*")/,/^(?:'(\\[']|[^'])*')/,/^(?:@)/,/^(?:true(?=([~}\s)])))/,/^(?:false(?=([~}\s)])))/,/^(?:-?[0-9]+(?:\.[0-9]+)?(?=([~}\s)])))/,/^(?:([^\s!"#%-,\.\/;->@\[-\^`\{-~]+(?=([=~}\s\/.)]))))/,/^(?:\[[^\]]*\])/,/^(?:.)/,/^(?:$)/];
- lexer.conditions = {"mu":{"rules":[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,33,34,35,36,37,38],"inclusive":false},"emu":{"rules":[2],"inclusive":false},"com":{"rules":[5],"inclusive":false},"raw":{"rules":[3,4],"inclusive":false},"INITIAL":{"rules":[0,1,38],"inclusive":true}};
+ lexer.rules = [/^(?:[^\x00]*?(?=(\{\{)))/,/^(?:[^\x00]+)/,/^(?:[^\x00]{2,}?(?=(\{\{|\\\{\{|\\\\\{\{|$)))/,/^(?:\{\{\{\{\/[^\s!"#%-,\.\/;->@\[-\^`\{-~]+(?=[=}\s\/.])\}\}\}\})/,/^(?:[^\x00]*?(?=(\{\{\{\{\/)))/,/^(?:[\s\S]*?--(~)?\}\})/,/^(?:\()/,/^(?:\))/,/^(?:\{\{\{\{)/,/^(?:\}\}\}\})/,/^(?:\{\{(~)?>)/,/^(?:\{\{(~)?#)/,/^(?:\{\{(~)?\/)/,/^(?:\{\{(~)?\^\s*(~)?\}\})/,/^(?:\{\{(~)?\s*else\s*(~)?\}\})/,/^(?:\{\{(~)?\^)/,/^(?:\{\{(~)?\s*else\b)/,/^(?:\{\{(~)?\{)/,/^(?:\{\{(~)?&)/,/^(?:\{\{(~)?!--)/,/^(?:\{\{(~)?![\s\S]*?\}\})/,/^(?:\{\{(~)?)/,/^(?:=)/,/^(?:\.\.)/,/^(?:\.(?=([=~}\s\/.)|])))/,/^(?:[\/.])/,/^(?:\s+)/,/^(?:\}(~)?\}\})/,/^(?:(~)?\}\})/,/^(?:"(\\["]|[^"])*")/,/^(?:'(\\[']|[^'])*')/,/^(?:@)/,/^(?:true(?=([~}\s)])))/,/^(?:false(?=([~}\s)])))/,/^(?:-?[0-9]+(?:\.[0-9]+)?(?=([~}\s)])))/,/^(?:as\s+\|)/,/^(?:\|)/,/^(?:([^\s!"#%-,\.\/;->@\[-\^`\{-~]+(?=([=~}\s\/.)|]))))/,/^(?:\[[^\]]*\])/,/^(?:.)/,/^(?:$)/];
+ lexer.conditions = {"mu":{"rules":[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,33,34,35,36,37,38,39,40],"inclusive":false},"emu":{"rules":[2],"inclusive":false},"com":{"rules":[5],"inclusive":false},"raw":{"rules":[3,4],"inclusive":false},"INITIAL":{"rules":[0,1,40],"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/helpers.js
-var __module10__ = (function(__dependency1__) {
+// handlebars/compiler/visitor.js
+var __module11__ = (function(__dependency1__, __dependency2__) {
"use strict";
- var __exports__ = {};
+ var __exports__;
var Exception = __dependency1__;
+ var AST = __dependency2__;
- function stripFlags(open, close) {
- return {
- left: open.charAt(2) === '~',
- right: close.charAt(close.length-3) === '~'
- };
+ function Visitor() {
+ this.parents = [];
}
- __exports__.stripFlags = stripFlags;
- function prepareBlock(mustache, program, inverseAndProgram, close, inverted, locInfo) {
- /*jshint -W040 */
- if (mustache.sexpr.id.original !== close.path.original) {
- throw new Exception(mustache.sexpr.id.original + ' doesn\'t match ' + close.path.original, mustache);
- }
+ Visitor.prototype = {
+ constructor: Visitor,
+ mutating: false,
- var inverse = inverseAndProgram && inverseAndProgram.program;
+ // Visits a given value. If mutating, will replace the value if necessary.
+ acceptKey: function(node, name) {
+ var value = this.accept(node[name]);
+ if (this.mutating) {
+ // Hacky sanity check:
+ if (value && (!value.type || !AST[value.type])) {
+ throw new Exception('Unexpected node type "' + value.type + '" found when accepting ' + name + ' on ' + node.type);
+ }
+ node[name] = value;
+ }
+ },
- var strip = {
- left: mustache.strip.left,
- right: close.strip.right,
+ // Performs an accept operation with added sanity check to ensure
+ // required keys are not removed.
+ acceptRequired: function(node, name) {
+ this.acceptKey(node, name);
- // Determine the standalone candiacy. Basically flag our content as being possibly standalone
- // so our parent can determine if we actually are standalone
- openStandalone: isNextWhitespace(program.statements),
- closeStandalone: isPrevWhitespace((inverse || program).statements)
- };
+ if (!node[name]) {
+ throw new Exception(node.type + ' requires ' + name);
+ }
+ },
- if (mustache.strip.right) {
- omitRight(program.statements, null, true);
- }
+ // Traverses a given array. If mutating, empty respnses will be removed
+ // for child elements.
+ acceptArray: function(array) {
+ for (var i = 0, l = array.length; i < l; i++) {
+ this.acceptKey(array, i);
- if (inverse) {
- var inverseStrip = inverseAndProgram.strip;
+ if (!array[i]) {
+ array.splice(i, 1);
+ i--;
+ l--;
+ }
+ }
+ },
- if (inverseStrip.left) {
- omitLeft(program.statements, null, true);
+ accept: function(object) {
+ if (!object) {
+ return;
}
- if (inverseStrip.right) {
- omitRight(inverse.statements, null, true);
+
+ if (this.current) {
+ this.parents.unshift(this.current);
}
- if (close.strip.left) {
- omitLeft(inverse.statements, null, true);
- }
+ this.current = object;
- // Find standalone else statments
- if (isPrevWhitespace(program.statements)
- && isNextWhitespace(inverse.statements)) {
+ var ret = this[object.type](object);
- omitLeft(program.statements);
- omitRight(inverse.statements);
+ this.current = this.parents.shift();
+
+ if (!this.mutating || ret) {
+ return ret;
+ } else if (ret !== false) {
+ return object;
}
- } else {
- if (close.strip.left) {
- omitLeft(program.statements, null, true);
- }
- }
+ },
- if (inverted) {
- return new this.BlockNode(mustache, inverse, program, strip, locInfo);
- } else {
- return new this.BlockNode(mustache, program, inverse, strip, locInfo);
+ Program: function(program) {
+ this.acceptArray(program.body);
+ },
+
+ MustacheStatement: function(mustache) {
+ this.acceptRequired(mustache, 'path');
+ this.acceptArray(mustache.params);
+ this.acceptKey(mustache, 'hash');
+ },
+
+ BlockStatement: function(block) {
+ this.acceptRequired(block, 'path');
+ this.acceptArray(block.params);
+ this.acceptKey(block, 'hash');
+
+ this.acceptKey(block, 'program');
+ this.acceptKey(block, 'inverse');
+ },
+
+ PartialStatement: function(partial) {
+ this.acceptRequired(partial, 'name');
+ this.acceptArray(partial.params);
+ this.acceptKey(partial, 'hash');
+ },
+
+ ContentStatement: function(/* content */) {},
+ CommentStatement: function(/* comment */) {},
+
+ SubExpression: function(sexpr) {
+ this.acceptRequired(sexpr, 'path');
+ this.acceptArray(sexpr.params);
+ this.acceptKey(sexpr, 'hash');
+ },
+ PartialExpression: function(partial) {
+ this.acceptRequired(partial, 'name');
+ this.acceptArray(partial.params);
+ this.acceptKey(partial, 'hash');
+ },
+
+ PathExpression: function(/* path */) {},
+
+ StringLiteral: function(/* string */) {},
+ NumberLiteral: function(/* number */) {},
+ BooleanLiteral: function(/* bool */) {},
+
+ Hash: function(hash) {
+ this.acceptArray(hash.pairs);
+ },
+ HashPair: function(pair) {
+ this.acceptRequired(pair, 'value');
}
+ };
+
+ __exports__ = Visitor;
+ return __exports__;
+})(__module4__, __module7__);
+
+// handlebars/compiler/whitespace-control.js
+var __module10__ = (function(__dependency1__) {
+ "use strict";
+ var __exports__;
+ var Visitor = __dependency1__;
+
+ function WhitespaceControl() {
}
+ WhitespaceControl.prototype = new Visitor();
- __exports__.prepareBlock = prepareBlock;
- function prepareProgram(statements, isRoot) {
- for (var i = 0, l = statements.length; i < l; i++) {
- var current = statements[i],
- strip = current.strip;
+ WhitespaceControl.prototype.Program = function(program) {
+ var isRoot = !this.isRootSeen;
+ this.isRootSeen = true;
+ var body = program.body;
+ for (var i = 0, l = body.length; i < l; i++) {
+ var current = body[i],
+ strip = this.accept(current);
+
if (!strip) {
continue;
}
- var _isPrevWhitespace = isPrevWhitespace(statements, i, isRoot, current.type === 'partial'),
- _isNextWhitespace = isNextWhitespace(statements, i, isRoot),
+ var _isPrevWhitespace = isPrevWhitespace(body, i, isRoot),
+ _isNextWhitespace = isNextWhitespace(body, i, isRoot),
openStandalone = strip.openStandalone && _isPrevWhitespace,
closeStandalone = strip.closeStandalone && _isNextWhitespace,
inlineStandalone = strip.inlineStandalone && _isPrevWhitespace && _isNextWhitespace;
- if (strip.right) {
- omitRight(statements, i, true);
+ if (strip.close) {
+ omitRight(body, i, true);
}
- if (strip.left) {
- omitLeft(statements, i, true);
+ if (strip.open) {
+ omitLeft(body, i, true);
}
if (inlineStandalone) {
- omitRight(statements, i);
+ omitRight(body, i);
- if (omitLeft(statements, i)) {
+ if (omitLeft(body, i)) {
// If we are on a standalone node, save the indent info for partials
- if (current.type === 'partial') {
- current.indent = (/([ \t]+$)/).exec(statements[i-1].original) ? RegExp.$1 : '';
+ if (current.type === 'PartialStatement') {
+ // Pull out the whitespace from the final line
+ current.indent = (/([ \t]+$)/).exec(body[i-1].original)[1];
}
}
}
if (openStandalone) {
- omitRight((current.program || current.inverse).statements);
+ omitRight((current.program || current.inverse).body);
// Strip out the previous content node if it's whitespace only
- omitLeft(statements, i);
+ omitLeft(body, i);
}
if (closeStandalone) {
// Always strip the next node
- omitRight(statements, i);
+ omitRight(body, i);
- omitLeft((current.inverse || current.program).statements);
+ omitLeft((current.inverse || current.program).body);
}
}
- return statements;
- }
+ return program;
+ };
+ WhitespaceControl.prototype.BlockStatement = function(block) {
+ this.accept(block.program);
+ this.accept(block.inverse);
- __exports__.prepareProgram = prepareProgram;function isPrevWhitespace(statements, i, isRoot) {
+ // Find the inverse program that is involed with whitespace stripping.
+ var program = block.program || block.inverse,
+ inverse = block.program && block.inverse,
+ firstInverse = inverse,
+ lastInverse = inverse;
+
+ if (inverse && inverse.chained) {
+ firstInverse = inverse.body[0].program;
+
+ // Walk the inverse chain to find the last inverse that is actually in the chain.
+ while (lastInverse.chained) {
+ lastInverse = lastInverse.body[lastInverse.body.length-1].program;
+ }
+ }
+
+ var strip = {
+ open: block.openStrip.open,
+ close: block.closeStrip.close,
+
+ // Determine the standalone candiacy. Basically flag our content as being possibly standalone
+ // so our parent can determine if we actually are standalone
+ openStandalone: isNextWhitespace(program.body),
+ closeStandalone: isPrevWhitespace((firstInverse || program).body)
+ };
+
+ if (block.openStrip.close) {
+ omitRight(program.body, null, true);
+ }
+
+ if (inverse) {
+ var inverseStrip = block.inverseStrip;
+
+ if (inverseStrip.open) {
+ omitLeft(program.body, null, true);
+ }
+
+ if (inverseStrip.close) {
+ omitRight(firstInverse.body, null, true);
+ }
+ if (block.closeStrip.open) {
+ omitLeft(lastInverse.body, null, true);
+ }
+
+ // Find standalone else statments
+ if (isPrevWhitespace(program.body)
+ && isNextWhitespace(firstInverse.body)) {
+
+ omitLeft(program.body);
+ omitRight(firstInverse.body);
+ }
+ } else {
+ if (block.closeStrip.open) {
+ omitLeft(program.body, null, true);
+ }
+ }
+
+ return strip;
+ };
+
+ WhitespaceControl.prototype.MustacheStatement = function(mustache) {
+ return mustache.strip;
+ };
+
+ WhitespaceControl.prototype.PartialStatement =
+ WhitespaceControl.prototype.CommentStatement = function(node) {
+ /* istanbul ignore next */
+ var strip = node.strip || {};
+ return {
+ inlineStandalone: true,
+ open: strip.open,
+ close: strip.close
+ };
+ };
+
+
+ function isPrevWhitespace(body, i, isRoot) {
if (i === undefined) {
- i = statements.length;
+ i = body.length;
}
// Nodes that end with newlines are considered whitespace (but are special
// cased for strip operations)
- var prev = statements[i-1],
- sibling = statements[i-2];
+ var prev = body[i-1],
+ sibling = body[i-2];
if (!prev) {
return isRoot;
}
- if (prev.type === 'content') {
+ if (prev.type === 'ContentStatement') {
return (sibling || !isRoot ? (/\r?\n\s*?$/) : (/(^|\r?\n)\s*?$/)).test(prev.original);
}
}
- function isNextWhitespace(statements, i, isRoot) {
+ function isNextWhitespace(body, i, isRoot) {
if (i === undefined) {
i = -1;
}
- var next = statements[i+1],
- sibling = statements[i+2];
+ var next = body[i+1],
+ sibling = body[i+2];
if (!next) {
return isRoot;
}
- if (next.type === 'content') {
+ if (next.type === 'ContentStatement') {
return (sibling || !isRoot ? (/^\s*?\r?\n/) : (/^\s*?(\r?\n|$)/)).test(next.original);
}
}
// Marks the node to the right of the position as omitted.
@@ -1540,79 +1748,216 @@
//
// If i is undefined, then the first child will be marked as such.
//
// If mulitple is truthy then all whitespace will be stripped out until non-whitespace
// content is met.
- function omitRight(statements, i, multiple) {
- var current = statements[i == null ? 0 : i + 1];
- if (!current || current.type !== 'content' || (!multiple && current.rightStripped)) {
+ function omitRight(body, i, multiple) {
+ var current = body[i == null ? 0 : i + 1];
+ if (!current || current.type !== 'ContentStatement' || (!multiple && current.rightStripped)) {
return;
}
- var original = current.string;
- current.string = current.string.replace(multiple ? (/^\s+/) : (/^[ \t]*\r?\n?/), '');
- current.rightStripped = current.string !== original;
+ var original = current.value;
+ current.value = current.value.replace(multiple ? (/^\s+/) : (/^[ \t]*\r?\n?/), '');
+ current.rightStripped = current.value !== original;
}
// Marks the node to the left of the position as omitted.
// I.e. ' '{{foo}} will mark the ' ' node as omitted.
//
// If i is undefined then the last child will be marked as such.
//
// If mulitple is truthy then all whitespace will be stripped out until non-whitespace
// content is met.
- function omitLeft(statements, i, multiple) {
- var current = statements[i == null ? statements.length - 1 : i - 1];
- if (!current || current.type !== 'content' || (!multiple && current.leftStripped)) {
+ function omitLeft(body, i, multiple) {
+ var current = body[i == null ? body.length - 1 : i - 1];
+ if (!current || current.type !== 'ContentStatement' || (!multiple && current.leftStripped)) {
return;
}
// We omit the last node if it's whitespace only and not preceeded by a non-content node.
- var original = current.string;
- current.string = current.string.replace(multiple ? (/\s+$/) : (/[ \t]+$/), '');
- current.leftStripped = current.string !== original;
+ var original = current.value;
+ current.value = current.value.replace(multiple ? (/\s+$/) : (/[ \t]+$/), '');
+ current.leftStripped = current.value !== original;
return current.leftStripped;
}
+
+ __exports__ = WhitespaceControl;
return __exports__;
-})(__module5__);
+})(__module11__);
+// handlebars/compiler/helpers.js
+var __module12__ = (function(__dependency1__) {
+ "use strict";
+ var __exports__ = {};
+ var Exception = __dependency1__;
+
+ function SourceLocation(source, locInfo) {
+ this.source = source;
+ this.start = {
+ line: locInfo.first_line,
+ column: locInfo.first_column
+ };
+ this.end = {
+ line: locInfo.last_line,
+ column: locInfo.last_column
+ };
+ }
+
+ __exports__.SourceLocation = SourceLocation;function stripFlags(open, close) {
+ return {
+ open: open.charAt(2) === '~',
+ close: close.charAt(close.length-3) === '~'
+ };
+ }
+
+ __exports__.stripFlags = stripFlags;function stripComment(comment) {
+ return comment.replace(/^\{\{~?\!-?-?/, '')
+ .replace(/-?-?~?\}\}$/, '');
+ }
+
+ __exports__.stripComment = stripComment;function preparePath(data, parts, locInfo) {
+ /*jshint -W040 */
+ locInfo = this.locInfo(locInfo);
+
+ var original = data ? '@' : '',
+ dig = [],
+ depth = 0,
+ depthString = '';
+
+ for(var i=0,l=parts.length; i<l; i++) {
+ var part = parts[i].part;
+ original += (parts[i].separator || '') + part;
+
+ if (part === '..' || part === '.' || part === 'this') {
+ if (dig.length > 0) {
+ throw new Exception('Invalid path: ' + original, {loc: locInfo});
+ } else if (part === '..') {
+ depth++;
+ depthString += '../';
+ }
+ } else {
+ dig.push(part);
+ }
+ }
+
+ return new this.PathExpression(data, depth, dig, original, locInfo);
+ }
+
+ __exports__.preparePath = preparePath;function prepareMustache(path, params, hash, open, strip, locInfo) {
+ /*jshint -W040 */
+ // Must use charAt to support IE pre-10
+ var escapeFlag = open.charAt(3) || open.charAt(2),
+ escaped = escapeFlag !== '{' && escapeFlag !== '&';
+
+ return new this.MustacheStatement(path, params, hash, escaped, strip, this.locInfo(locInfo));
+ }
+
+ __exports__.prepareMustache = prepareMustache;function prepareRawBlock(openRawBlock, content, close, locInfo) {
+ /*jshint -W040 */
+ if (openRawBlock.path.original !== close) {
+ var errorNode = {loc: openRawBlock.path.loc};
+
+ throw new Exception(openRawBlock.path.original + " doesn't match " + close, errorNode);
+ }
+
+ locInfo = this.locInfo(locInfo);
+ var program = new this.Program([content], null, {}, locInfo);
+
+ return new this.BlockStatement(
+ openRawBlock.path, openRawBlock.params, openRawBlock.hash,
+ program, undefined,
+ {}, {}, {},
+ locInfo);
+ }
+
+ __exports__.prepareRawBlock = prepareRawBlock;function prepareBlock(openBlock, program, inverseAndProgram, close, inverted, locInfo) {
+ /*jshint -W040 */
+ // When we are chaining inverse calls, we will not have a close path
+ if (close && close.path && openBlock.path.original !== close.path.original) {
+ var errorNode = {loc: openBlock.path.loc};
+
+ throw new Exception(openBlock.path.original + ' doesn\'t match ' + close.path.original, errorNode);
+ }
+
+ program.blockParams = openBlock.blockParams;
+
+ var inverse,
+ inverseStrip;
+
+ if (inverseAndProgram) {
+ if (inverseAndProgram.chain) {
+ inverseAndProgram.program.body[0].closeStrip = close.strip;
+ }
+
+ inverseStrip = inverseAndProgram.strip;
+ inverse = inverseAndProgram.program;
+ }
+
+ if (inverted) {
+ inverted = inverse;
+ inverse = program;
+ program = inverted;
+ }
+
+ return new this.BlockStatement(
+ openBlock.path, openBlock.params, openBlock.hash,
+ program, inverse,
+ openBlock.strip, inverseStrip, close && close.strip,
+ this.locInfo(locInfo));
+ }
+
+ __exports__.prepareBlock = prepareBlock;
+ return __exports__;
+})(__module4__);
+
// handlebars/compiler/base.js
-var __module8__ = (function(__dependency1__, __dependency2__, __dependency3__, __dependency4__) {
+var __module8__ = (function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__) {
"use strict";
var __exports__ = {};
var parser = __dependency1__;
var AST = __dependency2__;
- var Helpers = __dependency3__;
- var extend = __dependency4__.extend;
+ var WhitespaceControl = __dependency3__;
+ var Helpers = __dependency4__;
+ var extend = __dependency5__.extend;
__exports__.parser = parser;
var yy = {};
extend(yy, Helpers, AST);
- function parse(input) {
- // Just return if an already-compile AST was passed in.
- if (input.constructor === AST.ProgramNode) { return input; }
+ function parse(input, options) {
+ // Just return if an already-compiled AST was passed in.
+ if (input.type === 'Program') { return input; }
parser.yy = yy;
- return parser.parse(input);
+ // Altering the shared object here, but this is ok as parser is a sync operation
+ yy.locInfo = function(locInfo) {
+ return new yy.SourceLocation(options && options.srcName, locInfo);
+ };
+
+ var strip = new WhitespaceControl();
+ return strip.accept(parser.parse(input));
}
__exports__.parse = parse;
return __exports__;
-})(__module9__, __module7__, __module10__, __module3__);
+})(__module9__, __module7__, __module10__, __module12__, __module3__);
// handlebars/compiler/compiler.js
-var __module11__ = (function(__dependency1__, __dependency2__) {
+var __module13__ = (function(__dependency1__, __dependency2__, __dependency3__) {
"use strict";
var __exports__ = {};
var Exception = __dependency1__;
var isArray = __dependency2__.isArray;
+ var indexOf = __dependency2__.indexOf;
+ var AST = __dependency3__;
var slice = [].slice;
+
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,
@@ -1648,20 +1993,22 @@
},
guid: 0,
compile: function(program, options) {
+ this.sourceNode = [];
this.opcodes = [];
this.children = [];
- this.depths = {list: []};
this.options = options;
this.stringParams = options.stringParams;
this.trackIds = options.trackIds;
+ options.blockParams = options.blockParams || [];
+
// These changes will propagate to the other compiler components
- var knownHelpers = this.options.knownHelpers;
- this.options.knownHelpers = {
+ var knownHelpers = options.knownHelpers;
+ options.knownHelpers = {
'helperMissing': true,
'blockHelperMissing': true,
'each': true,
'if': true,
'unless': true,
@@ -1669,83 +2016,76 @@
'log': true,
'lookup': true
};
if (knownHelpers) {
for (var name in knownHelpers) {
- this.options.knownHelpers[name] = knownHelpers[name];
+ options.knownHelpers[name] = knownHelpers[name];
}
}
return this.accept(program);
},
- accept: function(node) {
- return this[node.type](node);
- },
-
- program: function(program) {
- var statements = program.statements;
-
- for(var i=0, l=statements.length; i<l; i++) {
- this.accept(statements[i]);
- }
- this.isSimple = l === 1;
-
- this.depths.list = this.depths.list.sort(function(a, b) {
- return a - b;
- });
-
- return this;
- },
-
compileProgram: function(program) {
var result = new this.compiler().compile(program, this.options);
- var guid = this.guid++, depth;
+ var guid = this.guid++;
this.usePartial = this.usePartial || result.usePartial;
this.children[guid] = result;
+ this.useDepths = this.useDepths || result.useDepths;
- for(var i=0, l=result.depths.list.length; i<l; i++) {
- depth = result.depths.list[i];
+ return guid;
+ },
- if(depth < 2) { continue; }
- else { this.addDepth(depth - 1); }
+ accept: function(node) {
+ this.sourceNode.unshift(node);
+ var ret = this[node.type](node);
+ this.sourceNode.shift();
+ return ret;
+ },
+
+ Program: function(program) {
+ this.options.blockParams.unshift(program.blockParams);
+
+ var body = program.body;
+ for(var i=0, l=body.length; i<l; i++) {
+ this.accept(body[i]);
}
- return guid;
+ this.options.blockParams.shift();
+
+ this.isSimple = l === 1;
+ this.blockParams = program.blockParams ? program.blockParams.length : 0;
+
+ return this;
},
- block: function(block) {
- var mustache = block.mustache,
- program = block.program,
+ BlockStatement: function(block) {
+ transformLiteralToPath(block);
+
+ var program = block.program,
inverse = block.inverse;
- if (program) {
- program = this.compileProgram(program);
- }
+ program = program && this.compileProgram(program);
+ inverse = inverse && this.compileProgram(inverse);
- if (inverse) {
- inverse = this.compileProgram(inverse);
- }
+ var type = this.classifySexpr(block);
- var sexpr = mustache.sexpr;
- var type = this.classifySexpr(sexpr);
+ if (type === 'helper') {
+ this.helperSexpr(block, program, inverse);
+ } else if (type === 'simple') {
+ this.simpleSexpr(block);
- if (type === "helper") {
- this.helperSexpr(sexpr, program, inverse);
- } else if (type === "simple") {
- this.simpleSexpr(sexpr);
-
// now that the simple mustache is resolved, we need to
// evaluate it by executing `blockHelperMissing`
this.opcode('pushProgram', program);
this.opcode('pushProgram', inverse);
this.opcode('emptyHash');
- this.opcode('blockValue', sexpr.id.original);
+ this.opcode('blockValue', block.path.original);
} else {
- this.ambiguousSexpr(sexpr, program, inverse);
+ this.ambiguousSexpr(block, program, inverse);
// now that the simple mustache is resolved, we need to
// evaluate it by executing `blockHelperMissing`
this.opcode('pushProgram', program);
this.opcode('pushProgram', inverse);
@@ -1754,236 +2094,278 @@
}
this.opcode('append');
},
- hash: function(hash) {
- var pairs = hash.pairs, i, l;
+ PartialStatement: function(partial) {
+ this.usePartial = true;
- this.opcode('pushHash');
+ var params = partial.params;
+ if (params.length > 1) {
+ throw new Exception('Unsupported number of partial arguments: ' + params.length, partial);
+ } else if (!params.length) {
+ params.push({type: 'PathExpression', parts: [], depth: 0});
+ }
- for(i=0, l=pairs.length; i<l; i++) {
- this.pushParam(pairs[i][1]);
+ var partialName = partial.name.original,
+ isDynamic = partial.name.type === 'SubExpression';
+ if (isDynamic) {
+ this.accept(partial.name);
}
- while(i--) {
- this.opcode('assignToHash', pairs[i][0]);
- }
- this.opcode('popHash');
- },
- partial: function(partial) {
- var partialName = partial.partialName;
- this.usePartial = true;
+ this.setupFullMustacheParams(partial, undefined, undefined, true);
- if (partial.hash) {
- this.accept(partial.hash);
- } else {
- this.opcode('push', 'undefined');
+ var indent = partial.indent || '';
+ if (this.options.preventIndent && indent) {
+ this.opcode('appendContent', indent);
+ indent = '';
}
- if (partial.context) {
- this.accept(partial.context);
- } else {
- this.opcode('getContext', 0);
- this.opcode('pushContext');
- }
-
- this.opcode('invokePartial', partialName.name, partial.indent || '');
+ this.opcode('invokePartial', isDynamic, partialName, indent);
this.opcode('append');
},
- content: function(content) {
- if (content.string) {
- this.opcode('appendContent', content.string);
- }
- },
+ MustacheStatement: function(mustache) {
+ this.SubExpression(mustache);
- mustache: function(mustache) {
- this.sexpr(mustache.sexpr);
-
if(mustache.escaped && !this.options.noEscape) {
this.opcode('appendEscaped');
} else {
this.opcode('append');
}
},
+ ContentStatement: function(content) {
+ if (content.value) {
+ this.opcode('appendContent', content.value);
+ }
+ },
+
+ CommentStatement: function() {},
+
+ SubExpression: function(sexpr) {
+ transformLiteralToPath(sexpr);
+ var type = this.classifySexpr(sexpr);
+
+ if (type === 'simple') {
+ this.simpleSexpr(sexpr);
+ } else if (type === 'helper') {
+ this.helperSexpr(sexpr);
+ } else {
+ this.ambiguousSexpr(sexpr);
+ }
+ },
ambiguousSexpr: function(sexpr, program, inverse) {
- var id = sexpr.id,
- name = id.parts[0],
+ var path = sexpr.path,
+ name = path.parts[0],
isBlock = program != null || inverse != null;
- this.opcode('getContext', id.depth);
+ this.opcode('getContext', path.depth);
this.opcode('pushProgram', program);
this.opcode('pushProgram', inverse);
- this.ID(id);
+ this.accept(path);
this.opcode('invokeAmbiguous', name, isBlock);
},
simpleSexpr: function(sexpr) {
- var id = sexpr.id;
-
- if (id.type === 'DATA') {
- this.DATA(id);
- } else if (id.parts.length) {
- this.ID(id);
- } else {
- // Simplified ID for `this`
- this.addDepth(id.depth);
- this.opcode('getContext', id.depth);
- this.opcode('pushContext');
- }
-
+ this.accept(sexpr.path);
this.opcode('resolvePossibleLambda');
},
helperSexpr: function(sexpr, program, inverse) {
var params = this.setupFullMustacheParams(sexpr, program, inverse),
- id = sexpr.id,
- name = id.parts[0];
+ path = sexpr.path,
+ name = path.parts[0];
if (this.options.knownHelpers[name]) {
this.opcode('invokeKnownHelper', params.length, name);
} else if (this.options.knownHelpersOnly) {
throw new Exception("You specified knownHelpersOnly, but used the unknown helper " + name, sexpr);
} else {
- id.falsy = true;
+ path.falsy = true;
- this.ID(id);
- this.opcode('invokeHelper', params.length, id.original, id.isSimple);
+ this.accept(path);
+ this.opcode('invokeHelper', params.length, path.original, AST.helpers.simpleId(path));
}
},
- sexpr: function(sexpr) {
- var type = this.classifySexpr(sexpr);
+ PathExpression: function(path) {
+ this.addDepth(path.depth);
+ this.opcode('getContext', path.depth);
- if (type === "simple") {
- this.simpleSexpr(sexpr);
- } else if (type === "helper") {
- this.helperSexpr(sexpr);
- } else {
- this.ambiguousSexpr(sexpr);
- }
- },
+ var name = path.parts[0],
+ scoped = AST.helpers.scopedId(path),
+ blockParamId = !path.depth && !scoped && this.blockParamIndex(name);
- ID: function(id) {
- this.addDepth(id.depth);
- this.opcode('getContext', id.depth);
-
- var name = id.parts[0];
- if (!name) {
+ if (blockParamId) {
+ this.opcode('lookupBlockParam', blockParamId, path.parts);
+ } else if (!name) {
// Context reference, i.e. `{{foo .}}` or `{{foo ..}}`
this.opcode('pushContext');
+ } else if (path.data) {
+ this.options.data = true;
+ this.opcode('lookupData', path.depth, path.parts);
} else {
- this.opcode('lookupOnContext', id.parts, id.falsy, id.isScoped);
+ this.opcode('lookupOnContext', path.parts, path.falsy, scoped);
}
},
- DATA: function(data) {
- this.options.data = true;
- this.opcode('lookupData', data.id.depth, data.id.parts);
+ StringLiteral: function(string) {
+ this.opcode('pushString', string.value);
},
- STRING: function(string) {
- this.opcode('pushString', string.string);
+ NumberLiteral: function(number) {
+ this.opcode('pushLiteral', number.value);
},
- NUMBER: function(number) {
- this.opcode('pushLiteral', number.number);
+ BooleanLiteral: function(bool) {
+ this.opcode('pushLiteral', bool.value);
},
- BOOLEAN: function(bool) {
- this.opcode('pushLiteral', bool.bool);
- },
+ Hash: function(hash) {
+ var pairs = hash.pairs, i, l;
- comment: function() {},
+ this.opcode('pushHash');
+ for (i=0, l=pairs.length; i<l; i++) {
+ this.pushParam(pairs[i].value);
+ }
+ while (i--) {
+ this.opcode('assignToHash', pairs[i].key);
+ }
+ this.opcode('popHash');
+ },
+
// HELPERS
opcode: function(name) {
- this.opcodes.push({ opcode: name, args: slice.call(arguments, 1) });
+ this.opcodes.push({ opcode: name, args: slice.call(arguments, 1), loc: this.sourceNode[0].loc });
},
addDepth: function(depth) {
- if(depth === 0) { return; }
-
- if(!this.depths[depth]) {
- this.depths[depth] = true;
- this.depths.list.push(depth);
+ if (!depth) {
+ return;
}
+
+ this.useDepths = true;
},
classifySexpr: function(sexpr) {
- var isHelper = sexpr.isHelper;
- var isEligible = sexpr.eligibleHelper;
- var options = this.options;
+ var isSimple = AST.helpers.simpleId(sexpr.path);
+ var isBlockParam = isSimple && !!this.blockParamIndex(sexpr.path.parts[0]);
+
+ // a mustache is an eligible helper if:
+ // * its id is simple (a single part, not `this` or `..`)
+ var isHelper = !isBlockParam && AST.helpers.helperExpression(sexpr);
+
+ // 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.
+ var isEligible = !isBlockParam && (isHelper || isSimple);
+
+ var options = this.options;
+
// if ambiguous, we can possibly resolve the ambiguity now
// An eligible helper is one that does not have a complex path, i.e. `this.foo`, `../foo` etc.
if (isEligible && !isHelper) {
- var name = sexpr.id.parts[0];
+ var name = sexpr.path.parts[0];
if (options.knownHelpers[name]) {
isHelper = true;
} else if (options.knownHelpersOnly) {
isEligible = false;
}
}
- if (isHelper) { return "helper"; }
- else if (isEligible) { return "ambiguous"; }
- else { return "simple"; }
+ if (isHelper) { return 'helper'; }
+ else if (isEligible) { return 'ambiguous'; }
+ else { return 'simple'; }
},
pushParams: function(params) {
for(var i=0, l=params.length; i<l; i++) {
this.pushParam(params[i]);
}
},
pushParam: function(val) {
+ var value = val.value != null ? val.value : val.original || '';
+
if (this.stringParams) {
+ if (value.replace) {
+ value = value
+ .replace(/^(\.?\.\/)*/g, '')
+ .replace(/\//g, '.');
+ }
+
if(val.depth) {
this.addDepth(val.depth);
}
this.opcode('getContext', val.depth || 0);
- this.opcode('pushStringParam', val.stringModeValue, val.type);
+ this.opcode('pushStringParam', value, val.type);
- if (val.type === 'sexpr') {
- // Subexpressions get evaluated and passed in
+ if (val.type === 'SubExpression') {
+ // SubExpressions get evaluated and passed in
// in string params mode.
- this.sexpr(val);
+ this.accept(val);
}
} else {
if (this.trackIds) {
- this.opcode('pushId', val.type, val.idName || val.stringModeValue);
+ var blockParamIndex;
+ if (val.parts && !AST.helpers.scopedId(val) && !val.depth) {
+ blockParamIndex = this.blockParamIndex(val.parts[0]);
+ }
+ if (blockParamIndex) {
+ var blockParamChild = val.parts.slice(1).join('.');
+ this.opcode('pushId', 'BlockParam', blockParamIndex, blockParamChild);
+ } else {
+ value = val.original || value;
+ if (value.replace) {
+ value = value
+ .replace(/^\.\//g, '')
+ .replace(/^\.$/g, '');
+ }
+
+ this.opcode('pushId', val.type, value);
+ }
}
this.accept(val);
}
},
- setupFullMustacheParams: function(sexpr, program, inverse) {
+ setupFullMustacheParams: function(sexpr, program, inverse, omitEmpty) {
var params = sexpr.params;
this.pushParams(params);
this.opcode('pushProgram', program);
this.opcode('pushProgram', inverse);
if (sexpr.hash) {
- this.hash(sexpr.hash);
+ this.accept(sexpr.hash);
} else {
- this.opcode('emptyHash');
+ this.opcode('emptyHash', omitEmpty);
}
return params;
+ },
+
+ blockParamIndex: function(name) {
+ for (var depth = 0, len = this.options.blockParams.length; depth < len; depth++) {
+ var blockParams = this.options.blockParams[depth],
+ param = blockParams && indexOf(blockParams, name);
+ if (blockParams && param >= 0) {
+ return [depth, param];
+ }
+ }
}
};
function precompile(input, options, env) {
- if (input == null || (typeof input !== 'string' && input.constructor !== env.AST.ProgramNode)) {
+ if (input == null || (typeof input !== 'string' && input.type !== 'Program')) {
throw new Exception("You must pass a string or Handlebars AST to Handlebars.precompile. You passed " + input);
}
options = options || {};
if (!('data' in options)) {
@@ -1991,17 +2373,17 @@
}
if (options.compat) {
options.useDepths = true;
}
- var ast = env.parse(input);
+ var ast = env.parse(input, options);
var environment = new env.Compiler().compile(ast, options);
return new env.JavaScriptCompiler().compile(environment, options);
}
__exports__.precompile = precompile;function compile(input, options, env) {
- if (input == null || (typeof input !== 'string' && input.constructor !== env.AST.ProgramNode)) {
+ if (input == null || (typeof input !== 'string' && input.type !== 'Program')) {
throw new Exception("You must pass a string or Handlebars AST to Handlebars.compile. You passed " + input);
}
options = options || {};
@@ -2013,11 +2395,11 @@
}
var compiled;
function compileInput() {
- var ast = env.parse(input);
+ var ast = env.parse(input, options);
var environment = new env.Compiler().compile(ast, options);
var templateSpec = new env.JavaScriptCompiler().compile(environment, options, undefined, true);
return env.template(templateSpec);
}
@@ -2032,15 +2414,15 @@
if (!compiled) {
compiled = compileInput();
}
return compiled._setup(options);
};
- ret._child = function(i, data, depths) {
+ ret._child = function(i, data, blockParams, depths) {
if (!compiled) {
compiled = compileInput();
}
- return compiled._child(i, data, depths);
+ return compiled._child(i, data, blockParams, depths);
};
return ret;
}
__exports__.compile = compile;function argEquals(a, b) {
@@ -2055,20 +2437,191 @@
}
}
return true;
}
}
+
+ function transformLiteralToPath(sexpr) {
+ if (!sexpr.path.parts) {
+ var literal = sexpr.path;
+ // Casting to string here to make false and 0 literal values play nicely with the rest
+ // of the system.
+ sexpr.path = new AST.PathExpression(false, 0, [literal.original+''], literal.original+'', literal.log);
+ }
+ }
return __exports__;
-})(__module5__, __module3__);
+})(__module4__, __module3__, __module7__);
+// handlebars/compiler/code-gen.js
+var __module15__ = (function(__dependency1__) {
+ "use strict";
+ var __exports__;
+ var isArray = __dependency1__.isArray;
+
+ try {
+ var SourceMap = require('source-map'),
+ SourceNode = SourceMap.SourceNode;
+ } catch (err) {
+ /* istanbul ignore next: tested but not covered in istanbul due to dist build */
+ SourceNode = function(line, column, srcFile, chunks) {
+ this.src = '';
+ if (chunks) {
+ this.add(chunks);
+ }
+ };
+ /* istanbul ignore next */
+ SourceNode.prototype = {
+ add: function(chunks) {
+ if (isArray(chunks)) {
+ chunks = chunks.join('');
+ }
+ this.src += chunks;
+ },
+ prepend: function(chunks) {
+ if (isArray(chunks)) {
+ chunks = chunks.join('');
+ }
+ this.src = chunks + this.src;
+ },
+ toStringWithSourceMap: function() {
+ return {code: this.toString()};
+ },
+ toString: function() {
+ return this.src;
+ }
+ };
+ }
+
+
+ function castChunk(chunk, codeGen, loc) {
+ if (isArray(chunk)) {
+ var ret = [];
+
+ for (var i = 0, len = chunk.length; i < len; i++) {
+ ret.push(codeGen.wrap(chunk[i], loc));
+ }
+ return ret;
+ } else if (typeof chunk === 'boolean' || typeof chunk === 'number') {
+ // Handle primitives that the SourceNode will throw up on
+ return chunk+'';
+ }
+ return chunk;
+ }
+
+
+ function CodeGen(srcFile) {
+ this.srcFile = srcFile;
+ this.source = [];
+ }
+
+ CodeGen.prototype = {
+ prepend: function(source, loc) {
+ this.source.unshift(this.wrap(source, loc));
+ },
+ push: function(source, loc) {
+ this.source.push(this.wrap(source, loc));
+ },
+
+ merge: function() {
+ var source = this.empty();
+ this.each(function(line) {
+ source.add([' ', line, '\n']);
+ });
+ return source;
+ },
+
+ each: function(iter) {
+ for (var i = 0, len = this.source.length; i < len; i++) {
+ iter(this.source[i]);
+ }
+ },
+
+ empty: function(loc) {
+ loc = loc || this.currentLocation || {start:{}};
+ return new SourceNode(loc.start.line, loc.start.column, this.srcFile);
+ },
+ wrap: function(chunk, loc) {
+ if (chunk instanceof SourceNode) {
+ return chunk;
+ }
+
+ loc = loc || this.currentLocation || {start:{}};
+ chunk = castChunk(chunk, this, loc);
+
+ return new SourceNode(loc.start.line, loc.start.column, this.srcFile, chunk);
+ },
+
+ functionCall: function(fn, type, params) {
+ params = this.generateList(params);
+ return this.wrap([fn, type ? '.' + type + '(' : '(', params, ')']);
+ },
+
+ 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') + '"';
+ },
+
+ objectLiteral: function(obj) {
+ var pairs = [];
+
+ for (var key in obj) {
+ if (obj.hasOwnProperty(key)) {
+ var value = castChunk(obj[key], this);
+ if (value !== 'undefined') {
+ pairs.push([this.quotedString(key), ':', value]);
+ }
+ }
+ }
+
+ var ret = this.generateList(pairs);
+ ret.prepend('{');
+ ret.add('}');
+ return ret;
+ },
+
+
+ generateList: function(entries, loc) {
+ var ret = this.empty(loc);
+
+ for (var i = 0, len = entries.length; i < len; i++) {
+ if (i) {
+ ret.add(',');
+ }
+
+ ret.add(castChunk(entries[i], this, loc));
+ }
+
+ return ret;
+ },
+
+ generateArray: function(entries, loc) {
+ var ret = this.generateList(entries, loc);
+ ret.prepend('[');
+ ret.add(']');
+
+ return ret;
+ }
+ };
+
+ __exports__ = CodeGen;
+ return __exports__;
+})(__module3__);
+
// handlebars/compiler/javascript-compiler.js
-var __module12__ = (function(__dependency1__, __dependency2__) {
+var __module14__ = (function(__dependency1__, __dependency2__, __dependency3__, __dependency4__) {
"use strict";
var __exports__;
var COMPILER_REVISION = __dependency1__.COMPILER_REVISION;
var REVISION_CHANGES = __dependency1__.REVISION_CHANGES;
var Exception = __dependency2__;
+ var isArray = __dependency3__.isArray;
+ var CodeGen = __dependency4__;
function Literal(value) {
this.value = value;
}
@@ -2077,44 +2630,48 @@
JavaScriptCompiler.prototype = {
// PUBLIC API: You can override these methods in a subclass to provide
// alternative compiled forms for name lookup and buffering semantics
nameLookup: function(parent, name /* , type*/) {
if (JavaScriptCompiler.isValidJavaScriptVariableName(name)) {
- return parent + "." + name;
+ return [parent, ".", name];
} else {
- return parent + "['" + name + "']";
+ return [parent, "['", name, "']"];
}
},
depthedLookup: function(name) {
- this.aliases.lookup = 'this.lookup';
-
- return 'lookup(depths, "' + name + '")';
+ return [this.aliasable('this.lookup'), '(depths, "', name, '")'];
},
compilerInfo: function() {
var revision = COMPILER_REVISION,
versions = REVISION_CHANGES[revision];
return [revision, versions];
},
- appendToBuffer: function(string) {
+ appendToBuffer: function(source, location, explicit) {
+ // Force a source as this simplifies the merge logic.
+ if (!isArray(source)) {
+ source = [source];
+ }
+ source = this.source.wrap(source, location);
+
if (this.environment.isSimple) {
- return "return " + string + ";";
+ return ['return ', source, ';'];
+ } else if (explicit) {
+ // This is a case where the buffer operation occurs as a child of another
+ // construct, generally braces. We have to explicitly output these buffer
+ // operations to ensure that the emitted code goes in the correct location.
+ return ['buffer += ', source, ';'];
} else {
- return {
- appendToBuffer: true,
- content: string,
- toString: function() { return "buffer += " + string + ";"; }
- };
+ source.appendToBuffer = true;
+ return source;
}
},
initializeBuffer: function() {
return this.quotedString("");
},
-
- namespace: "Handlebars",
// END PUBLIC API
compile: function(environment, options, context, asObject) {
this.environment = environment;
this.options = options;
@@ -2136,27 +2693,33 @@
this.aliases = {};
this.registers = { list: [] };
this.hashes = [];
this.compileStack = [];
this.inlineStack = [];
+ this.blockParams = [];
this.compileChildren(environment, options);
- this.useDepths = this.useDepths || environment.depths.list.length || this.options.compat;
+ this.useDepths = this.useDepths || environment.useDepths || this.options.compat;
+ this.useBlockParams = this.useBlockParams || environment.useBlockParams;
var opcodes = environment.opcodes,
opcode,
+ firstLoc,
i,
l;
for (i = 0, l = opcodes.length; i < l; i++) {
opcode = opcodes[i];
+ this.source.currentLocation = opcode.loc;
+ firstLoc = firstLoc || opcode.loc;
this[opcode.opcode].apply(this, opcode.args);
}
// Flush any trailing content that might be pending.
+ this.source.currentLocation = firstLoc;
this.pushSource('');
/* istanbul ignore next */
if (this.stackSlot || this.inlineStack.length || this.compileStack.length) {
throw new Exception('Compile completed with content left on stack');
@@ -2182,17 +2745,31 @@
ret.useData = true;
}
if (this.useDepths) {
ret.useDepths = true;
}
+ if (this.useBlockParams) {
+ ret.useBlockParams = true;
+ }
if (this.options.compat) {
ret.compat = true;
}
if (!asObject) {
ret.compiler = JSON.stringify(ret.compiler);
+
+ this.source.currentLocation = {start: {line: 1, column: 0}};
ret = this.objectLiteral(ret);
+
+ if (options.srcName) {
+ ret = ret.toStringWithSourceMap({file: options.destName});
+ ret.map = ret.map && ret.map.toString();
+ } else {
+ ret = ret.toString();
+ }
+ } else {
+ ret.compilerOptions = this.options;
}
return ret;
} else {
return fn;
@@ -2201,11 +2778,11 @@
preamble: function() {
// track the last context pushed into place to allow skipping the
// getContext opcode when it would be a noop
this.lastContext = 0;
- this.source = [];
+ this.source = new CodeGen(this.options.srcName);
},
createFunctionContext: function(asObject) {
var varDeclarations = '';
@@ -2213,18 +2790,30 @@
if(locals.length > 0) {
varDeclarations += ", " + locals.join(", ");
}
// Generate minimizer alias mappings
+ //
+ // When using true SourceNodes, this will update all references to the given alias
+ // as the source nodes are reused in situ. For the non-source node compilation mode,
+ // aliases will not be used, but this case is already being run on the client and
+ // we aren't concern about minimizing the template size.
+ var aliasCount = 0;
for (var alias in this.aliases) {
- if (this.aliases.hasOwnProperty(alias)) {
- varDeclarations += ', ' + alias + '=' + this.aliases[alias];
+ var node = this.aliases[alias];
+
+ if (this.aliases.hasOwnProperty(alias) && node.children && node.referenceCount > 1) {
+ varDeclarations += ', alias' + (++aliasCount) + '=' + alias;
+ node.children[0] = 'alias' + aliasCount;
}
}
var params = ["depth0", "helpers", "partials", "data"];
+ if (this.useBlockParams || this.useDepths) {
+ params.push('blockParams');
+ }
if (this.useDepths) {
params.push('depths');
}
// Perform a second pass over the output to merge content when possible
@@ -2233,63 +2822,71 @@
if (asObject) {
params.push(source);
return Function.apply(this, params);
} else {
- return 'function(' + params.join(',') + ') {\n ' + source + '}';
+ return this.source.wrap(['function(', params.join(','), ') {\n ', source, '}']);
}
},
mergeSource: function(varDeclarations) {
- var source = '',
- buffer,
+ var isSimple = this.environment.isSimple,
appendOnly = !this.forceBuffer,
- appendFirst;
+ appendFirst,
- for (var i = 0, len = this.source.length; i < len; i++) {
- var line = this.source[i];
+ sourceSeen,
+ bufferStart,
+ bufferEnd;
+ this.source.each(function(line) {
if (line.appendToBuffer) {
- if (buffer) {
- buffer = buffer + '\n + ' + line.content;
+ if (bufferStart) {
+ line.prepend(' + ');
} else {
- buffer = line.content;
+ bufferStart = line;
}
+ bufferEnd = line;
} else {
- if (buffer) {
- if (!source) {
+ if (bufferStart) {
+ if (!sourceSeen) {
appendFirst = true;
- source = buffer + ';\n ';
} else {
- source += 'buffer += ' + buffer + ';\n ';
+ bufferStart.prepend('buffer += ');
}
- buffer = undefined;
+ bufferEnd.add(';');
+ bufferStart = bufferEnd = undefined;
}
- source += line + '\n ';
- if (!this.environment.isSimple) {
+ sourceSeen = true;
+ if (!isSimple) {
appendOnly = false;
}
}
- }
+ });
+
if (appendOnly) {
- if (buffer || !source) {
- source += 'return ' + (buffer || '""') + ';\n';
+ if (bufferStart) {
+ bufferStart.prepend('return ');
+ bufferEnd.add(';');
+ } else if (!sourceSeen) {
+ this.source.push('return "";');
}
} else {
varDeclarations += ", buffer = " + (appendFirst ? '' : this.initializeBuffer());
- if (buffer) {
- source += 'return buffer + ' + buffer + ';\n';
+
+ if (bufferStart) {
+ bufferStart.prepend('return buffer + ');
+ bufferEnd.add(';');
} else {
- source += 'return buffer;\n';
+ this.source.push('return buffer;');
}
}
if (varDeclarations) {
- source = 'var ' + varDeclarations.substring(2) + (appendFirst ? '' : ';\n ') + source;
+ this.source.prepend('var ' + varDeclarations.substring(2) + (appendFirst ? '' : ';\n'));
}
- return source;
+ return this.source.merge();
},
// [blockValue]
//
// On stack, before: hash, inverse, program, value
@@ -2298,40 +2895,41 @@
// The purpose of this opcode is to take a block of the form
// `{{#this.foo}}...{{/this.foo}}`, resolve the value of `foo`, and
// replace it on the stack with the result of properly
// invoking blockHelperMissing.
blockValue: function(name) {
- this.aliases.blockHelperMissing = 'helpers.blockHelperMissing';
+ var blockHelperMissing = this.aliasable('helpers.blockHelperMissing'),
+ params = [this.contextName(0)];
+ this.setupHelperArgs(name, 0, params);
- var params = [this.contextName(0)];
- this.setupParams(name, 0, params);
-
var blockName = this.popStack();
params.splice(1, 0, blockName);
- this.push('blockHelperMissing.call(' + params.join(', ') + ')');
+ this.push(this.source.functionCall(blockHelperMissing, 'call', params));
},
// [ambiguousBlockValue]
//
// On stack, before: hash, inverse, program, value
// Compiler value, before: lastHelper=value of last found helper, if any
// On stack, after, if no lastHelper: same as [blockValue]
// On stack, after, if lastHelper: value
ambiguousBlockValue: function() {
- this.aliases.blockHelperMissing = 'helpers.blockHelperMissing';
-
// We're being a bit cheeky and reusing the options value from the prior exec
- var params = [this.contextName(0)];
- this.setupParams('', 0, params, true);
+ var blockHelperMissing = this.aliasable('helpers.blockHelperMissing'),
+ params = [this.contextName(0)];
+ this.setupHelperArgs('', 0, params, true);
this.flushInline();
var current = this.topStack();
params.splice(1, 0, current);
- this.pushSource("if (!" + this.lastHelper + ") { " + current + " = blockHelperMissing.call(" + params.join(", ") + "); }");
+ this.pushSource([
+ 'if (!', this.lastHelper, ') { ',
+ current, ' = ', this.source.functionCall(blockHelperMissing, 'call', params),
+ '}']);
},
// [appendContent]
//
// On stack, before: ...
@@ -2339,10 +2937,12 @@
//
// Appends the string value of `content` to the current buffer
appendContent: function(content) {
if (this.pendingContent) {
content = this.pendingContent + content;
+ } else {
+ this.pendingLocation = this.source.currentLocation;
}
this.pendingContent = content;
},
@@ -2354,30 +2954,34 @@
// Coerces `value` to a String and appends it to the current buffer.
//
// If `value` is truthy, or 0, it is coerced into a string and appended
// Otherwise, the empty string is appended
append: function() {
- // Force anything that is inlined onto the stack so we don't have duplication
- // when we examine local
- this.flushInline();
- var local = this.popStack();
- this.pushSource('if (' + local + ' != null) { ' + this.appendToBuffer(local) + ' }');
- if (this.environment.isSimple) {
- this.pushSource("else { " + this.appendToBuffer("''") + " }");
+ if (this.isInline()) {
+ this.replaceStack(function(current) {
+ return [' != null ? ', current, ' : ""'];
+ });
+
+ this.pushSource(this.appendToBuffer(this.popStack()));
+ } else {
+ var local = this.popStack();
+ this.pushSource(['if (', local, ' != null) { ', this.appendToBuffer(local, undefined, true), ' }']);
+ if (this.environment.isSimple) {
+ this.pushSource(['else { ', this.appendToBuffer("''", undefined, true), ' }']);
+ }
}
},
// [appendEscaped]
//
// On stack, before: value, ...
// On stack, after: ...
//
// Escape `value` and append it to the buffer
appendEscaped: function() {
- this.aliases.escapeExpression = 'this.escapeExpression';
-
- this.pushSource(this.appendToBuffer("escapeExpression(" + this.popStack() + ")"));
+ this.pushSource(this.appendToBuffer(
+ [this.aliasable('this.escapeExpression'), '(', this.popStack(), ')']));
},
// [getContext]
//
// On stack, before: ...
@@ -2405,37 +3009,37 @@
// On stack, after: currentContext[name], ...
//
// Looks up the value of `name` on the current context and pushes
// it onto the stack.
lookupOnContext: function(parts, falsy, scoped) {
- /*jshint -W083 */
- var i = 0,
- len = parts.length;
+ var i = 0;
if (!scoped && this.options.compat && !this.lastContext) {
// The depthed query is expected to handle the undefined logic for the root level that
// is implemented below, so we evaluate that directly in compat mode
this.push(this.depthedLookup(parts[i++]));
} else {
this.pushContext();
}
- for (; i < len; i++) {
- this.replaceStack(function(current) {
- var lookup = this.nameLookup(current, parts[i], 'context');
- // We want to ensure that zero and false are handled properly if the context (falsy flag)
- // needs to have the special handling for these values.
- if (!falsy) {
- return ' != null ? ' + lookup + ' : ' + current;
- } else {
- // Otherwise we can use generic falsy handling
- return ' && ' + lookup;
- }
- });
- }
+ this.resolvePath('context', parts, i, falsy);
},
+ // [lookupBlockParam]
+ //
+ // On stack, before: ...
+ // On stack, after: blockParam[name], ...
+ //
+ // Looks up the value of `parts` on the given block param and pushes
+ // it onto the stack.
+ lookupBlockParam: function(blockParamId, parts) {
+ this.useBlockParams = true;
+
+ this.push(['blockParams[', blockParamId[0], '][', blockParamId[1], ']']);
+ this.resolvePath('context', parts, 1);
+ },
+
// [lookupData]
//
// On stack, before: ...
// On stack, after: data, ...
//
@@ -2446,14 +3050,32 @@
this.pushStackLiteral('data');
} else {
this.pushStackLiteral('this.data(data, ' + depth + ')');
}
+ this.resolvePath('data', parts, 0, true);
+ },
+
+ resolvePath: function(type, parts, i, falsy) {
+ /*jshint -W083 */
+ if (this.options.strict || this.options.assumeObjects) {
+ this.push(strictLookup(this.options.strict, this, parts, type));
+ return;
+ }
+
var len = parts.length;
- for (var i = 0; i < len; i++) {
+ for (; i < len; i++) {
this.replaceStack(function(current) {
- return ' && ' + this.nameLookup(current, parts[i], 'data');
+ var lookup = this.nameLookup(current, parts[i], type);
+ // We want to ensure that zero and false are handled properly if the context (falsy flag)
+ // needs to have the special handling for these values.
+ if (!falsy) {
+ return [' != null ? ', lookup, ' : ', current];
+ } else {
+ // Otherwise we can use generic falsy handling
+ return [' && ', lookup];
+ }
});
}
},
// [resolvePossibleLambda]
@@ -2462,13 +3084,11 @@
// On stack, after: resolved value, ...
//
// If the `value` is a lambda, replace it on the stack by
// the return value of the lambda
resolvePossibleLambda: function() {
- this.aliases.lambda = 'this.lambda';
-
- this.push('lambda(' + this.popStack() + ', ' + this.contextName(0) + ')');
+ this.push([this.aliasable('this.lambda'), '(', this.popStack(), ', ', this.contextName(0), ')']);
},
// [pushStringParam]
//
// On stack, before: ...
@@ -2481,29 +3101,28 @@
this.pushContext();
this.pushString(type);
// If it's a subexpression, the string result
// will be pushed after this opcode.
- if (type !== 'sexpr') {
+ if (type !== 'SubExpression') {
if (typeof string === 'string') {
this.pushString(string);
} else {
this.pushStackLiteral(string);
}
}
},
- emptyHash: function() {
- this.pushStackLiteral('{}');
-
+ emptyHash: function(omitEmpty) {
if (this.trackIds) {
this.push('{}'); // hashIds
}
if (this.stringParams) {
this.push('{}'); // hashContexts
this.push('{}'); // hashTypes
}
+ this.pushStackLiteral(omitEmpty ? 'undefined' : '{}');
},
pushHash: function() {
if (this.hash) {
this.hashes.push(this.hash);
}
@@ -2512,18 +3131,18 @@
popHash: function() {
var hash = this.hash;
this.hash = this.hashes.pop();
if (this.trackIds) {
- this.push('{' + hash.ids.join(',') + '}');
+ this.push(this.objectLiteral(hash.ids));
}
if (this.stringParams) {
- this.push('{' + hash.contexts.join(',') + '}');
- this.push('{' + hash.types.join(',') + '}');
+ this.push(this.objectLiteral(hash.contexts));
+ this.push(this.objectLiteral(hash.types));
}
- this.push('{\n ' + hash.values.join(',\n ') + '\n }');
+ this.push(this.objectLiteral(hash.values));
},
// [pushString]
//
// On stack, before: ...
@@ -2532,21 +3151,10 @@
// Push a quoted version of `string` onto the stack
pushString: function(string) {
this.pushStackLiteral(this.quotedString(string));
},
- // [push]
- //
- // On stack, before: ...
- // On stack, after: expr, ...
- //
- // Push an expression onto the stack
- push: function(expr) {
- this.inlineStack.push(expr);
- return expr;
- },
-
// [pushLiteral]
//
// On stack, before: ...
// On stack, after: value, ...
//
@@ -2581,17 +3189,21 @@
// Pops off the helper's parameters, invokes the helper,
// and pushes the helper's return value onto the stack.
//
// If the helper is not found, `helperMissing` is called.
invokeHelper: function(paramSize, name, isSimple) {
- this.aliases.helperMissing = 'helpers.helperMissing';
-
var nonHelper = this.popStack();
var helper = this.setupHelper(paramSize, name);
+ var simple = isSimple ? [helper.name, ' || '] : '';
- var lookup = (isSimple ? helper.name + ' || ' : '') + nonHelper + ' || helperMissing';
- this.push('((' + lookup + ').call(' + helper.callParams + '))');
+ var lookup = ['('].concat(simple, nonHelper);
+ if (!this.options.strict) {
+ lookup.push(' || ', this.aliasable('helpers.helperMissing'));
+ }
+ lookup.push(')');
+
+ this.push(this.source.functionCall(lookup, 'call', helper.callParams));
},
// [invokeKnownHelper]
//
// On stack, before: hash, inverse, program, params..., ...
@@ -2599,11 +3211,11 @@
//
// This operation is used when the helper is known to exist,
// so a `helperMissing` fallback is not required.
invokeKnownHelper: function(paramSize, name) {
var helper = this.setupHelper(paramSize, name);
- this.push(helper.name + ".call(" + helper.callParams + ")");
+ this.push(this.source.functionCall(helper.name, 'call', helper.callParams));
},
// [invokeAmbiguous]
//
// On stack, before: hash, inverse, program, params..., ...
@@ -2615,47 +3227,71 @@
//
// This operation emits more code than the other options,
// and can be avoided by passing the `knownHelpers` and
// `knownHelpersOnly` flags at compile-time.
invokeAmbiguous: function(name, helperCall) {
- this.aliases.functionType = '"function"';
- this.aliases.helperMissing = 'helpers.helperMissing';
this.useRegister('helper');
var nonHelper = this.popStack();
this.emptyHash();
var helper = this.setupHelper(0, name, helperCall);
var helperName = this.lastHelper = this.nameLookup('helpers', name, 'helper');
- this.push(
- '((helper = (helper = ' + helperName + ' || ' + nonHelper + ') != null ? helper : helperMissing'
- + (helper.paramsInit ? '),(' + helper.paramsInit : '') + '),'
- + '(typeof helper === functionType ? helper.call(' + helper.callParams + ') : helper))');
+ var lookup = ['(', '(helper = ', helperName, ' || ', nonHelper, ')'];
+ if (!this.options.strict) {
+ lookup[0] = '(helper = ';
+ lookup.push(
+ ' != null ? helper : ',
+ this.aliasable('helpers.helperMissing')
+ );
+ }
+
+ this.push([
+ '(', lookup,
+ (helper.paramsInit ? ['),(', helper.paramsInit] : []), '),',
+ '(typeof helper === ', this.aliasable('"function"'), ' ? ',
+ this.source.functionCall('helper','call', helper.callParams), ' : helper))'
+ ]);
},
// [invokePartial]
//
// On stack, before: context, ...
// On stack after: result of partial invocation
//
// This operation pops off a context, invokes a partial with that context,
// and pushes the result of the invocation back.
- invokePartial: function(name, indent) {
- var params = [this.nameLookup('partials', name, 'partial'), "'" + indent + "'", "'" + name + "'", this.popStack(), this.popStack(), "helpers", "partials"];
+ invokePartial: function(isDynamic, name, indent) {
+ var params = [],
+ options = this.setupParams(name, 1, params, false);
- if (this.options.data) {
- params.push("data");
- } else if (this.options.compat) {
- params.push('undefined');
+ if (isDynamic) {
+ name = this.popStack();
+ delete options.name;
}
+
+ if (indent) {
+ options.indent = JSON.stringify(indent);
+ }
+ options.helpers = 'helpers';
+ options.partials = 'partials';
+
+ if (!isDynamic) {
+ params.unshift(this.nameLookup('partials', name, 'partial'));
+ } else {
+ params.unshift(name);
+ }
+
if (this.options.compat) {
- params.push('depths');
+ options.depths = 'depths';
}
+ options = this.objectLiteral(options);
+ params.push(options);
- this.push("this.invokePartial(" + params.join(", ") + ")");
+ this.push(this.source.functionCall('this.invokePartial', '', params));
},
// [assignToHash]
//
// On stack, before: value, ..., hash, ...
@@ -2676,25 +3312,29 @@
context = this.popStack();
}
var hash = this.hash;
if (context) {
- hash.contexts.push("'" + key + "': " + context);
+ hash.contexts[key] = context;
}
if (type) {
- hash.types.push("'" + key + "': " + type);
+ hash.types[key] = type;
}
if (id) {
- hash.ids.push("'" + key + "': " + id);
+ hash.ids[key] = id;
}
- hash.values.push("'" + key + "': (" + value + ")");
+ hash.values[key] = value;
},
- pushId: function(type, name) {
- if (type === 'ID' || type === 'DATA') {
+ pushId: function(type, name, child) {
+ if (type === 'BlockParam') {
+ this.pushStackLiteral(
+ 'blockParams[' + name[0] + '].path[' + name[1] + ']'
+ + (child ? ' + ' + JSON.stringify('.' + child) : ''));
+ } else if (type === 'PathExpression') {
this.pushString(name);
- } else if (type === 'sexpr') {
+ } else if (type === 'SubExpression') {
this.pushStackLiteral('true');
} else {
this.pushStackLiteral('null');
}
},
@@ -2719,13 +3359,17 @@
child.name = 'program' + index;
this.context.programs[index] = compiler.compile(child, options, this.context, !this.precompile);
this.context.environments[index] = child;
this.useDepths = this.useDepths || compiler.useDepths;
+ this.useBlockParams = this.useBlockParams || compiler.useBlockParams;
} else {
child.index = index;
child.name = 'program' + index;
+
+ this.useDepths = this.useDepths || child.useDepths;
+ this.useBlockParams = this.useBlockParams || child.useBlockParams;
}
}
},
matchExistingProgram: function(child) {
for (var i = 0, len = this.context.environments.length; i < len; i++) {
@@ -2736,17 +3380,16 @@
}
},
programExpression: function(guid) {
var child = this.environment.children[guid],
- depths = child.depths.list,
- useDepths = this.useDepths,
- depth;
+ programParams = [child.index, 'data', child.blockParams];
- var programParams = [child.index, 'data'];
-
- if (useDepths) {
+ if (this.useBlockParams || this.useDepths) {
+ programParams.push('blockParams');
+ }
+ if (this.useDepths) {
programParams.push('depths');
}
return 'this.program(' + programParams.join(', ') + ')';
},
@@ -2756,37 +3399,37 @@
this.registers[name] = true;
this.registers.list.push(name);
}
},
+ push: function(expr) {
+ if (!(expr instanceof Literal)) {
+ expr = this.source.wrap(expr);
+ }
+
+ this.inlineStack.push(expr);
+ return expr;
+ },
+
pushStackLiteral: function(item) {
- return this.push(new Literal(item));
+ this.push(new Literal(item));
},
pushSource: function(source) {
if (this.pendingContent) {
- this.source.push(this.appendToBuffer(this.quotedString(this.pendingContent)));
+ this.source.push(
+ this.appendToBuffer(this.source.quotedString(this.pendingContent), this.pendingLocation));
this.pendingContent = undefined;
}
if (source) {
this.source.push(source);
}
},
- pushStack: function(item) {
- this.flushInline();
-
- var stack = this.incrStack();
- this.pushSource(stack + " = " + item + ";");
- this.compileStack.push(stack);
- return stack;
- },
-
replaceStack: function(callback) {
- var prefix = '',
- inline = this.isInline(),
+ var prefix = ['('],
stack,
createdStack,
usedLiteral;
/* istanbul ignore next */
@@ -2797,18 +3440,19 @@
// We want to merge the inline statement into the replacement statement via ','
var top = this.popStack(true);
if (top instanceof Literal) {
// Literals do not need to be inlined
- prefix = stack = top.value;
+ stack = [top.value];
+ prefix = ['(', stack];
usedLiteral = true;
} else {
// Get or create the current stack name for use by the inline
- createdStack = !this.stackSlot;
- var name = !createdStack ? this.topStackName() : this.incrStack();
+ createdStack = true;
+ var name = this.incrStack();
- prefix = '(' + this.push(name) + ' = ' + top + ')';
+ prefix = ['((', this.push(name), ' = ', top, ')'];
stack = this.topStack();
}
var item = callback.call(this, stack);
@@ -2816,11 +3460,11 @@
this.popStack();
}
if (createdStack) {
this.stackSlot--;
}
- this.push('(' + prefix + item + ')');
+ this.push(prefix.concat(item, ')'));
},
incrStack: function() {
this.stackSlot++;
if(this.stackSlot > this.stackVars.length) { this.stackVars.push("stack" + this.stackSlot); }
@@ -2829,19 +3473,20 @@
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);
- }
+ this.inlineStack = [];
+ for (var i = 0, len = inlineStack.length; i < len; i++) {
+ var entry = inlineStack[i];
+ /* istanbul ignore if */
+ if (entry instanceof Literal) {
+ this.compileStack.push(entry);
+ } else {
+ var stack = this.incrStack();
+ this.pushSource([stack, ' = ', entry, ';']);
+ this.compileStack.push(stack);
}
}
},
isInline: function() {
return this.inlineStack.length;
@@ -2867,10 +3512,11 @@
topStack: function() {
var stack = (this.isInline() ? this.inlineStack : this.compileStack),
item = stack[stack.length - 1];
+ /* istanbul ignore if */
if (item instanceof Literal) {
return item.value;
} else {
return item;
}
@@ -2883,46 +3529,46 @@
return 'depth' + context;
}
},
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') + '"';
+ return this.source.quotedString(str);
},
objectLiteral: function(obj) {
- var pairs = [];
+ return this.source.objectLiteral(obj);
+ },
- for (var key in obj) {
- if (obj.hasOwnProperty(key)) {
- pairs.push(this.quotedString(key) + ':' + obj[key]);
- }
+ aliasable: function(name) {
+ var ret = this.aliases[name];
+ if (ret) {
+ ret.referenceCount++;
+ return ret;
}
- return '{' + pairs.join(',') + '}';
+ ret = this.aliases[name] = this.source.wrap(name);
+ ret.aliasable = true;
+ ret.referenceCount = 1;
+
+ return ret;
},
setupHelper: function(paramSize, name, blockHelper) {
var params = [],
- paramsInit = this.setupParams(name, paramSize, params, blockHelper);
+ paramsInit = this.setupHelperArgs(name, paramSize, params, blockHelper);
var foundHelper = this.nameLookup('helpers', name, 'helper');
return {
params: params,
paramsInit: paramsInit,
name: foundHelper,
- callParams: [this.contextName(0)].concat(params).join(", ")
+ callParams: [this.contextName(0)].concat(params)
};
},
- setupOptions: function(helper, paramSize, params) {
- var options = {}, contexts = [], types = [], ids = [], param, inverse, program;
+ setupParams: function(helper, paramSize, params) {
+ var options = {}, contexts = [], types = [], ids = [], param;
options.name = this.quotedString(helper);
options.hash = this.popStack();
if (this.trackIds) {
@@ -2931,26 +3577,18 @@
if (this.stringParams) {
options.hashTypes = this.popStack();
options.hashContexts = this.popStack();
}
- inverse = this.popStack();
- program = this.popStack();
+ var 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) {
- program = 'this.noop';
- }
-
- if (!inverse) {
- inverse = 'this.noop';
- }
-
- options.fn = program;
- options.inverse = inverse;
+ options.fn = program || 'this.noop';
+ options.inverse = inverse || 'this.noop';
}
// The parameters go on to the stack in order (making sure that they are evaluated in order)
// so we need to pop them off the stack in reverse order
var i = paramSize;
@@ -2966,40 +3604,41 @@
contexts[i] = this.popStack();
}
}
if (this.trackIds) {
- options.ids = "[" + ids.join(",") + "]";
+ options.ids = this.source.generateArray(ids);
}
if (this.stringParams) {
- options.types = "[" + types.join(",") + "]";
- options.contexts = "[" + contexts.join(",") + "]";
+ options.types = this.source.generateArray(types);
+ options.contexts = this.source.generateArray(contexts);
}
if (this.options.data) {
- options.data = "data";
+ options.data = 'data';
}
-
+ if (this.useBlockParams) {
+ options.blockParams = 'blockParams';
+ }
return options;
},
- // the params and contexts arguments are passed in arrays
- // to fill in
- setupParams: function(helperName, paramSize, params, useRegister) {
- var options = this.objectLiteral(this.setupOptions(helperName, paramSize, params));
-
+ setupHelperArgs: function(helper, paramSize, params, useRegister) {
+ var options = this.setupParams(helper, paramSize, params, true);
+ options = this.objectLiteral(options);
if (useRegister) {
this.useRegister('options');
params.push('options');
- return 'options=' + options;
+ return ['options=', options];
} else {
params.push(options);
return '';
}
}
};
+
var reservedWords = (
"break else new var" +
" case finally return void" +
" catch for switch while" +
" continue function this with" +
@@ -3011,11 +3650,12 @@
" byte extends long super" +
" char final native synchronized" +
" class float package throws" +
" const goto private transient" +
" debugger implements protected volatile" +
- " double import public let yield"
+ " double import public let yield await" +
+ " null true false"
).split(" ");
var compilerWords = JavaScriptCompiler.RESERVED_WORDS = {};
for(var i=0, l=reservedWords.length; i<l; i++) {
@@ -3024,13 +3664,33 @@
JavaScriptCompiler.isValidJavaScriptVariableName = function(name) {
return !JavaScriptCompiler.RESERVED_WORDS[name] && /^[a-zA-Z_$][0-9a-zA-Z_$]*$/.test(name);
};
+ function strictLookup(requireTerminal, compiler, parts, type) {
+ var stack = compiler.popStack();
+
+ var i = 0,
+ len = parts.length;
+ if (requireTerminal) {
+ len--;
+ }
+
+ for (; i < len; i++) {
+ stack = compiler.nameLookup(stack, parts[i], type);
+ }
+
+ if (requireTerminal) {
+ return [compiler.aliasable('this.strict'), '(', stack, ', ', compiler.quotedString(parts[i]), ')'];
+ } else {
+ return stack;
+ }
+ }
+
__exports__ = JavaScriptCompiler;
return __exports__;
-})(__module2__, __module5__);
+})(__module2__, __module4__, __module3__, __module15__);
// handlebars.js
var __module0__ = (function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__) {
"use strict";
var __exports__;
@@ -3067,13 +3727,24 @@
};
Handlebars = create();
Handlebars.create = create;
+ /*jshint -W040 */
+ /* istanbul ignore next */
+ var root = typeof global !== 'undefined' ? global : window,
+ $Handlebars = root.Handlebars;
+ /* istanbul ignore next */
+ Handlebars.noConflict = function() {
+ if (root.Handlebars === Handlebars) {
+ root.Handlebars = $Handlebars;
+ }
+ };
+
Handlebars['default'] = Handlebars;
__exports__ = Handlebars;
return __exports__;
-})(__module1__, __module7__, __module8__, __module11__, __module12__);
+})(__module1__, __module7__, __module8__, __module13__, __module14__);
return __module0__;
}));