UNPKG

@gov-cy/govcy-frontend-renderer

Version:

Render html for design elements of the Unified design system using njk or json template.

1,605 lines (1,556 loc) 700 kB
'use strict'; var require$$0$1 = require('domain'); var require$$0$2 = require('events'); var require$$0$4 = require('fs'); var require$$0$3 = require('path'); var require$$2 = require('util'); var require$$1 = require('stream'); var require$$2$1 = require('os'); var url = require('url'); var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null; var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {}; function getDefaultExportFromCjs (x) { return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x; } var lib$9 = {exports: {}}; var ArrayProto = Array.prototype; var ObjProto = Object.prototype; var escapeMap = { '&': '&amp;', '"': '&quot;', '\'': '&#39;', '<': '&lt;', '>': '&gt;', '\\': '&#92;' }; var escapeRegex = /[&"'<>\\]/g; var _exports$1 = lib$9.exports = {}; function hasOwnProp(obj, k) { return ObjProto.hasOwnProperty.call(obj, k); } _exports$1.hasOwnProp = hasOwnProp; function lookupEscape(ch) { return escapeMap[ch]; } function _prettifyError$1(path, withInternals, err) { if (!err.Update) { // not one of ours, cast it err = new _exports$1.TemplateError(err); } err.Update(path); // Unless they marked the dev flag, show them a trace from here if (!withInternals) { var old = err; err = new Error(old.message); err.name = old.name; } return err; } _exports$1._prettifyError = _prettifyError$1; function TemplateError$1(message, lineno, colno) { var err; var cause; if (message instanceof Error) { cause = message; message = cause.name + ": " + cause.message; } if (Object.setPrototypeOf) { err = new Error(message); Object.setPrototypeOf(err, TemplateError$1.prototype); } else { err = this; Object.defineProperty(err, 'message', { enumerable: false, writable: true, value: message }); } Object.defineProperty(err, 'name', { value: 'Template render error' }); if (Error.captureStackTrace) { Error.captureStackTrace(err, this.constructor); } var getStack; if (cause) { var stackDescriptor = Object.getOwnPropertyDescriptor(cause, 'stack'); getStack = stackDescriptor && (stackDescriptor.get || function () { return stackDescriptor.value; }); if (!getStack) { getStack = function getStack() { return cause.stack; }; } } else { var stack = new Error(message).stack; getStack = function getStack() { return stack; }; } Object.defineProperty(err, 'stack', { get: function get() { return getStack.call(err); } }); Object.defineProperty(err, 'cause', { value: cause }); err.lineno = lineno; err.colno = colno; err.firstUpdate = true; err.Update = function Update(path) { var msg = '(' + (path || 'unknown path') + ')'; // only show lineno + colno next to path of template // where error occurred if (this.firstUpdate) { if (this.lineno && this.colno) { msg += " [Line " + this.lineno + ", Column " + this.colno + "]"; } else if (this.lineno) { msg += " [Line " + this.lineno + "]"; } } msg += '\n '; if (this.firstUpdate) { msg += ' '; } this.message = msg + (this.message || ''); this.firstUpdate = false; return this; }; return err; } if (Object.setPrototypeOf) { Object.setPrototypeOf(TemplateError$1.prototype, Error.prototype); } else { TemplateError$1.prototype = Object.create(Error.prototype, { constructor: { value: TemplateError$1 } }); } _exports$1.TemplateError = TemplateError$1; function escape$2(val) { return val.replace(escapeRegex, lookupEscape); } _exports$1.escape = escape$2; function isFunction$1(obj) { return ObjProto.toString.call(obj) === '[object Function]'; } _exports$1.isFunction = isFunction$1; function isArray(obj) { return ObjProto.toString.call(obj) === '[object Array]'; } _exports$1.isArray = isArray; function isString$2(obj) { return ObjProto.toString.call(obj) === '[object String]'; } _exports$1.isString = isString$2; function isObject$1(obj) { return ObjProto.toString.call(obj) === '[object Object]'; } _exports$1.isObject = isObject$1; /** * @param {string|number} attr * @returns {(string|number)[]} * @private */ function _prepareAttributeParts(attr) { if (!attr) { return []; } if (typeof attr === 'string') { return attr.split('.'); } return [attr]; } /** * @param {string} attribute Attribute value. Dots allowed. * @returns {function(Object): *} */ function getAttrGetter(attribute) { var parts = _prepareAttributeParts(attribute); return function attrGetter(item) { var _item = item; for (var i = 0; i < parts.length; i++) { var part = parts[i]; // If item is not an object, and we still got parts to handle, it means // that something goes wrong. Just roll out to undefined in that case. if (hasOwnProp(_item, part)) { _item = _item[part]; } else { return undefined; } } return _item; }; } _exports$1.getAttrGetter = getAttrGetter; function groupBy(obj, val, throwOnUndefined) { var result = {}; var iterator = isFunction$1(val) ? val : getAttrGetter(val); for (var i = 0; i < obj.length; i++) { var value = obj[i]; var key = iterator(value, i); if (key === undefined && throwOnUndefined === true) { throw new TypeError("groupby: attribute \"" + val + "\" resolved to undefined"); } (result[key] || (result[key] = [])).push(value); } return result; } _exports$1.groupBy = groupBy; function toArray(obj) { return Array.prototype.slice.call(obj); } _exports$1.toArray = toArray; function without(array) { var result = []; if (!array) { return result; } var length = array.length; var contains = toArray(arguments).slice(1); var index = -1; while (++index < length) { if (indexOf(contains, array[index]) === -1) { result.push(array[index]); } } return result; } _exports$1.without = without; function repeat(char_, n) { var str = ''; for (var i = 0; i < n; i++) { str += char_; } return str; } _exports$1.repeat = repeat; function each(obj, func, context) { if (obj == null) { return; } if (ArrayProto.forEach && obj.forEach === ArrayProto.forEach) { obj.forEach(func, context); } else if (obj.length === +obj.length) { for (var i = 0, l = obj.length; i < l; i++) { func.call(context, obj[i], i, obj); } } } _exports$1.each = each; function map$1(obj, func) { var results = []; if (obj == null) { return results; } if (ArrayProto.map && obj.map === ArrayProto.map) { return obj.map(func); } for (var i = 0; i < obj.length; i++) { results[results.length] = func(obj[i], i); } if (obj.length === +obj.length) { results.length = obj.length; } return results; } _exports$1.map = map$1; function asyncIter(arr, iter, cb) { var i = -1; function next() { i++; if (i < arr.length) { iter(arr[i], i, next, cb); } else { cb(); } } next(); } _exports$1.asyncIter = asyncIter; function asyncFor(obj, iter, cb) { var keys = keys_(obj || {}); var len = keys.length; var i = -1; function next() { i++; var k = keys[i]; if (i < len) { iter(k, obj[k], i, len, next); } else { cb(); } } next(); } _exports$1.asyncFor = asyncFor; function indexOf(arr, searchElement, fromIndex) { return Array.prototype.indexOf.call(arr || [], searchElement, fromIndex); } _exports$1.indexOf = indexOf; function keys_(obj) { /* eslint-disable no-restricted-syntax */ var arr = []; for (var k in obj) { if (hasOwnProp(obj, k)) { arr.push(k); } } return arr; } _exports$1.keys = keys_; function _entries(obj) { return keys_(obj).map(function (k) { return [k, obj[k]]; }); } _exports$1._entries = _entries; function _values(obj) { return keys_(obj).map(function (k) { return obj[k]; }); } _exports$1._values = _values; function extend(obj1, obj2) { obj1 = obj1 || {}; keys_(obj2).forEach(function (k) { obj1[k] = obj2[k]; }); return obj1; } _exports$1._assign = _exports$1.extend = extend; function inOperator(key, val) { if (isArray(val) || isString$2(val)) { return val.indexOf(key) !== -1; } else if (isObject$1(val)) { return key in val; } throw new Error('Cannot use "in" operator to search for "' + key + '" in unexpected types.'); } _exports$1.inOperator = inOperator; var libExports = lib$9.exports; var domain; // The domain module is executed on demand var hasSetImmediate = typeof setImmediate === "function"; // Use the fastest means possible to execute a task in its own turn, with // priority over other events including network IO events in Node.js. // // An exception thrown by a task will permanently interrupt the processing of // subsequent tasks. The higher level `asap` function ensures that if an // exception is thrown by a task, that the task queue will continue flushing as // soon as possible, but if you use `rawAsap` directly, you are responsible to // either ensure that no exceptions are thrown from your task, or to manually // call `rawAsap.requestFlush` if an exception is thrown. var raw = rawAsap$1; function rawAsap$1(task) { if (!queue.length) { requestFlush(); flushing = true; } // Avoids a function call queue[queue.length] = task; } var queue = []; // Once a flush has been requested, no further calls to `requestFlush` are // necessary until the next `flush` completes. var flushing = false; // The position of the next task to execute in the task queue. This is // preserved between calls to `flush` so that it can be resumed if // a task throws an exception. var index = 0; // If a task schedules additional tasks recursively, the task queue can grow // unbounded. To prevent memory excaustion, the task queue will periodically // truncate already-completed tasks. var capacity = 1024; // The flush function processes all tasks that have been scheduled with // `rawAsap` unless and until one of those tasks throws an exception. // If a task throws an exception, `flush` ensures that its state will remain // consistent and will resume where it left off when called again. // However, `flush` does not make any arrangements to be called again if an // exception is thrown. function flush() { while (index < queue.length) { var currentIndex = index; // Advance the index before calling the task. This ensures that we will // begin flushing on the next task the task throws an error. index = index + 1; queue[currentIndex].call(); // Prevent leaking memory for long chains of recursive calls to `asap`. // If we call `asap` within tasks scheduled by `asap`, the queue will // grow, but to avoid an O(n) walk for every task we execute, we don't // shift tasks off the queue after they have been executed. // Instead, we periodically shift 1024 tasks off the queue. if (index > capacity) { // Manually shift all values starting at the index back to the // beginning of the queue. for (var scan = 0, newLength = queue.length - index; scan < newLength; scan++) { queue[scan] = queue[scan + index]; } queue.length -= index; index = 0; } } queue.length = 0; index = 0; flushing = false; } rawAsap$1.requestFlush = requestFlush; function requestFlush() { // Ensure flushing is not bound to any domain. // It is not sufficient to exit the domain, because domains exist on a stack. // To execute code outside of any domain, the following dance is necessary. var parentDomain = process.domain; if (parentDomain) { if (!domain) { // Lazy execute the domain module. // Only employed if the user elects to use domains. domain = require$$0$1; } domain.active = process.domain = null; } // `setImmediate` is slower that `process.nextTick`, but `process.nextTick` // cannot handle recursion. // `requestFlush` will only be called recursively from `asap.js`, to resume // flushing after an error is thrown into a domain. // Conveniently, `setImmediate` was introduced in the same version // `process.nextTick` started throwing recursion errors. if (flushing && hasSetImmediate) { setImmediate(flush); } else { process.nextTick(flush); } if (parentDomain) { domain.active = process.domain = parentDomain; } } var rawAsap = raw; var freeTasks = []; /** * Calls a task as soon as possible after returning, in its own event, with * priority over IO events. An exception thrown in a task can be handled by * `process.on("uncaughtException") or `domain.on("error")`, but will otherwise * crash the process. If the error is handled, all subsequent tasks will * resume. * * @param {{call}} task A callable object, typically a function that takes no * arguments. */ var asap_1 = asap$1; function asap$1(task) { var rawTask; if (freeTasks.length) { rawTask = freeTasks.pop(); } else { rawTask = new RawTask(); } rawTask.task = task; rawTask.domain = process.domain; rawAsap(rawTask); } function RawTask() { this.task = null; this.domain = null; } RawTask.prototype.call = function () { if (this.domain) { this.domain.enter(); } var threw = true; try { this.task.call(); threw = false; // If the task throws an exception (presumably) Node.js restores the // domain stack for the next event. if (this.domain) { this.domain.exit(); } } finally { // We use try/finally and a threw flag to avoid messing up stack traces // when we catch and release errors. if (threw) { // In Node.js, uncaught exceptions are considered fatal errors. // Re-throw them to interrupt flushing! // Ensure that flushing continues if an uncaught exception is // suppressed listening process.on("uncaughtException") or // domain.on("error"). rawAsap.requestFlush(); } // If the task threw an error, we do not want to exit the domain here. // Exiting the domain would prevent the domain from catching the error. this.task = null; this.domain = null; freeTasks.push(this); } }; var aSyncWaterfall = {exports: {}}; (function (module) { // MIT license (by Elan Shanker). (function(globals) { var executeSync = function(){ var args = Array.prototype.slice.call(arguments); if (typeof args[0] === 'function'){ args[0].apply(null, args.splice(1)); } }; var executeAsync = function(fn){ if (typeof setImmediate === 'function') { setImmediate(fn); } else if (typeof process !== 'undefined' && process.nextTick) { process.nextTick(fn); } else { setTimeout(fn, 0); } }; var makeIterator = function (tasks) { var makeCallback = function (index) { var fn = function () { if (tasks.length) { tasks[index].apply(null, arguments); } return fn.next(); }; fn.next = function () { return (index < tasks.length - 1) ? makeCallback(index + 1): null; }; return fn; }; return makeCallback(0); }; var _isArray = Array.isArray || function(maybeArray){ return Object.prototype.toString.call(maybeArray) === '[object Array]'; }; var waterfall = function (tasks, callback, forceAsync) { var nextTick = forceAsync ? executeAsync : executeSync; callback = callback || function () {}; if (!_isArray(tasks)) { var err = new Error('First argument to waterfall must be an array of functions'); return callback(err); } if (!tasks.length) { return callback(); } var wrapIterator = function (iterator) { return function (err) { if (err) { callback.apply(null, arguments); callback = function () {}; } else { var args = Array.prototype.slice.call(arguments, 1); var next = iterator.next(); if (next) { args.push(wrapIterator(next)); } else { args.push(callback); } nextTick(function () { iterator.apply(null, args); }); } }; }; wrapIterator(makeIterator(tasks))(); }; if (module.exports) { module.exports = waterfall; // CommonJS } else { globals.waterfall = waterfall; // <script> } })(commonjsGlobal); } (aSyncWaterfall)); var aSyncWaterfallExports = aSyncWaterfall.exports; var lib$8 = libExports; var whitespaceChars = " \n\t\r\xA0"; var delimChars = '()[]{}%*-+~/#,:|.<>=!'; var intChars = '0123456789'; var BLOCK_START = '{%'; var BLOCK_END = '%}'; var VARIABLE_START = '{{'; var VARIABLE_END = '}}'; var COMMENT_START = '{#'; var COMMENT_END = '#}'; var TOKEN_STRING = 'string'; var TOKEN_WHITESPACE = 'whitespace'; var TOKEN_DATA = 'data'; var TOKEN_BLOCK_START = 'block-start'; var TOKEN_BLOCK_END = 'block-end'; var TOKEN_VARIABLE_START = 'variable-start'; var TOKEN_VARIABLE_END = 'variable-end'; var TOKEN_COMMENT = 'comment'; var TOKEN_LEFT_PAREN = 'left-paren'; var TOKEN_RIGHT_PAREN = 'right-paren'; var TOKEN_LEFT_BRACKET = 'left-bracket'; var TOKEN_RIGHT_BRACKET = 'right-bracket'; var TOKEN_LEFT_CURLY = 'left-curly'; var TOKEN_RIGHT_CURLY = 'right-curly'; var TOKEN_OPERATOR = 'operator'; var TOKEN_COMMA = 'comma'; var TOKEN_COLON = 'colon'; var TOKEN_TILDE = 'tilde'; var TOKEN_PIPE = 'pipe'; var TOKEN_INT = 'int'; var TOKEN_FLOAT = 'float'; var TOKEN_BOOLEAN = 'boolean'; var TOKEN_NONE = 'none'; var TOKEN_SYMBOL = 'symbol'; var TOKEN_SPECIAL = 'special'; var TOKEN_REGEX = 'regex'; function token(type, value, lineno, colno) { return { type: type, value: value, lineno: lineno, colno: colno }; } var Tokenizer = /*#__PURE__*/function () { function Tokenizer(str, opts) { this.str = str; this.index = 0; this.len = str.length; this.lineno = 0; this.colno = 0; this.in_code = false; opts = opts || {}; var tags = opts.tags || {}; this.tags = { BLOCK_START: tags.blockStart || BLOCK_START, BLOCK_END: tags.blockEnd || BLOCK_END, VARIABLE_START: tags.variableStart || VARIABLE_START, VARIABLE_END: tags.variableEnd || VARIABLE_END, COMMENT_START: tags.commentStart || COMMENT_START, COMMENT_END: tags.commentEnd || COMMENT_END }; this.trimBlocks = !!opts.trimBlocks; this.lstripBlocks = !!opts.lstripBlocks; } var _proto = Tokenizer.prototype; _proto.nextToken = function nextToken() { var lineno = this.lineno; var colno = this.colno; var tok; if (this.in_code) { // Otherwise, if we are in a block parse it as code var cur = this.current(); if (this.isFinished()) { // We have nothing else to parse return null; } else if (cur === '"' || cur === '\'') { // We've hit a string return token(TOKEN_STRING, this._parseString(cur), lineno, colno); } else if (tok = this._extract(whitespaceChars)) { // We hit some whitespace return token(TOKEN_WHITESPACE, tok, lineno, colno); } else if ((tok = this._extractString(this.tags.BLOCK_END)) || (tok = this._extractString('-' + this.tags.BLOCK_END))) { // Special check for the block end tag // // It is a requirement that start and end tags are composed of // delimiter characters (%{}[] etc), and our code always // breaks on delimiters so we can assume the token parsing // doesn't consume these elsewhere this.in_code = false; if (this.trimBlocks) { cur = this.current(); if (cur === '\n') { // Skip newline this.forward(); } else if (cur === '\r') { // Skip CRLF newline this.forward(); cur = this.current(); if (cur === '\n') { this.forward(); } else { // Was not a CRLF, so go back this.back(); } } } return token(TOKEN_BLOCK_END, tok, lineno, colno); } else if ((tok = this._extractString(this.tags.VARIABLE_END)) || (tok = this._extractString('-' + this.tags.VARIABLE_END))) { // Special check for variable end tag (see above) this.in_code = false; return token(TOKEN_VARIABLE_END, tok, lineno, colno); } else if (cur === 'r' && this.str.charAt(this.index + 1) === '/') { // Skip past 'r/'. this.forwardN(2); // Extract until the end of the regex -- / ends it, \/ does not. var regexBody = ''; while (!this.isFinished()) { if (this.current() === '/' && this.previous() !== '\\') { this.forward(); break; } else { regexBody += this.current(); this.forward(); } } // Check for flags. // The possible flags are according to https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/RegExp) var POSSIBLE_FLAGS = ['g', 'i', 'm', 'y']; var regexFlags = ''; while (!this.isFinished()) { var isCurrentAFlag = POSSIBLE_FLAGS.indexOf(this.current()) !== -1; if (isCurrentAFlag) { regexFlags += this.current(); this.forward(); } else { break; } } return token(TOKEN_REGEX, { body: regexBody, flags: regexFlags }, lineno, colno); } else if (delimChars.indexOf(cur) !== -1) { // We've hit a delimiter (a special char like a bracket) this.forward(); var complexOps = ['==', '===', '!=', '!==', '<=', '>=', '//', '**']; var curComplex = cur + this.current(); var type; if (lib$8.indexOf(complexOps, curComplex) !== -1) { this.forward(); cur = curComplex; // See if this is a strict equality/inequality comparator if (lib$8.indexOf(complexOps, curComplex + this.current()) !== -1) { cur = curComplex + this.current(); this.forward(); } } switch (cur) { case '(': type = TOKEN_LEFT_PAREN; break; case ')': type = TOKEN_RIGHT_PAREN; break; case '[': type = TOKEN_LEFT_BRACKET; break; case ']': type = TOKEN_RIGHT_BRACKET; break; case '{': type = TOKEN_LEFT_CURLY; break; case '}': type = TOKEN_RIGHT_CURLY; break; case ',': type = TOKEN_COMMA; break; case ':': type = TOKEN_COLON; break; case '~': type = TOKEN_TILDE; break; case '|': type = TOKEN_PIPE; break; default: type = TOKEN_OPERATOR; } return token(type, cur, lineno, colno); } else { // We are not at whitespace or a delimiter, so extract the // text and parse it tok = this._extractUntil(whitespaceChars + delimChars); if (tok.match(/^[-+]?[0-9]+$/)) { if (this.current() === '.') { this.forward(); var dec = this._extract(intChars); return token(TOKEN_FLOAT, tok + '.' + dec, lineno, colno); } else { return token(TOKEN_INT, tok, lineno, colno); } } else if (tok.match(/^(true|false)$/)) { return token(TOKEN_BOOLEAN, tok, lineno, colno); } else if (tok === 'none') { return token(TOKEN_NONE, tok, lineno, colno); /* * Added to make the test `null is null` evaluate truthily. * Otherwise, Nunjucks will look up null in the context and * return `undefined`, which is not what we want. This *may* have * consequences is someone is using null in their templates as a * variable. */ } else if (tok === 'null') { return token(TOKEN_NONE, tok, lineno, colno); } else if (tok) { return token(TOKEN_SYMBOL, tok, lineno, colno); } else { throw new Error('Unexpected value while parsing: ' + tok); } } } else { // Parse out the template text, breaking on tag // delimiters because we need to look for block/variable start // tags (don't use the full delimChars for optimization) var beginChars = this.tags.BLOCK_START.charAt(0) + this.tags.VARIABLE_START.charAt(0) + this.tags.COMMENT_START.charAt(0) + this.tags.COMMENT_END.charAt(0); if (this.isFinished()) { return null; } else if ((tok = this._extractString(this.tags.BLOCK_START + '-')) || (tok = this._extractString(this.tags.BLOCK_START))) { this.in_code = true; return token(TOKEN_BLOCK_START, tok, lineno, colno); } else if ((tok = this._extractString(this.tags.VARIABLE_START + '-')) || (tok = this._extractString(this.tags.VARIABLE_START))) { this.in_code = true; return token(TOKEN_VARIABLE_START, tok, lineno, colno); } else { tok = ''; var data; var inComment = false; if (this._matches(this.tags.COMMENT_START)) { inComment = true; tok = this._extractString(this.tags.COMMENT_START); } // Continually consume text, breaking on the tag delimiter // characters and checking to see if it's a start tag. // // We could hit the end of the template in the middle of // our looping, so check for the null return value from // _extractUntil while ((data = this._extractUntil(beginChars)) !== null) { tok += data; if ((this._matches(this.tags.BLOCK_START) || this._matches(this.tags.VARIABLE_START) || this._matches(this.tags.COMMENT_START)) && !inComment) { if (this.lstripBlocks && this._matches(this.tags.BLOCK_START) && this.colno > 0 && this.colno <= tok.length) { var lastLine = tok.slice(-this.colno); if (/^\s+$/.test(lastLine)) { // Remove block leading whitespace from beginning of the string tok = tok.slice(0, -this.colno); if (!tok.length) { // All data removed, collapse to avoid unnecessary nodes // by returning next token (block start) return this.nextToken(); } } } // If it is a start tag, stop looping break; } else if (this._matches(this.tags.COMMENT_END)) { if (!inComment) { throw new Error('unexpected end of comment'); } tok += this._extractString(this.tags.COMMENT_END); break; } else { // It does not match any tag, so add the character and // carry on tok += this.current(); this.forward(); } } if (data === null && inComment) { throw new Error('expected end of comment, got end of file'); } return token(inComment ? TOKEN_COMMENT : TOKEN_DATA, tok, lineno, colno); } } }; _proto._parseString = function _parseString(delimiter) { this.forward(); var str = ''; while (!this.isFinished() && this.current() !== delimiter) { var cur = this.current(); if (cur === '\\') { this.forward(); switch (this.current()) { case 'n': str += '\n'; break; case 't': str += '\t'; break; case 'r': str += '\r'; break; default: str += this.current(); } this.forward(); } else { str += cur; this.forward(); } } this.forward(); return str; }; _proto._matches = function _matches(str) { if (this.index + str.length > this.len) { return null; } var m = this.str.slice(this.index, this.index + str.length); return m === str; }; _proto._extractString = function _extractString(str) { if (this._matches(str)) { this.forwardN(str.length); return str; } return null; }; _proto._extractUntil = function _extractUntil(charString) { // Extract all non-matching chars, with the default matching set // to everything return this._extractMatching(true, charString || ''); }; _proto._extract = function _extract(charString) { // Extract all matching chars (no default, so charString must be // explicit) return this._extractMatching(false, charString); }; _proto._extractMatching = function _extractMatching(breakOnMatch, charString) { // Pull out characters until a breaking char is hit. // If breakOnMatch is false, a non-matching char stops it. // If breakOnMatch is true, a matching char stops it. if (this.isFinished()) { return null; } var first = charString.indexOf(this.current()); // Only proceed if the first character doesn't meet our condition if (breakOnMatch && first === -1 || !breakOnMatch && first !== -1) { var t = this.current(); this.forward(); // And pull out all the chars one at a time until we hit a // breaking char var idx = charString.indexOf(this.current()); while ((breakOnMatch && idx === -1 || !breakOnMatch && idx !== -1) && !this.isFinished()) { t += this.current(); this.forward(); idx = charString.indexOf(this.current()); } return t; } return ''; }; _proto._extractRegex = function _extractRegex(regex) { var matches = this.currentStr().match(regex); if (!matches) { return null; } // Move forward whatever was matched this.forwardN(matches[0].length); return matches; }; _proto.isFinished = function isFinished() { return this.index >= this.len; }; _proto.forwardN = function forwardN(n) { for (var i = 0; i < n; i++) { this.forward(); } }; _proto.forward = function forward() { this.index++; if (this.previous() === '\n') { this.lineno++; this.colno = 0; } else { this.colno++; } }; _proto.backN = function backN(n) { for (var i = 0; i < n; i++) { this.back(); } }; _proto.back = function back() { this.index--; if (this.current() === '\n') { this.lineno--; var idx = this.src.lastIndexOf('\n', this.index - 1); if (idx === -1) { this.colno = this.index; } else { this.colno = this.index - idx; } } else { this.colno--; } } // current returns current character ; _proto.current = function current() { if (!this.isFinished()) { return this.str.charAt(this.index); } return ''; } // currentStr returns what's left of the unparsed string ; _proto.currentStr = function currentStr() { if (!this.isFinished()) { return this.str.substr(this.index); } return ''; }; _proto.previous = function previous() { return this.str.charAt(this.index - 1); }; return Tokenizer; }(); var lexer$2 = { lex: function lex(src, opts) { return new Tokenizer(src, opts); }, TOKEN_STRING: TOKEN_STRING, TOKEN_WHITESPACE: TOKEN_WHITESPACE, TOKEN_DATA: TOKEN_DATA, TOKEN_BLOCK_START: TOKEN_BLOCK_START, TOKEN_BLOCK_END: TOKEN_BLOCK_END, TOKEN_VARIABLE_START: TOKEN_VARIABLE_START, TOKEN_VARIABLE_END: TOKEN_VARIABLE_END, TOKEN_COMMENT: TOKEN_COMMENT, TOKEN_LEFT_PAREN: TOKEN_LEFT_PAREN, TOKEN_RIGHT_PAREN: TOKEN_RIGHT_PAREN, TOKEN_LEFT_BRACKET: TOKEN_LEFT_BRACKET, TOKEN_RIGHT_BRACKET: TOKEN_RIGHT_BRACKET, TOKEN_LEFT_CURLY: TOKEN_LEFT_CURLY, TOKEN_RIGHT_CURLY: TOKEN_RIGHT_CURLY, TOKEN_OPERATOR: TOKEN_OPERATOR, TOKEN_COMMA: TOKEN_COMMA, TOKEN_COLON: TOKEN_COLON, TOKEN_TILDE: TOKEN_TILDE, TOKEN_PIPE: TOKEN_PIPE, TOKEN_INT: TOKEN_INT, TOKEN_FLOAT: TOKEN_FLOAT, TOKEN_BOOLEAN: TOKEN_BOOLEAN, TOKEN_NONE: TOKEN_NONE, TOKEN_SYMBOL: TOKEN_SYMBOL, TOKEN_SPECIAL: TOKEN_SPECIAL, TOKEN_REGEX: TOKEN_REGEX }; // A simple class system, more documentation to come function _defineProperties$1(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, _toPropertyKey$1(descriptor.key), descriptor); } } function _createClass$1(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties$1(Constructor.prototype, protoProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; } function _toPropertyKey$1(arg) { var key = _toPrimitive$1(arg, "string"); return typeof key === "symbol" ? key : String(key); } function _toPrimitive$1(input, hint) { if (typeof input !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint); if (typeof res !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (String )(input); } function _inheritsLoose$7(subClass, superClass) { subClass.prototype = Object.create(superClass.prototype); subClass.prototype.constructor = subClass; _setPrototypeOf$7(subClass, superClass); } function _setPrototypeOf$7(o, p) { _setPrototypeOf$7 = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf$7(o, p); } var EventEmitter = require$$0$2; var lib$7 = libExports; function parentWrap(parent, prop) { if (typeof parent !== 'function' || typeof prop !== 'function') { return prop; } return function wrap() { // Save the current parent method var tmp = this.parent; // Set parent to the previous method, call, and restore this.parent = parent; var res = prop.apply(this, arguments); this.parent = tmp; return res; }; } function extendClass(cls, name, props) { props = props || {}; lib$7.keys(props).forEach(function (k) { props[k] = parentWrap(cls.prototype[k], props[k]); }); var subclass = /*#__PURE__*/function (_cls) { _inheritsLoose$7(subclass, _cls); function subclass() { return _cls.apply(this, arguments) || this; } _createClass$1(subclass, [{ key: "typename", get: function get() { return name; } }]); return subclass; }(cls); lib$7._assign(subclass.prototype, props); return subclass; } var Obj$4 = /*#__PURE__*/function () { function Obj() { // Unfortunately necessary for backwards compatibility this.init.apply(this, arguments); } var _proto = Obj.prototype; _proto.init = function init() {}; Obj.extend = function extend(name, props) { if (typeof name === 'object') { props = name; name = 'anonymous'; } return extendClass(this, name, props); }; _createClass$1(Obj, [{ key: "typename", get: function get() { return this.constructor.name; } }]); return Obj; }(); var EmitterObj$2 = /*#__PURE__*/function (_EventEmitter) { _inheritsLoose$7(EmitterObj, _EventEmitter); function EmitterObj() { var _this2; var _this; _this = _EventEmitter.call(this) || this; // Unfortunately necessary for backwards compatibility (_this2 = _this).init.apply(_this2, arguments); return _this; } var _proto2 = EmitterObj.prototype; _proto2.init = function init() {}; EmitterObj.extend = function extend(name, props) { if (typeof name === 'object') { props = name; name = 'anonymous'; } return extendClass(this, name, props); }; _createClass$1(EmitterObj, [{ key: "typename", get: function get() { return this.constructor.name; } }]); return EmitterObj; }(EventEmitter); var object = { Obj: Obj$4, EmitterObj: EmitterObj$2 }; function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, _toPropertyKey(descriptor.key), descriptor); } } function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; } function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return typeof key === "symbol" ? key : String(key); } function _toPrimitive(input, hint) { if (typeof input !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint); if (typeof res !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (String )(input); } function _inheritsLoose$6(subClass, superClass) { subClass.prototype = Object.create(superClass.prototype); subClass.prototype.constructor = subClass; _setPrototypeOf$6(subClass, superClass); } function _setPrototypeOf$6(o, p) { _setPrototypeOf$6 = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf$6(o, p); } var _require$6 = object, Obj$3 = _require$6.Obj; function traverseAndCheck(obj, type, results) { if (obj instanceof type) { results.push(obj); } if (obj instanceof Node) { obj.findAll(type, results); } } var Node = /*#__PURE__*/function (_Obj) { _inheritsLoose$6(Node, _Obj); function Node() { return _Obj.apply(this, arguments) || this; } var _proto = Node.prototype; _proto.init = function init(lineno, colno) { var _arguments = arguments, _this = this; for (var _len = arguments.length, args = new Array(_len > 2 ? _len - 2 : 0), _key = 2; _key < _len; _key++) { args[_key - 2] = arguments[_key]; } this.lineno = lineno; this.colno = colno; this.fields.forEach(function (field, i) { // The first two args are line/col numbers, so offset by 2 var val = _arguments[i + 2]; // Fields should never be undefined, but null. It makes // testing easier to normalize values. if (val === undefined) { val = null; } _this[field] = val; }); }; _proto.findAll = function findAll(type, results) { var _this2 = this; results = results || []; if (this instanceof NodeList) { this.children.forEach(function (child) { return traverseAndCheck(child, type, results); }); } else { this.fields.forEach(function (field) { return traverseAndCheck(_this2[field], type, results); }); } return results; }; _proto.iterFields = function iterFields(func) { var _this3 = this; this.fields.forEach(function (field) { func(_this3[field], field); }); }; return Node; }(Obj$3); // Abstract nodes var Value = /*#__PURE__*/function (_Node) { _inheritsLoose$6(Value, _Node); function Value() { return _Node.apply(this, arguments) || this; } _createClass(Value, [{ key: "typename", get: function get() { return 'Value'; } }, { key: "fields", get: function get() { return ['value']; } }]); return Value; }(Node); // Concrete nodes var NodeList = /*#__PURE__*/function (_Node2) { _inheritsLoose$6(NodeList, _Node2); function NodeList() { return _Node2.apply(this, arguments) || this; } var _proto2 = NodeList.prototype; _proto2.init = function init(lineno, colno, nodes) { _Node2.prototype.init.call(this, lineno, colno, nodes || []); }; _proto2.addChild = function addChild(node) { this.children.push(node); }; _createClass(NodeList, [{ key: "typename", get: function get() { return 'NodeList'; } }, { key: "fields", get: function get() { return ['children']; } }]); return NodeList; }(Node); var Root = NodeList.extend('Root'); var Literal = Value.extend('Literal'); var _Symbol = Value.extend('Symbol'); var Group = NodeList.extend('Group'); var ArrayNode = NodeList.extend('Array'); var Pair = Node.extend('Pair', { fields: ['key', 'value'] }); var Dict = NodeList.extend('Dict'); var LookupVal = Node.extend('LookupVal', { fields: ['target', 'val'] }); var If = Node.extend('If', { fields: ['cond', 'body', 'else_'] }); var IfAsync = If.extend('IfAsync'); var InlineIf = Node.extend('InlineIf', { fields: ['cond', 'body', 'else_'] }); var For = Node.extend('For', { fields: ['arr', 'name', 'body', 'else_'] }); var AsyncEach = For.extend('AsyncEach'); var AsyncAll = For.extend('AsyncAll'); var Macro = Node.extend('Macro', { fields: ['name', 'args', 'body'] }); var Caller = Macro.extend('Caller'); var Import = Node.extend('Import', { fields: ['template', 'target', 'withContext'] }); var FromImport = /*#__PURE__*/function (_Node3) { _inheritsLoose$6(FromImport, _Node3); function FromImport() { return _Node3.apply(this, arguments) || this; } var _proto3 = FromImport.prototype; _proto3.init = function init(lineno, colno, template, names, withContext) { _Node3.prototype.init.call(this, lineno, colno, template, names || new NodeList(), withContext); }; _createClass(FromImport, [{ key: "typename", get: function get() { return 'FromImport'; } }, { key: "fields", get: function get() { return ['template', 'names', 'withContext']; } }]); return FromImport; }(Node); var FunCall = Node.extend('FunCall', { fields: ['name', 'args'] }); var Filter = FunCall.extend('Filter'); var FilterAsync = Filter.extend('FilterAsync', { fields: ['name', 'args', 'symbol'] }); var KeywordArgs = Dict.extend('KeywordArgs'); var Block = Node.extend('Block', { fields: ['name', 'body'] }); var Super = Node.extend('Super', { fields: ['blockName', 'symbol'] }); var TemplateRef = Node.extend('TemplateRef', { fields: ['template'] }); var Extends = TemplateRef.extend('Extends'); var Include = Node.extend('Include', { fields: ['template', 'ignoreMissing'] }); var Set$1 = Node.extend('Set', { fields: ['targets', 'value'] }); var Switch = Node.extend('Switch', { fields: ['expr', 'cases', 'default'] }); var Case = Node.extend('Case', { fields: ['cond', 'body'] }); var Output = NodeList.extend('Output'); var Capture = Node.extend('Capture', { fields: ['body'] }); var TemplateData = Literal.extend('TemplateData'); var UnaryOp = Node.extend('UnaryOp', { fields: ['target'] }); var BinOp = Node.extend('BinOp', { fields: ['left', 'right'] }); var In = BinOp.extend('In'); var Is = BinOp.extend('Is'); var Or = BinOp.extend('Or'); var And = BinOp.extend('And'); var Not = UnaryOp.extend('Not'); var Add = BinOp.extend('Add'); var Concat = BinOp.extend('Concat'); var Sub = BinOp.extend('Sub'); var Mul = BinOp.extend('Mul'); var Div = BinOp.extend('Div'); var FloorDiv = BinOp.extend('FloorDiv'); var Mod = BinOp.extend('Mod'); var Pow = BinOp.extend('Pow'); var Neg = UnaryOp.extend('Neg'); var Pos = UnaryOp.extend('Pos'); var Compare = Node.extend('Compare', { fields: ['expr', 'ops'] }); var CompareOperand = Node.extend('CompareOperand', { fields: ['expr', 'type'] }); var CallExtension = Node.extend('CallExtension', { init: function init(ext, prop, args, contentArgs) { this.parent(); this.extName = ext.__name || ext; this.prop = prop; this.args = args || new NodeList(); this.contentArgs = contentArgs || []; this.autoescape = ext.autoescape; }, fields: ['extName', 'prop', 'args', 'contentArgs'] }); var CallExtensionAsync = CallExtension.extend('CallExtensionAsync'); // This is hacky, but this is just a debugging function anyway function print(str, indent, inline) { var lines = str.split('\n'); lines.forEach(function (line, i) { if (line && (inline && i > 0 || !inline)) { process.stdout.write(' '.repeat(indent)); } var nl = i === lines.length - 1 ? '' : '\n'; process.stdout.write("" + line + nl); }); } // Print the AST in a nicely formatted tree format for debuggin function printNodes(node, indent) { indent = indent || 0; print(node.typename + ': ', indent); if (node instanceof NodeList) { print('\n'); node.children.forEach(function (n) { printNodes(n, indent + 2); }); } else if (node instanceof CallExtension) { print(node.extName + "." + node.prop + "\n"); if (node.args) { printNodes(node.args, indent + 2); } if (node.contentArgs) { node.contentArgs.forEach(function (n) { printNodes(n, indent + 2); }); } } else { var nodes = []; var props = null; node.iterFields(function (val, fieldName) { if (val instanceof Node) { nodes.push([fieldName, val]); } else { props = props || {}; props[fieldName] = val; } }); if (props) { print(JSON.stringify(props, null, 2) + '\n', null, true); } else { print('\n'); } nodes.forEach(function (_ref) { var fieldName = _ref[0], n = _ref[1]; print("[" + fieldName + "] =>", indent + 2); printNodes(n, indent + 4); }); } } var nodes$4 = { Node: Node, Root: Root, NodeList: NodeList, Value: Value, Literal: Literal, Symbol: _Symbol, Group: Group, Array: ArrayNode, Pair: Pair, Dict: Dict, Output: Output, Capture: Capture, TemplateData: TemplateData, If: If, IfAsync: IfAsync, InlineIf: InlineIf, For: For, AsyncEach: AsyncEach, AsyncAll: AsyncAll, Macro: Macro, Caller: Caller, Import: Import, FromImport: FromImport, FunCall: FunCall, Filter: Filter, FilterAsync: FilterAsync, KeywordArgs: KeywordArgs, Block: Block, Super: Super, Extends: Extends, Include: Include, Set: Set$1, Switch: Switch, Case: Case, LookupVal: LookupVal, BinOp: BinOp, In: In, Is: Is, Or: Or, And: And, Not: Not, Add: Add, Concat: Concat, Sub: Sub, Mul: Mul, Div: Div, FloorDiv: FloorDiv, Mod: Mod, Pow: Pow, Neg: Neg, Pos: Pos, Compare: Compare, CompareOperand: CompareOperand, CallExtension: CallExtension, CallExtensionAsync: CallExtensionAsync, printNodes: printNodes }; function _inheritsLoose$5(subClass, superClass) { subClass.prototype = Object.create(superClass.prototype); subClass.prototype.constructor = subClass; _setPrototypeOf$5(subClass, superClass); } function _setPrototypeOf$5(o, p) { _setPrototypeOf$5 = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf$5(o, p); } var lexer$1 = lexer$2; var nodes$3 = nodes$4; var Obj$2 = object.Obj; var lib$6 = libExports; var Parser = /*#__PURE__*/function (_Obj) { _inheritsLoose$5(Parser, _Obj); function Parser() { return _Obj.apply(this, arguments) || this; } var _proto = Parser.prototype; _proto.init = function init(tokens) { this.tokens = tokens; this.peeked = null; this.breakOnBlocks = null; this.dropLeadingWhitespace = false; this.extensions = []; }; _proto.nextToken = function nextToken(withWhitespace) { var tok; if (this.peeked) { if (!withWhitespace && this.peeked.type === lexer$1.TOKEN_WHITESPACE) { this.peeked = null; } else { tok = this.peeked; this.peeked = null; return tok; } } tok = this.tokens.nextToken(); if (!withWhitespace) { while (tok && tok.type === lexer$1.TOKEN_WHITESPACE) { tok = this.tokens.nextToken(); } } return tok; }; _proto.peekToken = function peekToken() { this.peeked = this.peeked || this.nextToken(); return this.peeked; }; _proto.pushToken = function pushToken(tok) { if (this.peeked) { throw new Error('pushToken: can only push one token on between reads'); } this.peeked = tok; }; _proto.error = function error(msg, lineno, colno) { if (lineno === undefined || colno === undefined) { var tok = this.peekToken() || {}; lineno = tok.lineno; colno = tok.colno; } if (lineno !== undefined) { lineno += 1; } if (colno !== undefined) { colno += 1; } return new lib$6.TemplateError(msg, lineno, colno); }; _proto.fail = function fail(msg, lineno, colno) { throw this.error(msg, lineno, colno); }; _proto.skip = function skip(type) { var tok = this.nextToken(); if (!tok || tok.type !== type) { this.pushToken(tok); return false; } return true; }; _proto.expect = function expect(type) { var tok = this.nextToken(); if (tok.type !== type) { this.fail('expected ' + type + ', got ' + tok.type, tok.lineno, tok.colno); } return tok; }; _proto.skipValue = function skipValue(type, val) { var tok = this.nextToken(); if (!tok || tok.type !== type || tok.value !== val) { this.pushToken(tok); return false; } return true; }; _proto.skipSymbol = function skipSymbol(val) { return