UNPKG

liquidjs

Version:

A simple, expressive and safe Shopify / Github Pages compatible template engine in pure JavaScript.

1,420 lines (1,378 loc) 162 kB
/* * liquidjs@9.33.1, https://github.com/harttle/liquidjs * (c) 2016-2022 harttle * Released under the MIT License. */ /*! ***************************************************************************** Copyright (c) Microsoft Corporation. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted. THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ***************************************************************************** */ /* global Reflect, Promise */ var extendStatics = function(d, b) { extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; return extendStatics(d, b); }; function __extends(d, b) { if (typeof b !== "function" && b !== null) throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); } var __assign = function() { __assign = Object.assign || function __assign(t) { for (var s, i = 1, n = arguments.length; i < n; i++) { s = arguments[i]; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; } return t; }; return __assign.apply(this, arguments); }; function __awaiter(thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); } function __generator(thisArg, body) { var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; function verb(n) { return function (v) { return step([n, v]); }; } function step(op) { if (f) throw new TypeError("Generator is already executing."); while (_) try { if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; if (y = 0, t) op = [op[0] & 2, t.value]; switch (op[0]) { case 0: case 1: t = op; break; case 4: _.label++; return { value: op[1], done: false }; case 5: _.label++; y = op[1]; op = [0]; continue; case 7: op = _.ops.pop(); _.trys.pop(); continue; default: if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } if (t[2]) _.ops.pop(); _.trys.pop(); continue; } op = body.call(thisArg, _); } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; } } function __values(o) { var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0; if (m) return m.call(o); if (o && typeof o.length === "number") return { next: function () { if (o && i >= o.length) o = void 0; return { value: o && o[i++], done: !o }; } }; throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined."); } function __read(o, n) { var m = typeof Symbol === "function" && o[Symbol.iterator]; if (!m) return o; var i = m.call(o), r, ar = [], e; try { while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value); } catch (error) { e = { error: error }; } finally { try { if (r && !r.done && (m = i["return"])) m.call(i); } finally { if (e) throw e.error; } } return ar; } function __spreadArray(to, from, pack) { if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) { if (ar || !(i in from)) { if (!ar) ar = Array.prototype.slice.call(from, 0, i); ar[i] = from[i]; } } return to.concat(ar || Array.prototype.slice.call(from)); } var Drop = /** @class */ (function () { function Drop() { } Drop.prototype.valueOf = function () { return undefined; }; Drop.prototype.liquidMethodMissing = function (key) { return undefined; }; return Drop; }()); var toStr = Object.prototype.toString; var toLowerCase = String.prototype.toLowerCase; function isString(value) { return typeof value === 'string'; } // eslint-disable-next-line @typescript-eslint/ban-types function isFunction(value) { return typeof value === 'function'; } function escapeRegex(str) { return str.replace(/[-/\\^$*+?.()|[\]{}]/g, '\\$&'); } function stringify(value) { value = toValue$1(value); if (isString(value)) return value; if (isNil(value)) return ''; return String(value); } function toValue$1(value) { return value instanceof Drop ? value.valueOf() : value; } function isNumber(value) { return typeof value === 'number'; } function toLiquid(value) { if (value && isFunction(value.toLiquid)) return toLiquid(value.toLiquid()); return value; } function isNil(value) { return value == null; } function isArray(value) { // be compatible with IE 8 return toStr.call(value) === '[object Array]'; } /* * Iterates over own enumerable string keyed properties of an object and invokes iteratee for each property. * The iteratee is invoked with three arguments: (value, key, object). * Iteratee functions may exit iteration early by explicitly returning false. * @param {Object} object The object to iterate over. * @param {Function} iteratee The function invoked per iteration. * @return {Object} Returns object. */ function forOwn(obj, iteratee) { obj = obj || {}; for (var k in obj) { if (Object.hasOwnProperty.call(obj, k)) { if (iteratee(obj[k], k, obj) === false) break; } } return obj; } function last$1(arr) { return arr[arr.length - 1]; } /* * Checks if value is the language type of Object. * (e.g. arrays, functions, objects, regexes, new Number(0), and new String('')) * @param {any} value The value to check. * @return {Boolean} Returns true if value is an object, else false. */ function isObject(value) { var type = typeof value; return value !== null && (type === 'object' || type === 'function'); } function range(start, stop, step) { if (step === void 0) { step = 1; } var arr = []; for (var i = start; i < stop; i += step) { arr.push(i); } return arr; } function padStart(str, length, ch) { if (ch === void 0) { ch = ' '; } return pad(str, length, ch, function (str, ch) { return ch + str; }); } function padEnd(str, length, ch) { if (ch === void 0) { ch = ' '; } return pad(str, length, ch, function (str, ch) { return str + ch; }); } function pad(str, length, ch, add) { str = String(str); var n = length - str.length; while (n-- > 0) str = add(str, ch); return str; } function identify(val) { return val; } function snakeCase(str) { return str.replace(/(\w?)([A-Z])/g, function (_, a, b) { return (a ? a + '_' : '') + b.toLowerCase(); }); } function changeCase(str) { var hasLowerCase = __spreadArray([], __read(str), false).some(function (ch) { return ch >= 'a' && ch <= 'z'; }); return hasLowerCase ? str.toUpperCase() : str.toLowerCase(); } function ellipsis(str, N) { return str.length > N ? str.substr(0, N - 3) + '...' : str; } // compare string in case-insensitive way, undefined values to the tail function caseInsensitiveCompare(a, b) { if (a == null && b == null) return 0; if (a == null) return 1; if (b == null) return -1; a = toLowerCase.call(a); b = toLowerCase.call(b); if (a < b) return -1; if (a > b) return 1; return 0; } var Node = /** @class */ (function () { function Node(key, value, next, prev) { this.key = key; this.value = value; this.next = next; this.prev = prev; } return Node; }()); var LRU = /** @class */ (function () { function LRU(limit, size) { if (size === void 0) { size = 0; } this.limit = limit; this.size = size; this.cache = {}; this.head = new Node('HEAD', null, null, null); this.tail = new Node('TAIL', null, null, null); this.head.next = this.tail; this.tail.prev = this.head; } LRU.prototype.write = function (key, value) { if (this.cache[key]) { this.cache[key].value = value; } else { var node = new Node(key, value, this.head.next, this.head); this.head.next.prev = node; this.head.next = node; this.cache[key] = node; this.size++; this.ensureLimit(); } }; LRU.prototype.read = function (key) { if (!this.cache[key]) return; var value = this.cache[key].value; this.remove(key); this.write(key, value); return value; }; LRU.prototype.remove = function (key) { var node = this.cache[key]; node.prev.next = node.next; node.next.prev = node.prev; delete this.cache[key]; this.size--; }; LRU.prototype.clear = function () { this.head.next = this.tail; this.tail.prev = this.head; this.size = 0; this.cache = {}; }; LRU.prototype.ensureLimit = function () { if (this.size > this.limit) this.remove(this.tail.prev.key); }; return LRU; }()); function domResolve(root, path) { var base = document.createElement('base'); base.href = root; var head = document.getElementsByTagName('head')[0]; head.insertBefore(base, head.firstChild); var a = document.createElement('a'); a.href = path; var resolved = a.href; head.removeChild(base); return resolved; } function resolve(root, filepath, ext) { if (root.length && last$1(root) !== '/') root += '/'; var url = domResolve(root, filepath); return url.replace(/^(\w+:\/\/[^/]+)(\/[^?]+)/, function (str, origin, path) { var last = path.split('/').pop(); if (/\.\w+$/.test(last)) return str; return origin + path + ext; }); } function readFile(url) { return __awaiter(this, void 0, void 0, function () { return __generator(this, function (_a) { return [2 /*return*/, new Promise(function (resolve, reject) { var xhr = new XMLHttpRequest(); xhr.onload = function () { if (xhr.status >= 200 && xhr.status < 300) { resolve(xhr.responseText); } else { reject(new Error(xhr.statusText)); } }; xhr.onerror = function () { reject(new Error('An error occurred whilst receiving the response.')); }; xhr.open('GET', url); xhr.send(); })]; }); }); } function readFileSync(url) { var xhr = new XMLHttpRequest(); xhr.open('GET', url, false); xhr.send(); if (xhr.status < 200 || xhr.status >= 300) { throw new Error(xhr.statusText); } return xhr.responseText; } function exists(filepath) { return __awaiter(this, void 0, void 0, function () { return __generator(this, function (_a) { return [2 /*return*/, true]; }); }); } function existsSync(filepath) { return true; } function dirname(filepath) { return domResolve(filepath, '.'); } var sep = '/'; var fs = /*#__PURE__*/Object.freeze({ __proto__: null, resolve: resolve, readFile: readFile, readFileSync: readFileSync, exists: exists, existsSync: existsSync, dirname: dirname, sep: sep }); function isComparable(arg) { return arg && isFunction(arg.equals); } function isTruthy(val, ctx) { return !isFalsy(val, ctx); } function isFalsy(val, ctx) { if (ctx.opts.jsTruthy) { return !val; } else { return val === false || undefined === val || val === null; } } var defaultOperators = { '==': function (l, r) { if (isComparable(l)) return l.equals(r); if (isComparable(r)) return r.equals(l); return l === r; }, '!=': function (l, r) { if (isComparable(l)) return !l.equals(r); if (isComparable(r)) return !r.equals(l); return l !== r; }, '>': function (l, r) { if (isComparable(l)) return l.gt(r); if (isComparable(r)) return r.lt(l); return l > r; }, '<': function (l, r) { if (isComparable(l)) return l.lt(r); if (isComparable(r)) return r.gt(l); return l < r; }, '>=': function (l, r) { if (isComparable(l)) return l.geq(r); if (isComparable(r)) return r.leq(l); return l >= r; }, '<=': function (l, r) { if (isComparable(l)) return l.leq(r); if (isComparable(r)) return r.geq(l); return l <= r; }, 'contains': function (l, r) { return l && isFunction(l.indexOf) ? l.indexOf(r) > -1 : false; }, 'and': function (l, r, ctx) { return isTruthy(l, ctx) && isTruthy(r, ctx); }, 'or': function (l, r, ctx) { return isTruthy(l, ctx) || isTruthy(r, ctx); } }; // **DO NOT CHANGE THIS FILE** // // This file is generated by bin/character-gen.js // bitmask character types to boost performance var TYPES = [0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 4, 4, 4, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 2, 8, 0, 0, 0, 0, 8, 0, 0, 0, 64, 0, 65, 0, 0, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 0, 0, 2, 2, 2, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0]; var IDENTIFIER = 1; var BLANK = 4; var QUOTE = 8; var INLINE_BLANK = 16; var NUMBER = 32; var SIGN = 64; TYPES[160] = TYPES[5760] = TYPES[6158] = TYPES[8192] = TYPES[8193] = TYPES[8194] = TYPES[8195] = TYPES[8196] = TYPES[8197] = TYPES[8198] = TYPES[8199] = TYPES[8200] = TYPES[8201] = TYPES[8202] = TYPES[8232] = TYPES[8233] = TYPES[8239] = TYPES[8287] = TYPES[12288] = BLANK; function createTrie(operators) { var e_1, _a; var trie = {}; try { for (var _b = __values(Object.entries(operators)), _c = _b.next(); !_c.done; _c = _b.next()) { var _d = __read(_c.value, 2), name_1 = _d[0], handler = _d[1]; var node = trie; for (var i = 0; i < name_1.length; i++) { var c = name_1[i]; node[c] = node[c] || {}; if (i === name_1.length - 1 && (TYPES[name_1.charCodeAt(i)] & IDENTIFIER)) { node[c].needBoundary = true; } node = node[c]; } node.handler = handler; node.end = true; } } catch (e_1_1) { e_1 = { error: e_1_1 }; } finally { try { if (_c && !_c.done && (_a = _b.return)) _a.call(_b); } finally { if (e_1) throw e_1.error; } } return trie; } var defaultOptions = { root: ['.'], layouts: ['.'], partials: ['.'], relativeReference: true, jekyllInclude: false, cache: undefined, extname: '', fs: fs, dynamicPartials: true, jsTruthy: false, trimTagRight: false, trimTagLeft: false, trimOutputRight: false, trimOutputLeft: false, greedy: true, tagDelimiterLeft: '{%', tagDelimiterRight: '%}', outputDelimiterLeft: '{{', outputDelimiterRight: '}}', preserveTimezones: false, strictFilters: false, strictVariables: false, lenientIf: false, globals: {}, keepOutputType: false, operators: defaultOperators, operatorsTrie: createTrie(defaultOperators) }; function normalize(options) { if (options.hasOwnProperty('operators')) { options.operatorsTrie = createTrie(options.operators); } if (options.hasOwnProperty('root')) { if (!options.hasOwnProperty('partials')) options.partials = options.root; if (!options.hasOwnProperty('layouts')) options.layouts = options.root; } if (options.hasOwnProperty('cache')) { var cache = void 0; if (typeof options.cache === 'number') cache = options.cache > 0 ? new LRU(options.cache) : undefined; else if (typeof options.cache === 'object') cache = options.cache; else cache = options.cache ? new LRU(1024) : undefined; options.cache = cache; } options = __assign(__assign(__assign({}, defaultOptions), (options.jekyllInclude ? { dynamicPartials: false } : {})), options); if (!options.fs.dirname && options.relativeReference) { console.warn('[LiquidJS] `fs.dirname` is required for relativeReference, set relativeReference to `false` to suppress this warning, or provide implementation for `fs.dirname`'); options.relativeReference = false; } options.root = normalizeDirectoryList(options.root); options.partials = normalizeDirectoryList(options.partials); options.layouts = normalizeDirectoryList(options.layouts); return options; } function normalizeDirectoryList(value) { var list = []; if (isArray(value)) list = value; if (isString(value)) list = [value]; return list; } var LiquidError = /** @class */ (function (_super) { __extends(LiquidError, _super); function LiquidError(err, token) { var _this = _super.call(this, err.message) || this; _this.originalError = err; _this.token = token; _this.context = ''; return _this; } LiquidError.prototype.update = function () { var err = this.originalError; this.context = mkContext(this.token); this.message = mkMessage(err.message, this.token); this.stack = this.message + '\n' + this.context + '\n' + this.stack + '\nFrom ' + err.stack; }; return LiquidError; }(Error)); var TokenizationError = /** @class */ (function (_super) { __extends(TokenizationError, _super); function TokenizationError(message, token) { var _this = _super.call(this, new Error(message), token) || this; _this.name = 'TokenizationError'; _super.prototype.update.call(_this); return _this; } return TokenizationError; }(LiquidError)); var ParseError = /** @class */ (function (_super) { __extends(ParseError, _super); function ParseError(err, token) { var _this = _super.call(this, err, token) || this; _this.name = 'ParseError'; _this.message = err.message; _super.prototype.update.call(_this); return _this; } return ParseError; }(LiquidError)); var RenderError = /** @class */ (function (_super) { __extends(RenderError, _super); function RenderError(err, tpl) { var _this = _super.call(this, err, tpl.token) || this; _this.name = 'RenderError'; _this.message = err.message; _super.prototype.update.call(_this); return _this; } RenderError.is = function (obj) { return obj.name === 'RenderError'; }; return RenderError; }(LiquidError)); var UndefinedVariableError = /** @class */ (function (_super) { __extends(UndefinedVariableError, _super); function UndefinedVariableError(err, token) { var _this = _super.call(this, err, token) || this; _this.name = 'UndefinedVariableError'; _this.message = err.message; _super.prototype.update.call(_this); return _this; } return UndefinedVariableError; }(LiquidError)); // only used internally; raised where we don't have token information, // so it can't be an UndefinedVariableError. var InternalUndefinedVariableError = /** @class */ (function (_super) { __extends(InternalUndefinedVariableError, _super); function InternalUndefinedVariableError(variableName) { var _this = _super.call(this, "undefined variable: ".concat(variableName)) || this; _this.name = 'InternalUndefinedVariableError'; _this.variableName = variableName; return _this; } return InternalUndefinedVariableError; }(Error)); var AssertionError = /** @class */ (function (_super) { __extends(AssertionError, _super); function AssertionError(message) { var _this = _super.call(this, message) || this; _this.name = 'AssertionError'; _this.message = message + ''; return _this; } return AssertionError; }(Error)); function mkContext(token) { var _a = __read(token.getPosition(), 1), line = _a[0]; var lines = token.input.split('\n'); var begin = Math.max(line - 2, 1); var end = Math.min(line + 3, lines.length); var context = range(begin, end + 1) .map(function (lineNumber) { var indicator = (lineNumber === line) ? '>> ' : ' '; var num = padStart(String(lineNumber), String(end).length); var text = lines[lineNumber - 1]; return "".concat(indicator).concat(num, "| ").concat(text); }) .join('\n'); return context; } function mkMessage(msg, token) { if (token.file) msg += ", file:".concat(token.file); var _a = __read(token.getPosition(), 2), line = _a[0], col = _a[1]; msg += ", line:".concat(line, ", col:").concat(col); return msg; } var Context = /** @class */ (function () { function Context(env, opts, renderOptions) { if (env === void 0) { env = {}; } if (opts === void 0) { opts = defaultOptions; } if (renderOptions === void 0) { renderOptions = {}; } var _a, _b; /** * insert a Context-level empty scope, * for tags like {% capture %} {% assign %} to operate */ this.scopes = [{}]; this.registers = {}; this.sync = !!renderOptions.sync; this.opts = opts; this.globals = (_a = renderOptions.globals) !== null && _a !== void 0 ? _a : opts.globals; this.environments = env; this.strictVariables = (_b = renderOptions.strictVariables) !== null && _b !== void 0 ? _b : this.opts.strictVariables; } Context.prototype.getRegister = function (key) { return (this.registers[key] = this.registers[key] || {}); }; Context.prototype.setRegister = function (key, value) { return (this.registers[key] = value); }; Context.prototype.saveRegister = function () { var _this = this; var keys = []; for (var _i = 0; _i < arguments.length; _i++) { keys[_i] = arguments[_i]; } return keys.map(function (key) { return [key, _this.getRegister(key)]; }); }; Context.prototype.restoreRegister = function (keyValues) { var _this = this; return keyValues.forEach(function (_a) { var _b = __read(_a, 2), key = _b[0], value = _b[1]; return _this.setRegister(key, value); }); }; Context.prototype.getAll = function () { return __spreadArray([this.globals, this.environments], __read(this.scopes), false).reduce(function (ctx, val) { return __assign(ctx, val); }, {}); }; Context.prototype.get = function (paths) { var scope = this.findScope(paths[0]); return this.getFromScope(scope, paths); }; Context.prototype.getFromScope = function (scope, paths) { var _this = this; if (typeof paths === 'string') paths = paths.split('.'); return paths.reduce(function (scope, path) { scope = readProperty(scope, path); if (isNil(scope) && _this.strictVariables) { throw new InternalUndefinedVariableError(path); } return scope; }, scope); }; Context.prototype.push = function (ctx) { return this.scopes.push(ctx); }; Context.prototype.pop = function () { return this.scopes.pop(); }; Context.prototype.bottom = function () { return this.scopes[0]; }; Context.prototype.findScope = function (key) { for (var i = this.scopes.length - 1; i >= 0; i--) { var candidate = this.scopes[i]; if (key in candidate) return candidate; } if (key in this.environments) return this.environments; return this.globals; }; return Context; }()); function readProperty(obj, key) { if (isNil(obj)) return obj; obj = toLiquid(obj); if (isFunction(obj[key])) return obj[key](); if (obj instanceof Drop) { if (obj.hasOwnProperty(key)) return obj[key]; return obj.liquidMethodMissing(key); } if (key === 'size') return readSize(obj); if (key === 'first') return readFirst(obj); if (key === 'last') return readLast(obj); return obj[key]; } function readFirst(obj) { if (isArray(obj)) return obj[0]; return obj['first']; } function readLast(obj) { if (isArray(obj)) return obj[obj.length - 1]; return obj['last']; } function readSize(obj) { if (obj.hasOwnProperty('size') || obj['size'] !== undefined) return obj['size']; if (isArray(obj) || isString(obj)) return obj.length; if (typeof obj === 'object') return Object.keys(obj).length; } function assert(predicate, message) { if (!predicate) { var msg = typeof message === 'function' ? message() : (message || "expect ".concat(predicate, " to be true")); throw new AssertionError(msg); } } var LookupType; (function (LookupType) { LookupType["Partials"] = "partials"; LookupType["Layouts"] = "layouts"; LookupType["Root"] = "root"; })(LookupType || (LookupType = {})); var Loader = /** @class */ (function () { function Loader(options) { this.options = options; if (options.relativeReference) { var sep = options.fs.sep; assert(sep, '`fs.sep` is required for relative reference'); var rRelativePath_1 = new RegExp(['.' + sep, '..' + sep, './', '../'].map(function (prefix) { return escapeRegex(prefix); }).join('|')); this.shouldLoadRelative = function (referencedFile) { return rRelativePath_1.test(referencedFile); }; } else { this.shouldLoadRelative = function (referencedFile) { return false; }; } this.contains = this.options.fs.contains || (function () { return true; }); } Loader.prototype.lookup = function (file, type, sync, currentFile) { var fs, dirs, _a, _b, filepath, _c, e_1_1; var e_1, _d; return __generator(this, function (_e) { switch (_e.label) { case 0: fs = this.options.fs; dirs = this.options[type]; _e.label = 1; case 1: _e.trys.push([1, 8, 9, 10]); _a = __values(this.candidates(file, dirs, currentFile, type !== LookupType.Root)), _b = _a.next(); _e.label = 2; case 2: if (!!_b.done) return [3 /*break*/, 7]; filepath = _b.value; if (!sync) return [3 /*break*/, 3]; _c = fs.existsSync(filepath); return [3 /*break*/, 5]; case 3: return [4 /*yield*/, fs.exists(filepath)]; case 4: _c = _e.sent(); _e.label = 5; case 5: if (_c) return [2 /*return*/, filepath]; _e.label = 6; case 6: _b = _a.next(); return [3 /*break*/, 2]; case 7: return [3 /*break*/, 10]; case 8: e_1_1 = _e.sent(); e_1 = { error: e_1_1 }; return [3 /*break*/, 10]; case 9: try { if (_b && !_b.done && (_d = _a.return)) _d.call(_a); } finally { if (e_1) throw e_1.error; } return [7 /*endfinally*/]; case 10: throw this.lookupError(file, dirs); } }); }; Loader.prototype.candidates = function (file, dirs, currentFile, enforceRoot) { var _a, fs, extname, referenced, dirs_1, dirs_1_1, dir, e_2_1, dirs_2, dirs_2_1, dir, referenced, e_3_1, filepath; var e_2, _b, e_3, _c; return __generator(this, function (_d) { switch (_d.label) { case 0: _a = this.options, fs = _a.fs, extname = _a.extname; if (!(this.shouldLoadRelative(file) && currentFile)) return [3 /*break*/, 8]; referenced = fs.resolve(this.dirname(currentFile), file, extname); _d.label = 1; case 1: _d.trys.push([1, 6, 7, 8]); dirs_1 = __values(dirs), dirs_1_1 = dirs_1.next(); _d.label = 2; case 2: if (!!dirs_1_1.done) return [3 /*break*/, 5]; dir = dirs_1_1.value; if (!(!enforceRoot || this.contains(dir, referenced))) return [3 /*break*/, 4]; // the relatively referenced file is within one of root dirs return [4 /*yield*/, referenced]; case 3: // the relatively referenced file is within one of root dirs _d.sent(); return [3 /*break*/, 5]; case 4: dirs_1_1 = dirs_1.next(); return [3 /*break*/, 2]; case 5: return [3 /*break*/, 8]; case 6: e_2_1 = _d.sent(); e_2 = { error: e_2_1 }; return [3 /*break*/, 8]; case 7: try { if (dirs_1_1 && !dirs_1_1.done && (_b = dirs_1.return)) _b.call(dirs_1); } finally { if (e_2) throw e_2.error; } return [7 /*endfinally*/]; case 8: _d.trys.push([8, 13, 14, 15]); dirs_2 = __values(dirs), dirs_2_1 = dirs_2.next(); _d.label = 9; case 9: if (!!dirs_2_1.done) return [3 /*break*/, 12]; dir = dirs_2_1.value; referenced = fs.resolve(dir, file, extname); if (!(!enforceRoot || this.contains(dir, referenced))) return [3 /*break*/, 11]; return [4 /*yield*/, referenced]; case 10: _d.sent(); _d.label = 11; case 11: dirs_2_1 = dirs_2.next(); return [3 /*break*/, 9]; case 12: return [3 /*break*/, 15]; case 13: e_3_1 = _d.sent(); e_3 = { error: e_3_1 }; return [3 /*break*/, 15]; case 14: try { if (dirs_2_1 && !dirs_2_1.done && (_c = dirs_2.return)) _c.call(dirs_2); } finally { if (e_3) throw e_3.error; } return [7 /*endfinally*/]; case 15: if (!(fs.fallback !== undefined)) return [3 /*break*/, 17]; filepath = fs.fallback(file); if (!(filepath !== undefined)) return [3 /*break*/, 17]; return [4 /*yield*/, filepath]; case 16: _d.sent(); _d.label = 17; case 17: return [2 /*return*/]; } }); }; Loader.prototype.dirname = function (path) { var fs = this.options.fs; assert(fs.dirname, '`fs.dirname` is required for relative reference'); return fs.dirname(path); }; Loader.prototype.lookupError = function (file, roots) { var err = new Error('ENOENT'); err.message = "ENOENT: Failed to lookup \"".concat(file, "\" in \"").concat(roots, "\""); err.code = 'ENOENT'; return err; }; return Loader; }()); var SimpleEmitter = /** @class */ (function () { function SimpleEmitter() { this.buffer = ''; } SimpleEmitter.prototype.write = function (html) { this.buffer += stringify(html); }; return SimpleEmitter; }()); var StreamedEmitter = /** @class */ (function () { function StreamedEmitter() { this.buffer = ''; this.stream = null; throw new Error('streaming not supported in browser'); } return StreamedEmitter; }()); function createResolvedThenable(value) { var ret = { then: function (resolve) { return resolve(value); }, catch: function () { return ret; } }; return ret; } function createRejectedThenable(err) { var ret = { then: function (resolve, reject) { if (reject) return reject(err); return ret; }, catch: function (reject) { return reject(err); } }; return ret; } function isThenable(val) { return val && isFunction(val.then); } function isAsyncIterator(val) { return val && isFunction(val.next) && isFunction(val.throw) && isFunction(val.return); } // convert an async iterator to a thenable (Promise compatible) function toThenable(val) { if (isThenable(val)) return val; if (isAsyncIterator(val)) return reduce(); return createResolvedThenable(val); function reduce(prev) { var state; try { state = val.next(prev); } catch (err) { return createRejectedThenable(err); } if (state.done) return createResolvedThenable(state.value); return toThenable(state.value).then(reduce, function (err) { var state; try { state = val.throw(err); } catch (e) { return createRejectedThenable(e); } if (state.done) return createResolvedThenable(state.value); return reduce(state.value); }); } } function toPromise(val) { return Promise.resolve(toThenable(val)); } // get the value of async iterator in synchronous manner function toValue(val) { var ret; toThenable(val) .then(function (x) { ret = x; return createResolvedThenable(ret); }) .catch(function (err) { throw err; }); return ret; } var KeepingTypeEmitter = /** @class */ (function () { function KeepingTypeEmitter() { this.buffer = ''; } KeepingTypeEmitter.prototype.write = function (html) { html = toValue$1(html); // This will only preserve the type if the value is isolated. // I.E: // {{ my-port }} -> 42 // {{ my-host }}:{{ my-port }} -> 'host:42' if (typeof html !== 'string' && this.buffer === '') { this.buffer = html; } else { this.buffer = stringify(this.buffer) + stringify(html); } }; return KeepingTypeEmitter; }()); var Render = /** @class */ (function () { function Render() { } Render.prototype.renderTemplatesToNodeStream = function (templates, ctx) { var _this = this; var emitter = new StreamedEmitter(); Promise.resolve().then(function () { return toThenable(_this.renderTemplates(templates, ctx, emitter)); }) .then(function () { return emitter.end(); }, function (err) { return emitter.error(err); }); return emitter.stream; }; Render.prototype.renderTemplates = function (templates, ctx, emitter) { var templates_1, templates_1_1, tpl, html, e_1, err, e_2_1; var e_2, _a; return __generator(this, function (_b) { switch (_b.label) { case 0: if (!emitter) { emitter = ctx.opts.keepOutputType ? new KeepingTypeEmitter() : new SimpleEmitter(); } _b.label = 1; case 1: _b.trys.push([1, 8, 9, 10]); templates_1 = __values(templates), templates_1_1 = templates_1.next(); _b.label = 2; case 2: if (!!templates_1_1.done) return [3 /*break*/, 7]; tpl = templates_1_1.value; _b.label = 3; case 3: _b.trys.push([3, 5, , 6]); return [4 /*yield*/, tpl.render(ctx, emitter) // if not, it'll return an `html`, write to the emitter for it ]; case 4: html = _b.sent(); // if not, it'll return an `html`, write to the emitter for it html && emitter.write(html); if (emitter['break'] || emitter['continue']) return [3 /*break*/, 7]; return [3 /*break*/, 6]; case 5: e_1 = _b.sent(); err = RenderError.is(e_1) ? e_1 : new RenderError(e_1, tpl); throw err; case 6: templates_1_1 = templates_1.next(); return [3 /*break*/, 2]; case 7: return [3 /*break*/, 10]; case 8: e_2_1 = _b.sent(); e_2 = { error: e_2_1 }; return [3 /*break*/, 10]; case 9: try { if (templates_1_1 && !templates_1_1.done && (_a = templates_1.return)) _a.call(templates_1); } finally { if (e_2) throw e_2.error; } return [7 /*endfinally*/]; case 10: return [2 /*return*/, emitter.buffer]; } }); }; return Render; }()); var TokenKind; (function (TokenKind) { TokenKind[TokenKind["Number"] = 1] = "Number"; TokenKind[TokenKind["Literal"] = 2] = "Literal"; TokenKind[TokenKind["Tag"] = 4] = "Tag"; TokenKind[TokenKind["Output"] = 8] = "Output"; TokenKind[TokenKind["HTML"] = 16] = "HTML"; TokenKind[TokenKind["Filter"] = 32] = "Filter"; TokenKind[TokenKind["Hash"] = 64] = "Hash"; TokenKind[TokenKind["PropertyAccess"] = 128] = "PropertyAccess"; TokenKind[TokenKind["Word"] = 256] = "Word"; TokenKind[TokenKind["Range"] = 512] = "Range"; TokenKind[TokenKind["Quoted"] = 1024] = "Quoted"; TokenKind[TokenKind["Operator"] = 2048] = "Operator"; TokenKind[TokenKind["Delimited"] = 12] = "Delimited"; })(TokenKind || (TokenKind = {})); function isDelimitedToken(val) { return !!(getKind(val) & TokenKind.Delimited); } function isOperatorToken(val) { return getKind(val) === TokenKind.Operator; } function isHTMLToken(val) { return getKind(val) === TokenKind.HTML; } function isOutputToken(val) { return getKind(val) === TokenKind.Output; } function isTagToken(val) { return getKind(val) === TokenKind.Tag; } function isQuotedToken(val) { return getKind(val) === TokenKind.Quoted; } function isLiteralToken(val) { return getKind(val) === TokenKind.Literal; } function isNumberToken(val) { return getKind(val) === TokenKind.Number; } function isPropertyAccessToken(val) { return getKind(val) === TokenKind.PropertyAccess; } function isWordToken(val) { return getKind(val) === TokenKind.Word; } function isRangeToken(val) { return getKind(val) === TokenKind.Range; } function getKind(val) { return val ? val.kind : -1; } var typeGuards = /*#__PURE__*/Object.freeze({ __proto__: null, isDelimitedToken: isDelimitedToken, isOperatorToken: isOperatorToken, isHTMLToken: isHTMLToken, isOutputToken: isOutputToken, isTagToken: isTagToken, isQuotedToken: isQuotedToken, isLiteralToken: isLiteralToken, isNumberToken: isNumberToken, isPropertyAccessToken: isPropertyAccessToken, isWordToken: isWordToken, isRangeToken: isRangeToken }); var ParseStream = /** @class */ (function () { function ParseStream(tokens, parseToken) { this.handlers = {}; this.stopRequested = false; this.tokens = tokens; this.parseToken = parseToken; } ParseStream.prototype.on = function (name, cb) { this.handlers[name] = cb; return this; }; ParseStream.prototype.trigger = function (event, arg) { var h = this.handlers[event]; return h ? (h.call(this, arg), true) : false; }; ParseStream.prototype.start = function () { this.trigger('start'); var token; while (!this.stopRequested && (token = this.tokens.shift())) { if (this.trigger('token', token)) continue; if (isTagToken(token) && this.trigger("tag:".concat(token.name), token)) { continue; } var template = this.parseToken(token, this.tokens); this.trigger('template', template); } if (!this.stopRequested) this.trigger('end'); return this; }; ParseStream.prototype.stop = function () { this.stopRequested = true; return this; }; return ParseStream; }()); var TemplateImpl = /** @class */ (function () { function TemplateImpl(token) { this.token = token; } return TemplateImpl; }()); var NullDrop = /** @class */ (function (_super) { __extends(NullDrop, _super); function NullDrop() { return _super !== null && _super.apply(this, arguments) || this; } NullDrop.prototype.equals = function (value) { return isNil(toValue$1(value)); }; NullDrop.prototype.gt = function () { return false; }; NullDrop.prototype.geq = function () { return false; }; NullDrop.prototype.lt = function () { return false; }; NullDrop.prototype.leq = function () { return false; }; NullDrop.prototype.valueOf = function () { return null; }; return NullDrop; }(Drop)); var EmptyDrop = /** @class */ (function (_super) { __extends(EmptyDrop, _super); function EmptyDrop() { return _super !== null && _super.apply(this, arguments) || this; } EmptyDrop.prototype.equals = function (value) { if (value instanceof EmptyDrop) return false; value = toValue$1(value); if (isString(value) || isArray(value)) return value.length === 0; if (isObject(value)) return Object.keys(value).length === 0; return false; }; EmptyDrop.prototype.gt = function () { return false; }; EmptyDrop.prototype.geq = function () { return false; }; EmptyDrop.prototype.lt = function () { return false; }; EmptyDrop.prototype.leq = function () { return false; }; EmptyDrop.prototype.valueOf = function () { return ''; }; return EmptyDrop; }(Drop)); var BlankDrop = /** @class */ (function (_super) { __extends(BlankDrop, _super); function BlankDrop() { return _super !== null && _super.apply(this, arguments) || this; } BlankDrop.prototype.equals = function (value) { if (value === false) return true; if (isNil(toValue$1(value))) return true; if (isString(value)) return /^\s*$/.test(value); return _super.prototype.equals.call(this, value); }; return BlankDrop; }(EmptyDrop)); var nil = new NullDrop(); var literalValues = { 'true': true, 'false': false, 'nil': nil, 'null': nil, 'empty': new EmptyDrop(), 'blank': new BlankDrop() }; var rHex = /[\da-fA-F]/; var rOct = /[0-7]/; var escapeChar = { b: '\b', f: '\f', n: '\n', r: '\r', t: '\t', v: '\x0B' }; function hexVal(c) { var code = c.charCodeAt(0); if (code >= 97) return code - 87; if (code >= 65) return code - 55; return code - 48; } function parseStringLiteral(str) { var ret = ''; for (var i = 1; i < str.length - 1; i++) { if (str[i] !== '\\') { ret += str[i]; continue; } if (escapeChar[str[i + 1]] !== undefined) { ret += escapeChar[str[++i]]; } else if (str[i + 1] === 'u') { var val = 0; var j = i + 2; while (j <= i + 5 && rHex.test(str[j])) { val = val * 16 + hexVal(str[j++]); } i = j - 1; ret += String.fromCharCode(val); } else if (!rOct.test(str[i + 1])) { ret += str[++i]; } else { var j = i + 1; var val = 0; while (j <= i + 3 && rOct.test(str[j])) { val = val * 8 + hexVal(str[j++]); } i = j - 1; ret += String.fromCharCode(val); } } return ret; } var Expression = /** @class */ (function () { function Expression(tokens) { this.postfix = __spreadArray([], __read(toPostfix(tokens)), false); } Expression.prototype.evaluate = function (ctx, lenient) { var operands, _a, _b, token, r, l, result, _c, _d, e_1_1; var e_1, _e; return __generator(this, function (_f) { switch (_f.label) { case 0: assert(ctx, 'unable to evaluate: context not defined'); operands = []; _f.label = 1; case 1: _f.trys.push([1, 9, 10, 11]); _a = __values(this.postfix), _b = _a.next(); _f.label = 2; case 2: if (!!_b.done) return [3 /*break*/, 8]; token = _b.value; if (!isOperatorToken(token)) return [3 /*break*/, 5]; return [4 /*yield*/, operands.pop()]; case 3: r = _f.sent(); return [4 /*yield*/, operands.pop()];