/*! Sazae */ /******/ (() => { // webpackBootstrap /******/ var __webpack_modules__ = ({ /***/ "./src/api.config.js": /*!***************************!*\ !*** ./src/api.config.js ***! \***************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ config: () => (/* binding */ config) /* harmony export */ }); var config = { base: 'https://proactiv.demo-sites.me/submissions', products: 'https://proactiv.demo-sites.me/products', refresh: 'https://proactiv.demo-sites.me/refresh', a: 'test', b: 'this' }; /***/ }), /***/ "./src/form.js": /*!*********************!*\ !*** ./src/form.js ***! \*********************/ /***/ (() => { (function ($, Drupal) { 'use strict'; Drupal.behaviors.r_hubspot_forms = { attach: function attach(context, settings) { $('form').each(function () { // Add boostrap classes to HubspotForm $(this).find('.hs-fieldtype-select .input').addClass('form-wrapper'); $(this).find('.hs-fieldtype-select .input select').addClass('form-control').once('wrapped').wrap("
"); $(this).find('.hs-fieldtype-text .input').addClass('form-wrapper'); $(this).find('.hs-fieldtype-text .input input').addClass('form-control'); $(this).find('.hs-fieldtype-textarea .input').addClass('form-wrapper'); $(this).find('.hs-fieldtype-textarea .input textarea').addClass('form-control').once('wrapped').wrap("
"); $(this).find('.hs-fieldtype-date .input').addClass('form-wrapper'); // @TODO Move to attachBehaviors, this is being deprecated $(this).find('.form-textarea-wrapper').once('domed').bind('DOMSubtreeModified', function (e) { Drupal.attachBehaviors(); }); }); } }; })(jQuery, Drupal); /***/ }), /***/ "./src/pager.js": /*!**********************!*\ !*** ./src/pager.js ***! \**********************/ /***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => { function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); } function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; } function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); } var Twig = __webpack_require__(/*! twig */ "./node_modules/twig/src/twig.js"); (function ($, Drupal, window) { window.r_build_pager = function (element, route_name, total, total_pages, current_page, target, templateId) { var variables = { element: element, template: templateId, target: target, pager: { '#element': element, '#parameters': '', '#quantity': 3, '#route_name': route_name, '#route_parameters': [], '#tags': [] }, services: { 'pager.manager': _defineProperty({}, element, { total: total_pages, current_page: current_page }) } }; r_template_preprocess_pager(variables); var pager = document.getElementById('r-script-pager'); var pagerContent = pager.innerHTML; var template = Twig.twig({ data: pagerContent }); pagerContent = template.render(variables); return pagerContent; }; window.r_template_preprocess_pager = function (variables) { var element = variables['pager']['#element']; var parameters = variables['pager']['#parameters']; var quantity = parseInt(variables['pager']['#quantity'] ? variables['pager']['#quantity'] : 0); var route_name = variables['pager']['#route_name']; var route_parameters = variables['pager']['#route_parameters'] || []; // Invoking pager manager service var pager_manager = variables['services']['pager.manager']; var pager = pager_manager[element]; if (!pager) { return; } var pager_max = pager['total']; if (pager_max <= 1) { return; } var tags = variables['pager']['#tags']; var pager_middle = Math.ceil(quantity / 2); var current_page = parseInt(pager['current_page'] ? pager['current_page'] : 0); var pager_current = current_page + 1; var pager_first = pager_current - pager_middle + 1; var pager_last = pager_current + quantity - pager_middle; var i = pager_first; if (pager_last > pager_max) { i += pager_max - pager_last; pager_last = pager_max; } if (i <= 0) { pager_last += 1 - i; i = 1; } var items = {}; if (current_page > 0) { // "First" link items['first'] = { attributes: {} }; var options = { query: 'pager=0' }; // @TODO: Should check if route_name contains '?' then use '&' items['first']['href'] = route_name + '&' + options.query; if (tags && tags[0]) { items['first']['text'] = tags[0]; } // "Previous" link items['previous'] = { attributes: {} }; options = { query: 'pager=' + (current_page - 1) }; items['previous']['href'] = route_name + '&' + options.query; if (tags && tags[1]) { items['previous']['text'] = tags[1]; } } if (i != pager_max) { if (i > 1) { // Add ellipsis for previous pages variables['ellipses'] = { previous: true }; } // Generate actual pager piece for (; i <= pager_last && i <= pager_max; i++) { var _options = { query: 'pager=' + (element, i - 1) }; items['pages'] = items['pages'] || {}; items['pages'][i] = { href: route_name + '&' + _options.query, attributes: {} }; if (i === pager_current) { variables['current'] = i; } } if (i < pager_max + 1) { // Add ellipsis for next pages variables['ellipses'] = variables['ellipses'] || {}; variables['ellipses']['next'] = true; } } if (current_page < pager_max - 1) { // "Next" link items['next'] = { attributes: {} }; var _options2 = { query: 'pager=' + (current_page + 1) }; items['next']['href'] = route_name + '&' + _options2.query; if (tags && tags[3]) { items['next']['text'] = tags[3]; } // "Last" link items['last'] = { attributes: {} }; _options2 = { query: 'pager=' + (pager_max - 1) }; items['last']['href'] = route_name + '&' + _options2.query; if (tags && tags[4]) { items['last']['text'] = tags[4]; } } variables['items'] = items; variables['heading_id'] = 'pagination-heading'; return variables; }; (function ($, Drupal) { Drupal.behaviors.r_ajax_hubspot_pager = { attach: function attach(context, settings) { $('body').find('.r-ajax-pager').once('inited').each(function () { var $pager = $(this); $(this).find('[data-rel-href]').once('inited').click(function (e) { e.preventDefault(); var $link = $(event.currentTarget); var href = $link.attr('data-rel-href'); var target = $pager.attr('data-target'); var element = $pager.attr('data-element'); var template = $pager.attr('data-template'); var route_name = $pager.attr('data-route_name'); r_apply_json(element, template, target, href, route_name, function () { $([document.documentElement, document.body]).animate({ scrollTop: $(target).offset().top }, 600); }); }); }); } }; })(jQuery, Drupal); })(jQuery, Drupal, window); /***/ }), /***/ "./src/products-review.js": /*!********************************!*\ !*** ./src/products-review.js ***! \********************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ apply_form_behavior: () => (/* binding */ apply_form_behavior) /* harmony export */ }); function apply_form_behavior(selection, content_id) { var setup = false; window.addEventListener('message', function (event) { if (!(event.data.type === 'hsFormCallback' && event.data.eventName === 'onFormReady')) { return; } if (setup) { return; } setup = true; var reviewForm = document.querySelector(selection); if (!reviewForm) { return; } var contentIdElement = reviewForm.querySelector('[name="content_id"]'); var contentParentElement = reviewForm.querySelector('.hs_content_id'); // Set all fields' default value to blank reviewForm.querySelectorAll('input:not([type="hidden"]):not([type="submit"]), textarea').forEach(function (field) { field.value = ''; }); // Set the default value for content_id element and hide it contentIdElement.value = content_id; contentParentElement.style.display = 'none'; jQuery(contentIdElement).removeOnce('sci'); Drupal.attachBehaviors(); // Do not allow reviewForm to be submitted if content_id is not available reviewForm.addEventListener('submit', function (event) { if (!contentIdElement.value) { event.preventDefault(); alert('Product is not available. Form cannot be submitted.'); return false; } }); }); } /***/ }), /***/ "./node_modules/locutus/php/_helpers/_phpCastString.js": /*!*************************************************************!*\ !*** ./node_modules/locutus/php/_helpers/_phpCastString.js ***! \*************************************************************/ /***/ ((module) => { "use strict"; var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; module.exports = function _phpCastString(value) { // original by: Rafał Kukawski // example 1: _phpCastString(true) // returns 1: '1' // example 2: _phpCastString(false) // returns 2: '' // example 3: _phpCastString('foo') // returns 3: 'foo' // example 4: _phpCastString(0/0) // returns 4: 'NAN' // example 5: _phpCastString(1/0) // returns 5: 'INF' // example 6: _phpCastString(-1/0) // returns 6: '-INF' // example 7: _phpCastString(null) // returns 7: '' // example 8: _phpCastString(undefined) // returns 8: '' // example 9: _phpCastString([]) // returns 9: 'Array' // example 10: _phpCastString({}) // returns 10: 'Object' // example 11: _phpCastString(0) // returns 11: '0' // example 12: _phpCastString(1) // returns 12: '1' // example 13: _phpCastString(3.14) // returns 13: '3.14' var type = typeof value === 'undefined' ? 'undefined' : _typeof(value); switch (type) { case 'boolean': return value ? '1' : ''; case 'string': return value; case 'number': if (isNaN(value)) { return 'NAN'; } if (!isFinite(value)) { return (value < 0 ? '-' : '') + 'INF'; } return value + ''; case 'undefined': return ''; case 'object': if (Array.isArray(value)) { return 'Array'; } if (value !== null) { return 'Object'; } return ''; case 'function': // fall through default: throw new Error('Unsupported value type'); } }; //# sourceMappingURL=_phpCastString.js.map /***/ }), /***/ "./node_modules/locutus/php/_helpers/_php_cast_float.js": /*!**************************************************************!*\ !*** ./node_modules/locutus/php/_helpers/_php_cast_float.js ***! \**************************************************************/ /***/ ((module, __unused_webpack_exports, __webpack_require__) => { "use strict"; var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; module.exports = function _php_cast_float(value) { // original by: Rafał Kukawski // example 1: _php_cast_float(false) // returns 1: 0 // example 2: _php_cast_float(true) // returns 2: 1 // example 3: _php_cast_float(0) // returns 3: 0 // example 4: _php_cast_float(1) // returns 4: 1 // example 5: _php_cast_float(3.14) // returns 5: 3.14 // example 6: _php_cast_float('') // returns 6: 0 // example 7: _php_cast_float('0') // returns 7: 0 // example 8: _php_cast_float('abc') // returns 8: 0 // example 9: _php_cast_float(null) // returns 9: 0 // example 10: _php_cast_float(undefined) // returns 10: 0 // example 11: _php_cast_float('123abc') // returns 11: 123 // example 12: _php_cast_float('123e4') // returns 12: 1230000 // example 13: _php_cast_float(0x200000001) // returns 13: 8589934593 // example 14: _php_cast_float('3.14abc') // returns 14: 3.14 var type = typeof value === 'undefined' ? 'undefined' : _typeof(value); switch (type) { case 'number': return value; case 'string': return parseFloat(value) || 0; case 'boolean': // fall through default: // PHP docs state, that for types other than string // conversion is {input type}->int->float return __webpack_require__(/*! ./_php_cast_int */ "./node_modules/locutus/php/_helpers/_php_cast_int.js")(value); } }; //# sourceMappingURL=_php_cast_float.js.map /***/ }), /***/ "./node_modules/locutus/php/_helpers/_php_cast_int.js": /*!************************************************************!*\ !*** ./node_modules/locutus/php/_helpers/_php_cast_int.js ***! \************************************************************/ /***/ ((module) => { "use strict"; var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; module.exports = function _php_cast_int(value) { // original by: Rafał Kukawski // example 1: _php_cast_int(false) // returns 1: 0 // example 2: _php_cast_int(true) // returns 2: 1 // example 3: _php_cast_int(0) // returns 3: 0 // example 4: _php_cast_int(1) // returns 4: 1 // example 5: _php_cast_int(3.14) // returns 5: 3 // example 6: _php_cast_int('') // returns 6: 0 // example 7: _php_cast_int('0') // returns 7: 0 // example 8: _php_cast_int('abc') // returns 8: 0 // example 9: _php_cast_int(null) // returns 9: 0 // example 10: _php_cast_int(undefined) // returns 10: 0 // example 11: _php_cast_int('123abc') // returns 11: 123 // example 12: _php_cast_int('123e4') // returns 12: 123 // example 13: _php_cast_int(0x200000001) // returns 13: 8589934593 var type = typeof value === 'undefined' ? 'undefined' : _typeof(value); switch (type) { case 'number': if (isNaN(value) || !isFinite(value)) { // from PHP 7, NaN and Infinity are casted to 0 return 0; } return value < 0 ? Math.ceil(value) : Math.floor(value); case 'string': return parseInt(value, 10) || 0; case 'boolean': // fall through default: // Behaviour for types other than float, string, boolean // is undefined and can change any time. // To not invent complex logic // that mimics PHP 7.0 behaviour // casting value->bool->number is used return +!!value; } }; //# sourceMappingURL=_php_cast_int.js.map /***/ }), /***/ "./node_modules/locutus/php/datetime/date.js": /*!***************************************************!*\ !*** ./node_modules/locutus/php/datetime/date.js ***! \***************************************************/ /***/ ((module) => { "use strict"; module.exports = function date(format, timestamp) { // discuss at: https://locutus.io/php/date/ // original by: Carlos R. L. Rodrigues (https://www.jsfromhell.com) // original by: gettimeofday // parts by: Peter-Paul Koch (https://www.quirksmode.org/js/beat.html) // improved by: Kevin van Zonneveld (https://kvz.io) // improved by: MeEtc (https://yass.meetcweb.com) // improved by: Brad Touesnard // improved by: Tim Wiel // improved by: Bryan Elliott // improved by: David Randall // improved by: Theriault (https://github.com/Theriault) // improved by: Theriault (https://github.com/Theriault) // improved by: Brett Zamir (https://brett-zamir.me) // improved by: Theriault (https://github.com/Theriault) // improved by: Thomas Beaucourt (https://www.webapp.fr) // improved by: JT // improved by: Theriault (https://github.com/Theriault) // improved by: Rafał Kukawski (https://blog.kukawski.pl) // improved by: Theriault (https://github.com/Theriault) // input by: Brett Zamir (https://brett-zamir.me) // input by: majak // input by: Alex // input by: Martin // input by: Alex Wilson // input by: Haravikk // bugfixed by: Kevin van Zonneveld (https://kvz.io) // bugfixed by: majak // bugfixed by: Kevin van Zonneveld (https://kvz.io) // bugfixed by: Brett Zamir (https://brett-zamir.me) // bugfixed by: omid (https://locutus.io/php/380:380#comment_137122) // bugfixed by: Chris (https://www.devotis.nl/) // note 1: Uses global: locutus to store the default timezone // note 1: Although the function potentially allows timezone info // note 1: (see notes), it currently does not set // note 1: per a timezone specified by date_default_timezone_set(). Implementers might use // note 1: $locutus.currentTimezoneOffset and // note 1: $locutus.currentTimezoneDST set by that function // note 1: in order to adjust the dates in this function // note 1: (or our other date functions!) accordingly // example 1: date('H:m:s \\m \\i\\s \\m\\o\\n\\t\\h', 1062402400) // returns 1: '07:09:40 m is month' // example 2: date('F j, Y, g:i a', 1062462400) // returns 2: 'September 2, 2003, 12:26 am' // example 3: date('Y W o', 1062462400) // returns 3: '2003 36 2003' // example 4: var $x = date('Y m d', (new Date()).getTime() / 1000) // example 4: $x = $x + '' // example 4: var $result = $x.length // 2009 01 09 // returns 4: 10 // example 5: date('W', 1104534000) // returns 5: '52' // example 6: date('B t', 1104534000) // returns 6: '999 31' // example 7: date('W U', 1293750000.82); // 2010-12-31 // returns 7: '52 1293750000' // example 8: date('W', 1293836400); // 2011-01-01 // returns 8: '52' // example 9: date('W Y-m-d', 1293974054); // 2011-01-02 // returns 9: '52 2011-01-02' // test: skip-1 skip-2 skip-5 var jsdate = void 0, f = void 0; // Keep this here (works, but for code commented-out below for file size reasons) // var tal= []; var txtWords = ['Sun', 'Mon', 'Tues', 'Wednes', 'Thurs', 'Fri', 'Satur', 'January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December']; // trailing backslash -> (dropped) // a backslash followed by any character (including backslash) -> the character // empty string -> empty string var formatChr = /\\?(.?)/gi; var formatChrCb = function formatChrCb(t, s) { return f[t] ? f[t]() : s; }; var _pad = function _pad(n, c) { n = String(n); while (n.length < c) { n = '0' + n; } return n; }; f = { // Day d: function d() { // Day of month w/leading 0; 01..31 return _pad(f.j(), 2); }, D: function D() { // Shorthand day name; Mon...Sun return f.l().slice(0, 3); }, j: function j() { // Day of month; 1..31 return jsdate.getDate(); }, l: function l() { // Full day name; Monday...Sunday return txtWords[f.w()] + 'day'; }, N: function N() { // ISO-8601 day of week; 1[Mon]..7[Sun] return f.w() || 7; }, S: function S() { // Ordinal suffix for day of month; st, nd, rd, th var j = f.j(); var i = j % 10; if (i <= 3 && parseInt(j % 100 / 10, 10) === 1) { i = 0; } return ['st', 'nd', 'rd'][i - 1] || 'th'; }, w: function w() { // Day of week; 0[Sun]..6[Sat] return jsdate.getDay(); }, z: function z() { // Day of year; 0..365 var a = new Date(f.Y(), f.n() - 1, f.j()); var b = new Date(f.Y(), 0, 1); return Math.round((a - b) / 864e5); }, // Week W: function W() { // ISO-8601 week number var a = new Date(f.Y(), f.n() - 1, f.j() - f.N() + 3); var b = new Date(a.getFullYear(), 0, 4); return _pad(1 + Math.round((a - b) / 864e5 / 7), 2); }, // Month F: function F() { // Full month name; January...December return txtWords[6 + f.n()]; }, m: function m() { // Month w/leading 0; 01...12 return _pad(f.n(), 2); }, M: function M() { // Shorthand month name; Jan...Dec return f.F().slice(0, 3); }, n: function n() { // Month; 1...12 return jsdate.getMonth() + 1; }, t: function t() { // Days in month; 28...31 return new Date(f.Y(), f.n(), 0).getDate(); }, // Year L: function L() { // Is leap year?; 0 or 1 var j = f.Y(); return j % 4 === 0 & j % 100 !== 0 | j % 400 === 0; }, o: function o() { // ISO-8601 year var n = f.n(); var W = f.W(); var Y = f.Y(); return Y + (n === 12 && W < 9 ? 1 : n === 1 && W > 9 ? -1 : 0); }, Y: function Y() { // Full year; e.g. 1980...2010 return jsdate.getFullYear(); }, y: function y() { // Last two digits of year; 00...99 return f.Y().toString().slice(-2); }, // Time a: function a() { // am or pm return jsdate.getHours() > 11 ? 'pm' : 'am'; }, A: function A() { // AM or PM return f.a().toUpperCase(); }, B: function B() { // Swatch Internet time; 000..999 var H = jsdate.getUTCHours() * 36e2; // Hours var i = jsdate.getUTCMinutes() * 60; // Minutes // Seconds var s = jsdate.getUTCSeconds(); return _pad(Math.floor((H + i + s + 36e2) / 86.4) % 1e3, 3); }, g: function g() { // 12-Hours; 1..12 return f.G() % 12 || 12; }, G: function G() { // 24-Hours; 0..23 return jsdate.getHours(); }, h: function h() { // 12-Hours w/leading 0; 01..12 return _pad(f.g(), 2); }, H: function H() { // 24-Hours w/leading 0; 00..23 return _pad(f.G(), 2); }, i: function i() { // Minutes w/leading 0; 00..59 return _pad(jsdate.getMinutes(), 2); }, s: function s() { // Seconds w/leading 0; 00..59 return _pad(jsdate.getSeconds(), 2); }, u: function u() { // Microseconds; 000000-999000 return _pad(jsdate.getMilliseconds() * 1000, 6); }, // Timezone e: function e() { // Timezone identifier; e.g. Atlantic/Azores, ... // The following works, but requires inclusion of the very large // timezone_abbreviations_list() function. /* return that.date_default_timezone_get(); */ var msg = 'Not supported (see source code of date() for timezone on how to add support)'; throw new Error(msg); }, I: function I() { // DST observed?; 0 or 1 // Compares Jan 1 minus Jan 1 UTC to Jul 1 minus Jul 1 UTC. // If they are not equal, then DST is observed. var a = new Date(f.Y(), 0); // Jan 1 var c = Date.UTC(f.Y(), 0); // Jan 1 UTC var b = new Date(f.Y(), 6); // Jul 1 // Jul 1 UTC var d = Date.UTC(f.Y(), 6); return a - c !== b - d ? 1 : 0; }, O: function O() { // Difference to GMT in hour format; e.g. +0200 var tzo = jsdate.getTimezoneOffset(); var a = Math.abs(tzo); return (tzo > 0 ? '-' : '+') + _pad(Math.floor(a / 60) * 100 + a % 60, 4); }, P: function P() { // Difference to GMT w/colon; e.g. +02:00 var O = f.O(); return O.substr(0, 3) + ':' + O.substr(3, 2); }, T: function T() { // The following works, but requires inclusion of the very // large timezone_abbreviations_list() function. /* var abbr, i, os, _default; if (!tal.length) { tal = that.timezone_abbreviations_list(); } if ($locutus && $locutus.default_timezone) { _default = $locutus.default_timezone; for (abbr in tal) { for (i = 0; i < tal[abbr].length; i++) { if (tal[abbr][i].timezone_id === _default) { return abbr.toUpperCase(); } } } } for (abbr in tal) { for (i = 0; i < tal[abbr].length; i++) { os = -jsdate.getTimezoneOffset() * 60; if (tal[abbr][i].offset === os) { return abbr.toUpperCase(); } } } */ return 'UTC'; }, Z: function Z() { // Timezone offset in seconds (-43200...50400) return -jsdate.getTimezoneOffset() * 60; }, // Full Date/Time c: function c() { // ISO-8601 date. return 'Y-m-d\\TH:i:sP'.replace(formatChr, formatChrCb); }, r: function r() { // RFC 2822 return 'D, d M Y H:i:s O'.replace(formatChr, formatChrCb); }, U: function U() { // Seconds since UNIX epoch return jsdate / 1000 | 0; } }; var _date = function _date(format, timestamp) { jsdate = timestamp === undefined ? new Date() // Not provided : timestamp instanceof Date ? new Date(timestamp) // JS Date() : new Date(timestamp * 1000); // UNIX timestamp (auto-convert to int) return format.replace(formatChr, formatChrCb); }; return _date(format, timestamp); }; //# sourceMappingURL=date.js.map /***/ }), /***/ "./node_modules/locutus/php/datetime/strtotime.js": /*!********************************************************!*\ !*** ./node_modules/locutus/php/datetime/strtotime.js ***! \********************************************************/ /***/ ((module) => { "use strict"; var reSpace = '[ \\t]+'; var reSpaceOpt = '[ \\t]*'; var reMeridian = '(?:([ap])\\.?m\\.?([\\t ]|$))'; var reHour24 = '(2[0-4]|[01]?[0-9])'; var reHour24lz = '([01][0-9]|2[0-4])'; var reHour12 = '(0?[1-9]|1[0-2])'; var reMinute = '([0-5]?[0-9])'; var reMinutelz = '([0-5][0-9])'; var reSecond = '(60|[0-5]?[0-9])'; var reSecondlz = '(60|[0-5][0-9])'; var reFrac = '(?:\\.([0-9]+))'; var reDayfull = 'sunday|monday|tuesday|wednesday|thursday|friday|saturday'; var reDayabbr = 'sun|mon|tue|wed|thu|fri|sat'; var reDaytext = reDayfull + '|' + reDayabbr + '|weekdays?'; var reReltextnumber = 'first|second|third|fourth|fifth|sixth|seventh|eighth?|ninth|tenth|eleventh|twelfth'; var reReltexttext = 'next|last|previous|this'; var reReltextunit = '(?:second|sec|minute|min|hour|day|fortnight|forthnight|month|year)s?|weeks|' + reDaytext; var reYear = '([0-9]{1,4})'; var reYear2 = '([0-9]{2})'; var reYear4 = '([0-9]{4})'; var reYear4withSign = '([+-]?[0-9]{4})'; var reMonth = '(1[0-2]|0?[0-9])'; var reMonthlz = '(0[0-9]|1[0-2])'; var reDay = '(?:(3[01]|[0-2]?[0-9])(?:st|nd|rd|th)?)'; var reDaylz = '(0[0-9]|[1-2][0-9]|3[01])'; var reMonthFull = 'january|february|march|april|may|june|july|august|september|october|november|december'; var reMonthAbbr = 'jan|feb|mar|apr|may|jun|jul|aug|sept?|oct|nov|dec'; var reMonthroman = 'i[vx]|vi{0,3}|xi{0,2}|i{1,3}'; var reMonthText = '(' + reMonthFull + '|' + reMonthAbbr + '|' + reMonthroman + ')'; var reTzCorrection = '((?:GMT)?([+-])' + reHour24 + ':?' + reMinute + '?)'; var reTzAbbr = '\\(?([a-zA-Z]{1,6})\\)?'; var reDayOfYear = '(00[1-9]|0[1-9][0-9]|[12][0-9][0-9]|3[0-5][0-9]|36[0-6])'; var reWeekOfYear = '(0[1-9]|[1-4][0-9]|5[0-3])'; var reDateNoYear = reMonthText + '[ .\\t-]*' + reDay + '[,.stndrh\\t ]*'; function processMeridian(hour, meridian) { meridian = meridian && meridian.toLowerCase(); switch (meridian) { case 'a': hour += hour === 12 ? -12 : 0; break; case 'p': hour += hour !== 12 ? 12 : 0; break; } return hour; } function processYear(yearStr) { var year = +yearStr; if (yearStr.length < 4 && year < 100) { year += year < 70 ? 2000 : 1900; } return year; } function lookupMonth(monthStr) { return { jan: 0, january: 0, i: 0, feb: 1, february: 1, ii: 1, mar: 2, march: 2, iii: 2, apr: 3, april: 3, iv: 3, may: 4, v: 4, jun: 5, june: 5, vi: 5, jul: 6, july: 6, vii: 6, aug: 7, august: 7, viii: 7, sep: 8, sept: 8, september: 8, ix: 8, oct: 9, october: 9, x: 9, nov: 10, november: 10, xi: 10, dec: 11, december: 11, xii: 11 }[monthStr.toLowerCase()]; } function lookupWeekday(dayStr) { var desiredSundayNumber = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0; var dayNumbers = { mon: 1, monday: 1, tue: 2, tuesday: 2, wed: 3, wednesday: 3, thu: 4, thursday: 4, fri: 5, friday: 5, sat: 6, saturday: 6, sun: 0, sunday: 0 }; return dayNumbers[dayStr.toLowerCase()] || desiredSundayNumber; } function lookupRelative(relText) { var relativeNumbers = { last: -1, previous: -1, this: 0, first: 1, next: 1, second: 2, third: 3, fourth: 4, fifth: 5, sixth: 6, seventh: 7, eight: 8, eighth: 8, ninth: 9, tenth: 10, eleventh: 11, twelfth: 12 }; var relativeBehavior = { this: 1 }; var relTextLower = relText.toLowerCase(); return { amount: relativeNumbers[relTextLower], behavior: relativeBehavior[relTextLower] || 0 }; } function processTzCorrection(tzOffset, oldValue) { var reTzCorrectionLoose = /(?:GMT)?([+-])(\d+)(:?)(\d{0,2})/i; tzOffset = tzOffset && tzOffset.match(reTzCorrectionLoose); if (!tzOffset) { return oldValue; } var sign = tzOffset[1] === '-' ? -1 : 1; var hours = +tzOffset[2]; var minutes = +tzOffset[4]; if (!tzOffset[4] && !tzOffset[3]) { minutes = Math.floor(hours % 100); hours = Math.floor(hours / 100); } // timezone offset in seconds return sign * (hours * 60 + minutes) * 60; } // tz abbrevation : tz offset in seconds var tzAbbrOffsets = { acdt: 37800, acst: 34200, addt: -7200, adt: -10800, aedt: 39600, aest: 36000, ahdt: -32400, ahst: -36000, akdt: -28800, akst: -32400, amt: -13840, apt: -10800, ast: -14400, awdt: 32400, awst: 28800, awt: -10800, bdst: 7200, bdt: -36000, bmt: -14309, bst: 3600, cast: 34200, cat: 7200, cddt: -14400, cdt: -18000, cemt: 10800, cest: 7200, cet: 3600, cmt: -15408, cpt: -18000, cst: -21600, cwt: -18000, chst: 36000, dmt: -1521, eat: 10800, eddt: -10800, edt: -14400, eest: 10800, eet: 7200, emt: -26248, ept: -14400, est: -18000, ewt: -14400, ffmt: -14660, fmt: -4056, gdt: 39600, gmt: 0, gst: 36000, hdt: -34200, hkst: 32400, hkt: 28800, hmt: -19776, hpt: -34200, hst: -36000, hwt: -34200, iddt: 14400, idt: 10800, imt: 25025, ist: 7200, jdt: 36000, jmt: 8440, jst: 32400, kdt: 36000, kmt: 5736, kst: 30600, lst: 9394, mddt: -18000, mdst: 16279, mdt: -21600, mest: 7200, met: 3600, mmt: 9017, mpt: -21600, msd: 14400, msk: 10800, mst: -25200, mwt: -21600, nddt: -5400, ndt: -9052, npt: -9000, nst: -12600, nwt: -9000, nzdt: 46800, nzmt: 41400, nzst: 43200, pddt: -21600, pdt: -25200, pkst: 21600, pkt: 18000, plmt: 25590, pmt: -13236, ppmt: -17340, ppt: -25200, pst: -28800, pwt: -25200, qmt: -18840, rmt: 5794, sast: 7200, sdmt: -16800, sjmt: -20173, smt: -13884, sst: -39600, tbmt: 10751, tmt: 12344, uct: 0, utc: 0, wast: 7200, wat: 3600, wemt: 7200, west: 3600, wet: 0, wib: 25200, wita: 28800, wit: 32400, wmt: 5040, yddt: -25200, ydt: -28800, ypt: -28800, yst: -32400, ywt: -28800, a: 3600, b: 7200, c: 10800, d: 14400, e: 18000, f: 21600, g: 25200, h: 28800, i: 32400, k: 36000, l: 39600, m: 43200, n: -3600, o: -7200, p: -10800, q: -14400, r: -18000, s: -21600, t: -25200, u: -28800, v: -32400, w: -36000, x: -39600, y: -43200, z: 0 }; var formats = { yesterday: { regex: /^yesterday/i, name: 'yesterday', callback: function callback() { this.rd -= 1; return this.resetTime(); } }, now: { regex: /^now/i, name: 'now' // do nothing }, noon: { regex: /^noon/i, name: 'noon', callback: function callback() { return this.resetTime() && this.time(12, 0, 0, 0); } }, midnightOrToday: { regex: /^(midnight|today)/i, name: 'midnight | today', callback: function callback() { return this.resetTime(); } }, tomorrow: { regex: /^tomorrow/i, name: 'tomorrow', callback: function callback() { this.rd += 1; return this.resetTime(); } }, timestamp: { regex: /^@(-?\d+)/i, name: 'timestamp', callback: function callback(match, timestamp) { this.rs += +timestamp; this.y = 1970; this.m = 0; this.d = 1; this.dates = 0; return this.resetTime() && this.zone(0); } }, firstOrLastDay: { regex: /^(first|last) day of/i, name: 'firstdayof | lastdayof', callback: function callback(match, day) { if (day.toLowerCase() === 'first') { this.firstOrLastDayOfMonth = 1; } else { this.firstOrLastDayOfMonth = -1; } } }, backOrFrontOf: { regex: RegExp('^(back|front) of ' + reHour24 + reSpaceOpt + reMeridian + '?', 'i'), name: 'backof | frontof', callback: function callback(match, side, hours, meridian) { var back = side.toLowerCase() === 'back'; var hour = +hours; var minute = 15; if (!back) { hour -= 1; minute = 45; } hour = processMeridian(hour, meridian); return this.resetTime() && this.time(hour, minute, 0, 0); } }, weekdayOf: { regex: RegExp('^(' + reReltextnumber + '|' + reReltexttext + ')' + reSpace + '(' + reDayfull + '|' + reDayabbr + ')' + reSpace + 'of', 'i'), name: 'weekdayof' // todo }, mssqltime: { regex: RegExp('^' + reHour12 + ':' + reMinutelz + ':' + reSecondlz + '[:.]([0-9]+)' + reMeridian, 'i'), name: 'mssqltime', callback: function callback(match, hour, minute, second, frac, meridian) { return this.time(processMeridian(+hour, meridian), +minute, +second, +frac.substr(0, 3)); } }, oracledate: { regex: /^(\d{2})-([A-Z]{3})-(\d{2})$/i, name: 'd-M-y', callback: function callback(match, day, monthText, year) { var month = { JAN: 0, FEB: 1, MAR: 2, APR: 3, MAY: 4, JUN: 5, JUL: 6, AUG: 7, SEP: 8, OCT: 9, NOV: 10, DEC: 11 }[monthText.toUpperCase()]; return this.ymd(2000 + parseInt(year, 10), month, parseInt(day, 10)); } }, timeLong12: { regex: RegExp('^' + reHour12 + '[:.]' + reMinute + '[:.]' + reSecondlz + reSpaceOpt + reMeridian, 'i'), name: 'timelong12', callback: function callback(match, hour, minute, second, meridian) { return this.time(processMeridian(+hour, meridian), +minute, +second, 0); } }, timeShort12: { regex: RegExp('^' + reHour12 + '[:.]' + reMinutelz + reSpaceOpt + reMeridian, 'i'), name: 'timeshort12', callback: function callback(match, hour, minute, meridian) { return this.time(processMeridian(+hour, meridian), +minute, 0, 0); } }, timeTiny12: { regex: RegExp('^' + reHour12 + reSpaceOpt + reMeridian, 'i'), name: 'timetiny12', callback: function callback(match, hour, meridian) { return this.time(processMeridian(+hour, meridian), 0, 0, 0); } }, soap: { regex: RegExp('^' + reYear4 + '-' + reMonthlz + '-' + reDaylz + 'T' + reHour24lz + ':' + reMinutelz + ':' + reSecondlz + reFrac + reTzCorrection + '?', 'i'), name: 'soap', callback: function callback(match, year, month, day, hour, minute, second, frac, tzCorrection) { return this.ymd(+year, month - 1, +day) && this.time(+hour, +minute, +second, +frac.substr(0, 3)) && this.zone(processTzCorrection(tzCorrection)); } }, wddx: { regex: RegExp('^' + reYear4 + '-' + reMonth + '-' + reDay + 'T' + reHour24 + ':' + reMinute + ':' + reSecond), name: 'wddx', callback: function callback(match, year, month, day, hour, minute, second) { return this.ymd(+year, month - 1, +day) && this.time(+hour, +minute, +second, 0); } }, exif: { regex: RegExp('^' + reYear4 + ':' + reMonthlz + ':' + reDaylz + ' ' + reHour24lz + ':' + reMinutelz + ':' + reSecondlz, 'i'), name: 'exif', callback: function callback(match, year, month, day, hour, minute, second) { return this.ymd(+year, month - 1, +day) && this.time(+hour, +minute, +second, 0); } }, xmlRpc: { regex: RegExp('^' + reYear4 + reMonthlz + reDaylz + 'T' + reHour24 + ':' + reMinutelz + ':' + reSecondlz), name: 'xmlrpc', callback: function callback(match, year, month, day, hour, minute, second) { return this.ymd(+year, month - 1, +day) && this.time(+hour, +minute, +second, 0); } }, xmlRpcNoColon: { regex: RegExp('^' + reYear4 + reMonthlz + reDaylz + '[Tt]' + reHour24 + reMinutelz + reSecondlz), name: 'xmlrpcnocolon', callback: function callback(match, year, month, day, hour, minute, second) { return this.ymd(+year, month - 1, +day) && this.time(+hour, +minute, +second, 0); } }, clf: { regex: RegExp('^' + reDay + '/(' + reMonthAbbr + ')/' + reYear4 + ':' + reHour24lz + ':' + reMinutelz + ':' + reSecondlz + reSpace + reTzCorrection, 'i'), name: 'clf', callback: function callback(match, day, month, year, hour, minute, second, tzCorrection) { return this.ymd(+year, lookupMonth(month), +day) && this.time(+hour, +minute, +second, 0) && this.zone(processTzCorrection(tzCorrection)); } }, iso8601long: { regex: RegExp('^t?' + reHour24 + '[:.]' + reMinute + '[:.]' + reSecond + reFrac, 'i'), name: 'iso8601long', callback: function callback(match, hour, minute, second, frac) { return this.time(+hour, +minute, +second, +frac.substr(0, 3)); } }, dateTextual: { regex: RegExp('^' + reMonthText + '[ .\\t-]*' + reDay + '[,.stndrh\\t ]+' + reYear, 'i'), name: 'datetextual', callback: function callback(match, month, day, year) { return this.ymd(processYear(year), lookupMonth(month), +day); } }, pointedDate4: { regex: RegExp('^' + reDay + '[.\\t-]' + reMonth + '[.-]' + reYear4), name: 'pointeddate4', callback: function callback(match, day, month, year) { return this.ymd(+year, month - 1, +day); } }, pointedDate2: { regex: RegExp('^' + reDay + '[.\\t]' + reMonth + '\\.' + reYear2), name: 'pointeddate2', callback: function callback(match, day, month, year) { return this.ymd(processYear(year), month - 1, +day); } }, timeLong24: { regex: RegExp('^t?' + reHour24 + '[:.]' + reMinute + '[:.]' + reSecond), name: 'timelong24', callback: function callback(match, hour, minute, second) { return this.time(+hour, +minute, +second, 0); } }, dateNoColon: { regex: RegExp('^' + reYear4 + reMonthlz + reDaylz), name: 'datenocolon', callback: function callback(match, year, month, day) { return this.ymd(+year, month - 1, +day); } }, pgydotd: { regex: RegExp('^' + reYear4 + '\\.?' + reDayOfYear), name: 'pgydotd', callback: function callback(match, year, day) { return this.ymd(+year, 0, +day); } }, timeShort24: { regex: RegExp('^t?' + reHour24 + '[:.]' + reMinute, 'i'), name: 'timeshort24', callback: function callback(match, hour, minute) { return this.time(+hour, +minute, 0, 0); } }, iso8601noColon: { regex: RegExp('^t?' + reHour24lz + reMinutelz + reSecondlz, 'i'), name: 'iso8601nocolon', callback: function callback(match, hour, minute, second) { return this.time(+hour, +minute, +second, 0); } }, iso8601dateSlash: { // eventhough the trailing slash is optional in PHP // here it's mandatory and inputs without the slash // are handled by dateslash regex: RegExp('^' + reYear4 + '/' + reMonthlz + '/' + reDaylz + '/'), name: 'iso8601dateslash', callback: function callback(match, year, month, day) { return this.ymd(+year, month - 1, +day); } }, dateSlash: { regex: RegExp('^' + reYear4 + '/' + reMonth + '/' + reDay), name: 'dateslash', callback: function callback(match, year, month, day) { return this.ymd(+year, month - 1, +day); } }, american: { regex: RegExp('^' + reMonth + '/' + reDay + '/' + reYear), name: 'american', callback: function callback(match, month, day, year) { return this.ymd(processYear(year), month - 1, +day); } }, americanShort: { regex: RegExp('^' + reMonth + '/' + reDay), name: 'americanshort', callback: function callback(match, month, day) { return this.ymd(this.y, month - 1, +day); } }, gnuDateShortOrIso8601date2: { // iso8601date2 is complete subset of gnudateshort regex: RegExp('^' + reYear + '-' + reMonth + '-' + reDay), name: 'gnudateshort | iso8601date2', callback: function callback(match, year, month, day) { return this.ymd(processYear(year), month - 1, +day); } }, iso8601date4: { regex: RegExp('^' + reYear4withSign + '-' + reMonthlz + '-' + reDaylz), name: 'iso8601date4', callback: function callback(match, year, month, day) { return this.ymd(+year, month - 1, +day); } }, gnuNoColon: { regex: RegExp('^t?' + reHour24lz + reMinutelz, 'i'), name: 'gnunocolon', callback: function callback(match, hour, minute) { // this rule is a special case // if time was already set once by any preceding rule, it sets the captured value as year switch (this.times) { case 0: return this.time(+hour, +minute, 0, this.f); case 1: this.y = hour * 100 + +minute; this.times++; return true; default: return false; } } }, gnuDateShorter: { regex: RegExp('^' + reYear4 + '-' + reMonth), name: 'gnudateshorter', callback: function callback(match, year, month) { return this.ymd(+year, month - 1, 1); } }, pgTextReverse: { // note: allowed years are from 32-9999 // years below 32 should be treated as days in datefull regex: RegExp('^' + '(\\d{3,4}|[4-9]\\d|3[2-9])-(' + reMonthAbbr + ')-' + reDaylz, 'i'), name: 'pgtextreverse', callback: function callback(match, year, month, day) { return this.ymd(processYear(year), lookupMonth(month), +day); } }, dateFull: { regex: RegExp('^' + reDay + '[ \\t.-]*' + reMonthText + '[ \\t.-]*' + reYear, 'i'), name: 'datefull', callback: function callback(match, day, month, year) { return this.ymd(processYear(year), lookupMonth(month), +day); } }, dateNoDay: { regex: RegExp('^' + reMonthText + '[ .\\t-]*' + reYear4, 'i'), name: 'datenoday', callback: function callback(match, month, year) { return this.ymd(+year, lookupMonth(month), 1); } }, dateNoDayRev: { regex: RegExp('^' + reYear4 + '[ .\\t-]*' + reMonthText, 'i'), name: 'datenodayrev', callback: function callback(match, year, month) { return this.ymd(+year, lookupMonth(month), 1); } }, pgTextShort: { regex: RegExp('^(' + reMonthAbbr + ')-' + reDaylz + '-' + reYear, 'i'), name: 'pgtextshort', callback: function callback(match, month, day, year) { return this.ymd(processYear(year), lookupMonth(month), +day); } }, dateNoYear: { regex: RegExp('^' + reDateNoYear, 'i'), name: 'datenoyear', callback: function callback(match, month, day) { return this.ymd(this.y, lookupMonth(month), +day); } }, dateNoYearRev: { regex: RegExp('^' + reDay + '[ .\\t-]*' + reMonthText, 'i'), name: 'datenoyearrev', callback: function callback(match, day, month) { return this.ymd(this.y, lookupMonth(month), +day); } }, isoWeekDay: { regex: RegExp('^' + reYear4 + '-?W' + reWeekOfYear + '(?:-?([0-7]))?'), name: 'isoweekday | isoweek', callback: function callback(match, year, week, day) { day = day ? +day : 1; if (!this.ymd(+year, 0, 1)) { return false; } // get day of week for Jan 1st var dayOfWeek = new Date(this.y, this.m, this.d).getDay(); // and use the day to figure out the offset for day 1 of week 1 dayOfWeek = 0 - (dayOfWeek > 4 ? dayOfWeek - 7 : dayOfWeek); this.rd += dayOfWeek + (week - 1) * 7 + day; } }, relativeText: { regex: RegExp('^(' + reReltextnumber + '|' + reReltexttext + ')' + reSpace + '(' + reReltextunit + ')', 'i'), name: 'relativetext', callback: function callback(match, relValue, relUnit) { // todo: implement handling of 'this time-unit' // eslint-disable-next-line no-unused-vars var _lookupRelative = lookupRelative(relValue), amount = _lookupRelative.amount, behavior = _lookupRelative.behavior; switch (relUnit.toLowerCase()) { case 'sec': case 'secs': case 'second': case 'seconds': this.rs += amount; break; case 'min': case 'mins': case 'minute': case 'minutes': this.ri += amount; break; case 'hour': case 'hours': this.rh += amount; break; case 'day': case 'days': this.rd += amount; break; case 'fortnight': case 'fortnights': case 'forthnight': case 'forthnights': this.rd += amount * 14; break; case 'week': case 'weeks': this.rd += amount * 7; break; case 'month': case 'months': this.rm += amount; break; case 'year': case 'years': this.ry += amount; break; case 'mon': case 'monday': case 'tue': case 'tuesday': case 'wed': case 'wednesday': case 'thu': case 'thursday': case 'fri': case 'friday': case 'sat': case 'saturday': case 'sun': case 'sunday': this.resetTime(); this.weekday = lookupWeekday(relUnit, 7); this.weekdayBehavior = 1; this.rd += (amount > 0 ? amount - 1 : amount) * 7; break; case 'weekday': case 'weekdays': // todo break; } } }, relative: { regex: RegExp('^([+-]*)[ \\t]*(\\d+)' + reSpaceOpt + '(' + reReltextunit + '|week)', 'i'), name: 'relative', callback: function callback(match, signs, relValue, relUnit) { var minuses = signs.replace(/[^-]/g, '').length; var amount = +relValue * Math.pow(-1, minuses); switch (relUnit.toLowerCase()) { case 'sec': case 'secs': case 'second': case 'seconds': this.rs += amount; break; case 'min': case 'mins': case 'minute': case 'minutes': this.ri += amount; break; case 'hour': case 'hours': this.rh += amount; break; case 'day': case 'days': this.rd += amount; break; case 'fortnight': case 'fortnights': case 'forthnight': case 'forthnights': this.rd += amount * 14; break; case 'week': case 'weeks': this.rd += amount * 7; break; case 'month': case 'months': this.rm += amount; break; case 'year': case 'years': this.ry += amount; break; case 'mon': case 'monday': case 'tue': case 'tuesday': case 'wed': case 'wednesday': case 'thu': case 'thursday': case 'fri': case 'friday': case 'sat': case 'saturday': case 'sun': case 'sunday': this.resetTime(); this.weekday = lookupWeekday(relUnit, 7); this.weekdayBehavior = 1; this.rd += (amount > 0 ? amount - 1 : amount) * 7; break; case 'weekday': case 'weekdays': // todo break; } } }, dayText: { regex: RegExp('^(' + reDaytext + ')', 'i'), name: 'daytext', callback: function callback(match, dayText) { this.resetTime(); this.weekday = lookupWeekday(dayText, 0); if (this.weekdayBehavior !== 2) { this.weekdayBehavior = 1; } } }, relativeTextWeek: { regex: RegExp('^(' + reReltexttext + ')' + reSpace + 'week', 'i'), name: 'relativetextweek', callback: function callback(match, relText) { this.weekdayBehavior = 2; switch (relText.toLowerCase()) { case 'this': this.rd += 0; break; case 'next': this.rd += 7; break; case 'last': case 'previous': this.rd -= 7; break; } if (isNaN(this.weekday)) { this.weekday = 1; } } }, monthFullOrMonthAbbr: { regex: RegExp('^(' + reMonthFull + '|' + reMonthAbbr + ')', 'i'), name: 'monthfull | monthabbr', callback: function callback(match, month) { return this.ymd(this.y, lookupMonth(month), this.d); } }, tzCorrection: { regex: RegExp('^' + reTzCorrection, 'i'), name: 'tzcorrection', callback: function callback(tzCorrection) { return this.zone(processTzCorrection(tzCorrection)); } }, tzAbbr: { regex: RegExp('^' + reTzAbbr), name: 'tzabbr', callback: function callback(match, abbr) { var offset = tzAbbrOffsets[abbr.toLowerCase()]; if (isNaN(offset)) { return false; } return this.zone(offset); } }, ago: { regex: /^ago/i, name: 'ago', callback: function callback() { this.ry = -this.ry; this.rm = -this.rm; this.rd = -this.rd; this.rh = -this.rh; this.ri = -this.ri; this.rs = -this.rs; this.rf = -this.rf; } }, year4: { regex: RegExp('^' + reYear4), name: 'year4', callback: function callback(match, year) { this.y = +year; return true; } }, whitespace: { regex: /^[ .,\t]+/, name: 'whitespace' // do nothing }, dateShortWithTimeLong: { regex: RegExp('^' + reDateNoYear + 't?' + reHour24 + '[:.]' + reMinute + '[:.]' + reSecond, 'i'), name: 'dateshortwithtimelong', callback: function callback(match, month, day, hour, minute, second) { return this.ymd(this.y, lookupMonth(month), +day) && this.time(+hour, +minute, +second, 0); } }, dateShortWithTimeLong12: { regex: RegExp('^' + reDateNoYear + reHour12 + '[:.]' + reMinute + '[:.]' + reSecondlz + reSpaceOpt + reMeridian, 'i'), name: 'dateshortwithtimelong12', callback: function callback(match, month, day, hour, minute, second, meridian) { return this.ymd(this.y, lookupMonth(month), +day) && this.time(processMeridian(+hour, meridian), +minute, +second, 0); } }, dateShortWithTimeShort: { regex: RegExp('^' + reDateNoYear + 't?' + reHour24 + '[:.]' + reMinute, 'i'), name: 'dateshortwithtimeshort', callback: function callback(match, month, day, hour, minute) { return this.ymd(this.y, lookupMonth(month), +day) && this.time(+hour, +minute, 0, 0); } }, dateShortWithTimeShort12: { regex: RegExp('^' + reDateNoYear + reHour12 + '[:.]' + reMinutelz + reSpaceOpt + reMeridian, 'i'), name: 'dateshortwithtimeshort12', callback: function callback(match, month, day, hour, minute, meridian) { return this.ymd(this.y, lookupMonth(month), +day) && this.time(processMeridian(+hour, meridian), +minute, 0, 0); } } }; var resultProto = { // date y: NaN, m: NaN, d: NaN, // time h: NaN, i: NaN, s: NaN, f: NaN, // relative shifts ry: 0, rm: 0, rd: 0, rh: 0, ri: 0, rs: 0, rf: 0, // weekday related shifts weekday: NaN, weekdayBehavior: 0, // first or last day of month // 0 none, 1 first, -1 last firstOrLastDayOfMonth: 0, // timezone correction in minutes z: NaN, // counters dates: 0, times: 0, zones: 0, // helper functions ymd: function ymd(y, m, d) { if (this.dates > 0) { return false; } this.dates++; this.y = y; this.m = m; this.d = d; return true; }, time: function time(h, i, s, f) { if (this.times > 0) { return false; } this.times++; this.h = h; this.i = i; this.s = s; this.f = f; return true; }, resetTime: function resetTime() { this.h = 0; this.i = 0; this.s = 0; this.f = 0; this.times = 0; return true; }, zone: function zone(minutes) { if (this.zones <= 1) { this.zones++; this.z = minutes; return true; } return false; }, toDate: function toDate(relativeTo) { if (this.dates && !this.times) { this.h = this.i = this.s = this.f = 0; } // fill holes if (isNaN(this.y)) { this.y = relativeTo.getFullYear(); } if (isNaN(this.m)) { this.m = relativeTo.getMonth(); } if (isNaN(this.d)) { this.d = relativeTo.getDate(); } if (isNaN(this.h)) { this.h = relativeTo.getHours(); } if (isNaN(this.i)) { this.i = relativeTo.getMinutes(); } if (isNaN(this.s)) { this.s = relativeTo.getSeconds(); } if (isNaN(this.f)) { this.f = relativeTo.getMilliseconds(); } // adjust special early switch (this.firstOrLastDayOfMonth) { case 1: this.d = 1; break; case -1: this.d = 0; this.m += 1; break; } if (!isNaN(this.weekday)) { var date = new Date(relativeTo.getTime()); date.setFullYear(this.y, this.m, this.d); date.setHours(this.h, this.i, this.s, this.f); var dow = date.getDay(); if (this.weekdayBehavior === 2) { // To make "this week" work, where the current day of week is a "sunday" if (dow === 0 && this.weekday !== 0) { this.weekday = -6; } // To make "sunday this week" work, where the current day of week is not a "sunday" if (this.weekday === 0 && dow !== 0) { this.weekday = 7; } this.d -= dow; this.d += this.weekday; } else { var diff = this.weekday - dow; // some PHP magic if (this.rd < 0 && diff < 0 || this.rd >= 0 && diff <= -this.weekdayBehavior) { diff += 7; } if (this.weekday >= 0) { this.d += diff; } else { this.d -= 7 - (Math.abs(this.weekday) - dow); } this.weekday = NaN; } } // adjust relative this.y += this.ry; this.m += this.rm; this.d += this.rd; this.h += this.rh; this.i += this.ri; this.s += this.rs; this.f += this.rf; this.ry = this.rm = this.rd = 0; this.rh = this.ri = this.rs = this.rf = 0; var result = new Date(relativeTo.getTime()); // since Date constructor treats years <= 99 as 1900+ // it can't be used, thus this weird way result.setFullYear(this.y, this.m, this.d); result.setHours(this.h, this.i, this.s, this.f); // note: this is done twice in PHP // early when processing special relatives // and late // todo: check if the logic can be reduced // to just one time action switch (this.firstOrLastDayOfMonth) { case 1: result.setDate(1); break; case -1: result.setMonth(result.getMonth() + 1, 0); break; } // adjust timezone if (!isNaN(this.z) && result.getTimezoneOffset() !== this.z) { result.setUTCFullYear(result.getFullYear(), result.getMonth(), result.getDate()); result.setUTCHours(result.getHours(), result.getMinutes(), result.getSeconds() - this.z, result.getMilliseconds()); } return result; } }; module.exports = function strtotime(str, now) { // discuss at: https://locutus.io/php/strtotime/ // original by: Caio Ariede (https://caioariede.com) // improved by: Kevin van Zonneveld (https://kvz.io) // improved by: Caio Ariede (https://caioariede.com) // improved by: A. Matías Quezada (https://amatiasq.com) // improved by: preuter // improved by: Brett Zamir (https://brett-zamir.me) // improved by: Mirko Faber // input by: David // bugfixed by: Wagner B. Soares // bugfixed by: Artur Tchernychev // bugfixed by: Stephan Bösch-Plepelits (https://github.com/plepe) // reimplemented by: Rafał Kukawski // note 1: Examples all have a fixed timestamp to prevent // note 1: tests to fail because of variable time(zones) // example 1: strtotime('+1 day', 1129633200) // returns 1: 1129719600 // example 2: strtotime('+1 week 2 days 4 hours 2 seconds', 1129633200) // returns 2: 1130425202 // example 3: strtotime('last month', 1129633200) // returns 3: 1127041200 // example 4: strtotime('2009-05-04 08:30:00+00') // returns 4: 1241425800 // example 5: strtotime('2009-05-04 08:30:00+02:00') // returns 5: 1241418600 // example 6: strtotime('2009-05-04 08:30:00 YWT') // returns 6: 1241454600 // example 7: strtotime('10-JUL-17') // returns 7: 1499644800 if (now == null) { now = Math.floor(Date.now() / 1000); } // the rule order is important // if multiple rules match, the longest match wins // if multiple rules match the same string, the first match wins var rules = [formats.yesterday, formats.now, formats.noon, formats.midnightOrToday, formats.tomorrow, formats.timestamp, formats.firstOrLastDay, formats.backOrFrontOf, // formats.weekdayOf, // not yet implemented formats.timeTiny12, formats.timeShort12, formats.timeLong12, formats.mssqltime, formats.oracledate, formats.timeShort24, formats.timeLong24, formats.iso8601long, formats.gnuNoColon, formats.iso8601noColon, formats.americanShort, formats.american, formats.iso8601date4, formats.iso8601dateSlash, formats.dateSlash, formats.gnuDateShortOrIso8601date2, formats.gnuDateShorter, formats.dateFull, formats.pointedDate4, formats.pointedDate2, formats.dateNoDay, formats.dateNoDayRev, formats.dateTextual, formats.dateNoYear, formats.dateNoYearRev, formats.dateNoColon, formats.xmlRpc, formats.xmlRpcNoColon, formats.soap, formats.wddx, formats.exif, formats.pgydotd, formats.isoWeekDay, formats.pgTextShort, formats.pgTextReverse, formats.clf, formats.year4, formats.ago, formats.dayText, formats.relativeTextWeek, formats.relativeText, formats.monthFullOrMonthAbbr, formats.tzCorrection, formats.tzAbbr, formats.dateShortWithTimeShort12, formats.dateShortWithTimeLong12, formats.dateShortWithTimeShort, formats.dateShortWithTimeLong, formats.relative, formats.whitespace]; var result = Object.create(resultProto); while (str.length) { var longestMatch = null; var finalRule = null; for (var i = 0, l = rules.length; i < l; i++) { var format = rules[i]; var match = str.match(format.regex); if (match) { if (!longestMatch || match[0].length > longestMatch[0].length) { longestMatch = match; finalRule = format; } } } if (!finalRule || finalRule.callback && finalRule.callback.apply(result, longestMatch) === false) { return false; } str = str.substr(longestMatch[0].length); finalRule = null; longestMatch = null; } return Math.floor(result.toDate(new Date(now * 1000)) / 1000); }; //# sourceMappingURL=strtotime.js.map /***/ }), /***/ "./node_modules/locutus/php/math/max.js": /*!**********************************************!*\ !*** ./node_modules/locutus/php/math/max.js ***! \**********************************************/ /***/ ((module) => { "use strict"; var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; module.exports = function max() { // discuss at: https://locutus.io/php/max/ // original by: Onno Marsman (https://twitter.com/onnomarsman) // revised by: Onno Marsman (https://twitter.com/onnomarsman) // improved by: Jack // note 1: Long code cause we're aiming for maximum PHP compatibility // example 1: max(1, 3, 5, 6, 7) // returns 1: 7 // example 2: max([2, 4, 5]) // returns 2: 5 // example 3: max(0, 'hello') // returns 3: 0 // example 4: max('hello', 0) // returns 4: 'hello' // example 5: max(-1, 'hello') // returns 5: 'hello' // example 6: max([2, 4, 8], [2, 5, 7]) // returns 6: [2, 5, 7] var ar = void 0; var retVal = void 0; var i = 0; var n = 0; var argv = arguments; var argc = argv.length; var _obj2Array = function _obj2Array(obj) { if (Object.prototype.toString.call(obj) === '[object Array]') { return obj; } else { var _ar = []; for (var _i in obj) { if (obj.hasOwnProperty(_i)) { _ar.push(obj[_i]); } } return _ar; } }; var _compare = function _compare(current, next) { var i = 0; var n = 0; var tmp = 0; var nl = 0; var cl = 0; if (current === next) { return 0; } else if ((typeof current === 'undefined' ? 'undefined' : _typeof(current)) === 'object') { if ((typeof next === 'undefined' ? 'undefined' : _typeof(next)) === 'object') { current = _obj2Array(current); next = _obj2Array(next); cl = current.length; nl = next.length; if (nl > cl) { return 1; } else if (nl < cl) { return -1; } for (i = 0, n = cl; i < n; ++i) { tmp = _compare(current[i], next[i]); if (tmp === 1) { return 1; } else if (tmp === -1) { return -1; } } return 0; } return -1; } else if ((typeof next === 'undefined' ? 'undefined' : _typeof(next)) === 'object') { return 1; } else if (isNaN(next) && !isNaN(current)) { if (current === 0) { return 0; } return current < 0 ? 1 : -1; } else if (isNaN(current) && !isNaN(next)) { if (next === 0) { return 0; } return next > 0 ? 1 : -1; } if (next === current) { return 0; } return next > current ? 1 : -1; }; if (argc === 0) { throw new Error('At least one value should be passed to max()'); } else if (argc === 1) { if (_typeof(argv[0]) === 'object') { ar = _obj2Array(argv[0]); } else { throw new Error('Wrong parameter count for max()'); } if (ar.length === 0) { throw new Error('Array must contain at least one element for max()'); } } else { ar = argv; } retVal = ar[0]; for (i = 1, n = ar.length; i < n; ++i) { if (_compare(retVal, ar[i]) === 1) { retVal = ar[i]; } } return retVal; }; //# sourceMappingURL=max.js.map /***/ }), /***/ "./node_modules/locutus/php/math/min.js": /*!**********************************************!*\ !*** ./node_modules/locutus/php/math/min.js ***! \**********************************************/ /***/ ((module) => { "use strict"; var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; module.exports = function min() { // discuss at: https://locutus.io/php/min/ // original by: Onno Marsman (https://twitter.com/onnomarsman) // revised by: Onno Marsman (https://twitter.com/onnomarsman) // improved by: Jack // note 1: Long code cause we're aiming for maximum PHP compatibility // example 1: min(1, 3, 5, 6, 7) // returns 1: 1 // example 2: min([2, 4, 5]) // returns 2: 2 // example 3: min(0, 'hello') // returns 3: 0 // example 4: min('hello', 0) // returns 4: 'hello' // example 5: min(-1, 'hello') // returns 5: -1 // example 6: min([2, 4, 8], [2, 5, 7]) // returns 6: [2, 4, 8] var ar = void 0; var retVal = void 0; var i = 0; var n = 0; var argv = arguments; var argc = argv.length; var _obj2Array = function _obj2Array(obj) { if (Object.prototype.toString.call(obj) === '[object Array]') { return obj; } var ar = []; for (var _i in obj) { if (obj.hasOwnProperty(_i)) { ar.push(obj[_i]); } } return ar; }; var _compare = function _compare(current, next) { var i = 0; var n = 0; var tmp = 0; var nl = 0; var cl = 0; if (current === next) { return 0; } else if ((typeof current === 'undefined' ? 'undefined' : _typeof(current)) === 'object') { if ((typeof next === 'undefined' ? 'undefined' : _typeof(next)) === 'object') { current = _obj2Array(current); next = _obj2Array(next); cl = current.length; nl = next.length; if (nl > cl) { return 1; } else if (nl < cl) { return -1; } for (i = 0, n = cl; i < n; ++i) { tmp = _compare(current[i], next[i]); if (tmp === 1) { return 1; } else if (tmp === -1) { return -1; } } return 0; } return -1; } else if ((typeof next === 'undefined' ? 'undefined' : _typeof(next)) === 'object') { return 1; } else if (isNaN(next) && !isNaN(current)) { if (current === 0) { return 0; } return current < 0 ? 1 : -1; } else if (isNaN(current) && !isNaN(next)) { if (next === 0) { return 0; } return next > 0 ? 1 : -1; } if (next === current) { return 0; } return next > current ? 1 : -1; }; if (argc === 0) { throw new Error('At least one value should be passed to min()'); } else if (argc === 1) { if (_typeof(argv[0]) === 'object') { ar = _obj2Array(argv[0]); } else { throw new Error('Wrong parameter count for min()'); } if (ar.length === 0) { throw new Error('Array must contain at least one element for min()'); } } else { ar = argv; } retVal = ar[0]; for (i = 1, n = ar.length; i < n; ++i) { if (_compare(retVal, ar[i]) === -1) { retVal = ar[i]; } } return retVal; }; //# sourceMappingURL=min.js.map /***/ }), /***/ "./node_modules/locutus/php/math/round.js": /*!************************************************!*\ !*** ./node_modules/locutus/php/math/round.js ***! \************************************************/ /***/ ((module, __unused_webpack_exports, __webpack_require__) => { "use strict"; function roundToInt(value, mode) { var tmp = Math.floor(Math.abs(value) + 0.5); if (mode === 'PHP_ROUND_HALF_DOWN' && value === tmp - 0.5 || mode === 'PHP_ROUND_HALF_EVEN' && value === 0.5 + 2 * Math.floor(tmp / 2) || mode === 'PHP_ROUND_HALF_ODD' && value === 0.5 + 2 * Math.floor(tmp / 2) - 1) { tmp -= 1; } return value < 0 ? -tmp : tmp; } module.exports = function round(value) { var precision = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0; var mode = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 'PHP_ROUND_HALF_UP'; // discuss at: https://locutus.io/php/round/ // original by: Philip Peterson // revised by: Onno Marsman (https://twitter.com/onnomarsman) // revised by: T.Wild // revised by: Rafał Kukawski (https://blog.kukawski.pl) // input by: Greenseed // input by: meo // input by: William // input by: Josep Sanz (https://www.ws3.es/) // bugfixed by: Brett Zamir (https://brett-zamir.me) // revised by: Rafał Kukawski // example 1: round(1241757, -3) // returns 1: 1242000 // example 2: round(3.6) // returns 2: 4 // example 3: round(2.835, 2) // returns 3: 2.84 // example 4: round(1.1749999999999, 2) // returns 4: 1.17 // example 5: round(58551.799999999996, 2) // returns 5: 58551.8 // example 6: round(4096.485, 2) // returns 6: 4096.49 var floatCast = __webpack_require__(/*! ../_helpers/_php_cast_float */ "./node_modules/locutus/php/_helpers/_php_cast_float.js"); var intCast = __webpack_require__(/*! ../_helpers/_php_cast_int */ "./node_modules/locutus/php/_helpers/_php_cast_int.js"); var p = void 0; // the code is heavily based on the native PHP implementation // https://github.com/php/php-src/blob/PHP-7.4/ext/standard/math.c#L355 value = floatCast(value); precision = intCast(precision); p = Math.pow(10, precision); if (isNaN(value) || !isFinite(value)) { return value; } // if value already integer and positive precision // then nothing to do, return early if (Math.trunc(value) === value && precision >= 0) { return value; } // PHP does a pre-rounding before rounding to desired precision // https://wiki.php.net/rfc/rounding#pre-rounding_to_the_value_s_precision_if_possible var preRoundPrecision = 14 - Math.floor(Math.log10(Math.abs(value))); if (preRoundPrecision > precision && preRoundPrecision - 15 < precision) { value = roundToInt(value * Math.pow(10, preRoundPrecision), mode); value /= Math.pow(10, Math.abs(precision - preRoundPrecision)); } else { value *= p; } value = roundToInt(value, mode); return value / p; }; //# sourceMappingURL=round.js.map /***/ }), /***/ "./node_modules/locutus/php/strings/sprintf.js": /*!*****************************************************!*\ !*** ./node_modules/locutus/php/strings/sprintf.js ***! \*****************************************************/ /***/ ((module) => { "use strict"; module.exports = function sprintf() { // discuss at: https://locutus.io/php/sprintf/ // original by: Ash Searle (https://hexmen.com/blog/) // improved by: Michael White (https://getsprink.com) // improved by: Jack // improved by: Kevin van Zonneveld (https://kvz.io) // improved by: Kevin van Zonneveld (https://kvz.io) // improved by: Kevin van Zonneveld (https://kvz.io) // improved by: Dj // improved by: Allidylls // input by: Paulo Freitas // input by: Brett Zamir (https://brett-zamir.me) // improved by: Rafał Kukawski (https://kukawski.pl) // example 1: sprintf("%01.2f", 123.1) // returns 1: '123.10' // example 2: sprintf("[%10s]", 'monkey') // returns 2: '[ monkey]' // example 3: sprintf("[%'#10s]", 'monkey') // returns 3: '[####monkey]' // example 4: sprintf("%d", 123456789012345) // returns 4: '123456789012345' // example 5: sprintf('%-03s', 'E') // returns 5: 'E00' // example 6: sprintf('%+010d', 9) // returns 6: '+000000009' // example 7: sprintf('%+0\'@10d', 9) // returns 7: '@@@@@@@@+9' // example 8: sprintf('%.f', 3.14) // returns 8: '3.140000' // example 9: sprintf('%% %2$d', 1, 2) // returns 9: '% 2' var regex = /%%|%(?:(\d+)\$)?((?:[-+#0 ]|'[\s\S])*)(\d+)?(?:\.(\d*))?([\s\S])/g; var args = arguments; var i = 0; var format = args[i++]; var _pad = function _pad(str, len, chr, leftJustify) { if (!chr) { chr = ' '; } var padding = str.length >= len ? '' : new Array(1 + len - str.length >>> 0).join(chr); return leftJustify ? str + padding : padding + str; }; var justify = function justify(value, prefix, leftJustify, minWidth, padChar) { var diff = minWidth - value.length; if (diff > 0) { // when padding with zeros // on the left side // keep sign (+ or -) in front if (!leftJustify && padChar === '0') { value = [value.slice(0, prefix.length), _pad('', diff, '0', true), value.slice(prefix.length)].join(''); } else { value = _pad(value, minWidth, padChar, leftJustify); } } return value; }; var _formatBaseX = function _formatBaseX(value, base, leftJustify, minWidth, precision, padChar) { // Note: casts negative numbers to positive ones var number = value >>> 0; value = _pad(number.toString(base), precision || 0, '0', false); return justify(value, '', leftJustify, minWidth, padChar); }; // _formatString() var _formatString = function _formatString(value, leftJustify, minWidth, precision, customPadChar) { if (precision !== null && precision !== undefined) { value = value.slice(0, precision); } return justify(value, '', leftJustify, minWidth, customPadChar); }; // doFormat() var doFormat = function doFormat(substring, argIndex, modifiers, minWidth, precision, specifier) { var number = void 0, prefix = void 0, method = void 0, textTransform = void 0, value = void 0; if (substring === '%%') { return '%'; } // parse modifiers var padChar = ' '; // pad with spaces by default var leftJustify = false; var positiveNumberPrefix = ''; var j = void 0, l = void 0; for (j = 0, l = modifiers.length; j < l; j++) { switch (modifiers.charAt(j)) { case ' ': case '0': padChar = modifiers.charAt(j); break; case '+': positiveNumberPrefix = '+'; break; case '-': leftJustify = true; break; case "'": if (j + 1 < l) { padChar = modifiers.charAt(j + 1); j++; } break; } } if (!minWidth) { minWidth = 0; } else { minWidth = +minWidth; } if (!isFinite(minWidth)) { throw new Error('Width must be finite'); } if (!precision) { precision = specifier === 'd' ? 0 : 'fFeE'.indexOf(specifier) > -1 ? 6 : undefined; } else { precision = +precision; } if (argIndex && +argIndex === 0) { throw new Error('Argument number must be greater than zero'); } if (argIndex && +argIndex >= args.length) { throw new Error('Too few arguments'); } value = argIndex ? args[+argIndex] : args[i++]; switch (specifier) { case '%': return '%'; case 's': return _formatString(value + '', leftJustify, minWidth, precision, padChar); case 'c': return _formatString(String.fromCharCode(+value), leftJustify, minWidth, precision, padChar); case 'b': return _formatBaseX(value, 2, leftJustify, minWidth, precision, padChar); case 'o': return _formatBaseX(value, 8, leftJustify, minWidth, precision, padChar); case 'x': return _formatBaseX(value, 16, leftJustify, minWidth, precision, padChar); case 'X': return _formatBaseX(value, 16, leftJustify, minWidth, precision, padChar).toUpperCase(); case 'u': return _formatBaseX(value, 10, leftJustify, minWidth, precision, padChar); case 'i': case 'd': number = +value || 0; // Plain Math.round doesn't just truncate number = Math.round(number - number % 1); prefix = number < 0 ? '-' : positiveNumberPrefix; value = prefix + _pad(String(Math.abs(number)), precision, '0', false); if (leftJustify && padChar === '0') { // can't right-pad 0s on integers padChar = ' '; } return justify(value, prefix, leftJustify, minWidth, padChar); case 'e': case 'E': case 'f': // @todo: Should handle locales (as per setlocale) case 'F': case 'g': case 'G': number = +value; prefix = number < 0 ? '-' : positiveNumberPrefix; method = ['toExponential', 'toFixed', 'toPrecision']['efg'.indexOf(specifier.toLowerCase())]; textTransform = ['toString', 'toUpperCase']['eEfFgG'.indexOf(specifier) % 2]; value = prefix + Math.abs(number)[method](precision); return justify(value, prefix, leftJustify, minWidth, padChar)[textTransform](); default: // unknown specifier, consume that char and return empty return ''; } }; try { return format.replace(regex, doFormat); } catch (err) { return false; } }; //# sourceMappingURL=sprintf.js.map /***/ }), /***/ "./node_modules/locutus/php/strings/strip_tags.js": /*!********************************************************!*\ !*** ./node_modules/locutus/php/strings/strip_tags.js ***! \********************************************************/ /***/ ((module, __unused_webpack_exports, __webpack_require__) => { "use strict"; module.exports = function strip_tags(input, allowed) { // discuss at: https://locutus.io/php/strip_tags/ // original by: Kevin van Zonneveld (https://kvz.io) // improved by: Luke Godfrey // improved by: Kevin van Zonneveld (https://kvz.io) // input by: Pul // input by: Alex // input by: Marc Palau // input by: Brett Zamir (https://brett-zamir.me) // input by: Bobby Drake // input by: Evertjan Garretsen // bugfixed by: Kevin van Zonneveld (https://kvz.io) // bugfixed by: Onno Marsman (https://twitter.com/onnomarsman) // bugfixed by: Kevin van Zonneveld (https://kvz.io) // bugfixed by: Kevin van Zonneveld (https://kvz.io) // bugfixed by: Eric Nagel // bugfixed by: Kevin van Zonneveld (https://kvz.io) // bugfixed by: Tomasz Wesolowski // bugfixed by: Tymon Sturgeon (https://scryptonite.com) // bugfixed by: Tim de Koning (https://www.kingsquare.nl) // revised by: Rafał Kukawski (https://blog.kukawski.pl) // example 1: strip_tags('

Kevin


van Zonneveld', '') // returns 1: 'Kevin van Zonneveld' // example 2: strip_tags('

Kevin van Zonneveld

', '

') // returns 2: '

Kevin van Zonneveld

' // example 3: strip_tags("Kevin van Zonneveld", "") // returns 3: "Kevin van Zonneveld" // example 4: strip_tags('1 < 5 5 > 1') // returns 4: '1 < 5 5 > 1' // example 5: strip_tags('1
1') // returns 5: '1 1' // example 6: strip_tags('1
1', '
') // returns 6: '1
1' // example 7: strip_tags('1
1', '

') // returns 7: '1
1' // example 8: strip_tags('hello <script>world</script>') // returns 8: 'hello world' // example 9: strip_tags(4) // returns 9: '4' var _phpCastString = __webpack_require__(/*! ../_helpers/_phpCastString */ "./node_modules/locutus/php/_helpers/_phpCastString.js"); // making sure the allowed arg is a string containing only tags in lowercase () allowed = (((allowed || '') + '').toLowerCase().match(/<[a-z][a-z0-9]*>/g) || []).join(''); var tags = /<\/?([a-z0-9]*)\b[^>]*>?/gi; var commentsAndPhpTags = /|<\?(?:php)?[\s\S]*?\?>/gi; var after = _phpCastString(input); // removes tha '<' char at the end of the string to replicate PHP's behaviour after = after.substring(after.length - 1) === '<' ? after.substring(0, after.length - 1) : after; // recursively remove tags to ensure that the returned string doesn't contain forbidden tags after previous passes (e.g. '<switch/>') while (true) { var before = after; after = before.replace(commentsAndPhpTags, '').replace(tags, function ($0, $1) { return allowed.indexOf('<' + $1.toLowerCase() + '>') > -1 ? $0 : ''; }); // return once no more tags are removed if (before === after) { return after; } } }; //# sourceMappingURL=strip_tags.js.map /***/ }), /***/ "./node_modules/locutus/php/strings/vsprintf.js": /*!******************************************************!*\ !*** ./node_modules/locutus/php/strings/vsprintf.js ***! \******************************************************/ /***/ ((module, __unused_webpack_exports, __webpack_require__) => { "use strict"; module.exports = function vsprintf(format, args) { // discuss at: https://locutus.io/php/vsprintf/ // original by: ejsanders // example 1: vsprintf('%04d-%02d-%02d', [1988, 8, 1]) // returns 1: '1988-08-01' var sprintf = __webpack_require__(/*! ../strings/sprintf */ "./node_modules/locutus/php/strings/sprintf.js"); return sprintf.apply(this, [format].concat(args)); }; //# sourceMappingURL=vsprintf.js.map /***/ }), /***/ "./node_modules/locutus/php/var/boolval.js": /*!*************************************************!*\ !*** ./node_modules/locutus/php/var/boolval.js ***! \*************************************************/ /***/ ((module) => { "use strict"; module.exports = function boolval(mixedVar) { // original by: Will Rowe // example 1: boolval(true) // returns 1: true // example 2: boolval(false) // returns 2: false // example 3: boolval(0) // returns 3: false // example 4: boolval(0.0) // returns 4: false // example 5: boolval('') // returns 5: false // example 6: boolval('0') // returns 6: false // example 7: boolval([]) // returns 7: false // example 8: boolval('') // returns 8: false // example 9: boolval(null) // returns 9: false // example 10: boolval(undefined) // returns 10: false // example 11: boolval('true') // returns 11: true if (mixedVar === false) { return false; } if (mixedVar === 0 || mixedVar === 0.0) { return false; } if (mixedVar === '' || mixedVar === '0') { return false; } if (Array.isArray(mixedVar) && mixedVar.length === 0) { return false; } if (mixedVar === null || mixedVar === undefined) { return false; } return true; }; //# sourceMappingURL=boolval.js.map /***/ }), /***/ "./node_modules/path-browserify/index.js": /*!***********************************************!*\ !*** ./node_modules/path-browserify/index.js ***! \***********************************************/ /***/ ((module) => { "use strict"; // 'path' module extracted from Node.js v8.11.1 (only the posix part) // transplited with Babel // Copyright Joyent, Inc. and other Node contributors. // // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to permit // persons to whom the Software is furnished to do so, subject to the // following conditions: // // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE // USE OR OTHER DEALINGS IN THE SOFTWARE. function assertPath(path) { if (typeof path !== 'string') { throw new TypeError('Path must be a string. Received ' + JSON.stringify(path)); } } // Resolves . and .. elements in a path with directory names function normalizeStringPosix(path, allowAboveRoot) { var res = ''; var lastSegmentLength = 0; var lastSlash = -1; var dots = 0; var code; for (var i = 0; i <= path.length; ++i) { if (i < path.length) code = path.charCodeAt(i); else if (code === 47 /*/*/) break; else code = 47 /*/*/; if (code === 47 /*/*/) { if (lastSlash === i - 1 || dots === 1) { // NOOP } else if (lastSlash !== i - 1 && dots === 2) { if (res.length < 2 || lastSegmentLength !== 2 || res.charCodeAt(res.length - 1) !== 46 /*.*/ || res.charCodeAt(res.length - 2) !== 46 /*.*/) { if (res.length > 2) { var lastSlashIndex = res.lastIndexOf('/'); if (lastSlashIndex !== res.length - 1) { if (lastSlashIndex === -1) { res = ''; lastSegmentLength = 0; } else { res = res.slice(0, lastSlashIndex); lastSegmentLength = res.length - 1 - res.lastIndexOf('/'); } lastSlash = i; dots = 0; continue; } } else if (res.length === 2 || res.length === 1) { res = ''; lastSegmentLength = 0; lastSlash = i; dots = 0; continue; } } if (allowAboveRoot) { if (res.length > 0) res += '/..'; else res = '..'; lastSegmentLength = 2; } } else { if (res.length > 0) res += '/' + path.slice(lastSlash + 1, i); else res = path.slice(lastSlash + 1, i); lastSegmentLength = i - lastSlash - 1; } lastSlash = i; dots = 0; } else if (code === 46 /*.*/ && dots !== -1) { ++dots; } else { dots = -1; } } return res; } function _format(sep, pathObject) { var dir = pathObject.dir || pathObject.root; var base = pathObject.base || (pathObject.name || '') + (pathObject.ext || ''); if (!dir) { return base; } if (dir === pathObject.root) { return dir + base; } return dir + sep + base; } var posix = { // path.resolve([from ...], to) resolve: function resolve() { var resolvedPath = ''; var resolvedAbsolute = false; var cwd; for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) { var path; if (i >= 0) path = arguments[i]; else { if (cwd === undefined) cwd = process.cwd(); path = cwd; } assertPath(path); // Skip empty entries if (path.length === 0) { continue; } resolvedPath = path + '/' + resolvedPath; resolvedAbsolute = path.charCodeAt(0) === 47 /*/*/; } // At this point the path should be resolved to a full absolute path, but // handle relative paths to be safe (might happen when process.cwd() fails) // Normalize the path resolvedPath = normalizeStringPosix(resolvedPath, !resolvedAbsolute); if (resolvedAbsolute) { if (resolvedPath.length > 0) return '/' + resolvedPath; else return '/'; } else if (resolvedPath.length > 0) { return resolvedPath; } else { return '.'; } }, normalize: function normalize(path) { assertPath(path); if (path.length === 0) return '.'; var isAbsolute = path.charCodeAt(0) === 47 /*/*/; var trailingSeparator = path.charCodeAt(path.length - 1) === 47 /*/*/; // Normalize the path path = normalizeStringPosix(path, !isAbsolute); if (path.length === 0 && !isAbsolute) path = '.'; if (path.length > 0 && trailingSeparator) path += '/'; if (isAbsolute) return '/' + path; return path; }, isAbsolute: function isAbsolute(path) { assertPath(path); return path.length > 0 && path.charCodeAt(0) === 47 /*/*/; }, join: function join() { if (arguments.length === 0) return '.'; var joined; for (var i = 0; i < arguments.length; ++i) { var arg = arguments[i]; assertPath(arg); if (arg.length > 0) { if (joined === undefined) joined = arg; else joined += '/' + arg; } } if (joined === undefined) return '.'; return posix.normalize(joined); }, relative: function relative(from, to) { assertPath(from); assertPath(to); if (from === to) return ''; from = posix.resolve(from); to = posix.resolve(to); if (from === to) return ''; // Trim any leading backslashes var fromStart = 1; for (; fromStart < from.length; ++fromStart) { if (from.charCodeAt(fromStart) !== 47 /*/*/) break; } var fromEnd = from.length; var fromLen = fromEnd - fromStart; // Trim any leading backslashes var toStart = 1; for (; toStart < to.length; ++toStart) { if (to.charCodeAt(toStart) !== 47 /*/*/) break; } var toEnd = to.length; var toLen = toEnd - toStart; // Compare paths to find the longest common path from root var length = fromLen < toLen ? fromLen : toLen; var lastCommonSep = -1; var i = 0; for (; i <= length; ++i) { if (i === length) { if (toLen > length) { if (to.charCodeAt(toStart + i) === 47 /*/*/) { // We get here if `from` is the exact base path for `to`. // For example: from='/foo/bar'; to='/foo/bar/baz' return to.slice(toStart + i + 1); } else if (i === 0) { // We get here if `from` is the root // For example: from='/'; to='/foo' return to.slice(toStart + i); } } else if (fromLen > length) { if (from.charCodeAt(fromStart + i) === 47 /*/*/) { // We get here if `to` is the exact base path for `from`. // For example: from='/foo/bar/baz'; to='/foo/bar' lastCommonSep = i; } else if (i === 0) { // We get here if `to` is the root. // For example: from='/foo'; to='/' lastCommonSep = 0; } } break; } var fromCode = from.charCodeAt(fromStart + i); var toCode = to.charCodeAt(toStart + i); if (fromCode !== toCode) break; else if (fromCode === 47 /*/*/) lastCommonSep = i; } var out = ''; // Generate the relative path based on the path difference between `to` // and `from` for (i = fromStart + lastCommonSep + 1; i <= fromEnd; ++i) { if (i === fromEnd || from.charCodeAt(i) === 47 /*/*/) { if (out.length === 0) out += '..'; else out += '/..'; } } // Lastly, append the rest of the destination (`to`) path that comes after // the common path parts if (out.length > 0) return out + to.slice(toStart + lastCommonSep); else { toStart += lastCommonSep; if (to.charCodeAt(toStart) === 47 /*/*/) ++toStart; return to.slice(toStart); } }, _makeLong: function _makeLong(path) { return path; }, dirname: function dirname(path) { assertPath(path); if (path.length === 0) return '.'; var code = path.charCodeAt(0); var hasRoot = code === 47 /*/*/; var end = -1; var matchedSlash = true; for (var i = path.length - 1; i >= 1; --i) { code = path.charCodeAt(i); if (code === 47 /*/*/) { if (!matchedSlash) { end = i; break; } } else { // We saw the first non-path separator matchedSlash = false; } } if (end === -1) return hasRoot ? '/' : '.'; if (hasRoot && end === 1) return '//'; return path.slice(0, end); }, basename: function basename(path, ext) { if (ext !== undefined && typeof ext !== 'string') throw new TypeError('"ext" argument must be a string'); assertPath(path); var start = 0; var end = -1; var matchedSlash = true; var i; if (ext !== undefined && ext.length > 0 && ext.length <= path.length) { if (ext.length === path.length && ext === path) return ''; var extIdx = ext.length - 1; var firstNonSlashEnd = -1; for (i = path.length - 1; i >= 0; --i) { var code = path.charCodeAt(i); if (code === 47 /*/*/) { // If we reached a path separator that was not part of a set of path // separators at the end of the string, stop now if (!matchedSlash) { start = i + 1; break; } } else { if (firstNonSlashEnd === -1) { // We saw the first non-path separator, remember this index in case // we need it if the extension ends up not matching matchedSlash = false; firstNonSlashEnd = i + 1; } if (extIdx >= 0) { // Try to match the explicit extension if (code === ext.charCodeAt(extIdx)) { if (--extIdx === -1) { // We matched the extension, so mark this as the end of our path // component end = i; } } else { // Extension does not match, so our result is the entire path // component extIdx = -1; end = firstNonSlashEnd; } } } } if (start === end) end = firstNonSlashEnd;else if (end === -1) end = path.length; return path.slice(start, end); } else { for (i = path.length - 1; i >= 0; --i) { if (path.charCodeAt(i) === 47 /*/*/) { // If we reached a path separator that was not part of a set of path // separators at the end of the string, stop now if (!matchedSlash) { start = i + 1; break; } } else if (end === -1) { // We saw the first non-path separator, mark this as the end of our // path component matchedSlash = false; end = i + 1; } } if (end === -1) return ''; return path.slice(start, end); } }, extname: function extname(path) { assertPath(path); var startDot = -1; var startPart = 0; var end = -1; var matchedSlash = true; // Track the state of characters (if any) we see before our first dot and // after any path separator we find var preDotState = 0; for (var i = path.length - 1; i >= 0; --i) { var code = path.charCodeAt(i); if (code === 47 /*/*/) { // If we reached a path separator that was not part of a set of path // separators at the end of the string, stop now if (!matchedSlash) { startPart = i + 1; break; } continue; } if (end === -1) { // We saw the first non-path separator, mark this as the end of our // extension matchedSlash = false; end = i + 1; } if (code === 46 /*.*/) { // If this is our first dot, mark it as the start of our extension if (startDot === -1) startDot = i; else if (preDotState !== 1) preDotState = 1; } else if (startDot !== -1) { // We saw a non-dot and non-path separator before our dot, so we should // have a good chance at having a non-empty extension preDotState = -1; } } if (startDot === -1 || end === -1 || // We saw a non-dot character immediately before the dot preDotState === 0 || // The (right-most) trimmed path component is exactly '..' preDotState === 1 && startDot === end - 1 && startDot === startPart + 1) { return ''; } return path.slice(startDot, end); }, format: function format(pathObject) { if (pathObject === null || typeof pathObject !== 'object') { throw new TypeError('The "pathObject" argument must be of type Object. Received type ' + typeof pathObject); } return _format('/', pathObject); }, parse: function parse(path) { assertPath(path); var ret = { root: '', dir: '', base: '', ext: '', name: '' }; if (path.length === 0) return ret; var code = path.charCodeAt(0); var isAbsolute = code === 47 /*/*/; var start; if (isAbsolute) { ret.root = '/'; start = 1; } else { start = 0; } var startDot = -1; var startPart = 0; var end = -1; var matchedSlash = true; var i = path.length - 1; // Track the state of characters (if any) we see before our first dot and // after any path separator we find var preDotState = 0; // Get non-dir info for (; i >= start; --i) { code = path.charCodeAt(i); if (code === 47 /*/*/) { // If we reached a path separator that was not part of a set of path // separators at the end of the string, stop now if (!matchedSlash) { startPart = i + 1; break; } continue; } if (end === -1) { // We saw the first non-path separator, mark this as the end of our // extension matchedSlash = false; end = i + 1; } if (code === 46 /*.*/) { // If this is our first dot, mark it as the start of our extension if (startDot === -1) startDot = i;else if (preDotState !== 1) preDotState = 1; } else if (startDot !== -1) { // We saw a non-dot and non-path separator before our dot, so we should // have a good chance at having a non-empty extension preDotState = -1; } } if (startDot === -1 || end === -1 || // We saw a non-dot character immediately before the dot preDotState === 0 || // The (right-most) trimmed path component is exactly '..' preDotState === 1 && startDot === end - 1 && startDot === startPart + 1) { if (end !== -1) { if (startPart === 0 && isAbsolute) ret.base = ret.name = path.slice(1, end);else ret.base = ret.name = path.slice(startPart, end); } } else { if (startPart === 0 && isAbsolute) { ret.name = path.slice(1, startDot); ret.base = path.slice(1, end); } else { ret.name = path.slice(startPart, startDot); ret.base = path.slice(startPart, end); } ret.ext = path.slice(startDot, end); } if (startPart > 0) ret.dir = path.slice(0, startPart - 1);else if (isAbsolute) ret.dir = '/'; return ret; }, sep: '/', delimiter: ':', win32: null, posix: null }; posix.posix = posix; module.exports = posix; /***/ }), /***/ "./node_modules/twig/src/twig.async.js": /*!*********************************************!*\ !*** ./node_modules/twig/src/twig.async.js ***! \*********************************************/ /***/ ((module) => { // ## twig.async.js // // This file handles asynchronous tasks within twig. module.exports = function (Twig) { 'use strict'; const STATE_UNKNOWN = 0; const STATE_RESOLVED = 1; const STATE_REJECTED = 2; Twig.ParseState.prototype.parseAsync = function (tokens, context) { return this.parse(tokens, context, true); }; Twig.expression.parseAsync = function (tokens, context, tokensAreParameters) { const state = this; return Twig.expression.parse.call(state, tokens, context, tokensAreParameters, true); }; Twig.logic.parseAsync = function (token, context, chain) { const state = this; return Twig.logic.parse.call(state, token, context, chain, true); }; Twig.Template.prototype.renderAsync = function (context, params) { return this.render(context, params, true); }; Twig.async = {}; /** * Checks for `thenable` objects */ Twig.isPromise = function (obj) { return obj && obj.then && (typeof obj.then === 'function'); }; /** * Handling of code paths that might either return a promise * or a value depending on whether async code is used. * * @see https://github.com/twigjs/twig.js/blob/master/ASYNC.md#detecting-asynchronous-behaviour */ function potentiallyAsyncSlow(that, allowAsync, action) { let result = action.call(that); let err = null; let isAsync = true; if (!Twig.isPromise(result)) { return result; } result.then(res => { result = res; isAsync = false; }).catch(error => { err = error; }); if (err !== null) { throw err; } if (isAsync) { throw new Twig.Error('You are using Twig.js in sync mode in combination with async extensions.'); } return result; } Twig.async.potentiallyAsync = function (that, allowAsync, action) { if (allowAsync) { return Twig.Promise.resolve(action.call(that)); } return potentiallyAsyncSlow(that, allowAsync, action); }; function run(fn, resolve, reject) { try { fn(resolve, reject); } catch (error) { reject(error); } } function pending(handlers, onResolved, onRejected) { const h = [onResolved, onRejected, -2]; // The promise has yet to be rejected or resolved. if (!handlers) { handlers = h; } else if (handlers[2] === -2) { // Only allocate an array when there are multiple handlers handlers = [handlers, h]; } else { handlers.push(h); } return handlers; } /** * Really small thenable to represent promises that resolve immediately. * */ Twig.Thenable = function (then, value, state) { this.then = then; this._value = state ? value : null; this._state = state || STATE_UNKNOWN; }; Twig.Thenable.prototype.catch = function (onRejected) { // THe promise will not throw, it has already resolved. if (this._state === STATE_RESOLVED) { return this; } return this.then(null, onRejected); }; /** * The `then` method attached to a Thenable when it has resolved. * */ Twig.Thenable.resolvedThen = function (onResolved) { try { return Twig.Promise.resolve(onResolved(this._value)); } catch (error) { return Twig.Promise.reject(error); } }; /** * The `then` method attached to a Thenable when it has rejected. * */ Twig.Thenable.rejectedThen = function (onResolved, onRejected) { // Shortcut for rejected twig promises if (!onRejected || typeof onRejected !== 'function') { return this; } const value = this._value; let result; try { result = onRejected(value); } catch (error) { result = Twig.Promise.reject(error); } return Twig.Promise.resolve(result); }; /** * An alternate implementation of a Promise that does not fully follow * the spec, but instead works fully synchronous while still being * thenable. * * These promises can be mixed with regular promises at which point * the synchronous behaviour is lost. */ Twig.Promise = function (executor) { let state = STATE_UNKNOWN; let value = null; let changeState = function (nextState, nextValue) { state = nextState; value = nextValue; }; function onReady(v) { changeState(STATE_RESOLVED, v); } function onReject(e) { changeState(STATE_REJECTED, e); } run(executor, onReady, onReject); // If the promise settles right after running the executor we can // return a Promise with it's state already set. // // Twig.Promise.resolve and Twig.Promise.reject both use the more // efficient `Twig.Thenable` for this purpose. if (state === STATE_RESOLVED) { return Twig.Promise.resolve(value); } if (state === STATE_REJECTED) { return Twig.Promise.reject(value); } // If we managed to get here our promise is going to resolve asynchronous. changeState = new Twig.FullPromise(); return changeState.promise; }; /** * Promise implementation that can handle being resolved at any later time. * */ Twig.FullPromise = function () { let handlers = null; // The state has been changed to either resolve, or reject // which means we should call the handler. function resolved(onResolved) { onResolved(p._value); } function rejected(onResolved, onRejected) { onRejected(p._value); } let append = function (onResolved, onRejected) { handlers = pending(handlers, onResolved, onRejected); }; function changeState(newState, v) { if (p._state) { return; } p._value = v; p._state = newState; append = newState === STATE_RESOLVED ? resolved : rejected; if (!handlers) { return; } if (handlers[2] === -2) { append(handlers[0], handlers[1]); handlers = null; return; } handlers.forEach(h => { append(h[0], h[1]); }); handlers = null; } const p = new Twig.Thenable((onResolved, onRejected) => { const hasResolved = typeof onResolved === 'function'; // Shortcut for resolved twig promises if (p._state === STATE_RESOLVED && !hasResolved) { return Twig.Promise.resolve(p._value); } if (p._state === STATE_RESOLVED) { try { return Twig.Promise.resolve(onResolved(p._value)); } catch (error) { return Twig.Promise.reject(error); } } const hasRejected = typeof onRejected === 'function'; return new Twig.Promise((resolve, reject) => { append( hasResolved ? result => { try { resolve(onResolved(result)); } catch (error) { reject(error); } } : resolve, hasRejected ? err => { try { resolve(onRejected(err)); } catch (error) { reject(error); } } : reject ); }); }); changeState.promise = p; return changeState; }; Twig.Promise.defaultResolved = new Twig.Thenable(Twig.Thenable.resolvedThen, undefined, STATE_RESOLVED); Twig.Promise.emptyStringResolved = new Twig.Thenable(Twig.Thenable.resolvedThen, '', STATE_RESOLVED); Twig.Promise.resolve = function (value) { if (arguments.length === 0 || typeof value === 'undefined') { return Twig.Promise.defaultResolved; } if (Twig.isPromise(value)) { return value; } // Twig often resolves with an empty string, we optimize for this // scenario by returning a fixed promise. This reduces the load on // garbage collection. if (value === '') { return Twig.Promise.emptyStringResolved; } return new Twig.Thenable(Twig.Thenable.resolvedThen, value, STATE_RESOLVED); }; Twig.Promise.reject = function (e) { // `e` should never be a promise. return new Twig.Thenable(Twig.Thenable.rejectedThen, e, STATE_REJECTED); }; Twig.Promise.all = function (promises) { const results = new Array(promises.length); return Twig.async.forEach(promises, (p, index) => { if (!Twig.isPromise(p)) { results[index] = p; return; } if (p._state === STATE_RESOLVED) { results[index] = p._value; return; } return p.then(v => { results[index] = v; }); }).then(() => { return results; }); }; /** * Go over each item in a fashion compatible with Twig.forEach, * allow the function to return a promise or call the third argument * to signal it is finished. * * Each item in the array will be called sequentially. */ Twig.async.forEach = function (arr, callback) { const len = arr ? arr.length : 0; let index = 0; function next() { let resp = null; do { if (index === len) { return Twig.Promise.resolve(); } resp = callback(arr[index], index); index++; // While the result of the callback is not a promise or it is // a promise that has settled we can use a regular loop which // is much faster. } while (!resp || !Twig.isPromise(resp) || resp._state === STATE_RESOLVED); return resp.then(next); } return next(); }; return Twig; }; /***/ }), /***/ "./node_modules/twig/src/twig.compiler.js": /*!************************************************!*\ !*** ./node_modules/twig/src/twig.compiler.js ***! \************************************************/ /***/ ((module) => { // ## twig.compiler.js // // This file handles compiling templates into JS module.exports = function (Twig) { /** * Namespace for compilation. */ Twig.compiler = { module: {} }; // Compile a Twig Template to output. Twig.compiler.compile = function (template, options) { // Get tokens const tokens = JSON.stringify(template.tokens); const {id} = template; let output = null; if (options.module) { if (Twig.compiler.module[options.module] === undefined) { throw new Twig.Error('Unable to find module type ' + options.module); } output = Twig.compiler.module[options.module](id, tokens, options.twig); } else { output = Twig.compiler.wrap(id, tokens); } return output; }; Twig.compiler.module = { amd(id, tokens, pathToTwig) { return 'define(["' + pathToTwig + '"], function (Twig) {\n\tvar twig, templates;\ntwig = Twig.twig;\ntemplates = ' + Twig.compiler.wrap(id, tokens) + '\n\treturn templates;\n});'; }, node(id, tokens) { return 'var twig = require("twig").twig;\nexports.template = ' + Twig.compiler.wrap(id, tokens); }, cjs2(id, tokens, pathToTwig) { return 'module.declare([{ twig: "' + pathToTwig + '" }], function (require, exports, module) {\n\tvar twig = require("twig").twig;\n\texports.template = ' + Twig.compiler.wrap(id, tokens) + '\n});'; } }; Twig.compiler.wrap = function (id, tokens) { return 'twig({id:"' + id.replace('"', '\\"') + '", data:' + tokens + ', precompiled: true});\n'; }; return Twig; }; /***/ }), /***/ "./node_modules/twig/src/twig.core.js": /*!********************************************!*\ !*** ./node_modules/twig/src/twig.core.js ***! \********************************************/ /***/ ((module) => { // ## twig.core.js // // This file handles template level tokenizing, compiling and parsing. module.exports = function (Twig) { 'use strict'; Twig.trace = false; Twig.debug = false; // Default caching to true for the improved performance it offers Twig.cache = true; Twig.noop = function () {}; Twig.merge = function (target, source, onlyChanged) { Object.keys(source).forEach(key => { if (onlyChanged && !(key in target)) { return; } target[key] = source[key]; }); return target; }; /** * Exception thrown by twig.js. */ Twig.Error = function (message, file) { this.message = message; this.name = 'TwigException'; this.type = 'TwigException'; this.file = file; }; /** * Get the string representation of a Twig error. */ Twig.Error.prototype.toString = function () { const output = this.name + ': ' + this.message; return output; }; /** * Wrapper for logging to the console. */ Twig.log = { trace(...args) { if (Twig.trace && console) { console.log(Array.prototype.slice.call(args)); } }, debug(...args) { if (Twig.debug && console) { console.log(Array.prototype.slice.call(args)); } } }; if (typeof console === 'undefined') { Twig.log.error = function () {}; } else if (typeof console.error !== 'undefined') { Twig.log.error = function (...args) { console.error(...args); }; } else if (typeof console.log !== 'undefined') { Twig.log.error = function (...args) { console.log(...args); }; } /** * Container for methods related to handling high level template tokens * (for example: {{ expression }}, {% logic %}, {# comment #}, raw data) */ Twig.token = {}; /** * Token types. */ Twig.token.type = { output: 'output', logic: 'logic', comment: 'comment', raw: 'raw', outputWhitespacePre: 'output_whitespace_pre', outputWhitespacePost: 'output_whitespace_post', outputWhitespaceBoth: 'output_whitespace_both', logicWhitespacePre: 'logic_whitespace_pre', logicWhitespacePost: 'logic_whitespace_post', logicWhitespaceBoth: 'logic_whitespace_both' }; /** * Token syntax definitions. */ Twig.token.definitions = [ { type: Twig.token.type.raw, open: '{% raw %}', close: '{% endraw %}' }, { type: Twig.token.type.raw, open: '{% verbatim %}', close: '{% endverbatim %}' }, // *Whitespace type tokens* // // These typically take the form `{{- expression -}}` or `{{- expression }}` or `{{ expression -}}`. { type: Twig.token.type.outputWhitespacePre, open: '{{-', close: '}}' }, { type: Twig.token.type.outputWhitespacePost, open: '{{', close: '-}}' }, { type: Twig.token.type.outputWhitespaceBoth, open: '{{-', close: '-}}' }, { type: Twig.token.type.logicWhitespacePre, open: '{%-', close: '%}' }, { type: Twig.token.type.logicWhitespacePost, open: '{%', close: '-%}' }, { type: Twig.token.type.logicWhitespaceBoth, open: '{%-', close: '-%}' }, // *Output type tokens* // // These typically take the form `{{ expression }}`. { type: Twig.token.type.output, open: '{{', close: '}}' }, // *Logic type tokens* // // These typically take a form like `{% if expression %}` or `{% endif %}` { type: Twig.token.type.logic, open: '{%', close: '%}' }, // *Comment type tokens* // // These take the form `{# anything #}` { type: Twig.token.type.comment, open: '{#', close: '#}' } ]; /** * What characters start "strings" in token definitions. We need this to ignore token close * strings inside an expression. */ Twig.token.strings = ['"', '\'']; Twig.token.findStart = function (template) { const output = { position: null, def: null }; let closePosition = null; const len = Twig.token.definitions.length; let i; let tokenTemplate; let firstKeyPosition; let closeKeyPosition; for (i = 0; i < len; i++) { tokenTemplate = Twig.token.definitions[i]; firstKeyPosition = template.indexOf(tokenTemplate.open); closeKeyPosition = template.indexOf(tokenTemplate.close); Twig.log.trace('Twig.token.findStart: ', 'Searching for ', tokenTemplate.open, ' found at ', firstKeyPosition); // Special handling for mismatched tokens if (firstKeyPosition >= 0) { // This token matches the template if (tokenTemplate.open.length !== tokenTemplate.close.length) { // This token has mismatched closing and opening tags if (closeKeyPosition < 0) { // This token's closing tag does not match the template continue; } } } // Does this token occur before any other types? if (firstKeyPosition >= 0 && (output.position === null || firstKeyPosition < output.position)) { output.position = firstKeyPosition; output.def = tokenTemplate; closePosition = closeKeyPosition; } else if (firstKeyPosition >= 0 && output.position !== null && firstKeyPosition === output.position) { /* This token exactly matches another token, greedily match to check if this token has a greater specificity */ if (tokenTemplate.open.length > output.def.open.length) { // This token's opening tag is more specific than the previous match output.position = firstKeyPosition; output.def = tokenTemplate; closePosition = closeKeyPosition; } else if (tokenTemplate.open.length === output.def.open.length) { if (tokenTemplate.close.length > output.def.close.length) { // This token's opening tag is as specific as the previous match, // but the closing tag has greater specificity if (closeKeyPosition >= 0 && closeKeyPosition < closePosition) { // This token's closing tag exists in the template, // and it occurs sooner than the previous match output.position = firstKeyPosition; output.def = tokenTemplate; closePosition = closeKeyPosition; } } else if (closeKeyPosition >= 0 && closeKeyPosition < closePosition) { // This token's closing tag is not more specific than the previous match, // but it occurs sooner than the previous match output.position = firstKeyPosition; output.def = tokenTemplate; closePosition = closeKeyPosition; } } } } return output; }; Twig.token.findEnd = function (template, tokenDef, start) { let end = null; let found = false; let offset = 0; // String position variables let strPos = null; let strFound = null; let pos = null; let endOffset = null; let thisStrPos = null; let endStrPos = null; // For loop variables let i; let l; while (!found) { strPos = null; strFound = null; pos = template.indexOf(tokenDef.close, offset); if (pos >= 0) { end = pos; found = true; } else { // Throw an exception throw new Twig.Error('Unable to find closing bracket \'' + tokenDef.close + '\' opened near template position ' + start); } // Ignore quotes within comments; just look for the next comment close sequence, // regardless of what comes before it. https://github.com/justjohn/twig.js/issues/95 if (tokenDef.type === Twig.token.type.comment) { break; } // Ignore quotes within raw tag // Fixes #283 if (tokenDef.type === Twig.token.type.raw) { break; } l = Twig.token.strings.length; for (i = 0; i < l; i += 1) { thisStrPos = template.indexOf(Twig.token.strings[i], offset); if (thisStrPos > 0 && thisStrPos < pos && (strPos === null || thisStrPos < strPos)) { strPos = thisStrPos; strFound = Twig.token.strings[i]; } } // We found a string before the end of the token, now find the string's end and set the search offset to it if (strPos !== null) { endOffset = strPos + 1; end = null; found = false; for (;;) { endStrPos = template.indexOf(strFound, endOffset); if (endStrPos < 0) { throw Twig.Error('Unclosed string in template'); } // Ignore escaped quotes if (template.slice(endStrPos - 1, endStrPos) === '\\') { endOffset = endStrPos + 1; } else { offset = endStrPos + 1; break; } } } } return end; }; /** * Convert a template into high-level tokens. */ Twig.tokenize = function (template) { const tokens = []; // An offset for reporting errors locations and the position of the nodes in the template. let currentPosition = 0; // The start and type of the first token found in the template. let foundToken = null; // The end position of the matched token. let end = null; while (template.length > 0) { // Find the first occurance of any token type in the template foundToken = Twig.token.findStart(template); Twig.log.trace('Twig.tokenize: ', 'Found token: ', foundToken); if (foundToken.position === null) { // No more tokens -> add the rest of the template as a raw-type token tokens.push({ type: Twig.token.type.raw, value: template, position: { start: currentPosition, end: currentPosition + foundToken.position } }); template = ''; } else { // Add a raw type token for anything before the start of the token if (foundToken.position > 0) { tokens.push({ type: Twig.token.type.raw, value: template.slice(0, Math.max(0, foundToken.position)), position: { start: currentPosition, end: currentPosition + Math.max(0, foundToken.position) } }); } template = template.slice(foundToken.position + foundToken.def.open.length); currentPosition += foundToken.position + foundToken.def.open.length; // Find the end of the token end = Twig.token.findEnd(template, foundToken.def, currentPosition); Twig.log.trace('Twig.tokenize: ', 'Token ends at ', end); tokens.push({ type: foundToken.def.type, value: template.slice(0, Math.max(0, end)).trim(), position: { start: currentPosition - foundToken.def.open.length, end: currentPosition + end + foundToken.def.close.length } }); if (template.slice(end + foundToken.def.close.length, end + foundToken.def.close.length + 1) === '\n') { switch (foundToken.def.type) { case 'logic_whitespace_pre': case 'logic_whitespace_post': case 'logic_whitespace_both': case 'logic': // Newlines directly after logic tokens are ignored end += 1; break; default: break; } } template = template.slice(end + foundToken.def.close.length); // Increment the position in the template currentPosition += end + foundToken.def.close.length; } } return tokens; }; Twig.compile = function (tokens) { const self = this; try { // Output and intermediate stacks const output = []; const stack = []; // The tokens between open and close tags let intermediateOutput = []; let token = null; let logicToken = null; let unclosedToken = null; // Temporary previous token. let prevToken = null; // Temporary previous output. let prevOutput = null; // Temporary previous intermediate output. let prevIntermediateOutput = null; // The previous token's template let prevTemplate = null; // Token lookahead let nextToken = null; // The output token let tokOutput = null; // Logic Token values let type = null; let open = null; let next = null; const compileOutput = function (token) { Twig.expression.compile.call(self, token); if (stack.length > 0) { intermediateOutput.push(token); } else { output.push(token); } }; const compileLogic = function (token) { // Compile the logic token logicToken = Twig.logic.compile.call(self, token); logicToken.position = token.position; type = logicToken.type; open = Twig.logic.handler[type].open; next = Twig.logic.handler[type].next; Twig.log.trace('Twig.compile: ', 'Compiled logic token to ', logicToken, ' next is: ', next, ' open is : ', open); // Not a standalone token, check logic stack to see if this is expected if (open !== undefined && !open) { prevToken = stack.pop(); prevTemplate = Twig.logic.handler[prevToken.type]; if (!prevTemplate.next.includes(type)) { throw new Error(type + ' not expected after a ' + prevToken.type); } prevToken.output = prevToken.output || []; prevToken.output = prevToken.output.concat(intermediateOutput); intermediateOutput = []; tokOutput = { type: Twig.token.type.logic, token: prevToken, position: { open: prevToken.position, close: token.position } }; if (stack.length > 0) { intermediateOutput.push(tokOutput); } else { output.push(tokOutput); } } // This token requires additional tokens to complete the logic structure. if (next !== undefined && next.length > 0) { Twig.log.trace('Twig.compile: ', 'Pushing ', logicToken, ' to logic stack.'); if (stack.length > 0) { // Put any currently held output into the output list of the logic operator // currently at the head of the stack before we push a new one on. prevToken = stack.pop(); prevToken.output = prevToken.output || []; prevToken.output = prevToken.output.concat(intermediateOutput); stack.push(prevToken); intermediateOutput = []; } // Push the new logic token onto the logic stack stack.push(logicToken); } else if (open !== undefined && open) { tokOutput = { type: Twig.token.type.logic, token: logicToken, position: logicToken.position }; // Standalone token (like {% set ... %} if (stack.length > 0) { intermediateOutput.push(tokOutput); } else { output.push(tokOutput); } } }; while (tokens.length > 0) { token = tokens.shift(); prevOutput = output[output.length - 1]; prevIntermediateOutput = intermediateOutput[intermediateOutput.length - 1]; nextToken = tokens[0]; Twig.log.trace('Compiling token ', token); switch (token.type) { case Twig.token.type.raw: if (stack.length > 0) { intermediateOutput.push(token); } else { output.push(token); } break; case Twig.token.type.logic: compileLogic.call(self, token); break; // Do nothing, comments should be ignored case Twig.token.type.comment: break; case Twig.token.type.output: compileOutput.call(self, token); break; // Kill whitespace ahead and behind this token case Twig.token.type.logicWhitespacePre: case Twig.token.type.logicWhitespacePost: case Twig.token.type.logicWhitespaceBoth: case Twig.token.type.outputWhitespacePre: case Twig.token.type.outputWhitespacePost: case Twig.token.type.outputWhitespaceBoth: if (token.type !== Twig.token.type.outputWhitespacePost && token.type !== Twig.token.type.logicWhitespacePost) { if (prevOutput) { // If the previous output is raw, pop it off if (prevOutput.type === Twig.token.type.raw) { output.pop(); prevOutput.value = prevOutput.value.trimEnd(); // Repush the previous output output.push(prevOutput); } } if (prevIntermediateOutput) { // If the previous intermediate output is raw, pop it off if (prevIntermediateOutput.type === Twig.token.type.raw) { intermediateOutput.pop(); prevIntermediateOutput.value = prevIntermediateOutput.value.trimEnd(); // Repush the previous intermediate output intermediateOutput.push(prevIntermediateOutput); } } } // Compile this token switch (token.type) { case Twig.token.type.outputWhitespacePre: case Twig.token.type.outputWhitespacePost: case Twig.token.type.outputWhitespaceBoth: compileOutput.call(self, token); break; case Twig.token.type.logicWhitespacePre: case Twig.token.type.logicWhitespacePost: case Twig.token.type.logicWhitespaceBoth: compileLogic.call(self, token); break; default: break; } if (token.type !== Twig.token.type.outputWhitespacePre && token.type !== Twig.token.type.logicWhitespacePre) { if (nextToken) { // If the next token is raw, shift it out if (nextToken.type === Twig.token.type.raw) { tokens.shift(); nextToken.value = nextToken.value.trimStart(); // Unshift the next token tokens.unshift(nextToken); } } } break; default: break; } Twig.log.trace('Twig.compile: ', ' Output: ', output, ' Logic Stack: ', stack, ' Pending Output: ', intermediateOutput ); } // Verify that there are no logic tokens left in the stack. if (stack.length > 0) { unclosedToken = stack.pop(); throw new Error('Unable to find an end tag for ' + unclosedToken.type + ', expecting one of ' + unclosedToken.next); } return output; } catch (error) { if (self.options.rethrow) { if (error.type === 'TwigException' && !error.file) { error.file = self.id; } throw error; } else { Twig.log.error('Error compiling twig template ' + self.id + ': '); if (error.stack) { Twig.log.error(error.stack); } else { Twig.log.error(error.toString()); } } } }; function handleException(state, ex) { if (state.template.options.rethrow) { if (typeof ex === 'string') { ex = new Twig.Error(ex); } if (ex.type === 'TwigException' && !ex.file) { ex.file = state.template.id; } throw ex; } else { Twig.log.error('Error parsing twig template ' + state.template.id + ': '); if (ex.stack) { Twig.log.error(ex.stack); } else { Twig.log.error(ex.toString()); } if (Twig.debug) { return ex.toString(); } } } /** * Tokenize and compile a string template. * * @param {string} data The template. * * @return {Array} The compiled tokens. */ Twig.prepare = function (data) { // Tokenize Twig.log.debug('Twig.prepare: ', 'Tokenizing ', data); const rawTokens = Twig.tokenize.call(this, data); // Compile Twig.log.debug('Twig.prepare: ', 'Compiling ', rawTokens); const tokens = Twig.compile.call(this, rawTokens); Twig.log.debug('Twig.prepare: ', 'Compiled ', tokens); return tokens; }; /** * Join the output token's stack and escape it if needed * * @param {Array} Output token's stack * * @return {string|String} Autoescaped output */ Twig.output = function (output) { const {autoescape} = this.options; if (!autoescape) { return output.join(''); } const strategy = (typeof autoescape === 'string') ? autoescape : 'html'; const escapedOutput = output.map(str => { if ( str && (str.twigMarkup !== true && str.twigMarkup !== strategy) && !(strategy === 'html' && str.twigMarkup === 'html_attr') ) { str = Twig.filters.escape(str, [strategy]); } return str; }); if (escapedOutput.length === 0) { return ''; } const joinedOutput = escapedOutput.join(''); if (joinedOutput.length === 0) { return ''; } return new Twig.Markup(joinedOutput, true); }; // Namespace for template storage and retrieval Twig.Templates = { /** * Registered template loaders - use Twig.Templates.registerLoader to add supported loaders * @type {Object} */ loaders: {}, /** * Registered template parsers - use Twig.Templates.registerParser to add supported parsers * @type {Object} */ parsers: {}, /** * Cached / loaded templates * @type {Object} */ registry: {} }; /** * Is this id valid for a twig template? * * @param {string} id The ID to check. * * @throws {Twig.Error} If the ID is invalid or used. * @return {boolean} True if the ID is valid. */ Twig.validateId = function (id) { if (id === 'prototype') { throw new Twig.Error(id + ' is not a valid twig identifier'); } else if (Twig.cache && Object.hasOwnProperty.call(Twig.Templates.registry, id)) { throw new Twig.Error('There is already a template with the ID ' + id); } return true; }; /** * Register a template loader * * @example * Twig.extend(function (Twig) { * Twig.Templates.registerLoader('custom_loader', function (location, params, callback, errorCallback) { * // ... load the template ... * params.data = loadedTemplateData; * // create and return the template * var template = new Twig.Template(params); * if (typeof callback === 'function') { * callback(template); * } * return template; * }); * }); * * @param {String} methodName The method this loader is intended for (ajax, fs) * @param {Function} func The function to execute when loading the template * @param {Object|undefined} scope Optional scope parameter to bind func to * * @throws Twig.Error * * @return {void} */ Twig.Templates.registerLoader = function (methodName, func, scope) { if (typeof func !== 'function') { throw new Twig.Error('Unable to add loader for ' + methodName + ': Invalid function reference given.'); } if (scope) { func = func.bind(scope); } this.loaders[methodName] = func; }; /** * Remove a registered loader * * @param {String} methodName The method name for the loader you wish to remove * * @return {void} */ Twig.Templates.unRegisterLoader = function (methodName) { if (this.isRegisteredLoader(methodName)) { delete this.loaders[methodName]; } }; /** * See if a loader is registered by its method name * * @param {String} methodName The name of the loader you are looking for * * @return {boolean} */ Twig.Templates.isRegisteredLoader = function (methodName) { return Object.hasOwnProperty.call(this.loaders, methodName); }; /** * Register a template parser * * @example * Twig.extend(function (Twig) { * Twig.Templates.registerParser('custom_parser', function (params) { * // this template source can be accessed in params.data * var template = params.data * * // ... custom process that modifies the template * * // return the parsed template * return template; * }); * }); * * @param {String} methodName The method this parser is intended for (twig, source) * @param {Function} func The function to execute when parsing the template * @param {Object|undefined} scope Optional scope parameter to bind func to * * @throws Twig.Error * * @return {void} */ Twig.Templates.registerParser = function (methodName, func, scope) { if (typeof func !== 'function') { throw new Twig.Error('Unable to add parser for ' + methodName + ': Invalid function regerence given.'); } if (scope) { func = func.bind(scope); } this.parsers[methodName] = func; }; /** * Remove a registered parser * * @param {String} methodName The method name for the parser you wish to remove * * @return {void} */ Twig.Templates.unRegisterParser = function (methodName) { if (this.isRegisteredParser(methodName)) { delete this.parsers[methodName]; } }; /** * See if a parser is registered by its method name * * @param {String} methodName The name of the parser you are looking for * * @return {boolean} */ Twig.Templates.isRegisteredParser = function (methodName) { return Object.hasOwnProperty.call(this.parsers, methodName); }; /** * Save a template object to the store. * * @param {Twig.Template} template The twig.js template to store. */ Twig.Templates.save = function (template) { if (template.id === undefined) { throw new Twig.Error('Unable to save template with no id'); } Twig.Templates.registry[template.id] = template; }; /** * Load a previously saved template from the store. * * @param {string} id The ID of the template to load. * * @return {Twig.Template} A twig.js template stored with the provided ID. */ Twig.Templates.load = function (id) { if (!Object.hasOwnProperty.call(Twig.Templates.registry, id)) { return null; } return Twig.Templates.registry[id]; }; /** * Load a template from a remote location using AJAX and saves in with the given ID. * * Available parameters: * * async: Should the HTTP request be performed asynchronously. * Defaults to true. * method: What method should be used to load the template * (fs or ajax) * parser: What method should be used to parse the template * (twig or source) * precompiled: Has the template already been compiled. * * @param {string} location The remote URL to load as a template. * @param {Object} params The template parameters. * @param {function} callback A callback triggered when the template finishes loading. * @param {function} errorCallback A callback triggered if an error occurs loading the template. * * */ Twig.Templates.loadRemote = function (location, params, callback, errorCallback) { // Default to the URL so the template is cached. const id = typeof params.id === 'undefined' ? location : params.id; const cached = Twig.Templates.registry[id]; // Check for existing template if (Twig.cache && typeof cached !== 'undefined') { // A template is already saved with the given id. if (typeof callback === 'function') { callback(cached); } // TODO: if async, return deferred promise return cached; } // If the parser name hasn't been set, default it to twig params.parser = params.parser || 'twig'; params.id = id; // Default to async if (typeof params.async === 'undefined') { params.async = true; } // Assume 'fs' if the loader is not defined const loader = this.loaders[params.method] || this.loaders.fs; return loader.call(this, location, params, callback, errorCallback); }; // Determine object type function is(type, obj) { const clas = Object.prototype.toString.call(obj).slice(8, -1); return obj !== undefined && obj !== null && clas === type; } /** * A wrapper for template blocks. * * @param {Twig.Template} The template that the block was originally defined in. * @param {Object} The compiled block token. */ Twig.Block = function (template, token) { this.template = template; this.token = token; }; /** * Render the block using a specific parse state and context. * * @param {Twig.ParseState} parseState * @param {Object} context * * @return {Promise} */ Twig.Block.prototype.render = function (parseState, context) { const originalTemplate = parseState.template; let promise; parseState.template = this.template; if (this.token.expression) { promise = Twig.expression.parseAsync.call(parseState, this.token.output, context); } else { promise = parseState.parseAsync(this.token.output, context); } return promise .then(value => { return Twig.expression.parseAsync.call( parseState, { type: Twig.expression.type.string, value }, context ); }) .then(output => { parseState.template = originalTemplate; return output; }); }; /** * Holds the state needed to parse a template. * * @param {Twig.Template} template The template that the tokens being parsed are associated with. * @param {Object} blockOverrides Any blocks that should override those defined in the associated template. */ Twig.ParseState = function (template, blockOverrides, context) { this.renderedBlocks = {}; this.overrideBlocks = blockOverrides === undefined ? {} : blockOverrides; this.context = context === undefined ? {} : context; this.macros = {}; this.nestingStack = []; this.template = template; }; /** * Get a block by its name, resolving in the following order: * - override blocks specified when initialized (except when excluded) * - blocks resolved from the associated template * - blocks resolved from the parent template when extending * * @param {String} name The name of the block to return. * @param {Boolean} checkOnlyInheritedBlocks Whether to skip checking the overrides and associated template, will not skip by default. * * @return {Twig.Block|undefined} */ Twig.ParseState.prototype.getBlock = function (name, checkOnlyInheritedBlocks) { let block; if (checkOnlyInheritedBlocks !== true) { // Blocks specified when initialized block = this.overrideBlocks[name]; } if (block === undefined) { // Block defined by the associated template block = this.template.getBlock(name, checkOnlyInheritedBlocks); } if (block === undefined && this.template.parentTemplate !== null) { // Block defined in the parent template when extending block = this.template.parentTemplate.getBlock(name); } return block; }; /** * Get all the available blocks, resolving in the following order: * - override blocks specified when initialized * - blocks resolved from the associated template * - blocks resolved from the parent template when extending (except when excluded) * * @param {Boolean} includeParentBlocks Whether to get blocks from the parent template when extending, will always do so by default. * * @return {Object} */ Twig.ParseState.prototype.getBlocks = function (includeParentBlocks) { let blocks = {}; if (includeParentBlocks !== false && this.template.parentTemplate !== null && // Prevent infinite loop this.template.parentTemplate !== this.template ) { // Blocks from the parent template when extending blocks = this.template.parentTemplate.getBlocks(); } blocks = { ...blocks, // Override with any blocks defined within the associated template ...this.template.getBlocks(), // Override with any blocks specified when initialized ...this.overrideBlocks }; return blocks; }; /** * Get the closest token of a specific type to the current nest level. * * @param {String} type The logic token type * * @return {Object} */ Twig.ParseState.prototype.getNestingStackToken = function (type) { let matchingToken; this.nestingStack.forEach(token => { if (matchingToken === undefined && token.type === type) { matchingToken = token; } }); return matchingToken; }; /** * Parse a set of tokens using the current state. * * @param {Array} tokens The compiled tokens. * @param {Object} context The context to set the state to while parsing. * @param {Boolean} allowAsync Whether to parse asynchronously. * @param {Object} blocks Blocks that should override any defined while parsing. * * @return {String} The rendered tokens. * */ Twig.ParseState.prototype.parse = function (tokens, context, allowAsync) { const state = this; let output = []; // Store any error that might be thrown by the promise chain. let err = null; // This will be set to isAsync if template renders synchronously let isAsync = true; let promise = null; // Track logic chains let chain = true; if (context) { state.context = context; } /* * Extracted into it's own function such that the function * does not get recreated over and over again in the `forEach` * loop below. This method can be compiled and optimized * a single time instead of being recreated on each iteration. */ function outputPush(o) { output.push(o); } function parseTokenLogic(logic) { if (typeof logic.chain !== 'undefined') { chain = logic.chain; } if (typeof logic.context !== 'undefined') { state.context = logic.context; } if (typeof logic.output !== 'undefined') { output.push(logic.output); } } promise = Twig.async.forEach(tokens, token => { Twig.log.debug('Twig.ParseState.parse: ', 'Parsing token: ', token); switch (token.type) { case Twig.token.type.raw: output.push(Twig.filters.raw(token.value)); break; case Twig.token.type.logic: return Twig.logic.parseAsync.call(state, token.token /* logicToken */, state.context, chain) .then(parseTokenLogic); case Twig.token.type.comment: // Do nothing, comments should be ignored break; // Fall through whitespace to output case Twig.token.type.outputWhitespacePre: case Twig.token.type.outputWhitespacePost: case Twig.token.type.outputWhitespaceBoth: case Twig.token.type.output: Twig.log.debug('Twig.ParseState.parse: ', 'Output token: ', token.stack); // Parse the given expression in the given context return Twig.expression.parseAsync.call(state, token.stack, state.context) .then(outputPush); default: break; } }).then(() => { output = Twig.output.call(state.template, output); isAsync = false; return output; }).catch(error => { if (allowAsync) { handleException(state, error); } err = error; }); // If `allowAsync` we will always return a promise since we do not // know in advance if we are going to run asynchronously or not. if (allowAsync) { return promise; } // Handle errors here if we fail synchronously. if (err !== null) { return handleException(state, err); } // If `allowAsync` is not true we should not allow the user // to use asynchronous functions or filters. if (isAsync) { throw new Twig.Error('You are using Twig.js in sync mode in combination with async extensions.'); } return output; }; /** * Create a new twig.js template. * * Parameters: { * data: The template, either pre-compiled tokens or a string template * id: The name of this template * } * * @param {Object} params The template parameters. */ Twig.Template = function (params) { const {data, id, base, path, url, name, method, options} = params; // # What is stored in a Twig.Template // // The Twig Template hold several chucks of data. // // { // id: The token ID (if any) // tokens: The list of tokens that makes up this template. // base: The base template (if any) // options: { // Compiler/parser options // // strict_variables: true/false // Should missing variable/keys emit an error message. If false, they default to null. // } // } // this.base = base; this.blocks = { defined: {}, imported: {} }; this.id = id; this.method = method; this.name = name; this.options = options; this.parentTemplate = null; this.path = path; this.url = url; if (is('String', data)) { this.tokens = Twig.prepare.call(this, data); } else { this.tokens = data; } if (id !== undefined) { Twig.Templates.save(this); } }; /** * Get a block by its name, resolving in the following order: * - blocks defined in the template itself * - blocks imported from another template * * @param {String} name The name of the block to return. * @param {Boolean} checkOnlyInheritedBlocks Whether to skip checking the blocks defined in the template itself, will not skip by default. * * @return {Twig.Block|undefined} */ Twig.Template.prototype.getBlock = function (name, checkOnlyInheritedBlocks, checkImports = true) { let block; if (checkOnlyInheritedBlocks !== true) { block = this.blocks.defined[name]; } if (checkImports && block === undefined) { block = this.blocks.imported[name]; } if (block === undefined && this.parentTemplate !== null) { /** * Block defined in the parent template when extending. * This recursion is useful to inherit from ascendants. * But take care of not considering ascendants' {% use %} */ block = this.parentTemplate.getBlock(name, checkOnlyInheritedBlocks, checkImports = false); } return block; }; /** * Get all the available blocks, resolving in the following order: * - blocks defined in the template itself * - blocks imported from other templates * * @return {Object} */ Twig.Template.prototype.getBlocks = function () { let blocks = {}; blocks = { ...blocks, // Get any blocks imported from other templates ...this.blocks.imported, // Override with any blocks defined within the template itself ...this.blocks.defined }; return blocks; }; Twig.Template.prototype.render = function (context, params, allowAsync) { const template = this; params = params || {}; return Twig.async.potentiallyAsync(template, allowAsync, () => { const state = new Twig.ParseState(template, params.blocks, context); return state.parseAsync(template.tokens) .then(output => { let parentTemplate; let url; if (template.parentTemplate !== null) { // This template extends another template if (template.options.allowInlineIncludes) { // The template is provided inline parentTemplate = Twig.Templates.load(template.parentTemplate); if (parentTemplate) { parentTemplate.options = template.options; } } // Check for the template file via include if (!parentTemplate) { url = Twig.path.parsePath(template, template.parentTemplate); parentTemplate = Twig.Templates.loadRemote(url, { method: template.getLoaderMethod(), base: template.base, async: false, id: url, options: template.options }); } template.parentTemplate = parentTemplate; return template.parentTemplate.renderAsync( state.context, { blocks: state.getBlocks(false), isInclude: true } ); } if (params.isInclude === true) { return output; } return output.valueOf(); }); }); }; Twig.Template.prototype.importFile = function (file) { let url = null; let subTemplate; if (!this.url && this.options.allowInlineIncludes) { file = this.path ? Twig.path.parsePath(this, file) : file; subTemplate = Twig.Templates.load(file); if (!subTemplate) { subTemplate = Twig.Templates.loadRemote(url, { id: file, method: this.getLoaderMethod(), async: false, path: file, options: this.options }); if (!subTemplate) { throw new Twig.Error('Unable to find the template ' + file); } } subTemplate.options = this.options; return subTemplate; } url = Twig.path.parsePath(this, file); // Load blocks from an external file subTemplate = Twig.Templates.loadRemote(url, { method: this.getLoaderMethod(), base: this.base, async: false, options: this.options, id: url }); return subTemplate; }; Twig.Template.prototype.getLoaderMethod = function () { if (this.path) { return 'fs'; } if (this.url) { return 'ajax'; } return this.method || 'fs'; }; Twig.Template.prototype.compile = function (options) { // Compile the template into raw JS return Twig.compiler.compile(this, options); }; /** * Create safe output * * @param {string} Content safe to output * * @return {String} Content wrapped into a String */ Twig.Markup = function (content, strategy) { if (typeof content !== 'string') { return content; } /* eslint-disable no-new-wrappers, unicorn/new-for-builtins */ const output = new String(content); /* eslint-enable */ output.twigMarkup = (typeof strategy === 'undefined') ? true : strategy; return output; }; return Twig; }; /***/ }), /***/ "./node_modules/twig/src/twig.exports.js": /*!***********************************************!*\ !*** ./node_modules/twig/src/twig.exports.js ***! \***********************************************/ /***/ ((module) => { // ## twig.exports.js // // This file provides extension points and other hooks into the twig functionality. module.exports = function (Twig) { 'use strict'; Twig.exports = { VERSION: Twig.VERSION }; /** * Create and compile a twig.js template. * * @param {Object} param Paramteres for creating a Twig template. * * @return {Twig.Template} A Twig template ready for rendering. */ Twig.exports.twig = function (params) { 'use strict'; const {id} = params; const options = { strictVariables: params.strict_variables || false, // TODO: turn autoscape on in the next major version autoescape: (params.autoescape !== null && params.autoescape) || false, allowInlineIncludes: params.allowInlineIncludes || false, rethrow: params.rethrow || false, namespaces: params.namespaces }; if (Twig.cache && id) { Twig.validateId(id); } if (params.debug !== undefined) { Twig.debug = params.debug; } if (params.trace !== undefined) { Twig.trace = params.trace; } if (params.data !== undefined) { return Twig.Templates.parsers.twig({ data: params.data, path: Object.hasOwnProperty.call(params, 'path') ? params.path : undefined, module: params.module, id, options }); } if (params.ref !== undefined) { if (params.id !== undefined) { throw new Twig.Error('Both ref and id cannot be set on a twig.js template.'); } return Twig.Templates.load(params.ref); } if (params.method !== undefined) { if (!Twig.Templates.isRegisteredLoader(params.method)) { throw new Twig.Error('Loader for "' + params.method + '" is not defined.'); } return Twig.Templates.loadRemote(params.name || params.href || params.path || id || undefined, { id, method: params.method, parser: params.parser || 'twig', base: params.base, module: params.module, precompiled: params.precompiled, async: params.async, options }, params.load, params.error); } if (params.href !== undefined) { return Twig.Templates.loadRemote(params.href, { id, method: 'ajax', parser: params.parser || 'twig', base: params.base, module: params.module, precompiled: params.precompiled, async: params.async, options }, params.load, params.error); } if (params.path !== undefined) { return Twig.Templates.loadRemote(params.path, { id, method: 'fs', parser: params.parser || 'twig', base: params.base, module: params.module, precompiled: params.precompiled, async: params.async, options }, params.load, params.error); } }; // Extend Twig with a new filter. Twig.exports.extendFilter = function (filter, definition) { Twig.filter.extend(filter, definition); }; // Extend Twig with a new function. Twig.exports.extendFunction = function (fn, definition) { Twig._function.extend(fn, definition); }; // Extend Twig with a new test. Twig.exports.extendTest = function (test, definition) { Twig.test.extend(test, definition); }; // Extend Twig with a new definition. Twig.exports.extendTag = function (definition) { Twig.logic.extend(definition); }; // Provide an environment for extending Twig core. // Calls fn with the internal Twig object. Twig.exports.extend = function (fn) { fn(Twig); }; /** * Provide an extension for use with express 2. * * @param {string} markup The template markup. * @param {array} options The express options. * * @return {string} The rendered template. */ Twig.exports.compile = function (markup, options) { const id = options.filename; const path = options.filename; // Try to load the template from the cache const template = new Twig.Template({ data: markup, path, id, options: options.settings['twig options'] }); // Twig.Templates.load(id) || return function (context) { return template.render(context); }; }; /** * Provide an extension for use with express 3. * * @param {string} path The location of the template file on disk. * @param {Object|Function} The options or callback. * @param {Function} fn callback. * * @throws Twig.Error */ Twig.exports.renderFile = function (path, options, fn) { // Handle callback in options if (typeof options === 'function') { fn = options; options = {}; } options = options || {}; const settings = options.settings || {}; // Mixin any options provided to the express app. const viewOptions = settings['twig options']; const params = { path, base: settings.views, load(template) { // Render and return template as a simple string, see https://github.com/twigjs/twig.js/pull/348 for more information if (!viewOptions || !viewOptions.allowAsync) { fn(null, String(template.render(options))); return; } template.renderAsync(options) .then(out => fn(null, out), fn); }, error(err) { fn(err); } }; if (viewOptions) { for (const option in viewOptions) { if (Object.hasOwnProperty.call(viewOptions, option)) { params[option] = viewOptions[option]; } } } Twig.exports.twig(params); }; // Express 3 handler Twig.exports.__express = Twig.exports.renderFile; /** * Shoud Twig.js cache templates. * Disable during development to see changes to templates without * reloading, and disable in production to improve performance. * * @param {boolean} cache */ Twig.exports.cache = function (cache) { Twig.cache = cache; }; // We need to export the path module so we can effectively test it Twig.exports.path = Twig.path; // Export our filters. // Resolves #307 Twig.exports.filters = Twig.filters; // Export our tests. Twig.exports.tests = Twig.tests; // Export our functions. Twig.exports.functions = Twig.functions; Twig.exports.Promise = Twig.Promise; return Twig; }; /***/ }), /***/ "./node_modules/twig/src/twig.expression.js": /*!**************************************************!*\ !*** ./node_modules/twig/src/twig.expression.js ***! \**************************************************/ /***/ ((module, __unused_webpack_exports, __webpack_require__) => { // ## twig.expression.js // // This file handles tokenizing, compiling and parsing expressions. module.exports = function (Twig) { 'use strict'; function parseParams(state, params, context) { if (params) { return Twig.expression.parseAsync.call(state, params, context); } return Twig.Promise.resolve(false); } /** * Namespace for expression handling. */ Twig.expression = { }; __webpack_require__(/*! ./twig.expression.operator */ "./node_modules/twig/src/twig.expression.operator.js")(Twig); /** * Reserved word that can't be used as variable names. */ Twig.expression.reservedWords = [ 'true', 'false', 'null', 'TRUE', 'FALSE', 'NULL', '_context', 'and', 'b-and', 'or', 'b-or', 'b-xor', 'in', 'not in', 'if', 'matches', 'starts', 'ends', 'with' ]; /** * The type of tokens used in expressions. */ Twig.expression.type = { comma: 'Twig.expression.type.comma', operator: { unary: 'Twig.expression.type.operator.unary', binary: 'Twig.expression.type.operator.binary' }, string: 'Twig.expression.type.string', bool: 'Twig.expression.type.bool', slice: 'Twig.expression.type.slice', array: { start: 'Twig.expression.type.array.start', end: 'Twig.expression.type.array.end' }, object: { start: 'Twig.expression.type.object.start', end: 'Twig.expression.type.object.end' }, parameter: { start: 'Twig.expression.type.parameter.start', end: 'Twig.expression.type.parameter.end' }, subexpression: { start: 'Twig.expression.type.subexpression.start', end: 'Twig.expression.type.subexpression.end' }, key: { period: 'Twig.expression.type.key.period', brackets: 'Twig.expression.type.key.brackets' }, filter: 'Twig.expression.type.filter', _function: 'Twig.expression.type._function', variable: 'Twig.expression.type.variable', number: 'Twig.expression.type.number', _null: 'Twig.expression.type.null', context: 'Twig.expression.type.context', test: 'Twig.expression.type.test' }; Twig.expression.set = { // What can follow an expression (in general) operations: [ Twig.expression.type.filter, Twig.expression.type.operator.unary, Twig.expression.type.operator.binary, Twig.expression.type.array.end, Twig.expression.type.object.end, Twig.expression.type.parameter.end, Twig.expression.type.subexpression.end, Twig.expression.type.comma, Twig.expression.type.test ], expressions: [ Twig.expression.type._function, Twig.expression.type.bool, Twig.expression.type.string, Twig.expression.type.variable, Twig.expression.type.number, Twig.expression.type._null, Twig.expression.type.context, Twig.expression.type.parameter.start, Twig.expression.type.array.start, Twig.expression.type.object.start, Twig.expression.type.subexpression.start, Twig.expression.type.operator.unary ] }; // Most expressions allow a '.' or '[' after them, so we provide a convenience set Twig.expression.set.operationsExtended = Twig.expression.set.operations.concat([ Twig.expression.type.key.period, Twig.expression.type.key.brackets, Twig.expression.type.slice ]); // Some commonly used compile and parse functions. Twig.expression.fn = { compile: { push(token, stack, output) { output.push(token); }, pushBoth(token, stack, output) { output.push(token); stack.push(token); } }, parse: { push(token, stack) { stack.push(token); }, pushValue(token, stack) { stack.push(token.value); } } }; // The regular expressions and compile/parse logic used to match tokens in expressions. // // Properties: // // type: The type of expression this matches // // regex: One or more regular expressions that matche the format of the token. // // next: Valid tokens that can occur next in the expression. // // Functions: // // compile: A function that compiles the raw regular expression match into a token. // // parse: A function that parses the compiled token into output. // Twig.expression.definitions = [ { type: Twig.expression.type.test, regex: /^is\s+(not)?\s*([a-zA-Z_]\w*(\s?(?:as|by))?)/, next: Twig.expression.set.operations.concat([Twig.expression.type.parameter.start]), compile(token, stack, output) { token.filter = token.match[2]; token.modifier = token.match[1]; delete token.match; delete token.value; output.push(token); }, parse(token, stack, context) { const value = stack.pop(); const state = this; return parseParams(state, token.params, context) .then(params => { const result = Twig.test(token.filter, value, params); if (token.modifier === 'not') { stack.push(!result); } else { stack.push(result); } }); } }, { type: Twig.expression.type.comma, // Match a comma regex: /^,/, next: Twig.expression.set.expressions.concat([Twig.expression.type.array.end, Twig.expression.type.object.end]), compile(token, stack, output) { let i = stack.length - 1; let stackToken; delete token.match; delete token.value; // Pop tokens off the stack until the start of the object for (;i >= 0; i--) { stackToken = stack.pop(); if (stackToken.type === Twig.expression.type.object.start || stackToken.type === Twig.expression.type.parameter.start || stackToken.type === Twig.expression.type.array.start) { stack.push(stackToken); break; } output.push(stackToken); } output.push(token); } }, { /** * Match a number (integer or decimal) */ type: Twig.expression.type.number, // Match a number regex: /^-?\d+(\.\d+)?/, next: Twig.expression.set.operations, compile(token, stack, output) { token.value = Number(token.value); output.push(token); }, parse: Twig.expression.fn.parse.pushValue }, { type: Twig.expression.type.operator.binary, // Match any of ??, ?:, +, *, /, -, %, ~, <=>, <, <=, >, >=, !=, ==, **, ?, :, and, b-and, or, b-or, b-xor, in, not in // and, or, in, not in, matches, starts with, ends with can be followed by a space or parenthesis regex: /(^\?\?|^\?:|^(b-and)|^(b-or)|^(b-xor)|^[+\-~%?]|^(<=>)|^[:](?!\d\])|^[!=]==?|^[!<>]=?|^\*\*?|^\/\/?|^(and)[(|\s+]|^(or)[(|\s+]|^(in)[(|\s+]|^(not in)[(|\s+]|^(matches)|^(starts with)|^(ends with)|^\.\.)/, next: Twig.expression.set.expressions, transform(match, tokens) { switch (match[0]) { case 'and(': case 'or(': case 'in(': case 'not in(': // Strip off the ( if it exists tokens[tokens.length - 1].value = match[2]; return match[0]; default: return ''; } }, compile(token, stack, output) { delete token.match; token.value = token.value.trim(); const {value} = token; const operator = Twig.expression.operator.lookup(value, token); Twig.log.trace('Twig.expression.compile: ', 'Operator: ', operator, ' from ', value); while (stack.length > 0 && (stack[stack.length - 1].type === Twig.expression.type.operator.unary || stack[stack.length - 1].type === Twig.expression.type.operator.binary) && ( (operator.associativity === Twig.expression.operator.leftToRight && operator.precidence >= stack[stack.length - 1].precidence) || (operator.associativity === Twig.expression.operator.rightToLeft && operator.precidence > stack[stack.length - 1].precidence) ) ) { const temp = stack.pop(); output.push(temp); } if (value === ':') { // Check if this is a ternary or object key being set if (stack[stack.length - 1] && stack[stack.length - 1].value === '?') { // Continue as normal for a ternary } else { // This is not a ternary so we push the token to the output where it can be handled // when the assocated object is closed. const keyToken = output.pop(); if (keyToken.type === Twig.expression.type.string || keyToken.type === Twig.expression.type.variable) { token.key = keyToken.value; } else if (keyToken.type === Twig.expression.type.number) { // Convert integer keys into string keys token.key = keyToken.value.toString(); } else if (keyToken.expression && (keyToken.type === Twig.expression.type.parameter.end || keyToken.type === Twig.expression.type.subexpression.end)) { token.params = keyToken.params; } else { throw new Twig.Error('Unexpected value before \':\' of ' + keyToken.type + ' = ' + keyToken.value); } output.push(token); } } else { stack.push(operator); } }, parse(token, stack, context) { const state = this; if (token.key) { // Handle ternary ':' operator stack.push(token); } else if (token.params) { // Handle "{(expression):value}" return Twig.expression.parseAsync.call(state, token.params, context) .then(key => { token.key = key; stack.push(token); // If we're in a loop, we might need token.params later, especially in this form of "(expression):value" if (!context.loop) { delete (token.params); } }); } else { Twig.expression.operator.parse(token.value, stack); } } }, { type: Twig.expression.type.operator.unary, // Match any of not regex: /(^not\s+)/, next: Twig.expression.set.expressions, compile(token, stack, output) { delete token.match; token.value = token.value.trim(); const {value} = token; const operator = Twig.expression.operator.lookup(value, token); Twig.log.trace('Twig.expression.compile: ', 'Operator: ', operator, ' from ', value); while (stack.length > 0 && (stack[stack.length - 1].type === Twig.expression.type.operator.unary || stack[stack.length - 1].type === Twig.expression.type.operator.binary) && ( (operator.associativity === Twig.expression.operator.leftToRight && operator.precidence >= stack[stack.length - 1].precidence) || (operator.associativity === Twig.expression.operator.rightToLeft && operator.precidence > stack[stack.length - 1].precidence) ) ) { const temp = stack.pop(); output.push(temp); } stack.push(operator); }, parse(token, stack) { Twig.expression.operator.parse(token.value, stack); } }, { /** * Match a string. This is anything between a pair of single or double quotes. */ type: Twig.expression.type.string, // See: http://blog.stevenlevithan.com/archives/match-quoted-string regex: /^(["'])(?:(?=(\\?))\2[\s\S])*?\1/, next: Twig.expression.set.operationsExtended, compile(token, stack, output) { let {value} = token; delete token.match; // Remove the quotes from the string if (value.slice(0, 1) === '"') { value = value.replace('\\"', '"'); } else { value = value.replace('\\\'', '\''); } token.value = value.slice(1, -1).replace(/\\n/g, '\n').replace(/\\r/g, '\r'); Twig.log.trace('Twig.expression.compile: ', 'String value: ', token.value); output.push(token); }, parse: Twig.expression.fn.parse.pushValue }, { /** * Match a subexpression set start. */ type: Twig.expression.type.subexpression.start, regex: /^\(/, next: Twig.expression.set.expressions.concat([Twig.expression.type.subexpression.end]), compile(token, stack, output) { token.value = '('; output.push(token); stack.push(token); }, parse: Twig.expression.fn.parse.push }, { /** * Match a subexpression set end. */ type: Twig.expression.type.subexpression.end, regex: /^\)/, next: Twig.expression.set.operationsExtended, validate(match, tokens) { // Iterate back through previous tokens to ensure we follow a subexpression start let i = tokens.length - 1; let foundSubexpressionStart = false; let nextSubexpressionStartInvalid = false; let unclosedParameterCount = 0; while (!foundSubexpressionStart && i >= 0) { const token = tokens[i]; foundSubexpressionStart = token.type === Twig.expression.type.subexpression.start; // If we have previously found a subexpression end, then this subexpression start is the start of // that subexpression, not the subexpression we are searching for if (foundSubexpressionStart && nextSubexpressionStartInvalid) { nextSubexpressionStartInvalid = false; foundSubexpressionStart = false; } // Count parameter tokens to ensure we dont return truthy for a parameter opener if (token.type === Twig.expression.type.parameter.start) { unclosedParameterCount++; } else if (token.type === Twig.expression.type.parameter.end) { unclosedParameterCount--; } else if (token.type === Twig.expression.type.subexpression.end) { nextSubexpressionStartInvalid = true; } i--; } // If we found unclosed parameters, return false // If we didnt find subexpression start, return false // Otherwise return true return (foundSubexpressionStart && (unclosedParameterCount === 0)); }, compile(token, stack, output) { // This is basically a copy of parameter end compilation let stackToken; const endToken = token; stackToken = stack.pop(); while (stack.length > 0 && stackToken.type !== Twig.expression.type.subexpression.start) { output.push(stackToken); stackToken = stack.pop(); } // Move contents of parens into preceding filter const paramStack = []; while (token.type !== Twig.expression.type.subexpression.start) { // Add token to arguments stack paramStack.unshift(token); token = output.pop(); } paramStack.unshift(token); // If the token at the top of the *stack* is a function token, pop it onto the output queue. // Get the token preceding the parameters stackToken = stack[stack.length - 1]; if (stackToken === undefined || (stackToken.type !== Twig.expression.type._function && stackToken.type !== Twig.expression.type.filter && stackToken.type !== Twig.expression.type.test && stackToken.type !== Twig.expression.type.key.brackets)) { endToken.expression = true; // Remove start and end token from stack paramStack.pop(); paramStack.shift(); endToken.params = paramStack; output.push(endToken); } else { // This should never be hit endToken.expression = false; stackToken.params = paramStack; } }, parse(token, stack, context) { const state = this; if (token.expression) { return Twig.expression.parseAsync.call(state, token.params, context) .then(value => { stack.push(value); }); } throw new Twig.Error('Unexpected subexpression end when token is not marked as an expression'); } }, { /** * Match a parameter set start. */ type: Twig.expression.type.parameter.start, regex: /^\(/, next: Twig.expression.set.expressions.concat([Twig.expression.type.parameter.end]), validate(match, tokens) { const lastToken = tokens[tokens.length - 1]; // We can't use the regex to test if we follow a space because expression is trimmed return lastToken && (!Twig.expression.reservedWords.includes(lastToken.value.trim())); }, compile: Twig.expression.fn.compile.pushBoth, parse: Twig.expression.fn.parse.push }, { /** * Match a parameter set end. */ type: Twig.expression.type.parameter.end, regex: /^\)/, next: Twig.expression.set.operationsExtended, compile(token, stack, output) { let stackToken; const endToken = token; stackToken = stack.pop(); while (stack.length > 0 && stackToken.type !== Twig.expression.type.parameter.start) { output.push(stackToken); stackToken = stack.pop(); } // Move contents of parens into preceding filter const paramStack = []; while (token.type !== Twig.expression.type.parameter.start) { // Add token to arguments stack paramStack.unshift(token); token = output.pop(); } paramStack.unshift(token); // Get the token preceding the parameters token = output[output.length - 1]; if (token === undefined || (token.type !== Twig.expression.type._function && token.type !== Twig.expression.type.filter && token.type !== Twig.expression.type.test && token.type !== Twig.expression.type.key.brackets)) { endToken.expression = true; // Remove start and end token from stack paramStack.pop(); paramStack.shift(); endToken.params = paramStack; output.push(endToken); } else { endToken.expression = false; token.params = paramStack; } }, parse(token, stack, context) { const newArray = []; let arrayEnded = false; let value = null; const state = this; if (token.expression) { return Twig.expression.parseAsync.call(state, token.params, context) .then(value => { stack.push(value); }); } while (stack.length > 0) { value = stack.pop(); // Push values into the array until the start of the array if (value && value.type && value.type === Twig.expression.type.parameter.start) { arrayEnded = true; break; } newArray.unshift(value); } if (!arrayEnded) { throw new Twig.Error('Expected end of parameter set.'); } stack.push(newArray); } }, { type: Twig.expression.type.slice, regex: /^\[(-?\w*:-?\w*)\]/, next: Twig.expression.set.operationsExtended, compile(token, stack, output) { const sliceRange = token.match[1].split(':'); // SliceStart can be undefined when we pass parameters to the slice filter later const sliceStart = sliceRange[0]; const sliceEnd = sliceRange[1]; token.value = 'slice'; token.params = [sliceStart, sliceEnd]; // SliceEnd can't be undefined as the slice filter doesn't check for this, but it does check the length // of the params array, so just shorten it. if (!sliceEnd) { token.params = [sliceStart]; } output.push(token); }, parse(token, stack, context) { const input = stack.pop(); let {params} = token; const state = this; if (parseInt(params[0], 10).toString() === params[0]) { params[0] = parseInt(params[0], 10); } else { const value = context[params[0]]; if (state.template.options.strictVariables && value === undefined) { throw new Twig.Error('Variable "' + params[0] + '" does not exist.'); } params[0] = value; } if (params[1]) { if (parseInt(params[1], 10).toString() === params[1]) { params[1] = parseInt(params[1], 10); } else { const value = context[params[1]]; if (state.template.options.strictVariables && value === undefined) { throw new Twig.Error('Variable "' + params[1] + '" does not exist.'); } if (value === undefined) { params = [params[0]]; } else { params[1] = value; } } } stack.push(Twig.filter.call(state, token.value, input, params)); } }, { /** * Match an array start. */ type: Twig.expression.type.array.start, regex: /^\[/, next: Twig.expression.set.expressions.concat([Twig.expression.type.array.end]), compile: Twig.expression.fn.compile.pushBoth, parse: Twig.expression.fn.parse.push }, { /** * Match an array end. */ type: Twig.expression.type.array.end, regex: /^\]/, next: Twig.expression.set.operationsExtended, compile(token, stack, output) { let i = stack.length - 1; let stackToken; // Pop tokens off the stack until the start of the object for (;i >= 0; i--) { stackToken = stack.pop(); if (stackToken.type === Twig.expression.type.array.start) { break; } output.push(stackToken); } output.push(token); }, parse(token, stack) { const newArray = []; let arrayEnded = false; let value = null; while (stack.length > 0) { value = stack.pop(); // Push values into the array until the start of the array if (value && value.type && value.type === Twig.expression.type.array.start) { arrayEnded = true; break; } newArray.unshift(value); } if (!arrayEnded) { throw new Twig.Error('Expected end of array.'); } stack.push(newArray); } }, // Token that represents the start of a hash map '}' // // Hash maps take the form: // { "key": 'value', "another_key": item } // // Keys must be quoted (either single or double) and values can be any expression. { type: Twig.expression.type.object.start, regex: /^\{/, next: Twig.expression.set.expressions.concat([Twig.expression.type.object.end]), compile: Twig.expression.fn.compile.pushBoth, parse: Twig.expression.fn.parse.push }, // Token that represents the end of a Hash Map '}' // // This is where the logic for building the internal // representation of a hash map is defined. { type: Twig.expression.type.object.end, regex: /^\}/, next: Twig.expression.set.operationsExtended, compile(token, stack, output) { let i = stack.length - 1; let stackToken; // Pop tokens off the stack until the start of the object for (;i >= 0; i--) { stackToken = stack.pop(); if (stackToken && stackToken.type === Twig.expression.type.object.start) { break; } output.push(stackToken); } output.push(token); }, parse(endToken, stack) { const newObject = {}; let objectEnded = false; let token = null; let hasValue = false; let value = null; while (stack.length > 0) { token = stack.pop(); // Push values into the array until the start of the object if (token && token.type && token.type === Twig.expression.type.object.start) { objectEnded = true; break; } if (token && token.type && (token.type === Twig.expression.type.operator.binary || token.type === Twig.expression.type.operator.unary) && token.key) { if (!hasValue) { throw new Twig.Error('Missing value for key \'' + token.key + '\' in object definition.'); } newObject[token.key] = value; // Preserve the order that elements are added to the map // This is necessary since JavaScript objects don't // guarantee the order of keys if (newObject._keys === undefined) { newObject._keys = []; } newObject._keys.unshift(token.key); // Reset value check value = null; hasValue = false; } else { hasValue = true; value = token; } } if (!objectEnded) { throw new Twig.Error('Unexpected end of object.'); } stack.push(newObject); } }, // Token representing a filter // // Filters can follow any expression and take the form: // expression|filter(optional, args) // // Filter parsing is done in the Twig.filters namespace. { type: Twig.expression.type.filter, // Match a | then a letter or _, then any number of letters, numbers, _ or - regex: /^\|\s?([a-zA-Z_][a-zA-Z0-9_-]*)/, next: Twig.expression.set.operationsExtended.concat([ Twig.expression.type.parameter.start ]), compile(token, stack, output) { token.value = token.match[1]; output.push(token); }, parse(token, stack, context) { const input = stack.pop(); const state = this; return parseParams(state, token.params, context) .then(params => { return Twig.filter.call(state, token.value, input, params); }) .then(value => { stack.push(value); }); } }, { type: Twig.expression.type._function, // Match any letter or _, then any number of letters, numbers, _ or - followed by ( regex: /^([a-zA-Z_]\w*)\s*\(/, next: Twig.expression.type.parameter.start, validate(match) { // Make sure this function is not a reserved word return match[1] && (!Twig.expression.reservedWords.includes(match[1])); }, transform() { return '('; }, compile(token, stack, output) { const fn = token.match[1]; token.fn = fn; // Cleanup token delete token.match; delete token.value; output.push(token); }, parse(token, stack, context) { const state = this; const {fn} = token; let value; return parseParams(state, token.params, context) .then(params => { if (Twig.functions[fn]) { // Get the function from the built-in functions value = Twig.functions[fn].apply(state, params); } else if (typeof context[fn] === 'function') { // Get the function from the user/context defined functions value = context[fn](...params); } else { throw new Twig.Error(fn + ' function does not exist and is not defined in the context'); } return value; }) .then(result => { stack.push(result); }); } }, // Token representing a variable. // // Variables can contain letters, numbers, underscores and // dashes, but must start with a letter or underscore. // // Variables are retrieved from the render context and take // the value of 'undefined' if the given variable doesn't // exist in the context. { type: Twig.expression.type.variable, // Match any letter or _, then any number of letters, numbers, _ or - regex: /^[a-zA-Z_]\w*/, next: Twig.expression.set.operationsExtended.concat([ Twig.expression.type.parameter.start ]), compile: Twig.expression.fn.compile.push, validate(match) { return (!Twig.expression.reservedWords.includes(match[0])); }, parse(token, stack, context) { const state = this; // Get the variable from the context return Twig.expression.resolveAsync.call(state, context[token.value], context) .then(value => { if (state.template.options.strictVariables && value === undefined) { throw new Twig.Error('Variable "' + token.value + '" does not exist.'); } stack.push(value); }); } }, { type: Twig.expression.type.key.period, regex: /^\.(\w+)/, next: Twig.expression.set.operationsExtended.concat([ Twig.expression.type.parameter.start ]), compile(token, stack, output) { token.key = token.match[1]; delete token.match; delete token.value; output.push(token); }, parse(token, stack, context, nextToken) { const state = this; const {key} = token; const object = stack.pop(); let value; if (object && !Object.prototype.hasOwnProperty.call(object, key) && state.template.options.strictVariables) { const keys = Object.keys(object); if (keys.length > 0) { throw new Twig.Error('Key "' + key + '" for object with keys "' + Object.keys(object).join(', ') + '" does not exist.'); } else { throw new Twig.Error('Key "' + key + '" does not exist as the object is empty.'); } } return parseParams(state, token.params, context) .then(params => { if (object === null || object === undefined) { value = undefined; } else { const capitalize = function (value) { return value.slice(0, 1).toUpperCase() + value.slice(1); }; // Get the variable from the context if (typeof object === 'object' && key in object) { value = object[key]; } else if (object['get' + capitalize(key)]) { value = object['get' + capitalize(key)]; } else if (object['is' + capitalize(key)]) { value = object['is' + capitalize(key)]; } else { value = undefined; } } // When resolving an expression we need to pass nextToken in case the expression is a function return Twig.expression.resolveAsync.call(state, value, context, params, nextToken, object); }) .then(result => { stack.push(result); }); } }, { type: Twig.expression.type.key.brackets, regex: /^\[([^\]]*)\]/, next: Twig.expression.set.operationsExtended.concat([ Twig.expression.type.parameter.start ]), compile(token, stack, output) { const match = token.match[1]; delete token.value; delete token.match; // The expression stack for the key token.stack = Twig.expression.compile({ value: match }).stack; output.push(token); }, parse(token, stack, context, nextToken) { // Evaluate key const state = this; let params = null; let object; let value; return parseParams(state, token.params, context) .then(parameters => { params = parameters; return Twig.expression.parseAsync.call(state, token.stack, context); }) .then(key => { object = stack.pop(); if (object && !Object.prototype.hasOwnProperty.call(object, key) && state.template.options.strictVariables) { const keys = Object.keys(object); if (keys.length > 0) { throw new Twig.Error('Key "' + key + '" for array with keys "' + keys.join(', ') + '" does not exist.'); } else { throw new Twig.Error('Key "' + key + '" does not exist as the array is empty.'); } } else if (object === null || object === undefined) { return null; } // Get the variable from the context if (typeof object === 'object' && key in object) { value = object[key]; } else { value = null; } // When resolving an expression we need to pass nextToken in case the expression is a function return Twig.expression.resolveAsync.call(state, value, object, params, nextToken); }) .then(result => { stack.push(result); }); } }, { /** * Match a null value. */ type: Twig.expression.type._null, // Match a number regex: /^(null|NULL|none|NONE)/, next: Twig.expression.set.operations, compile(token, stack, output) { delete token.match; token.value = null; output.push(token); }, parse: Twig.expression.fn.parse.pushValue }, { /** * Match the context */ type: Twig.expression.type.context, regex: /^_context/, next: Twig.expression.set.operationsExtended.concat([ Twig.expression.type.parameter.start ]), compile: Twig.expression.fn.compile.push, parse(token, stack, context) { stack.push(context); } }, { /** * Match a boolean */ type: Twig.expression.type.bool, regex: /^(true|TRUE|false|FALSE)/, next: Twig.expression.set.operations, compile(token, stack, output) { token.value = (token.match[0].toLowerCase() === 'true'); delete token.match; output.push(token); }, parse: Twig.expression.fn.parse.pushValue } ]; /** * Resolve a context value. * * If the value is a function, it is executed with a context parameter. * * @param {string} key The context object key. * @param {Object} context The render context. */ Twig.expression.resolveAsync = function (value, context, params, nextToken, object) { const state = this; if (typeof value !== 'function') { return Twig.Promise.resolve(value); } let promise = Twig.Promise.resolve(params); /* If value is a function, it will have been impossible during the compile stage to determine that a following set of parentheses were parameters for this function. Those parentheses will have therefore been marked as an expression, with their own parameters, which really belong to this function. Those parameters will also need parsing in case they are actually an expression to pass as parameters. */ if (nextToken && nextToken.type === Twig.expression.type.parameter.end) { // When parsing these parameters, we need to get them all back, not just the last item on the stack. const tokensAreParameters = true; promise = promise.then(() => { return nextToken.params && Twig.expression.parseAsync.call(state, nextToken.params, context, tokensAreParameters); }) .then(p => { // Clean up the parentheses tokens on the next loop nextToken.cleanup = true; return p; }); } return promise.then(params => { return value.apply(object || context, params || []); }); }; Twig.expression.resolve = function (value, context, params, nextToken, object) { return Twig.async.potentiallyAsync(this, false, function () { return Twig.expression.resolveAsync.call(this, value, context, params, nextToken, object); }); }; /** * Registry for logic handlers. */ Twig.expression.handler = {}; /** * Define a new expression type, available at Twig.logic.type.{type} * * @param {string} type The name of the new type. */ Twig.expression.extendType = function (type) { Twig.expression.type[type] = 'Twig.expression.type.' + type; }; /** * Extend the expression parsing functionality with a new definition. * * Token definitions follow this format: * { * type: One of Twig.expression.type.[type], either pre-defined or added using * Twig.expression.extendType * * next: Array of types from Twig.expression.type that can follow this token, * * regex: A regex or array of regex's that should match the token. * * compile: function(token, stack, output) called when this token is being compiled. * Should return an object with stack and output set. * * parse: function(token, stack, context) called when this token is being parsed. * Should return an object with stack and context set. * } * * @param {Object} definition A token definition. */ Twig.expression.extend = function (definition) { if (!definition.type) { throw new Twig.Error('Unable to extend logic definition. No type provided for ' + definition); } Twig.expression.handler[definition.type] = definition; }; // Extend with built-in expressions while (Twig.expression.definitions.length > 0) { Twig.expression.extend(Twig.expression.definitions.shift()); } /** * Break an expression into tokens defined in Twig.expression.definitions. * * @param {Object} rawToken The string to tokenize. * * @return {Array} An array of tokens. */ Twig.expression.tokenize = function (rawToken) { let expression = rawToken.value; const tokens = []; // Keep an offset of the location in the expression for error messages. let expOffset = 0; // The valid next tokens of the previous token let next = null; // Match information let type; let regex; let regexI; // The possible next token for the match let tokenNext; // Has a match been found from the definitions let matchFound; let invalidMatches = []; const matchFunction = function (...args) { // Don't pass arguments to `Array.slice`, that is a performance killer let matchI = arguments.length - 2; const match = new Array(matchI); while (matchI-- > 0) { match[matchI] = args[matchI]; } Twig.log.trace('Twig.expression.tokenize', 'Matched a ', type, ' regular expression of ', match); if (next && !next.includes(type)) { invalidMatches.push( type + ' cannot follow a ' + tokens[tokens.length - 1].type + ' at template:' + expOffset + ' near \'' + match[0].slice(0, 20) + '...\'' ); // Not a match, don't change the expression return match[0]; } const handler = Twig.expression.handler[type]; // Validate the token if a validation function is provided if (handler.validate && !handler.validate(match, tokens)) { return match[0]; } invalidMatches = []; const token = { type, value: match[0], match }; if (rawToken.position) { token.position = rawToken.position; } tokens.push(token); matchFound = true; next = tokenNext; expOffset += match[0].length; // Does the token need to return output back to the expression string // e.g. a function match of cycle( might return the '(' back to the expression // This allows look-ahead to differentiate between token types (e.g. functions and variable names) if (handler.transform) { return handler.transform(match, tokens); } return ''; }; Twig.log.debug('Twig.expression.tokenize', 'Tokenizing expression ', expression); while (expression.length > 0) { expression = expression.trim(); for (type in Twig.expression.handler) { if (Object.hasOwnProperty.call(Twig.expression.handler, type)) { tokenNext = Twig.expression.handler[type].next; regex = Twig.expression.handler[type].regex; Twig.log.trace('Checking type ', type, ' on ', expression); matchFound = false; if (Array.isArray(regex)) { regexI = regex.length; while (regexI-- > 0) { expression = expression.replace(regex[regexI], matchFunction); } } else { expression = expression.replace(regex, matchFunction); } // An expression token has been matched. Break the for loop and start trying to // match the next template (if expression isn't empty.) if (matchFound) { break; } } } if (!matchFound) { if (invalidMatches.length > 0) { throw new Twig.Error(invalidMatches.join(' OR ')); } else { throw new Twig.Error('Unable to parse \'' + expression + '\' at template position' + expOffset); } } } Twig.log.trace('Twig.expression.tokenize', 'Tokenized to ', tokens); return tokens; }; /** * Compile an expression token. * * @param {Object} rawToken The uncompiled token. * * @return {Object} The compiled token. */ Twig.expression.compile = function (rawToken) { // Tokenize expression const tokens = Twig.expression.tokenize(rawToken); let token = null; const output = []; const stack = []; let tokenTemplate = null; Twig.log.trace('Twig.expression.compile: ', 'Compiling ', rawToken.value); // Push tokens into RPN stack using the Shunting-yard algorithm // See http://en.wikipedia.org/wiki/Shunting_yard_algorithm while (tokens.length > 0) { token = tokens.shift(); tokenTemplate = Twig.expression.handler[token.type]; Twig.log.trace('Twig.expression.compile: ', 'Compiling ', token); // Compile the template tokenTemplate.compile(token, stack, output); Twig.log.trace('Twig.expression.compile: ', 'Stack is', stack); Twig.log.trace('Twig.expression.compile: ', 'Output is', output); } while (stack.length > 0) { output.push(stack.pop()); } Twig.log.trace('Twig.expression.compile: ', 'Final output is', output); rawToken.stack = output; delete rawToken.value; return rawToken; }; /** * Parse an RPN expression stack within a context. * * @param {Array} tokens An array of compiled expression tokens. * @param {Object} context The render context to parse the tokens with. * * @return {Object} The result of parsing all the tokens. The result * can be anything, String, Array, Object, etc... based on * the given expression. */ Twig.expression.parse = function (tokens, context, tokensAreParameters, allowAsync) { const state = this; // If the token isn't an array, make it one. if (!Array.isArray(tokens)) { tokens = [tokens]; } // The output stack const stack = []; const loopTokenFixups = []; const binaryOperator = Twig.expression.type.operator.binary; return Twig.async.potentiallyAsync(state, allowAsync, () => { return Twig.async.forEach(tokens, (token, index) => { let tokenTemplate = null; let nextToken = null; let result; // If the token is marked for cleanup, we don't need to parse it if (token.cleanup) { return; } // Determine the token that follows this one so that we can pass it to the parser if (tokens.length > index + 1) { nextToken = tokens[index + 1]; } tokenTemplate = Twig.expression.handler[token.type]; if (tokenTemplate.parse) { result = tokenTemplate.parse.call(state, token, stack, context, nextToken); } // Store any binary tokens for later if we are in a loop. if (token.type === binaryOperator && context.loop) { loopTokenFixups.push(token); } return result; }) .then(() => { // Check every fixup and remove "key" as long as they still have "params". This covers the use case where // a ":" operator is used in a loop with a "(expression):" statement. We need to be able to evaluate the expression let len = loopTokenFixups.length; let loopTokenFixup = null; while (len-- > 0) { loopTokenFixup = loopTokenFixups[len]; if (loopTokenFixup.params && loopTokenFixup.key) { delete loopTokenFixup.key; } } // If parse has been called with a set of tokens that are parameters, we need to return the whole stack, // wrapped in an Array. if (tokensAreParameters) { const params = stack.splice(0); stack.push(params); } // Pop the final value off the stack return stack.pop(); }); }); }; return Twig; }; /***/ }), /***/ "./node_modules/twig/src/twig.expression.operator.js": /*!***********************************************************!*\ !*** ./node_modules/twig/src/twig.expression.operator.js ***! \***********************************************************/ /***/ ((module) => { // ## twig.expression.operator.js // // This file handles operator lookups and parsing. module.exports = function (Twig) { 'use strict'; /** * Operator associativity constants. */ Twig.expression.operator = { leftToRight: 'leftToRight', rightToLeft: 'rightToLeft' }; const containment = function (a, b) { if (b === undefined || b === null) { return null; } if (b.indexOf !== undefined) { // String return (a === b || a !== '') && b.includes(a); } let el; for (el in b) { if (Object.hasOwnProperty.call(b, el) && b[el] === a) { return true; } } return false; }; /** * Get the precidence and associativity of an operator. These follow the order that C/C++ use. * See http://en.wikipedia.org/wiki/Operators_in_C_and_C++ for the table of values. */ Twig.expression.operator.lookup = function (operator, token) { switch (operator) { case '..': token.precidence = 20; token.associativity = Twig.expression.operator.leftToRight; break; case ',': token.precidence = 18; token.associativity = Twig.expression.operator.leftToRight; break; // Ternary case '?:': case '?': case ':': token.precidence = 16; token.associativity = Twig.expression.operator.rightToLeft; break; // Null-coalescing operator case '??': token.precidence = 15; token.associativity = Twig.expression.operator.rightToLeft; break; case 'or': token.precidence = 14; token.associativity = Twig.expression.operator.leftToRight; break; case 'and': token.precidence = 13; token.associativity = Twig.expression.operator.leftToRight; break; case 'b-or': token.precidence = 12; token.associativity = Twig.expression.operator.leftToRight; break; case 'b-xor': token.precidence = 11; token.associativity = Twig.expression.operator.leftToRight; break; case 'b-and': token.precidence = 10; token.associativity = Twig.expression.operator.leftToRight; break; case '==': case '!=': token.precidence = 9; token.associativity = Twig.expression.operator.leftToRight; break; case '<=>': token.precidence = 9; token.associativity = Twig.expression.operator.leftToRight; break; case '<': case '<=': case '>': case '>=': case 'not in': case 'in': token.precidence = 8; token.associativity = Twig.expression.operator.leftToRight; break; case '~': // String concatination case '+': case '-': token.precidence = 6; token.associativity = Twig.expression.operator.leftToRight; break; case '//': case '**': case '*': case '/': case '%': token.precidence = 5; token.associativity = Twig.expression.operator.leftToRight; break; case 'not': token.precidence = 3; token.associativity = Twig.expression.operator.rightToLeft; break; case 'matches': token.precidence = 8; token.associativity = Twig.expression.operator.leftToRight; break; case 'starts with': token.precidence = 8; token.associativity = Twig.expression.operator.leftToRight; break; case 'ends with': token.precidence = 8; token.associativity = Twig.expression.operator.leftToRight; break; default: throw new Twig.Error('Failed to lookup operator: ' + operator + ' is an unknown operator.'); } token.operator = operator; return token; }; /** * Handle operations on the RPN stack. * * Returns the updated stack. */ Twig.expression.operator.parse = function (operator, stack) { Twig.log.trace('Twig.expression.operator.parse: ', 'Handling ', operator); let a; let b; let c; if (operator === '?') { c = stack.pop(); } b = stack.pop(); if (operator !== 'not') { a = stack.pop(); } if (operator !== 'in' && operator !== 'not in' && operator !== '??') { if (a && Array.isArray(a)) { a = a.length; } if (operator !== '?' && (b && Array.isArray(b))) { b = b.length; } } if (operator === 'matches') { if (b && typeof b === 'string') { const reParts = b.match(/^\/(.*)\/([gims]?)$/); const reBody = reParts[1]; const reFlags = reParts[2]; b = new RegExp(reBody, reFlags); } } switch (operator) { case ':': // Ignore break; case '??': if (a === undefined) { a = b; b = c; c = undefined; } if (a !== undefined && a !== null) { stack.push(a); } else { stack.push(b); } break; case '?:': if (Twig.lib.boolval(a)) { stack.push(a); } else { stack.push(b); } break; case '?': if (a === undefined) { // An extended ternary. a = b; b = c; c = undefined; } if (Twig.lib.boolval(a)) { stack.push(b); } else { stack.push(c); } break; case '+': b = parseFloat(b); a = parseFloat(a); stack.push(a + b); break; case '-': b = parseFloat(b); a = parseFloat(a); stack.push(a - b); break; case '*': b = parseFloat(b); a = parseFloat(a); stack.push(a * b); break; case '/': b = parseFloat(b); a = parseFloat(a); stack.push(a / b); break; case '//': b = parseFloat(b); a = parseFloat(a); stack.push(Math.floor(a / b)); break; case '%': b = parseFloat(b); a = parseFloat(a); stack.push(a % b); break; case '~': stack.push((typeof a !== 'undefined' && a !== null ? a.toString() : '') + (typeof b !== 'undefined' && b !== null ? b.toString() : '')); break; case 'not': case '!': stack.push(!Twig.lib.boolval(b)); break; case '<=>': stack.push(a === b ? 0 : (a < b ? -1 : 1)); break; case '<': stack.push(a < b); break; case '<=': stack.push(a <= b); break; case '>': stack.push(a > b); break; case '>=': stack.push(a >= b); break; case '===': stack.push(a === b); break; case '==': /* eslint-disable-next-line eqeqeq */ stack.push(a == b); break; case '!==': stack.push(a !== b); break; case '!=': /* eslint-disable-next-line eqeqeq */ stack.push(a != b); break; case 'or': stack.push(Twig.lib.boolval(a) || Twig.lib.boolval(b)); break; case 'b-or': stack.push(a | b); break; case 'b-xor': stack.push(a ^ b); break; case 'and': stack.push(Twig.lib.boolval(a) && Twig.lib.boolval(b)); break; case 'b-and': stack.push(a & b); break; case '**': stack.push(a ** b); break; case 'not in': stack.push(!containment(a, b)); break; case 'in': stack.push(containment(a, b)); break; case 'matches': stack.push(b.test(a)); break; case 'starts with': stack.push(typeof a === 'string' && a.indexOf(b) === 0); break; case 'ends with': stack.push(typeof a === 'string' && a.includes(b, a.length - b.length)); break; case '..': stack.push(Twig.functions.range(a, b)); break; default: throw new Twig.Error('Failed to parse operator: ' + operator + ' is an unknown operator.'); } }; return Twig; }; /***/ }), /***/ "./node_modules/twig/src/twig.factory.js": /*!***********************************************!*\ !*** ./node_modules/twig/src/twig.factory.js ***! \***********************************************/ /***/ ((module, __unused_webpack_exports, __webpack_require__) => { // ## twig.factory.js // // This file handles creating the Twig library module.exports = function factory() { const Twig = { VERSION: '1.17.1' }; __webpack_require__(/*! ./twig.core */ "./node_modules/twig/src/twig.core.js")(Twig); __webpack_require__(/*! ./twig.compiler */ "./node_modules/twig/src/twig.compiler.js")(Twig); __webpack_require__(/*! ./twig.expression */ "./node_modules/twig/src/twig.expression.js")(Twig); __webpack_require__(/*! ./twig.filters */ "./node_modules/twig/src/twig.filters.js")(Twig); __webpack_require__(/*! ./twig.functions */ "./node_modules/twig/src/twig.functions.js")(Twig); __webpack_require__(/*! ./twig.lib */ "./node_modules/twig/src/twig.lib.js")(Twig); __webpack_require__(/*! ./twig.loader.ajax */ "./node_modules/twig/src/twig.loader.ajax.js")(Twig); __webpack_require__(/*! ./twig.loader.fs */ "./node_modules/twig/src/twig.loader.fs.js")(Twig); __webpack_require__(/*! ./twig.logic */ "./node_modules/twig/src/twig.logic.js")(Twig); __webpack_require__(/*! ./twig.parser.source */ "./node_modules/twig/src/twig.parser.source.js")(Twig); __webpack_require__(/*! ./twig.parser.twig */ "./node_modules/twig/src/twig.parser.twig.js")(Twig); __webpack_require__(/*! ./twig.path */ "./node_modules/twig/src/twig.path.js")(Twig); __webpack_require__(/*! ./twig.tests */ "./node_modules/twig/src/twig.tests.js")(Twig); __webpack_require__(/*! ./twig.async */ "./node_modules/twig/src/twig.async.js")(Twig); __webpack_require__(/*! ./twig.exports */ "./node_modules/twig/src/twig.exports.js")(Twig); Twig.exports.factory = factory; return Twig.exports; }; /***/ }), /***/ "./node_modules/twig/src/twig.filters.js": /*!***********************************************!*\ !*** ./node_modules/twig/src/twig.filters.js ***! \***********************************************/ /***/ ((module) => { // ## twig.filters.js // // This file handles parsing filters. module.exports = function (Twig) { // Determine object type function is(type, obj) { const clas = Object.prototype.toString.call(obj).slice(8, -1); return obj !== undefined && obj !== null && clas === type; } Twig.filters = { // String Filters upper(value) { if (typeof value !== 'string') { return value; } return value.toUpperCase(); }, lower(value) { if (typeof value !== 'string') { return value; } return value.toLowerCase(); }, capitalize(value) { if (typeof value !== 'string') { return value; } return value.slice(0, 1).toUpperCase() + value.toLowerCase().slice(1); }, title(value) { if (typeof value !== 'string') { return value; } return value.toLowerCase().replace(/(^|\s)([a-z])/g, (m, p1, p2) => { return p1 + p2.toUpperCase(); }); }, length(value) { if (Twig.lib.is('Array', value) || typeof value === 'string') { return value.length; } if (Twig.lib.is('Object', value)) { if (value._keys === undefined) { return Object.keys(value).length; } return value._keys.length; } return 0; }, // Array/Object Filters reverse(value) { if (is('Array', value)) { return value.reverse(); } if (is('String', value)) { return value.split('').reverse().join(''); } if (is('Object', value)) { const keys = value._keys || Object.keys(value).reverse(); value._keys = keys; return value; } }, sort(value) { if (is('Array', value)) { return value.sort(); } if (is('Object', value)) { // Sorting objects isn't obvious since the order of // returned keys isn't guaranteed in JavaScript. // Because of this we use a "hidden" key called _keys to // store the keys in the order we want to return them. delete value._keys; const keys = Object.keys(value); const sortedKeys = keys.sort((a, b) => { let a1; let b1; // If a and b are comparable, we're fine :-) if ((value[a] > value[b]) === !(value[a] <= value[b])) { return value[a] > value[b] ? 1 : (value[a] < value[b] ? -1 : 0); } // If a and b can be parsed as numbers, we can compare // their numeric value if (!isNaN(a1 = parseFloat(value[a])) && !isNaN(b1 = parseFloat(value[b]))) { return a1 > b1 ? 1 : (a1 < b1 ? -1 : 0); } // If one of the values is a string, we convert the // other value to string as well if (typeof value[a] === 'string') { return value[a] > value[b].toString() ? 1 : (value[a] < value[b].toString() ? -1 : 0); } if (typeof value[b] === 'string') { return value[a].toString() > value[b] ? 1 : (value[a].toString() < value[b] ? -1 : 0); } // Everything failed - return 'null' as sign, that // the values are not comparable return null; }); value._keys = sortedKeys; return value; } }, keys(value) { if (value === undefined || value === null) { return; } const keyset = value._keys || Object.keys(value); const output = []; keyset.forEach(key => { if (key === '_keys') { return; } // Ignore the _keys property if (Object.hasOwnProperty.call(value, key)) { output.push(key); } }); return output; }, /* eslint-disable-next-line camelcase */ url_encode(value) { if (value === undefined || value === null) { return; } if (Twig.lib.is('Object', value)) { const serialize = function (obj, prefix) { const result = []; const keyset = obj._keys || Object.keys(obj); keyset.forEach(key => { if (!Object.prototype.hasOwnProperty.call(obj, key)) { return; } const resultKey = prefix ? prefix + '[' + key + ']' : key; const resultValue = obj[key]; result.push( (Twig.lib.is('Object', resultValue) || Array.isArray(resultValue)) ? serialize(resultValue, resultKey) : encodeURIComponent(resultKey) + '=' + encodeURIComponent(resultValue) ); }); return result.join('&'); }; return serialize(value); } let result = encodeURIComponent(value); result = result.replace('\'', '%27'); return result; }, join(value, params) { if (value === undefined || value === null) { return; } let joinStr = ''; let output = []; let keyset = null; if (params && params[0]) { joinStr = params[0]; } if (is('Array', value)) { output = value; } else { keyset = value._keys || Object.keys(value); keyset.forEach(key => { if (key === '_keys') { return; } // Ignore the _keys property if (Object.hasOwnProperty.call(value, key)) { output.push(value[key]); } }); } return output.join(joinStr); }, default(value, params) { if (params !== undefined && params.length > 1) { throw new Twig.Error('default filter expects one argument'); } if (value === undefined || value === null || value === '') { if (params === undefined) { return ''; } return params[0]; } return value; }, /* eslint-disable-next-line camelcase */ json_encode(value) { if (value === undefined || value === null) { return 'null'; } if ((typeof value === 'object') && (is('Array', value))) { const output = []; value.forEach(v => { output.push(Twig.filters.json_encode(v)); }); return '[' + output.join(',') + ']'; } if ((typeof value === 'object') && (is('Date', value))) { return '"' + value.toISOString() + '"'; } if (typeof value === 'object') { const keyset = value._keys || Object.keys(value); const output = []; keyset.forEach(key => { output.push(JSON.stringify(key) + ':' + Twig.filters.json_encode(value[key])); }); return '{' + output.join(',') + '}'; } return JSON.stringify(value); }, merge(value, params) { let obj = []; let arrIndex = 0; let keyset = []; // Check to see if all the objects being merged are arrays if (is('Array', value)) { params.forEach(param => { if (!is('Array', param)) { obj = { }; } }); } else { // Create obj as an Object obj = { }; } if (!is('Array', obj)) { obj._keys = []; } if (is('Array', value)) { value.forEach(val => { if (obj._keys) { obj._keys.push(arrIndex); } obj[arrIndex] = val; arrIndex++; }); } else { keyset = value._keys || Object.keys(value); keyset.forEach(key => { obj[key] = value[key]; obj._keys.push(key); // Handle edge case where a number index in an object is greater than // the array counter. In such a case, the array counter is increased // one past the index. // // Example {{ ["a", "b"]|merge({"4":"value"}, ["c", "d"]) // Without this, d would have an index of "4" and overwrite the value // of "value" const intKey = parseInt(key, 10); if (!isNaN(intKey) && intKey >= arrIndex) { arrIndex = intKey + 1; } }); } // Mixin the merge arrays params.forEach(param => { if (is('Array', param)) { param.forEach(val => { if (obj._keys) { obj._keys.push(arrIndex); } obj[arrIndex] = val; arrIndex++; }); } else { keyset = param._keys || Object.keys(param); keyset.forEach(key => { if (!obj[key]) { obj._keys.push(key); } obj[key] = param[key]; const intKey = parseInt(key, 10); if (!isNaN(intKey) && intKey >= arrIndex) { arrIndex = intKey + 1; } }); } }); if (params.length === 0) { throw new Twig.Error('Filter merge expects at least one parameter'); } return obj; }, date(value, params) { const date = Twig.functions.date(value); const format = params && Boolean(params.length) ? params[0] : 'F j, Y H:i'; return Twig.lib.date(format.replace(/\\\\/g, '\\'), date); }, /* eslint-disable-next-line camelcase */ date_modify(value, params) { if (value === undefined || value === null) { return; } if (params === undefined || params.length !== 1) { throw new Twig.Error('date_modify filter expects 1 argument'); } const modifyText = params[0]; let time; if (Twig.lib.is('Date', value)) { time = Twig.lib.strtotime(modifyText, value.getTime() / 1000); } if (Twig.lib.is('String', value)) { time = Twig.lib.strtotime(modifyText, Twig.lib.strtotime(value)); } if (Twig.lib.is('Number', value)) { time = Twig.lib.strtotime(modifyText, value); } return new Date(time * 1000); }, replace(value, params) { if (value === undefined || value === null) { return; } const pairs = params[0]; let tag; for (tag in pairs) { if (Object.hasOwnProperty.call(pairs, tag) && tag !== '_keys') { value = Twig.lib.replaceAll(value, tag, pairs[tag]); } } return value; }, format(value, params) { if (value === undefined || value === null) { return; } return Twig.lib.vsprintf(value, params); }, striptags(value, allowed) { if (value === undefined || value === null) { return; } return Twig.lib.stripTags(value, allowed); }, escape(value, params) { if (value === undefined || value === null || value === '') { return; } let strategy = 'html'; if (params && Boolean(params.length) && params[0] !== true) { strategy = params[0]; } if (strategy === 'html') { const rawValue = value.toString().replace(/&/g, '&') .replace(//g, '>') .replace(/"/g, '"') .replace(/'/g, '''); return new Twig.Markup(rawValue, 'html'); } if (strategy === 'js') { const rawValue = value.toString(); let result = ''; for (let i = 0; i < rawValue.length; i++) { if (rawValue[i].match(/^[a-zA-Z0-9,._]$/)) { result += rawValue[i]; } else { const char = rawValue.charAt(i); const charCode = rawValue.charCodeAt(i); // A few characters have short escape sequences in JSON and JavaScript. // Escape sequences supported only by JavaScript, not JSON, are ommitted. // \" is also supported but omitted, because the resulting string is not HTML safe. const shortMap = { '\\': '\\\\', '/': '\\/', '\u0008': '\\b', '\u000C': '\\f', '\u000A': '\\n', '\u000D': '\\r', '\u0009': '\\t' }; if (shortMap[char]) { result += shortMap[char]; } else { result += Twig.lib.sprintf('\\u%04s', charCode.toString(16).toUpperCase()); } } } return new Twig.Markup(result, 'js'); } if (strategy === 'css') { const rawValue = value.toString(); let result = ''; for (let i = 0; i < rawValue.length; i++) { if (rawValue[i].match(/^[a-zA-Z0-9]$/)) { result += rawValue[i]; } else { const charCode = rawValue.charCodeAt(i); result += '\\' + charCode.toString(16).toUpperCase() + ' '; } } return new Twig.Markup(result, 'css'); } if (strategy === 'url') { const result = Twig.filters.url_encode(value); return new Twig.Markup(result, 'url'); } if (strategy === 'html_attr') { const rawValue = value.toString(); let result = ''; for (let i = 0; i < rawValue.length; i++) { if (rawValue[i].match(/^[a-zA-Z0-9,.\-_]$/)) { result += rawValue[i]; } else if (rawValue[i].match(/^[&<>"]$/)) { result += rawValue[i].replace(/&/g, '&') .replace(//g, '>') .replace(/"/g, '"'); } else { const charCode = rawValue.charCodeAt(i); // The following replaces characters undefined in HTML with // the hex entity for the Unicode replacement character. if (charCode <= 0x1F && charCode !== 0x09 && charCode !== 0x0A && charCode !== 0x0D) { result += '�'; } else if (charCode < 0x80) { result += Twig.lib.sprintf('&#x%02s;', charCode.toString(16).toUpperCase()); } else { result += Twig.lib.sprintf('&#x%04s;', charCode.toString(16).toUpperCase()); } } } return new Twig.Markup(result, 'html_attr'); } throw new Twig.Error('escape strategy unsupported'); }, /* Alias of escape */ e(value, params) { return Twig.filters.escape(value, params); }, nl2br(value) { if (value === undefined || value === null || value === '') { return; } const linebreakTag = 'BACKSLASH_n_replace'; const br = '
' + linebreakTag; value = Twig.filters.escape(value) .replace(/\r\n/g, br) .replace(/\r/g, br) .replace(/\n/g, br); value = Twig.lib.replaceAll(value, linebreakTag, '\n'); return new Twig.Markup(value); }, /** * Adapted from: http://phpjs.org/functions/number_format:481 */ /* eslint-disable-next-line camelcase */ number_format(value, params) { let number = value; const decimals = (params && params[0]) ? params[0] : undefined; const dec = (params && params[1] !== undefined) ? params[1] : '.'; const sep = (params && params[2] !== undefined) ? params[2] : ','; number = (String(number)).replace(/[^0-9+\-Ee.]/g, ''); const n = isFinite(Number(number)) ? Number(number) : 0; const prec = isFinite(Number(decimals)) ? Math.abs(decimals) : 0; let s = ''; const toFixedFix = function (n, prec) { const k = 10 ** prec; return String(Math.round(n * k) / k); }; // Fix for IE parseFloat(0.55).toFixed(0) = 0; s = (prec ? toFixedFix(n, prec) : String(Math.round(n))).split('.'); if (s[0].length > 3) { s[0] = s[0].replace(/\B(?=(?:\d{3})+(?!\d))/g, sep); } if ((s[1] || '').length < prec) { s[1] = s[1] || ''; s[1] += new Array(prec - s[1].length + 1).join('0'); } return s.join(dec); }, trim(value, params) { if (value === undefined || value === null) { return; } let str = String(value); let whitespace; if (params && params[0]) { whitespace = String(params[0]); } else { whitespace = ' \n\r\t\f\u000B\u00A0\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u200b\u2028\u2029\u3000'; } for (let i = 0; i < str.length; i++) { if (!whitespace.includes(str.charAt(i))) { str = str.slice(Math.max(0, i)); break; } } for (let i = str.length - 1; i >= 0; i--) { if (!whitespace.includes(str.charAt(i))) { str = str.slice(0, Math.max(0, i + 1)); break; } } return whitespace.includes(str.charAt(0)) ? '' : str; }, truncate(value, params) { let length = 30; let preserve = false; let separator = '...'; value = String(value); if (params) { if (params[0]) { length = params[0]; } if (params[1]) { preserve = params[1]; } if (params[2]) { separator = params[2]; } } if (value.length > length) { if (preserve) { length = value.indexOf(' ', length); if (length === -1) { return value; } } value = value.slice(0, length) + separator; } return value; }, slice(value, params) { if (value === undefined || value === null) { return; } if (params === undefined || params.length === 0) { throw new Twig.Error('slice filter expects at least 1 argument'); } // Default to start of string const start = params[0] || 0; // Default to length of string let length = params.length > 1 ? params[1] : value.length; // Handle negative start values const startIndex = start >= 0 ? start : Math.max(value.length + start, 0); // Handle negative length values if (length < 0) { length = value.length - startIndex + length; } if (Twig.lib.is('Array', value)) { const output = []; for (let i = startIndex; i < startIndex + length && i < value.length; i++) { output.push(value[i]); } return output; } if (Twig.lib.is('String', value)) { return value.slice(startIndex, startIndex + length); } throw new Twig.Error('slice filter expects value to be an array or string'); }, abs(value) { if (value === undefined || value === null) { return; } return Math.abs(value); }, first(value) { if (is('Array', value)) { return value[0]; } if (is('Object', value)) { if ('_keys' in value) { return value[value._keys[0]]; } } else if (typeof value === 'string') { return value.slice(0, 1); } }, split(value, params) { if (value === undefined || value === null) { return; } if (params === undefined || params.length === 0 || params.length > 2) { throw new Twig.Error('split filter expects 1 or 2 argument'); } if (Twig.lib.is('String', value)) { const delimiter = params[0]; const limit = params[1]; const split = value.split(delimiter); if (limit === undefined) { return split; } if (limit < 0) { return value.split(delimiter, split.length + limit); } const limitedSplit = []; if (delimiter === '') { // Empty delimiter // "aabbcc"|split('', 2) // -> ['aa', 'bb', 'cc'] while (split.length > 0) { let temp = ''; for (let i = 0; i < limit && split.length > 0; i++) { temp += split.shift(); } limitedSplit.push(temp); } } else { // Non-empty delimiter // "one,two,three,four,five"|split(',', 3) // -> ['one', 'two', 'three,four,five'] for (let i = 0; i < limit - 1 && split.length > 0; i++) { limitedSplit.push(split.shift()); } if (split.length > 0) { limitedSplit.push(split.join(delimiter)); } } return limitedSplit; } throw new Twig.Error('split filter expects value to be a string'); }, last(value) { if (Twig.lib.is('Object', value)) { let keys; if (value._keys === undefined) { keys = Object.keys(value); } else { keys = value._keys; } return value[keys[keys.length - 1]]; } if (Twig.lib.is('Number', value)) { return value.toString().slice(-1); } // String|array return value[value.length - 1]; }, raw(value) { return new Twig.Markup(value || ''); }, batch(items, params) { let size = params.shift(); const fill = params.shift(); let last; let missing; if (!Twig.lib.is('Array', items)) { throw new Twig.Error('batch filter expects items to be an array'); } if (!Twig.lib.is('Number', size)) { throw new Twig.Error('batch filter expects size to be a number'); } size = Math.ceil(size); const result = Twig.lib.chunkArray(items, size); if (fill && items.length % size !== 0) { last = result.pop(); missing = size - last.length; while (missing--) { last.push(fill); } result.push(last); } return result; }, round(value, params) { params = params || []; const precision = params.length > 0 ? params[0] : 0; const method = params.length > 1 ? params[1] : 'common'; value = parseFloat(value); if (precision && !Twig.lib.is('Number', precision)) { throw new Twig.Error('round filter expects precision to be a number'); } if (method === 'common') { return Twig.lib.round(value, precision); } if (!Twig.lib.is('Function', Math[method])) { throw new Twig.Error('round filter expects method to be \'floor\', \'ceil\', or \'common\''); } return Math[method](value * (10 ** precision)) / (10 ** precision); }, spaceless(value) { return value.replace(/>\s+<').trim(); } }; Twig.filter = function (filter, value, params) { const state = this; if (!Twig.filters[filter]) { throw new Twig.Error('Unable to find filter ' + filter); } return Twig.filters[filter].call(state, value, params); }; Twig.filter.extend = function (filter, definition) { Twig.filters[filter] = definition; }; return Twig; }; /***/ }), /***/ "./node_modules/twig/src/twig.functions.js": /*!*************************************************!*\ !*** ./node_modules/twig/src/twig.functions.js ***! \*************************************************/ /***/ ((module) => { // ## twig.functions.js // // This file handles parsing filters. module.exports = function (Twig) { /** * @constant * @type {string} */ const TEMPLATE_NOT_FOUND_MESSAGE = 'Template "{name}" is not defined.'; Twig.functions = { // Attribute, block, constant, date, dump, parent, random,. // Range function from http://phpjs.org/functions/range:499 // Used under an MIT License range(low, high, step) { // http://kevin.vanzonneveld.net // + original by: Waldo Malqui Silva // * example 1: range ( 0, 12 ); // * returns 1: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12] // * example 2: range( 0, 100, 10 ); // * returns 2: [0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100] // * example 3: range( 'a', 'i' ); // * returns 3: ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i'] // * example 4: range( 'c', 'a' ); // * returns 4: ['c', 'b', 'a'] const matrix = []; let inival; let endval; const walker = step || 1; let chars = false; if (!isNaN(low) && !isNaN(high)) { inival = parseInt(low, 10); endval = parseInt(high, 10); } else if (isNaN(low) && isNaN(high)) { chars = true; inival = low.charCodeAt(0); endval = high.charCodeAt(0); } else { inival = (isNaN(low) ? 0 : low); endval = (isNaN(high) ? 0 : high); } const plus = (!((inival > endval))); if (plus) { while (inival <= endval) { matrix.push(((chars) ? String.fromCharCode(inival) : inival)); inival += walker; } } else { while (inival >= endval) { matrix.push(((chars) ? String.fromCharCode(inival) : inival)); inival -= walker; } } return matrix; }, cycle(arr, i) { const pos = i % arr.length; return arr[pos]; }, dump(...args) { // Don't pass arguments to `Array.slice`, that is a performance killer const argsCopy = [...args]; const state = this; const EOL = '\n'; const indentChar = ' '; let indentTimes = 0; let out = ''; const indent = function (times) { let ind = ''; while (times > 0) { times--; ind += indentChar; } return ind; }; const displayVar = function (variable) { out += indent(indentTimes); if (typeof (variable) === 'object') { dumpVar(variable); } else if (typeof (variable) === 'function') { out += 'function()' + EOL; } else if (typeof (variable) === 'string') { out += 'string(' + variable.length + ') "' + variable + '"' + EOL; } else if (typeof (variable) === 'number') { out += 'number(' + variable + ')' + EOL; } else if (typeof (variable) === 'boolean') { out += 'bool(' + variable + ')' + EOL; } }; const dumpVar = function (variable) { let i; if (variable === null) { out += 'NULL' + EOL; } else if (variable === undefined) { out += 'undefined' + EOL; } else if (typeof variable === 'object') { out += indent(indentTimes) + typeof (variable); indentTimes++; out += '(' + (function (obj) { let size = 0; let key; for (key in obj) { if (Object.hasOwnProperty.call(obj, key)) { size++; } } return size; })(variable) + ') {' + EOL; for (i in variable) { if (Object.hasOwnProperty.call(variable, i)) { out += indent(indentTimes) + '[' + i + ']=> ' + EOL; displayVar(variable[i]); } } indentTimes--; out += indent(indentTimes) + '}' + EOL; } else { displayVar(variable); } }; // Handle no argument case by dumping the entire render context if (argsCopy.length === 0) { argsCopy.push(state.context); } argsCopy.forEach(variable => { dumpVar(variable); }); return out; }, date(date) { let dateObj; if (date === undefined || date === null || date === '') { dateObj = new Date(); } else if (Twig.lib.is('Date', date)) { dateObj = date; } else if (Twig.lib.is('String', date)) { if (date.match(/^\d+$/)) { dateObj = new Date(date * 1000); } else { dateObj = new Date(Twig.lib.strtotime(date) * 1000); } } else if (Twig.lib.is('Number', date)) { // Timestamp dateObj = new Date(date * 1000); } else { throw new Twig.Error('Unable to parse date ' + date); } return dateObj; }, block(blockName) { const state = this; const block = state.getBlock(blockName); if (block !== undefined) { return block.render(state, state.context); } }, parent() { const state = this; return state.getBlock(state.getNestingStackToken(Twig.logic.type.block).blockName, true).render(state, state.context); }, attribute(object, method, params) { if (Twig.lib.is('Object', object)) { if (Object.hasOwnProperty.call(object, method)) { if (typeof object[method] === 'function') { return object[method].apply(undefined, params); } return object[method]; } } // Array will return element 0-index return object ? (object[method] || undefined) : undefined; }, max(values, ...args) { if (Twig.lib.is('Object', values)) { delete values._keys; return Twig.lib.max(values); } return Reflect.apply(Twig.lib.max, null, [values, ...args]); }, min(values, ...args) { if (Twig.lib.is('Object', values)) { delete values._keys; return Twig.lib.min(values); } return Reflect.apply(Twig.lib.min, null, [values, ...args]); }, /* eslint-disable-next-line camelcase */ template_from_string(template) { const state = this; if (template === undefined) { template = ''; } return Twig.Templates.parsers.twig({ options: state.template.options, data: template }); }, random(value) { const LIMIT_INT31 = 0x80000000; function getRandomNumber(n) { const random = Math.floor(Math.random() * LIMIT_INT31); const min = Math.min.call(null, 0, n); const max = Math.max.call(null, 0, n); return min + Math.floor((max - min + 1) * random / LIMIT_INT31); } if (Twig.lib.is('Number', value)) { return getRandomNumber(value); } if (Twig.lib.is('String', value)) { return value.charAt(getRandomNumber(value.length - 1)); } if (Twig.lib.is('Array', value)) { return value[getRandomNumber(value.length - 1)]; } if (Twig.lib.is('Object', value)) { const keys = Object.keys(value); return value[keys[getRandomNumber(keys.length - 1)]]; } return getRandomNumber(LIMIT_INT31 - 1); }, /** * Returns the content of a template without rendering it * @param {string} name * @param {boolean} [ignoreMissing=false] * @returns {string} */ source(name, ignoreMissing) { const state = this; const {namespaces} = state.template.options; let templateSource; let templateFound = false; const isNodeEnvironment = true && typeof module.exports !== 'undefined' && typeof window === 'undefined'; let loader; let path = name; if (namespaces && typeof namespaces === 'object') { path = Twig.path.expandNamespace(namespaces, path); } // If we are running in a node.js environment, set the loader to 'fs'. if (isNodeEnvironment) { loader = 'fs'; } else { loader = 'ajax'; } // Build the params object const params = { id: name, path, method: loader, parser: 'source', async: false, fetchTemplateSource: true }; // Default ignoreMissing to false if (typeof ignoreMissing === 'undefined') { ignoreMissing = false; } // Try to load the remote template // // on exception, log it try { templateSource = Twig.Templates.loadRemote(name, params); // If the template is undefined or null, set the template to an empty string and do NOT flip the // boolean indicating we found the template // // else, all is good! flip the boolean indicating we found the template if (typeof templateSource === 'undefined' || templateSource === null) { templateSource = ''; } else { templateFound = true; } } catch (error) { Twig.log.debug('Twig.functions.source: ', 'Problem loading template ', error); } // If the template was NOT found AND we are not ignoring missing templates, return the same message // that is returned by the PHP implementation of the twig source() function // // else, return the template source if (!templateFound && !ignoreMissing) { return TEMPLATE_NOT_FOUND_MESSAGE.replace('{name}', name); } return templateSource; } }; Twig._function = function (_function, value, params) { if (!Twig.functions[_function]) { throw new Twig.Error('Unable to find function ' + _function); } return Twig.functions[_function](value, params); }; Twig._function.extend = function (_function, definition) { Twig.functions[_function] = definition; }; return Twig; }; /***/ }), /***/ "./node_modules/twig/src/twig.js": /*!***************************************!*\ !*** ./node_modules/twig/src/twig.js ***! \***************************************/ /***/ ((module, __unused_webpack_exports, __webpack_require__) => { /** * Twig.js * * @copyright 2011-2020 John Roepke and the Twig.js Contributors * @license Available under the BSD 2-Clause License * @link https://github.com/twigjs/twig.js */ module.exports = __webpack_require__(/*! ./twig.factory */ "./node_modules/twig/src/twig.factory.js")(); /***/ }), /***/ "./node_modules/twig/src/twig.lib.js": /*!*******************************************!*\ !*** ./node_modules/twig/src/twig.lib.js ***! \*******************************************/ /***/ ((module, __unused_webpack_exports, __webpack_require__) => { // ## twig.lib.js // // This file contains 3rd party libraries used within twig. // // Copies of the licenses for the code included here can be found in the // LICENSES.md file. // module.exports = function (Twig) { // Namespace for libraries Twig.lib = { }; Twig.lib.sprintf = __webpack_require__(/*! locutus/php/strings/sprintf */ "./node_modules/locutus/php/strings/sprintf.js"); Twig.lib.vsprintf = __webpack_require__(/*! locutus/php/strings/vsprintf */ "./node_modules/locutus/php/strings/vsprintf.js"); Twig.lib.round = __webpack_require__(/*! locutus/php/math/round */ "./node_modules/locutus/php/math/round.js"); Twig.lib.max = __webpack_require__(/*! locutus/php/math/max */ "./node_modules/locutus/php/math/max.js"); Twig.lib.min = __webpack_require__(/*! locutus/php/math/min */ "./node_modules/locutus/php/math/min.js"); Twig.lib.stripTags = __webpack_require__(/*! locutus/php/strings/strip_tags */ "./node_modules/locutus/php/strings/strip_tags.js"); Twig.lib.strtotime = __webpack_require__(/*! locutus/php/datetime/strtotime */ "./node_modules/locutus/php/datetime/strtotime.js"); Twig.lib.date = __webpack_require__(/*! locutus/php/datetime/date */ "./node_modules/locutus/php/datetime/date.js"); Twig.lib.boolval = __webpack_require__(/*! locutus/php/var/boolval */ "./node_modules/locutus/php/var/boolval.js"); Twig.lib.is = function (type, obj) { if (typeof obj === 'undefined' || obj === null) { return false; } switch (type) { case 'Array': return Array.isArray(obj); case 'Date': return obj instanceof Date; case 'String': return (typeof obj === 'string' || obj instanceof String); case 'Number': return (typeof obj === 'number' || obj instanceof Number); case 'Function': return (typeof obj === 'function'); case 'Object': return obj instanceof Object; default: return false; } }; Twig.lib.replaceAll = function (string, search, replace) { // Convert type to string if needed const stringToChange = typeof string === 'string' ? string : string.toString(); // Escape possible regular expression syntax const searchEscaped = search.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); return stringToChange.replace(new RegExp(searchEscaped, 'g'), replace); }; // Chunk an array (arr) into arrays of (size) items, returns an array of arrays, or an empty array on invalid input Twig.lib.chunkArray = function (arr, size) { const returnVal = []; let x = 0; const len = arr.length; if (size < 1 || !Array.isArray(arr)) { return []; } while (x < len) { returnVal.push(arr.slice(x, x += size)); } return returnVal; }; return Twig; }; /***/ }), /***/ "./node_modules/twig/src/twig.loader.ajax.js": /*!***************************************************!*\ !*** ./node_modules/twig/src/twig.loader.ajax.js ***! \***************************************************/ /***/ ((module) => { module.exports = function (Twig) { 'use strict'; Twig.Templates.registerLoader('ajax', function (location, params, callback, errorCallback) { let template; const {precompiled} = params; const parser = this.parsers[params.parser] || this.parser.twig; if (typeof XMLHttpRequest === 'undefined') { throw new Twig.Error('Unsupported platform: Unable to do ajax requests ' + 'because there is no "XMLHTTPRequest" implementation'); } const xmlhttp = new XMLHttpRequest(); xmlhttp.onreadystatechange = function () { let data = null; if (xmlhttp.readyState === 4) { if (xmlhttp.status === 200 || (window.cordova && xmlhttp.status === 0)) { Twig.log.debug('Got template ', xmlhttp.responseText); if (precompiled === true) { data = JSON.parse(xmlhttp.responseText); } else { data = xmlhttp.responseText; } params.url = location; params.data = data; template = parser.call(this, params); if (typeof callback === 'function') { callback(template); } } else if (typeof errorCallback === 'function') { errorCallback(xmlhttp); } } }; xmlhttp.open('GET', location, Boolean(params.async)); xmlhttp.overrideMimeType('text/plain'); xmlhttp.send(); if (params.async) { // TODO: return deferred promise return true; } return template; }); }; /***/ }), /***/ "./node_modules/twig/src/twig.loader.fs.js": /*!*************************************************!*\ !*** ./node_modules/twig/src/twig.loader.fs.js ***! \*************************************************/ /***/ ((module, __unused_webpack_exports, __webpack_require__) => { module.exports = function (Twig) { 'use strict'; let fs; let path; try { // Require lib dependencies at runtime fs = __webpack_require__(/*! fs */ "?506a"); path = __webpack_require__(/*! path */ "./node_modules/path-browserify/index.js"); } catch (error) { // NOTE: this is in a try/catch to avoid errors cross platform console.warn('Missing fs and path modules. ' + error); } Twig.Templates.registerLoader('fs', function (location, params, callback, errorCallback) { let template; let data = null; const {precompiled} = params; const parser = this.parsers[params.parser] || this.parser.twig; if (!fs || !path) { throw new Twig.Error('Unsupported platform: Unable to load from file ' + 'because there is no "fs" or "path" implementation'); } const loadTemplateFn = function (err, data) { if (err) { if (typeof errorCallback === 'function') { errorCallback(err); } return; } if (precompiled === true) { data = JSON.parse(data); } params.data = data; params.path = params.path || location; // Template is in data template = parser.call(this, params); if (typeof callback === 'function') { callback(template); } }; params.path = params.path || location; if (params.async) { fs.stat(params.path, (err, stats) => { if (err || !stats.isFile()) { if (typeof errorCallback === 'function') { errorCallback(new Twig.Error('Unable to find template file ' + params.path)); } return; } fs.readFile(params.path, 'utf8', loadTemplateFn); }); // TODO: return deferred promise return true; } try { if (!fs.statSync(params.path).isFile()) { throw new Twig.Error('Unable to find template file ' + params.path); } } catch (error) { throw new Twig.Error('Unable to find template file ' + params.path + '. ' + error); } data = fs.readFileSync(params.path, 'utf8'); loadTemplateFn(undefined, data); return template; }); }; /***/ }), /***/ "./node_modules/twig/src/twig.logic.js": /*!*********************************************!*\ !*** ./node_modules/twig/src/twig.logic.js ***! \*********************************************/ /***/ ((module) => { // ## twig.logic.js // // This file handles tokenizing, compiling and parsing logic tokens. {% ... %} module.exports = function (Twig) { 'use strict'; /** * Namespace for logic handling. */ Twig.logic = {}; /** * Logic token types. */ Twig.logic.type = { if_: 'Twig.logic.type.if', endif: 'Twig.logic.type.endif', for_: 'Twig.logic.type.for', endfor: 'Twig.logic.type.endfor', else_: 'Twig.logic.type.else', elseif: 'Twig.logic.type.elseif', set: 'Twig.logic.type.set', setcapture: 'Twig.logic.type.setcapture', endset: 'Twig.logic.type.endset', filter: 'Twig.logic.type.filter', endfilter: 'Twig.logic.type.endfilter', apply: 'Twig.logic.type.apply', endapply: 'Twig.logic.type.endapply', do: 'Twig.logic.type.do', shortblock: 'Twig.logic.type.shortblock', block: 'Twig.logic.type.block', endblock: 'Twig.logic.type.endblock', extends_: 'Twig.logic.type.extends', use: 'Twig.logic.type.use', include: 'Twig.logic.type.include', spaceless: 'Twig.logic.type.spaceless', endspaceless: 'Twig.logic.type.endspaceless', macro: 'Twig.logic.type.macro', endmacro: 'Twig.logic.type.endmacro', import_: 'Twig.logic.type.import', from: 'Twig.logic.type.from', embed: 'Twig.logic.type.embed', endembed: 'Twig.logic.type.endembed', with: 'Twig.logic.type.with', endwith: 'Twig.logic.type.endwith', deprecated: 'Twig.logic.type.deprecated' }; // Regular expressions for handling logic tokens. // // Properties: // // type: The type of expression this matches // // regex: A regular expression that matches the format of the token // // next: What logic tokens (if any) pop this token off the logic stack. If empty, the // logic token is assumed to not require an end tag and isn't push onto the stack. // // open: Does this tag open a logic expression or is it standalone. For example, // {% endif %} cannot exist without an opening {% if ... %} tag, so open = false. // // Functions: // // compile: A function that handles compiling the token into an output token ready for // parsing with the parse function. // // parse: A function that parses the compiled token into output (HTML / whatever the // template represents). Twig.logic.definitions = [ { /** * If type logic tokens. * * Format: {% if expression %} */ type: Twig.logic.type.if_, regex: /^if\s?([\s\S]+)$/, next: [ Twig.logic.type.else_, Twig.logic.type.elseif, Twig.logic.type.endif ], open: true, compile(token) { const expression = token.match[1]; // Compile the expression. token.stack = Twig.expression.compile.call(this, { type: Twig.expression.type.expression, value: expression }).stack; delete token.match; return token; }, parse(token, context, chain) { const state = this; return Twig.expression.parseAsync.call(state, token.stack, context) .then(result => { chain = true; if (Twig.lib.boolval(result)) { chain = false; return state.parseAsync(token.output, context); } return ''; }) .then(output => { return { chain, output }; }); } }, { /** * Else if type logic tokens. * * Format: {% elseif expression %} */ type: Twig.logic.type.elseif, regex: /^elseif\s*([^\s].*)$/, next: [ Twig.logic.type.else_, Twig.logic.type.elseif, Twig.logic.type.endif ], open: false, compile(token) { const expression = token.match[1]; // Compile the expression. token.stack = Twig.expression.compile.call(this, { type: Twig.expression.type.expression, value: expression }).stack; delete token.match; return token; }, parse(token, context, chain) { const state = this; return Twig.expression.parseAsync.call(state, token.stack, context) .then(result => { if (chain && Twig.lib.boolval(result)) { chain = false; return state.parseAsync(token.output, context); } return ''; }) .then(output => { return { chain, output }; }); } }, { /** * Else type logic tokens. * * Format: {% else %} */ type: Twig.logic.type.else_, regex: /^else$/, next: [ Twig.logic.type.endif, Twig.logic.type.endfor ], open: false, parse(token, context, chain) { let promise = Twig.Promise.resolve(''); const state = this; if (chain) { promise = state.parseAsync(token.output, context); } return promise.then(output => { return { chain, output }; }); } }, { /** * End if type logic tokens. * * Format: {% endif %} */ type: Twig.logic.type.endif, regex: /^endif$/, next: [], open: false }, { /** * For type logic tokens. * * Format: {% for expression %} */ type: Twig.logic.type.for_, regex: /^for\s+([a-zA-Z0-9_,\s]+)\s+in\s+([\S\s]+?)(?:\s+if\s+([^\s].*))?$/, next: [ Twig.logic.type.else_, Twig.logic.type.endfor ], open: true, compile(token) { const keyValue = token.match[1]; const expression = token.match[2]; const conditional = token.match[3]; let kvSplit = null; token.keyVar = null; token.valueVar = null; if (keyValue.includes(',')) { kvSplit = keyValue.split(','); if (kvSplit.length === 2) { token.keyVar = kvSplit[0].trim(); token.valueVar = kvSplit[1].trim(); } else { throw new Twig.Error('Invalid expression in for loop: ' + keyValue); } } else { token.valueVar = keyValue.trim(); } // Valid expressions for a for loop // for item in expression // for key,item in expression // Compile the expression. token.expression = Twig.expression.compile.call(this, { type: Twig.expression.type.expression, value: expression }).stack; // Compile the conditional (if available) if (conditional) { token.conditional = Twig.expression.compile.call(this, { type: Twig.expression.type.expression, value: conditional }).stack; } delete token.match; return token; }, parse(token, context, continueChain) { // Parse expression const output = []; let len; let index = 0; let keyset; const state = this; const {conditional} = token; const buildLoop = function (index, len) { const isConditional = conditional !== undefined; return { index: index + 1, index0: index, revindex: isConditional ? undefined : len - index, revindex0: isConditional ? undefined : len - index - 1, first: (index === 0), last: isConditional ? undefined : (index === len - 1), length: isConditional ? undefined : len, parent: context }; }; // Run once for each iteration of the loop const loop = function (key, value) { const innerContext = {...context}; innerContext[token.valueVar] = value; if (token.keyVar) { innerContext[token.keyVar] = key; } // Loop object innerContext.loop = buildLoop(index, len); const promise = conditional === undefined ? Twig.Promise.resolve(true) : Twig.expression.parseAsync.call(state, conditional, innerContext); return promise.then(condition => { if (!condition) { return; } return state.parseAsync(token.output, innerContext) .then(tokenOutput => { output.push(tokenOutput); index += 1; }); }) .then(() => { // Delete loop-related variables from the context delete innerContext.loop; delete innerContext[token.valueVar]; delete innerContext[token.keyVar]; // Merge in values that exist in context but have changed // in inner_context. Twig.merge(context, innerContext, true); }); }; return Twig.expression.parseAsync.call(state, token.expression, context) .then(result => { if (Array.isArray(result)) { len = result.length; return Twig.async.forEach(result, value => { const key = index; return loop(key, value); }); } if (Twig.lib.is('Object', result)) { if (result._keys === undefined) { keyset = Object.keys(result); } else { keyset = result._keys; } len = keyset.length; return Twig.async.forEach(keyset, key => { // Ignore the _keys property, it's internal to twig.js if (key === '_keys') { return; } return loop(key, result[key]); }); } }) .then(() => { // Only allow else statements if no output was generated continueChain = (output.length === 0); return { chain: continueChain, context, output: Twig.output.call(state.template, output) }; }); } }, { /** * End for type logic tokens. * * Format: {% endfor %} */ type: Twig.logic.type.endfor, regex: /^endfor$/, next: [], open: false }, { /** * Set type logic tokens. * * Format: {% set key = expression %} */ type: Twig.logic.type.set, regex: /^set\s+([a-zA-Z0-9_,\s]+)\s*=\s*([\s\S]+)$/, next: [], open: true, compile(token) { // const key = token.match[1].trim(); const expression = token.match[2]; // Compile the expression. const expressionStack = Twig.expression.compile.call(this, { type: Twig.expression.type.expression, value: expression }).stack; token.key = key; token.expression = expressionStack; delete token.match; return token; }, parse(token, context, continueChain) { const {key} = token; const state = this; return Twig.expression.parseAsync.call(state, token.expression, context) .then(value => { if (value === context) { /* If storing the context in a variable, it needs to be a clone of the current state of context. Otherwise we have a context with infinite recursion. Fixes #341 */ value = {...value}; } context[key] = value; return { chain: continueChain, context }; }); } }, { /** * Set capture type logic tokens. * * Format: {% set key %} */ type: Twig.logic.type.setcapture, regex: /^set\s+([a-zA-Z0-9_,\s]+)$/, next: [ Twig.logic.type.endset ], open: true, compile(token) { const key = token.match[1].trim(); token.key = key; delete token.match; return token; }, parse(token, context, continueChain) { const state = this; const {key} = token; return state.parseAsync(token.output, context) .then(output => { // Set on both the global and local context state.context[key] = output; context[key] = output; return { chain: continueChain, context }; }); } }, { /** * End set type block logic tokens. * * Format: {% endset %} */ type: Twig.logic.type.endset, regex: /^endset$/, next: [], open: false }, { /** * Filter logic tokens. * * Format: {% filter upper %} or {% filter lower|escape %} */ type: Twig.logic.type.filter, regex: /^filter\s+(.+)$/, next: [ Twig.logic.type.endfilter ], open: true, compile(token) { const expression = '|' + token.match[1].trim(); // Compile the expression. token.stack = Twig.expression.compile.call(this, { type: Twig.expression.type.expression, value: expression }).stack; delete token.match; return token; }, parse(token, context, chain) { const state = this; return state.parseAsync(token.output, context) .then(output => { const stack = [{ type: Twig.expression.type.string, value: output }].concat(token.stack); return Twig.expression.parseAsync.call(state, stack, context); }) .then(output => { return { chain, output }; }); } }, { /** * End filter logic tokens. * * Format: {% endfilter %} */ type: Twig.logic.type.endfilter, regex: /^endfilter$/, next: [], open: false }, { /** * Apply logic tokens. * * Format: {% apply upper %} or {% apply lower|escape %} */ type: Twig.logic.type.apply, regex: /^apply\s+(.+)$/, next: [ Twig.logic.type.endapply ], open: true, compile(token) { const expression = '|' + token.match[1].trim(); // Compile the expression. token.stack = Twig.expression.compile.call(this, { type: Twig.expression.type.expression, value: expression }).stack; delete token.match; return token; }, parse(token, context, chain) { const state = this; return state.parseAsync(token.output, context) .then(output => { const stack = [{ type: Twig.expression.type.string, value: output }].concat(token.stack); return Twig.expression.parseAsync.call(state, stack, context); }) .then(output => { return { chain, output }; }); } }, { /** * End apply logic tokens. * * Format: {% endapply %} */ type: Twig.logic.type.endapply, regex: /^endapply$/, next: [], open: false }, { /** * Set type logic tokens. * * Format: {% do expression %} */ type: Twig.logic.type.do, regex: /^do\s+([\S\s]+)$/, next: [], open: true, compile(token) { // const expression = token.match[1]; // Compile the expression. const expressionStack = Twig.expression.compile.call(this, { type: Twig.expression.type.expression, value: expression }).stack; token.expression = expressionStack; delete token.match; return token; }, parse(token, context, continueChain) { const state = this; return Twig.expression.parseAsync.call(state, token.expression, context) .then(() => { return { chain: continueChain, context }; }); } }, { /** * Block logic tokens. * * Format: {% block title %} */ type: Twig.logic.type.block, regex: /^block\s+(\w+)$/, next: [ Twig.logic.type.endblock ], open: true, compile(token) { token.blockName = token.match[1].trim(); delete token.match; return token; }, parse(token, context, chain) { const state = this; let promise = Twig.Promise.resolve(); state.template.blocks.defined[token.blockName] = new Twig.Block(state.template, token); if ( state.template.parentTemplate === null || state.template.parentTemplate instanceof Twig.Template ) { promise = state.getBlock(token.blockName).render(state, context); } return promise.then(output => { return { chain, output }; }); } }, { /** * Block shorthand logic tokens. * * Format: {% block title expression %} */ type: Twig.logic.type.shortblock, regex: /^block\s+(\w+)\s+(.+)$/, next: [], open: true, compile(token) { const template = this; token.expression = token.match[2].trim(); token.output = Twig.expression.compile({ type: Twig.expression.type.expression, value: token.expression }).stack; return Twig.logic.handler[Twig.logic.type.block].compile.apply(template, [token]); }, parse(...args) { const state = this; return Twig.logic.handler[Twig.logic.type.block].parse.apply(state, args); } }, { /** * End block logic tokens. * * Format: {% endblock %} */ type: Twig.logic.type.endblock, regex: /^endblock(?:\s+(\w+))?$/, next: [], open: false }, { /** * Block logic tokens. * * Format: {% extends "template.twig" %} */ type: Twig.logic.type.extends_, regex: /^extends\s+(.+)$/, next: [], open: true, compile(token) { const expression = token.match[1].trim(); delete token.match; token.stack = Twig.expression.compile.call(this, { type: Twig.expression.type.expression, value: expression }).stack; return token; }, parse(token, context, chain) { const state = this; return Twig.expression.parseAsync.call(state, token.stack, context) .then(fileName => { if (Array.isArray(fileName)) { const result = fileName.reverse().reduce((acc, file) => { try { return { render: state.template.importFile(file), fileName: file }; /* eslint-disable-next-line no-unused-vars */ } catch (error) { return acc; } }, { render: null, fileName: null }); if (result.fileName !== null) { state.template.parentTemplate = result.fileName; } } else { state.template.parentTemplate = fileName; } return { chain, output: '' }; }); } }, { /** * Block logic tokens. * * Format: {% use "template.twig" %} */ type: Twig.logic.type.use, regex: /^use\s+(.+)$/, next: [], open: true, compile(token) { const expression = token.match[1].trim(); delete token.match; token.stack = Twig.expression.compile.call(this, { type: Twig.expression.type.expression, value: expression }).stack; return token; }, parse(token, context, chain) { const state = this; return Twig.expression.parseAsync.call(state, token.stack, context) .then(filePath => { // Create a new state instead of using the current state // any defined blocks will be created in isolation const useTemplate = state.template.importFile(filePath); const useState = new Twig.ParseState(useTemplate); return useState.parseAsync(useTemplate.tokens) .then(() => { state.template.blocks.imported = { ...state.template.blocks.imported, ...useState.getBlocks() }; }); }) .then(() => { return { chain, output: '' }; }); } }, { /** * Block logic tokens. * * Format: {% includes "template.twig" [with {some: 'values'} only] %} */ type: Twig.logic.type.include, regex: /^include\s+(.+?)(?:\s|$)(ignore missing(?:\s|$))?(?:with\s+([\S\s]+?))?(?:\s|$)(only)?$/, next: [], open: true, compile(token) { const {match} = token; const expression = match[1].trim(); const ignoreMissing = match[2] !== undefined; const withContext = match[3]; const only = ((match[4] !== undefined) && match[4].length); delete token.match; token.only = only; token.ignoreMissing = ignoreMissing; token.stack = Twig.expression.compile.call(this, { type: Twig.expression.type.expression, value: expression }).stack; if (withContext !== undefined) { token.withStack = Twig.expression.compile.call(this, { type: Twig.expression.type.expression, value: withContext.trim() }).stack; } return token; }, parse(token, context, chain) { // Resolve filename let innerContext = token.only ? {} : {...context}; const {ignoreMissing} = token; const state = this; let promise = null; const result = {chain, output: ''}; if (typeof token.withStack === 'undefined') { promise = Twig.Promise.resolve(); } else { promise = Twig.expression.parseAsync.call(state, token.withStack, context) .then(withContext => { innerContext = { ...innerContext, ...withContext }; }); } return promise .then(() => { return Twig.expression.parseAsync.call(state, token.stack, context); }) .then(file => { let files; if (Array.isArray(file)) { files = file; } else { files = [file]; } const result = files.reduce((acc, file) => { if (acc.render === null) { if (file instanceof Twig.Template) { return { render: file.renderAsync( innerContext, { isInclude: true } ), lastError: null }; } try { return { render: state.template.importFile(file).renderAsync( innerContext, { isInclude: true } ), lastError: null }; } catch (error) { return { render: null, lastError: error }; } } return acc; }, {render: null, lastError: null}); if (result.render !== null) { return result.render; } if (result.render === null && ignoreMissing) { return ''; } throw result.lastError; }) .then(output => { if (output !== '') { result.output = output; } return result; }); } }, { type: Twig.logic.type.spaceless, regex: /^spaceless$/, next: [ Twig.logic.type.endspaceless ], open: true, // Parse the html and return it without any spaces between tags parse(token, context, chain) { const state = this; // Parse the output without any filter return state.parseAsync(token.output, context) .then(tokenOutput => { const // A regular expression to find closing and opening tags with spaces between them rBetweenTagSpaces = />\s+<').trim(); // Rewrap output as a Twig.Markup output = new Twig.Markup(output); return { chain, output }; }); } }, // Add the {% endspaceless %} token { type: Twig.logic.type.endspaceless, regex: /^endspaceless$/, next: [], open: false }, { /** * Macro logic tokens. * * Format: {% macro input(name = default, value, type, size) %} * */ type: Twig.logic.type.macro, regex: /^macro\s+(\w+)\s*\(\s*((?:\w+(?:\s*=\s*([\s\S]+))?(?:,\s*)?)*)\s*\)$/, next: [ Twig.logic.type.endmacro ], open: true, compile(token) { const macroName = token.match[1]; const rawParameters = token.match[2].split(/\s*,\s*/); const parameters = rawParameters.map(rawParameter => { return rawParameter.split(/\s*=\s*/)[0]; }); const parametersCount = parameters.length; // Duplicate check if (parametersCount > 1) { const uniq = {}; for (let i = 0; i < parametersCount; i++) { const parameter = parameters[i]; if (uniq[parameter]) { throw new Twig.Error('Duplicate arguments for parameter: ' + parameter); } else { uniq[parameter] = 1; } } } token.macroName = macroName; token.parameters = parameters; token.defaults = rawParameters.reduce(function (defaults, rawParameter) { const pair = rawParameter.split(/\s*=\s*/); const key = pair[0]; const expression = pair[1]; if (expression) { defaults[key] = Twig.expression.compile.call(this, { type: Twig.expression.type.expression, value: expression }).stack; } else { defaults[key] = undefined; } return defaults; }, {}); delete token.match; return token; }, parse(token, context, chain) { const state = this; state.macros[token.macroName] = function (...args) { // Pass global context and other macros const macroContext = { // Use current state context because state context includes current loop variables as well ...state.context, _self: state.macros }; // Save arguments return Twig.async.forEach(token.parameters, function (prop, i) { // Add parameters from context to macroContext if (typeof args[i] !== 'undefined') { macroContext[prop] = args[i]; return true; } if (typeof token.defaults[prop] !== 'undefined') { return Twig.expression.parseAsync.call(this, token.defaults[prop], context) .then(value => { macroContext[prop] = value; return Twig.Promise.resolve(); }); } macroContext[prop] = undefined; return true; }).then(() => { // Render return state.parseAsync(token.output, macroContext); }); }; return { chain, output: '' }; } }, { /** * End macro logic tokens. * * Format: {% endmacro %} */ type: Twig.logic.type.endmacro, regex: /^endmacro$/, next: [], open: false }, { /* * Import logic tokens. * * Format: {% import "template.twig" as form %} */ type: Twig.logic.type.import_, regex: /^import\s+(.+)\s+as\s+(\w+)$/, next: [], open: true, compile(token) { const expression = token.match[1].trim(); const contextName = token.match[2].trim(); delete token.match; token.expression = expression; token.contextName = contextName; token.stack = Twig.expression.compile.call(this, { type: Twig.expression.type.expression, value: expression }).stack; return token; }, parse(token, context, chain) { const state = this; const output = { chain, output: '' }; if (token.expression === '_self') { context[token.contextName] = state.macros; return output; } return Twig.expression.parseAsync.call(state, token.stack, context) .then(filePath => { return state.template.importFile(filePath || token.expression); }) .then(importTemplate => { const importState = new Twig.ParseState(importTemplate); return importState.parseAsync(importTemplate.tokens).then(() => { context[token.contextName] = importState.macros; return output; }); }); } }, { /* * From logic tokens. * * Format: {% from "template.twig" import func as form %} */ type: Twig.logic.type.from, regex: /^from\s+(.+)\s+import\s+([a-zA-Z0-9_, ]+)$/, next: [], open: true, compile(token) { const expression = token.match[1].trim(); const macroExpressions = token.match[2].trim().split(/\s*,\s*/); const macroNames = {}; for (const res of macroExpressions) { // Match function as variable const macroMatch = res.match(/^(\w+)\s+as\s+(\w+)$/); if (macroMatch) { macroNames[macroMatch[1].trim()] = macroMatch[2].trim(); } else if (res.match(/^(\w+)$/)) { macroNames[res] = res; } else { // ignore import } } delete token.match; token.expression = expression; token.macroNames = macroNames; token.stack = Twig.expression.compile.call(this, { type: Twig.expression.type.expression, value: expression }).stack; return token; }, parse(token, context, chain) { const state = this; let promise; if (token.expression === '_self') { promise = Twig.Promise.resolve(state.macros); } else { promise = Twig.expression.parseAsync.call(state, token.stack, context) .then(filePath => { return state.template.importFile(filePath || token.expression); }) .then(importTemplate => { const importState = new Twig.ParseState(importTemplate); return importState.parseAsync(importTemplate.tokens).then(() => { return importState.macros; }); }); } return promise .then(macros => { for (const macroName in token.macroNames) { if (macros[macroName] !== undefined) { context[token.macroNames[macroName]] = macros[macroName]; } } return { chain, output: '' }; }); } }, { /** * The embed tag combines the behaviour of include and extends. * It allows you to include another template's contents, just like include does. * * Format: {% embed "template.twig" [with {some: 'values'} only] %} */ type: Twig.logic.type.embed, regex: /^embed\s+(.+?)(?:\s+(ignore missing))?(?:\s+with\s+([\S\s]+?))?(?:\s+(only))?$/, next: [ Twig.logic.type.endembed ], open: true, compile(token) { const {match} = token; const expression = match[1].trim(); const ignoreMissing = match[2] !== undefined; const withContext = match[3]; const only = ((match[4] !== undefined) && match[4].length); delete token.match; token.only = only; token.ignoreMissing = ignoreMissing; token.stack = Twig.expression.compile.call(this, { type: Twig.expression.type.expression, value: expression }).stack; if (withContext !== undefined) { token.withStack = Twig.expression.compile.call(this, { type: Twig.expression.type.expression, value: withContext.trim() }).stack; } return token; }, parse(token, context, chain) { let embedContext = {}; let promise = Twig.Promise.resolve(); let state = this; if (!token.only) { embedContext = {...context}; } if (token.withStack !== undefined) { promise = Twig.expression.parseAsync.call(state, token.withStack, context).then(withContext => { embedContext = {...embedContext, ...withContext}; }); } return promise .then(() => { return Twig.expression.parseAsync.call(state, token.stack, embedContext); }) .then(fileName => { const embedOverrideTemplate = new Twig.Template({ data: token.output, base: state.template.base, path: state.template.path, url: state.template.url, name: state.template.name, method: state.template.method, options: state.template.options }); try { embedOverrideTemplate.importFile(fileName); } catch (error) { if (token.ignoreMissing) { return ''; } // Errors preserve references to variables in scope, // this removes `this` from the scope. state = null; throw error; } embedOverrideTemplate.parentTemplate = fileName; return embedOverrideTemplate.renderAsync( embedContext, { isInclude: true } ); }) .then(output => { return { chain, output }; }); } }, /* Add the {% endembed %} token * */ { type: Twig.logic.type.endembed, regex: /^endembed$/, next: [], open: false }, { /** * Block logic tokens. * * Format: {% with {some: 'values'} [only] %} */ type: Twig.logic.type.with, regex: /^(?:with(?:\s+([\S\s]+?))?)(?:\s|$)(only)?$/, next: [ Twig.logic.type.endwith ], open: true, compile(token) { const {match} = token; const withContext = match[1]; const only = ((match[2] !== undefined) && match[2].length); delete token.match; token.only = only; if (withContext !== undefined) { token.withStack = Twig.expression.compile.call(this, { type: Twig.expression.type.expression, value: withContext.trim() }).stack; } return token; }, parse(token, context, chain) { // Resolve filename let innerContext = {}; let i; const state = this; let promise = Twig.Promise.resolve(); if (!token.only) { innerContext = {...context}; } if (token.withStack !== undefined) { promise = Twig.expression.parseAsync.call(state, token.withStack, context) .then(withContext => { for (i in withContext) { if (Object.hasOwnProperty.call(withContext, i)) { innerContext[i] = withContext[i]; } } }); } const isolatedState = new Twig.ParseState(state.template, undefined, innerContext); return promise .then(() => { return isolatedState.parseAsync(token.output); }) .then(output => { return { chain, output }; }); } }, { type: Twig.logic.type.endwith, regex: /^endwith$/, next: [], open: false }, { /** * Deprecated type logic tokens. * * Format: {% deprecated 'Description' %} */ type: Twig.logic.type.deprecated, regex: /^deprecated\s+(.+)$/, next: [], open: true, compile(token) { console.warn('Deprecation notice: ' + token.match[1]); return token; }, parse() { return {}; } } ]; /** * Registry for logic handlers. */ Twig.logic.handler = {}; /** * Define a new token type, available at Twig.logic.type.{type} */ Twig.logic.extendType = function (type, value) { value = value || ('Twig.logic.type' + type); Twig.logic.type[type] = value; }; /** * Extend the logic parsing functionality with a new token definition. * * // Define a new tag * Twig.logic.extend({ * type: Twig.logic.type.{type}, * // The pattern to match for this token * regex: ..., * // What token types can follow this token, leave blank if any. * next: [ ... ] * // Create and return compiled version of the token * compile: function(token) { ... } * // Parse the compiled token with the context provided by the render call * // and whether this token chain is complete. * parse: function(token, context, chain) { ... } * }); * * @param {Object} definition The new logic expression. */ Twig.logic.extend = function (definition) { if (definition.type) { Twig.logic.extendType(definition.type); } else { throw new Twig.Error('Unable to extend logic definition. No type provided for ' + definition); } Twig.logic.handler[definition.type] = definition; }; // Extend with built-in expressions while (Twig.logic.definitions.length > 0) { Twig.logic.extend(Twig.logic.definitions.shift()); } /** * Compile a logic token into an object ready for parsing. * * @param {Object} rawToken An uncompiled logic token. * * @return {Object} A compiled logic token, ready for parsing. */ Twig.logic.compile = function (rawToken) { const expression = rawToken.value.trim(); let token = Twig.logic.tokenize.call(this, expression); const tokenTemplate = Twig.logic.handler[token.type]; // Check if the token needs compiling if (tokenTemplate.compile) { token = tokenTemplate.compile.call(this, token); Twig.log.trace('Twig.logic.compile: ', 'Compiled logic token to ', token); } return token; }; /** * Tokenize logic expressions. This function matches token expressions against regular * expressions provided in token definitions provided with Twig.logic.extend. * * @param {string} expression the logic token expression to tokenize * (i.e. what's between {% and %}) * * @return {Object} The matched token with type set to the token type and match to the regex match. */ Twig.logic.tokenize = function (expression) { let tokenTemplateType = null; let tokenType = null; let tokenRegex = null; let regexArray = null; let regexLen = null; let regexI = null; let match = null; // Ignore whitespace around expressions. expression = expression.trim(); for (tokenTemplateType in Twig.logic.handler) { if (Object.hasOwnProperty.call(Twig.logic.handler, tokenTemplateType)) { // Get the type and regex for this template type tokenType = Twig.logic.handler[tokenTemplateType].type; tokenRegex = Twig.logic.handler[tokenTemplateType].regex; // Handle multiple regular expressions per type. regexArray = tokenRegex; if (!Array.isArray(tokenRegex)) { regexArray = [tokenRegex]; } regexLen = regexArray.length; // Check regular expressions in the order they were specified in the definition. for (regexI = 0; regexI < regexLen; regexI++) { match = regexArray[regexI].exec(expression); if (match !== null) { Twig.log.trace('Twig.logic.tokenize: ', 'Matched a ', tokenType, ' regular expression of ', match); return { type: tokenType, match }; } } } } // No regex matches throw new Twig.Error('Unable to parse \'' + expression.trim() + '\''); }; /** * Parse a logic token within a given context. * * What are logic chains? * Logic chains represent a series of tokens that are connected, * for example: * {% if ... %} {% else %} {% endif %} * * The chain parameter is used to signify if a chain is open of closed. * open: * More tokens in this chain should be parsed. * closed: * This token chain has completed parsing and any additional * tokens (else, elseif, etc...) should be ignored. * * @param {Object} token The compiled token. * @param {Object} context The render context. * @param {boolean} chain Is this an open logic chain. If false, that means a * chain is closed and no further cases should be parsed. */ Twig.logic.parse = function (token, context, chain, allowAsync) { return Twig.async.potentiallyAsync(this, allowAsync, function () { Twig.log.debug('Twig.logic.parse: ', 'Parsing logic token ', token); const tokenTemplate = Twig.logic.handler[token.type]; let result; const state = this; if (!tokenTemplate.parse) { return ''; } state.nestingStack.unshift(token); result = tokenTemplate.parse.call(state, token, context || {}, chain); if (Twig.isPromise(result)) { result = result.then(result => { state.nestingStack.shift(); return result; }); } else { state.nestingStack.shift(); } return result; }); }; return Twig; }; /***/ }), /***/ "./node_modules/twig/src/twig.parser.source.js": /*!*****************************************************!*\ !*** ./node_modules/twig/src/twig.parser.source.js ***! \*****************************************************/ /***/ ((module) => { module.exports = function (Twig) { 'use strict'; Twig.Templates.registerParser('source', params => { return params.data || ''; }); }; /***/ }), /***/ "./node_modules/twig/src/twig.parser.twig.js": /*!***************************************************!*\ !*** ./node_modules/twig/src/twig.parser.twig.js ***! \***************************************************/ /***/ ((module) => { module.exports = function (Twig) { 'use strict'; Twig.Templates.registerParser('twig', params => { return new Twig.Template(params); }); }; /***/ }), /***/ "./node_modules/twig/src/twig.path.js": /*!********************************************!*\ !*** ./node_modules/twig/src/twig.path.js ***! \********************************************/ /***/ ((module, __unused_webpack_exports, __webpack_require__) => { // ## twig.path.js // // This file handles path parsing module.exports = function (Twig) { 'use strict'; /** * Namespace for path handling. */ Twig.path = {}; /** * @param {Twig.Template} template * @param {string} path */ Twig.path.expandNamespace = function (namespaces, path) { const namespaceIdentifiers = Object.keys(namespaces); const pattern = new RegExp(`^(?:@(${namespaceIdentifiers.join('|')})/|(${namespaceIdentifiers.join('|')})::)`); return path.replace(pattern, (wholeMatch, atNamespace, colonNamespace) => { const namespaceIdentifier = (atNamespace === undefined ? colonNamespace : atNamespace); return `${namespaces[namespaceIdentifier]}/`; }); }; /** * Generate the canonical version of a url based on the given base path and file path and in * the previously registered namespaces. * * @param {string} template The Twig Template * @param {string} _file The file path, may be relative and may contain namespaces. * * @return {string} The canonical version of the path */ Twig.path.parsePath = function (template, _file) { const {namespaces} = template.options; const file = _file || ''; const hasNamespaces = namespaces && typeof namespaces === 'object'; let path = (hasNamespaces ? Twig.path.expandNamespace(namespaces, file) : file); if (path === file) { path = Twig.path.relativePath(template, file); } return path; }; /** * Generate the relative canonical version of a url based on the given base path and file path. * * @param {Twig.Template} template The Twig.Template. * @param {string} _file The file path, relative to the base path. * * @return {string} The canonical version of the path. */ Twig.path.relativePath = function (template, _file) { let base; let basePath; let sepChr = '/'; const newPath = []; let file = _file || ''; let val; if (template.url) { if (typeof template.base === 'undefined') { base = template.url; } else { // Add slash to the end of path base = template.base.replace(/([^/])$/, '$1/'); } } else if (template.path) { // Get the system-specific path separator const path = __webpack_require__(/*! path */ "./node_modules/path-browserify/index.js"); const sep = path.sep || sepChr; const relative = new RegExp('^\\.{1,2}' + sep.replace('\\', '\\\\')); file = file.replace(/\//g, sep); if (template.base !== undefined && file.match(relative) === null) { file = file.replace(template.base, ''); base = template.base + sep; } else { base = path.normalize(template.path); } base = base.replace(sep + sep, sep); sepChr = sep; } else if ((template.name || template.id) && template.method && template.method !== 'fs' && template.method !== 'ajax') { // Custom registered loader base = template.base || template.name || template.id; } else { throw new Twig.Error('Cannot extend an inline template.'); } basePath = base.split(sepChr); // Remove file from url basePath.pop(); basePath = basePath.concat(file.split(sepChr)); while (basePath.length > 0) { val = basePath.shift(); if (val === '.') { // Ignore } else if (val === '..' && newPath.length > 0 && newPath[newPath.length - 1] !== '..') { newPath.pop(); } else { newPath.push(val); } } return newPath.join(sepChr); }; return Twig; }; /***/ }), /***/ "./node_modules/twig/src/twig.tests.js": /*!*********************************************!*\ !*** ./node_modules/twig/src/twig.tests.js ***! \*********************************************/ /***/ ((module) => { // ## twig.tests.js // // This file handles expression tests. (is empty, is not defined, etc...) module.exports = function (Twig) { 'use strict'; Twig.tests = { empty(value) { // Handle boolean true if (value === true) { return false; } // Handle null or undefined if (value === null || value === undefined) { return true; } // Handler numbers if (typeof value === 'number') { return false; } // Numbers are never "empty" // Handle strings and arrays if (value.length > 0) { return false; } // Handle objects for (const key in value) { if (Object.hasOwnProperty.call(value, key)) { return false; } } return true; }, odd(value) { return value % 2 === 1; }, even(value) { return value % 2 === 0; }, 'divisible by'(value, params) { return value % params[0] === 0; }, divisibleby(value, params) { console.warn('`divisibleby` is deprecated use `divisible by`'); return Twig.tests['divisible by'](value, params); }, defined(value) { return value !== undefined; }, none(value) { return value === null; }, null(value) { return this.none(value); // Alias of none }, 'same as'(value, params) { return value === params[0]; }, sameas(value, params) { console.warn('`sameas` is deprecated use `same as`'); return Twig.tests['same as'](value, params); }, iterable(value) { return value && (Twig.lib.is('Array', value) || Twig.lib.is('Object', value)); } /* Constant ? */ }; Twig.test = function (test, value, params) { if (!Twig.tests[test]) { throw Twig.Error('Test ' + test + ' is not defined.'); } return Twig.tests[test](value, params); }; Twig.test.extend = function (test, definition) { Twig.tests[test] = definition; }; return Twig; }; /***/ }), /***/ "?506a": /*!********************!*\ !*** fs (ignored) ***! \********************/ /***/ (() => { /* (ignored) */ /***/ }) /******/ }); /************************************************************************/ /******/ // The module cache /******/ var __webpack_module_cache__ = {}; /******/ /******/ // The require function /******/ function __webpack_require__(moduleId) { /******/ // Check if module is in cache /******/ var cachedModule = __webpack_module_cache__[moduleId]; /******/ if (cachedModule !== undefined) { /******/ return cachedModule.exports; /******/ } /******/ // Create a new module (and put it into the cache) /******/ var module = __webpack_module_cache__[moduleId] = { /******/ // no module.id needed /******/ // no module.loaded needed /******/ exports: {} /******/ }; /******/ /******/ // Execute the module function /******/ __webpack_modules__[moduleId](module, module.exports, __webpack_require__); /******/ /******/ // Return the exports of the module /******/ return module.exports; /******/ } /******/ /************************************************************************/ /******/ /* webpack/runtime/compat get default export */ /******/ (() => { /******/ // getDefaultExport function for compatibility with non-harmony modules /******/ __webpack_require__.n = (module) => { /******/ var getter = module && module.__esModule ? /******/ () => (module['default']) : /******/ () => (module); /******/ __webpack_require__.d(getter, { a: getter }); /******/ return getter; /******/ }; /******/ })(); /******/ /******/ /* webpack/runtime/define property getters */ /******/ (() => { /******/ // define getter functions for harmony exports /******/ __webpack_require__.d = (exports, definition) => { /******/ for(var key in definition) { /******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) { /******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] }); /******/ } /******/ } /******/ }; /******/ })(); /******/ /******/ /* webpack/runtime/hasOwnProperty shorthand */ /******/ (() => { /******/ __webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop)) /******/ })(); /******/ /******/ /* webpack/runtime/make namespace object */ /******/ (() => { /******/ // define __esModule on exports /******/ __webpack_require__.r = (exports) => { /******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { /******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); /******/ } /******/ Object.defineProperty(exports, '__esModule', { value: true }); /******/ }; /******/ })(); /******/ /************************************************************************/ var __webpack_exports__ = {}; // This entry need to be wrapped in an IIFE because it need to be in strict mode. (() => { "use strict"; /*!*****************************************!*\ !*** ./src/blog-product-reviews.lib.js ***! \*****************************************/ __webpack_require__.r(__webpack_exports__); /* harmony import */ var _products_review_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./products-review.js */ "./src/products-review.js"); /* harmony import */ var _pager_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./pager.js */ "./src/pager.js"); /* harmony import */ var _pager_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_pager_js__WEBPACK_IMPORTED_MODULE_1__); /* harmony import */ var _form_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./form.js */ "./src/form.js"); /* harmony import */ var _form_js__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(_form_js__WEBPACK_IMPORTED_MODULE_2__); /* harmony import */ var _api_config_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./api.config.js */ "./src/api.config.js"); function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); } function _regeneratorRuntime() { "use strict"; /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/facebook/regenerator/blob/main/LICENSE */ _regeneratorRuntime = function _regeneratorRuntime() { return e; }; var t, e = {}, r = Object.prototype, n = r.hasOwnProperty, o = Object.defineProperty || function (t, e, r) { t[e] = r.value; }, i = "function" == typeof Symbol ? Symbol : {}, a = i.iterator || "@@iterator", c = i.asyncIterator || "@@asyncIterator", u = i.toStringTag || "@@toStringTag"; function define(t, e, r) { return Object.defineProperty(t, e, { value: r, enumerable: !0, configurable: !0, writable: !0 }), t[e]; } try { define({}, ""); } catch (t) { define = function define(t, e, r) { return t[e] = r; }; } function wrap(t, e, r, n) { var i = e && e.prototype instanceof Generator ? e : Generator, a = Object.create(i.prototype), c = new Context(n || []); return o(a, "_invoke", { value: makeInvokeMethod(t, r, c) }), a; } function tryCatch(t, e, r) { try { return { type: "normal", arg: t.call(e, r) }; } catch (t) { return { type: "throw", arg: t }; } } e.wrap = wrap; var h = "suspendedStart", l = "suspendedYield", f = "executing", s = "completed", y = {}; function Generator() {} function GeneratorFunction() {} function GeneratorFunctionPrototype() {} var p = {}; define(p, a, function () { return this; }); var d = Object.getPrototypeOf, v = d && d(d(values([]))); v && v !== r && n.call(v, a) && (p = v); var g = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(p); function defineIteratorMethods(t) { ["next", "throw", "return"].forEach(function (e) { define(t, e, function (t) { return this._invoke(e, t); }); }); } function AsyncIterator(t, e) { function invoke(r, o, i, a) { var c = tryCatch(t[r], t, o); if ("throw" !== c.type) { var u = c.arg, h = u.value; return h && "object" == _typeof(h) && n.call(h, "__await") ? e.resolve(h.__await).then(function (t) { invoke("next", t, i, a); }, function (t) { invoke("throw", t, i, a); }) : e.resolve(h).then(function (t) { u.value = t, i(u); }, function (t) { return invoke("throw", t, i, a); }); } a(c.arg); } var r; o(this, "_invoke", { value: function value(t, n) { function callInvokeWithMethodAndArg() { return new e(function (e, r) { invoke(t, n, e, r); }); } return r = r ? r.then(callInvokeWithMethodAndArg, callInvokeWithMethodAndArg) : callInvokeWithMethodAndArg(); } }); } function makeInvokeMethod(e, r, n) { var o = h; return function (i, a) { if (o === f) throw Error("Generator is already running"); if (o === s) { if ("throw" === i) throw a; return { value: t, done: !0 }; } for (n.method = i, n.arg = a;;) { var c = n.delegate; if (c) { var u = maybeInvokeDelegate(c, n); if (u) { if (u === y) continue; return u; } } if ("next" === n.method) n.sent = n._sent = n.arg;else if ("throw" === n.method) { if (o === h) throw o = s, n.arg; n.dispatchException(n.arg); } else "return" === n.method && n.abrupt("return", n.arg); o = f; var p = tryCatch(e, r, n); if ("normal" === p.type) { if (o = n.done ? s : l, p.arg === y) continue; return { value: p.arg, done: n.done }; } "throw" === p.type && (o = s, n.method = "throw", n.arg = p.arg); } }; } function maybeInvokeDelegate(e, r) { var n = r.method, o = e.iterator[n]; if (o === t) return r.delegate = null, "throw" === n && e.iterator["return"] && (r.method = "return", r.arg = t, maybeInvokeDelegate(e, r), "throw" === r.method) || "return" !== n && (r.method = "throw", r.arg = new TypeError("The iterator does not provide a '" + n + "' method")), y; var i = tryCatch(o, e.iterator, r.arg); if ("throw" === i.type) return r.method = "throw", r.arg = i.arg, r.delegate = null, y; var a = i.arg; return a ? a.done ? (r[e.resultName] = a.value, r.next = e.nextLoc, "return" !== r.method && (r.method = "next", r.arg = t), r.delegate = null, y) : a : (r.method = "throw", r.arg = new TypeError("iterator result is not an object"), r.delegate = null, y); } function pushTryEntry(t) { var e = { tryLoc: t[0] }; 1 in t && (e.catchLoc = t[1]), 2 in t && (e.finallyLoc = t[2], e.afterLoc = t[3]), this.tryEntries.push(e); } function resetTryEntry(t) { var e = t.completion || {}; e.type = "normal", delete e.arg, t.completion = e; } function Context(t) { this.tryEntries = [{ tryLoc: "root" }], t.forEach(pushTryEntry, this), this.reset(!0); } function values(e) { if (e || "" === e) { var r = e[a]; if (r) return r.call(e); if ("function" == typeof e.next) return e; if (!isNaN(e.length)) { var o = -1, i = function next() { for (; ++o < e.length;) if (n.call(e, o)) return next.value = e[o], next.done = !1, next; return next.value = t, next.done = !0, next; }; return i.next = i; } } throw new TypeError(_typeof(e) + " is not iterable"); } return GeneratorFunction.prototype = GeneratorFunctionPrototype, o(g, "constructor", { value: GeneratorFunctionPrototype, configurable: !0 }), o(GeneratorFunctionPrototype, "constructor", { value: GeneratorFunction, configurable: !0 }), GeneratorFunction.displayName = define(GeneratorFunctionPrototype, u, "GeneratorFunction"), e.isGeneratorFunction = function (t) { var e = "function" == typeof t && t.constructor; return !!e && (e === GeneratorFunction || "GeneratorFunction" === (e.displayName || e.name)); }, e.mark = function (t) { return Object.setPrototypeOf ? Object.setPrototypeOf(t, GeneratorFunctionPrototype) : (t.__proto__ = GeneratorFunctionPrototype, define(t, u, "GeneratorFunction")), t.prototype = Object.create(g), t; }, e.awrap = function (t) { return { __await: t }; }, defineIteratorMethods(AsyncIterator.prototype), define(AsyncIterator.prototype, c, function () { return this; }), e.AsyncIterator = AsyncIterator, e.async = function (t, r, n, o, i) { void 0 === i && (i = Promise); var a = new AsyncIterator(wrap(t, r, n, o), i); return e.isGeneratorFunction(r) ? a : a.next().then(function (t) { return t.done ? t.value : a.next(); }); }, defineIteratorMethods(g), define(g, u, "Generator"), define(g, a, function () { return this; }), define(g, "toString", function () { return "[object Generator]"; }), e.keys = function (t) { var e = Object(t), r = []; for (var n in e) r.push(n); return r.reverse(), function next() { for (; r.length;) { var t = r.pop(); if (t in e) return next.value = t, next.done = !1, next; } return next.done = !0, next; }; }, e.values = values, Context.prototype = { constructor: Context, reset: function reset(e) { if (this.prev = 0, this.next = 0, this.sent = this._sent = t, this.done = !1, this.delegate = null, this.method = "next", this.arg = t, this.tryEntries.forEach(resetTryEntry), !e) for (var r in this) "t" === r.charAt(0) && n.call(this, r) && !isNaN(+r.slice(1)) && (this[r] = t); }, stop: function stop() { this.done = !0; var t = this.tryEntries[0].completion; if ("throw" === t.type) throw t.arg; return this.rval; }, dispatchException: function dispatchException(e) { if (this.done) throw e; var r = this; function handle(n, o) { return a.type = "throw", a.arg = e, r.next = n, o && (r.method = "next", r.arg = t), !!o; } for (var o = this.tryEntries.length - 1; o >= 0; --o) { var i = this.tryEntries[o], a = i.completion; if ("root" === i.tryLoc) return handle("end"); if (i.tryLoc <= this.prev) { var c = n.call(i, "catchLoc"), u = n.call(i, "finallyLoc"); if (c && u) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } else if (c) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); } else { if (!u) throw Error("try statement without catch or finally"); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } } } }, abrupt: function abrupt(t, e) { for (var r = this.tryEntries.length - 1; r >= 0; --r) { var o = this.tryEntries[r]; if (o.tryLoc <= this.prev && n.call(o, "finallyLoc") && this.prev < o.finallyLoc) { var i = o; break; } } i && ("break" === t || "continue" === t) && i.tryLoc <= e && e <= i.finallyLoc && (i = null); var a = i ? i.completion : {}; return a.type = t, a.arg = e, i ? (this.method = "next", this.next = i.finallyLoc, y) : this.complete(a); }, complete: function complete(t, e) { if ("throw" === t.type) throw t.arg; return "break" === t.type || "continue" === t.type ? this.next = t.arg : "return" === t.type ? (this.rval = this.arg = t.arg, this.method = "return", this.next = "end") : "normal" === t.type && e && (this.next = e), y; }, finish: function finish(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.finallyLoc === t) return this.complete(r.completion, r.afterLoc), resetTryEntry(r), y; } }, "catch": function _catch(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.tryLoc === t) { var n = r.completion; if ("throw" === n.type) { var o = n.arg; resetTryEntry(r); } return o; } } throw Error("illegal catch attempt"); }, delegateYield: function delegateYield(e, r, n) { return this.delegate = { iterator: values(e), resultName: r, nextLoc: n }, "next" === this.method && (this.arg = t), y; } }, e; } function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } } function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); } _next(undefined); }); }; } // Allow form behavior changes to use custom selection var Twig = __webpack_require__(/*! twig */ "./node_modules/twig/src/twig.js"); window.apply_form_behavior = _products_review_js__WEBPACK_IMPORTED_MODULE_0__.apply_form_behavior; // @TODO: Consider to move this to global (function ($, Drupal, window) { // Get the script element with id "my-custom-html" window.r_apply_json = /*#__PURE__*/function () { var _ref = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee(element, templateId, target, url, route_name) { var callback, customHtmlScript, $ajaxLoading, rawContent, username, password, base64Credentials, response, data, template, randomTime, _args = arguments; return _regeneratorRuntime().wrap(function _callee$(_context) { while (1) switch (_context.prev = _context.next) { case 0: callback = _args.length > 5 && _args[5] !== undefined ? _args[5] : function () {}; customHtmlScript = document.getElementById(templateId); $ajaxLoading = $('nothing'); // Check if $(target) exists if ($(target).length === 0) { // Create an ajax-loading div after customHtmlScript $(customHtmlScript).after('
'); $ajaxLoading = $(customHtmlScript).next('.ajax-loading'); } else { // Add ajax-loading class to the target $(target).addClass('ajax-loading'); } // Trigger ajax-loading event on the document $(document).trigger('r-ajax-loading'); // Get the raw content inside the script tag rawContent = customHtmlScript.innerHTML; // Fetch JSON data from the URL username = _api_config_js__WEBPACK_IMPORTED_MODULE_3__.config.a; password = _api_config_js__WEBPACK_IMPORTED_MODULE_3__.config.b; // Encode the username and password to Base64 base64Credentials = btoa(username + ':' + password); // We should await _context.prev = 9; _context.next = 12; return fetch(url, { headers: { Authorization: 'Basic ' + base64Credentials } }); case 12: response = _context.sent; _context.next = 15; return response.json(); case 15: data = _context.sent; $ajaxLoading.removeClass('ajax-loading'); $(target).removeClass('ajax-loading'); template = Twig.twig({ data: rawContent }); data.pager = r_build_pager(element, route_name, data.total, data.total_pages, data.current, target, templateId); data.route_name = route_name; rawContent = template.render(data); // Write out the updated raw content to my-custom-html position $(target).remove(); customHtmlScript.insertAdjacentHTML('afterend', rawContent); Drupal.attachBehaviors(); callback(); _context.next = 33; break; case 28: _context.prev = 28; _context.t0 = _context["catch"](9); console.error('Retrying. Error fetching JSON:', _context.t0); randomTime = Math.floor(Math.random() * 3000) + 500; setTimeout(function () { r_apply_json(element, templateId, target, url, route_name, callback); }, randomTime); case 33: $(document).trigger('r-ajax-loaded'); case 34: case "end": return _context.stop(); } }, _callee, null, [[9, 28]]); })); return function (_x, _x2, _x3, _x4, _x5) { return _ref.apply(this, arguments); }; }(); })(jQuery, Drupal, window); })(); /******/ })() ; //# sourceMappingURL=blog-product-reviews.lib.js.map