diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..6897dcc --- /dev/null +++ b/.env.example @@ -0,0 +1,4 @@ +# Copy to .env (git-ignored) to use a real Iframely API key with the demo +# pages served by `pnpm serve`. scripts/serve.mjs substitutes it into the +# demo HTML at request time; without it the pages use the TEST placeholder. +IFRAMELY_API_KEY= diff --git a/.eslintrc b/.eslintrc deleted file mode 100644 index a6f957a..0000000 --- a/.eslintrc +++ /dev/null @@ -1,51 +0,0 @@ -{ - "env": { - "browser": true, - "commonjs": true, - "es6": true, - "jest": true - }, - "extends": "eslint:recommended", - "parserOptions": { - "sourceType": "module" - }, - "globals": { - "ActiveXObject": true - }, - "rules": { - "indent": [ - "error", - 4, - { - "ignoreComments": true - } - ], - "linebreak-style": [ - "error", - "unix" - ], - "quotes": [ - "error", - "single", - { - "avoidEscape": true - } - ], - "semi": [ - "error", - "always" - ], - "no-console": [ - "warn", - { - "allow": ["warn", "error"] - } - ], - "no-empty": [ - "error", - { - "allowEmptyCatch": true - } - ] - } -} \ No newline at end of file diff --git a/.gitignore b/.gitignore index 02ba458..80c5ca2 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,6 @@ node_modules/ package-lock.json .npmrc +test-results/ +playwright-report/ +.env diff --git a/.node-version b/.node-version new file mode 100644 index 0000000..ca5c350 --- /dev/null +++ b/.node-version @@ -0,0 +1 @@ +24.18.0 diff --git a/README.md b/README.md index a9d344e..92a5eb6 100644 --- a/README.md +++ b/README.md @@ -1,68 +1,100 @@ # Iframely.com Embed.js -Embed.js script is a part of [Iframely](https://iframely.com) cloud service for rich media embeds and works *only* with Iframely-hosted [iFrame helpers](https://iframely.com/docs/iframes). The script is normally hosted on Iframely's CDN and is included when required into HTML codes that our API returns. If you wish to self-host the script rather than rely on our CDN, we make the script available here on GitHub and on NPM. - -The script's main function is to adjust height of rich media with variable sizes (say, Twitter, Facebook or Iframely summary cards) and to handle other messages received from Iframely iFrames. The script also enables lazy-loading through intersection observer (including video placeholders), unfurls URLs if you use Iframely without making API requests first, and uses web component imports to speed-up bulk inserts of rich media. - -Read more about the script itself at [iframely.com/docs/embedjs](https://iframely.com/docs/embedjs). The description below focuses solely on self-hosting of the script. - +Embed.js script is a part of [Iframely](https://iframely.com) cloud service for rich media embeds and works *only* with +Iframely-hosted [iFrame helpers](https://iframely.com/docs/iframes). The script is normally hosted on Iframely's CDN and +is included when required in HTML codes that our API returns. If you wish to self-host the script rather than rely on +our CDN, we make the script available here on GitHub and on NPM. + +The script's main function is to adjust the height of rich media with variable sizes (say, Twitter, Facebook, or +Iframely summary cards) and to handle other messages received from Iframely iFrames. The script also enables +lazy-loading through intersection observer (including video placeholders), unfurls URLs if you use Iframely without +making API requests first, and uses web component imports to speed up bulk inserts of rich media. Read more about the +script itself at [iframely.com/docs/embedjs](https://iframely.com/docs/embedjs). The description below focuses solely on +self-hosting of the script. ## Host embed.js on your servers -To serve embed.js script from your network, your reverse proxy needs to be configured to point `embed.js` file to its location on the local disc. +To serve embed.js script from your network, your reverse proxy needs to be configured to point `embed.js` file to its +location on the local disc. * `dist/embed.js` - not minified development version * `dist/embed.min.js` - minified production version -You can either clone repo from GitHub, or pull library from NPM as `@iframely/embed.js`. We recommend creating a symlink to a file first for a simpler reverse proxy config. +You can either clone repo from GitHub or pull the library from NPM as `@iframely/embed.js`. We recommend creating a +symlink to a file first for a simpler reverse proxy config. + +Alternatively, you may include the contents of embed.js in your other JavaScript distributions. The package ships an ES +module build: `import { iframely } from '@iframely/embed.js'` (embed only) or `'@iframely/embed.js/options'` (embed + +options form). TypeScript declarations are included. Unlike the script tag, the ES module does **not** auto-run on +DOMContentLoaded — activate it when your page is ready: -Alternatively, you may include the contents of embed.js into your other JavaScript distributions. Include `src/index.js` main script or entire `"@iframely/embed.js"` module in your own build configuration to pull all dependencides. + import { iframely } from '@iframely/embed.js'; + iframely.configure({ api_key: '...' }); + iframely.load(); + +The module is safe to import in isomorphic setups (SvelteKit, Next.js, etc.): on the server it exports an inert +no-op stub and performs no side effects, so you can import it at the top level and call `iframely.load()` from +client-only code (e.g. Svelte's `onMount`). + +To deactivate, `iframely.unload()` (or `iframely.unload(container)`) removes the widgets that `load()` built and +releases their intersection observers and pending timers — pair it with `load()` across route changes or in unmount +hooks. It does not restore the original `` markup (re-render it yourself to re-embed), and it +does not cover import/shadow-DOM widgets. ## Omit cloud embed.js from API responses -The HTML embed codes you get from Iframely APIs will include the cloud copy of embed.js by default (as ` +
+Watch the video +
+ + diff --git a/demo/double.html b/demo/double.html new file mode 100644 index 0000000..ce368d8 --- /dev/null +++ b/demo/double.html @@ -0,0 +1,26 @@ + + +double-load test + + + + + + diff --git a/demo/esm.html b/demo/esm.html new file mode 100644 index 0000000..2f40c43 --- /dev/null +++ b/demo/esm.html @@ -0,0 +1,21 @@ + + +ESM consumer test + +

ESM manual activation test

+
+ +
+ + + diff --git a/demo/index.html b/demo/index.html new file mode 100644 index 0000000..1e8e3f2 --- /dev/null +++ b/demo/index.html @@ -0,0 +1,11 @@ + + +embed.js demo + +

embed.js smoke test

+ +
+ +
+ + diff --git a/demo/new.html b/demo/new.html new file mode 100644 index 0000000..4b97a90 --- /dev/null +++ b/demo/new.html @@ -0,0 +1,7 @@ + + +new embed.js surface + + + + diff --git a/demo/options-standalone.html b/demo/options-standalone.html new file mode 100644 index 0000000..6bc2c4d --- /dev/null +++ b/demo/options-standalone.html @@ -0,0 +1,21 @@ + + +standalone options.js test + +

options.js without embed.js

+
+ + + + diff --git a/demo/options.html b/demo/options.html new file mode 100644 index 0000000..12752a7 --- /dev/null +++ b/demo/options.html @@ -0,0 +1,23 @@ + + +options form demo + +

options form smoke test

+
+ + + + + diff --git a/dist/embed-autoplay.js b/dist/embed-autoplay.js deleted file mode 100644 index b65ee7b..0000000 --- a/dist/embed-autoplay.js +++ /dev/null @@ -1,100 +0,0 @@ -/******/ (function(modules) { // webpackBootstrap -/******/ // The module cache -/******/ var installedModules = {}; -/******/ -/******/ // The require function -/******/ function __webpack_require__(moduleId) { -/******/ -/******/ // Check if module is in cache -/******/ if(installedModules[moduleId]) { -/******/ return installedModules[moduleId].exports; -/******/ } -/******/ // Create a new module (and put it into the cache) -/******/ var module = installedModules[moduleId] = { -/******/ i: moduleId, -/******/ l: false, -/******/ exports: {} -/******/ }; -/******/ -/******/ // Execute the module function -/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); -/******/ -/******/ // Flag the module as loaded -/******/ module.l = true; -/******/ -/******/ // Return the exports of the module -/******/ return module.exports; -/******/ } -/******/ -/******/ -/******/ // expose the modules object (__webpack_modules__) -/******/ __webpack_require__.m = modules; -/******/ -/******/ // expose the module cache -/******/ __webpack_require__.c = installedModules; -/******/ -/******/ // define getter function for harmony exports -/******/ __webpack_require__.d = function(exports, name, getter) { -/******/ if(!__webpack_require__.o(exports, name)) { -/******/ Object.defineProperty(exports, name, { enumerable: true, get: getter }); -/******/ } -/******/ }; -/******/ -/******/ // define __esModule on exports -/******/ __webpack_require__.r = function(exports) { -/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { -/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); -/******/ } -/******/ Object.defineProperty(exports, '__esModule', { value: true }); -/******/ }; -/******/ -/******/ // create a fake namespace object -/******/ // mode & 1: value is a module id, require it -/******/ // mode & 2: merge all properties of value into the ns -/******/ // mode & 4: return value when already ns object -/******/ // mode & 8|1: behave like require -/******/ __webpack_require__.t = function(value, mode) { -/******/ if(mode & 1) value = __webpack_require__(value); -/******/ if(mode & 8) return value; -/******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value; -/******/ var ns = Object.create(null); -/******/ __webpack_require__.r(ns); -/******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value }); -/******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key)); -/******/ return ns; -/******/ }; -/******/ -/******/ // getDefaultExport function for compatibility with non-harmony modules -/******/ __webpack_require__.n = function(module) { -/******/ var getter = module && module.__esModule ? -/******/ function getDefault() { return module['default']; } : -/******/ function getModuleExports() { return module; }; -/******/ __webpack_require__.d(getter, 'a', getter); -/******/ return getter; -/******/ }; -/******/ -/******/ // Object.prototype.hasOwnProperty.call -/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; -/******/ -/******/ // __webpack_public_path__ -/******/ __webpack_require__.p = ""; -/******/ -/******/ -/******/ // Load entry module and return exports -/******/ return __webpack_require__(__webpack_require__.s = "./index-play-on-scroll.js"); -/******/ }) -/************************************************************************/ -/******/ ({ - -/***/ "./index-play-on-scroll.js": -/*!*********************************!*\ - !*** ./index-play-on-scroll.js ***! - \*********************************/ -/*! no static exports found */ -/***/ (function(module, exports) { - -eval("throw new Error(\"Module build failed: Error: ENOENT: no such file or directory, open '/Users/nazar/Documents/workspace/embedjs/src/index-play-on-scroll.js'\");\n\n//# sourceURL=webpack:///./index-play-on-scroll.js?"); - -/***/ }) - -/******/ }); \ No newline at end of file diff --git a/dist/embed-autoplay.min.js b/dist/embed-autoplay.min.js deleted file mode 100644 index 613e819..0000000 --- a/dist/embed-autoplay.min.js +++ /dev/null @@ -1,8 +0,0 @@ -!function(e){var t={};function r(n){if(t[n])return t[n].exports;var i=t[n]={i:n,l:!1,exports:{}};return e[n].call(i.exports,i,i.exports,r),i.l=!0,i.exports}r.m=e,r.c=t,r.d=function(e,t,n){r.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:n})},r.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},r.t=function(e,t){if(1&t&&(e=r(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var n=Object.create(null);if(r.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var i in e)r.d(n,i,function(t){return e[t]}.bind(null,i));return n},r.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return r.d(t,"a",t),t},r.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},r.p="",r(r.s=18)}([function(e,t){var r=window.iframely=window.iframely||{};r.config=r.config||{},e.exports=r},function(e,t,r){var n=r(0),i=r(2);n.on("init",function(){n.extendOptions(function(){for(var e=document.querySelectorAll('script[src*="embed.js"], script[src*="iframely.js"]'),t=0;t0)return i}}return{}}()),function(){var e=document.getElementById("iframely-styles");if(!e){var t=".iframely-responsive{top:0;left:0;width:100%;height:0;position:relative;padding-bottom:56.25%;box-sizing:border-box;}.iframely-responsive>*{top:0;left:0;width:100%;height:100%;position:absolute;border:0;box-sizing:border-box;}";(e=document.createElement("style")).id="iframely-styles",e.type="text/css",e.styleSheet?e.styleSheet.cssText=t:e.innerHTML=t,document.getElementsByTagName("head")[0].appendChild(e)}}(),function(e){for(var t=document.querySelectorAll('iframe[src*="'+(e||n.DOMAINS).join('"], iframe[src*="')+'"]'),r=0;r2||t&&r.getAttribute("class")!==n.ASPECT_WRAPPER_CLASS||!t&&"relative"!==r.style.position&&r.getAttribute("class")!==n.ASPECT_WRAPPER_CLASS)){var i=r.parentNode;if(!(!i||"DIV"!==i.nodeName||s(i)>1||t&&i.getAttribute("class")!==n.MAXWIDTH_WRAPPER_CLASS||!t&&i.getAttribute("class")&&!i.getAttribute("class").match(/iframely/i)))return{aspectWrapper:r,maxWidthWrapper:i}}};t.addDefaultWrappers=function(e){var t=e.parentNode,r=document.createElement("div");r.className=n.MAXWIDTH_WRAPPER_CLASS;var i=document.createElement("div");return i.className=n.ASPECT_WRAPPER_CLASS,r.appendChild(i),t.insertBefore(r,e),{aspectWrapper:i,maxWidthWrapper:r}},t.getWidget=function(e){var t=o(e);if(t){var r={iframe:e,aspectWrapper:t.aspectWrapper,maxWidthWrapper:t.maxWidthWrapper};if("A"===e.nodeName&&e.hasAttribute("href"))r.url=e.getAttribute("href");else if(e.hasAttribute("src")&&/url=/.test(e.getAttribute("src"))){var n=d(e.getAttribute("src"));n.url&&(r.url=n.url)}return r}},n.getElementComputedStyle=function(e,t){return window.getComputedStyle&&window.getComputedStyle(e).getPropertyValue(t)},t.setStyles=function(e,t){e&&Object.keys(t).forEach(function(r){var i=t[r];("number"==typeof i||"string"==typeof i&&/^(\d+)?\.?(\d+)$/.test(i))&&(i+="px"),window.getComputedStyle&&(n.getElementComputedStyle(e,r)==i||"iframely-responsive"==e.className&&"paddingBottom"===r&&!e.style[r]&&/^56\.2\d+%$/.test(i))||(e.style[r]=i||"")})};var a=t.addQueryString=function(e,t){var r="";return Object.keys(t).forEach(function(n){var i=t[n];if("[object Array]"===Object.prototype.toString.call(i)){var o=i.map(function(e){return n+"="+encodeURIComponent(e)});r+="&"+o.join("&")}else void 0!==i&&-1===e.indexOf(n+"=")&&(!0===i&&(i=1),!1===i&&(i=0),r+="&"+n+"="+encodeURIComponent(i))}),e+(""!==r?(e.indexOf("?")>-1?"&":"?")+r.replace(/^&/,""):"")};function s(e){for(var t=0,r=0;r4&&(t=null);var n=t&&t.parentNode;n&&n.getAttribute("class")===i.MAXWIDTH_WRAPPER_CLASS&&(t.removeAttribute("style"),t.removeAttribute("class"),n.removeAttribute("style"))}i.on("load",function(e){if(!e&&!1!==i.config.import&&document.head.attachShadow&&(i.debug||"http:"===document.location.protocol||"https:"===document.location.protocol)&&!i.config.playerjs&&!i.config.lazy&&!i.import){var t=document.querySelectorAll("a[data-iframely-url]:not([data-import-uri])");t.length>1&&function(e){var t=document.createElement("script"),r=[],a=[],u=null;function d(e,t){o[e]||(o[e]=[]),o[e].push(t)}function c(e){var t=e.getAttribute("data-iframely-url"),o=t.match(i.ID_RE),s=o&&o[1],c=n.parseQueryString(t,i.SUPPORTED_QUERY_STRING.concat("url")),l=c.url;delete c.url;var p="0"===c.import||"false"===c.import||"1"===c.playerjs||"true"===c.playerjs;if(!p){var f=t.match(i.BASE_RE);c.CDN=f&&f[0],u?JSON.stringify(c,Object.keys(c).sort())!==JSON.stringify(u,Object.keys(u).sort())&&(p=!0):u=c}if(p)i.trigger("load",e);else if(s)e.setAttribute("data-import-uri",s),-1===a.indexOf(s)&&a.push(s),d(s,e);else{l||(l=e.getAttribute("href"));var m=u.key||u.api_key||i.config.api_key||i.config.key;m&&l?(e.setAttribute("data-import-uri",l),-1===r.indexOf(l)&&r.push(l),d(l,e)):i.trigger("load",e)}}for(var l=0;l0||a.length>0?((u=u||{}).touch=i.isTouch(),u.flash=function(){var e=!1;try{var t=new ActiveXObject("ShockwaveFlash.ShockwaveFlash");e=!!t}catch(t){e=!(!navigator.mimeTypes||null==navigator.mimeTypes["application/x-shockwave-flash"]||!navigator.mimeTypes["application/x-shockwave-flash"].enabledPlugin)}return e}(),u.app=1,r.length>0&&(u.uri=r),a.length>0&&(u.ids=a.join("&")),u.v=i.VERSION,t.src=n.getEndpoint("/api/import/v2",u,i.SUPPORTED_QUERY_STRING),t.onerror=function(){s()},document.head.appendChild(t),i.import=t):(s(),i.trigger("load"))}(t)}}),i.on("load",function(e,t){if(e&&e.uri&&(e.html||e.cancel)){var r=o[e.uri];if(r)for(var n=0;n1&&function(e,t){for(var r=0,n=0;n=0;return r&&e}(e.maxWidthWrapper,n.config.parent);i&&(t=i.parentNode,r=i)}if(e.url){var o=e.iframe&&(e.iframe.textContent||e.iframe.innerText);n.triggerAsync("cancel",e.url,t,o,r.nextSibling)}t.removeChild(r)}else console.warn("iframely.cancelWidget called without widget param")}},function(e,t,r){var n=r(1),i=r(0);i.on("message",function(e,t){if("setIframelyWidgetSize"===t.method||"resize"===t.method||"setIframelyEmbedData"===t.method){var r={};t.data&&t.data.media&&t.data.media.frame_style?(t.data.media.frame_style.split(";").forEach(function(e){if(""!==e.trim()&&e.indexOf(":")>-1){var t=e.split(":");2===t.length&&(r[t[0].trim()]=t[1].trim())}}),s(e,r)):"setIframelyEmbedData"===t.method&&s(e,null),function(e,t){if(t&&Object.keys(t).length>0&&e){var r=function(e){var t=e.iframe&&e.iframe.style.border||e.aspectWrapper&&e.aspectWrapper.style.border,r=t&&t.match(/(\d+)px/)||0;r&&(r=parseInt(r[1]),r*=2);return r}(e),o=window.getComputedStyle&&window.getComputedStyle(e.iframe).getPropertyValue("height");n.setStyles(e.maxWidthWrapper,{"max-width":t["max-width"]&&t["max-width"]+r,"min-width":t["min-width"]&&t["min-width"]+r,width:t.width&&t.width+r}),t.scrolling&&e.iframe&&e.iframe.setAttribute("scrolling",t.scrolling);var a=t["aspect-ratio"];n.setStyles(e.aspectWrapper,{paddingBottom:a?Math.round(1e5/a)/1e3+"%":0,paddingTop:a&&t["padding-bottom"],height:a?0:t.height&&t.height+r});var s=window.getComputedStyle&&window.getComputedStyle(e.iframe).getPropertyValue("height");o&&o!==s&&i.triggerAsync("heightChanged",e.iframe,o,s)}}(e,t.data&&t.data.media||{height:t.height})}});var o={border:"","border-radius":"","box-shadow":"",overflow:""},a={border:"0","border-radius":"","box-shadow":"",overflow:""};function s(e,t){t&&e&&e.iframe?t["border-radius"]?(t.overflow="hidden",n.setStyles(e.aspectWrapper,t)):n.setStyles(e.iframe,t):!t&&e&&e.iframe&&(n.setStyles(e.aspectWrapper,o),n.setStyles(e.iframe,a))}},function(e,t,r){var n=r(0);n.on("message",function(e,t){"open-href"!==t.method&&"click"!==t.method||n.trigger(t.method,t.href)}),n.on("open-href",function(e){n.triggerAsync("click",e),0===e.indexOf(window.location.origin)?window.location.href=e:window.open(e,"_blank")})},function(e,t,r){var n=r(0);n.on("message",function(e,t){"setIframelyEmbedOptions"===t.method&&n.trigger("options",e,t.data)})},function(e,t,r){var n=r(0);n.widgets=n.widgets||{},n.widgets.load=n.load,n.events||(n.events={},n.events.on=n.on,n.events.trigger=n.trigger),n.on("cancel",function(e,t,r,n){if(e&&t&&r&&""!==r){var i=document.createElement("a");i.setAttribute("href",e),i.setAttribute("target","_blank"),i.textContent=r,n?t.insertBefore(i,n):t.appendChild(i)}})},,function(e,t,r){r(3);var n=r(0);n._loaded||(n._loaded=!0,r(4),r(5),r(7),r(8),r(9),r(10),r(11),r(19),r(12),r(13),r(14),r(15),r(16),n.trigger("init")),t.iframely=n},function(e,t,r){var n,i=r(20),o=r(0),a={threshold:1};var s=[];function u(e){e.forEach(function(e){if(e.isIntersecting){var t=function(e){for(var t,r=0;r0,"Get methods require a callback."),r.unshift(t)):(/^set/.test(e)&&(a.assert(0!==r.length,"Set methods require a value."),t.value=r[0]),r=[t]),this.send.apply(this,r)}}a.DEBUG=!1,a.VERSION="0.0.11",a.CONTEXT="player.js",a.POST_MESSAGE=!!i.postMessage,a.origin=function(e){return"//"===e.substr(0,2)&&(e=i.location.protocol+e),e.split("/").slice(0,3).join("/")},a.addEvent=function(e,t,r){e&&(e.addEventListener?e.addEventListener(t,r,!1):e.attachEvent?e.attachEvent("on"+t,r):e["on"+t]=r)},a.log=function(){a.log.history=a.log.history||[],a.log.history.push(arguments),i.console&&a.DEBUG&&i.console.log(Array.prototype.slice.call(arguments))},a.isString=function(e){return"[object String]"===Object.prototype.toString.call(e)},a.isObject=function(e){return"[object Object]"===Object.prototype.toString.call(e)},a.isArray=function(e){return"[object Array]"===Object.prototype.toString.call(e)},a.isNone=function(e){return null==e},a.has=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},a.indexOf=function(e,t){if(null==e)return-1;var r=0,n=e.length;if(Array.prototype.IndexOf&&e.indexOf===Array.prototype.IndexOf)return e.indexOf(t);for(;r-1?r.loaded=!0:this.elem.onload=function(){r.loaded=!0}},a.Player.prototype.send=function(e,t,r){if(e.context=a.CONTEXT,e.version=a.VERSION,t){var n=this.keeper.getUUID();e.listener=n,this.keeper.one(n,e.method,t,r)}return this.isReady||"ready"===e.value?(a.log("Player.send",e,this.origin),!0===this.loaded&&this.elem.contentWindow.postMessage(JSON.stringify(e),this.origin),!0):(a.log("Player.queue",e),this.queue.push(e),!1)},a.Player.prototype.receive=function(e){if(a.log("Player.receive",e),e.origin!==this.origin)return!1;var t;try{t=JSON.parse(e.data)}catch(e){return!1}if(t.context!==a.CONTEXT)return!1;"ready"===t.event&&t.value&&t.value.src===this.elem.src&&this.ready(t),this.keeper.has(t.event,t.listener)&&this.keeper.execute(t.event,t.listener,t.value,this)},a.Player.prototype.ready=function(e){if(!0===this.isReady)return!1;e.value.events&&(this.events=e.value.events),e.value.methods&&(this.methods=e.value.methods),this.isReady=!0,this.loaded=!0;for(var t=0;t0)for(var n in r)return this.send({method:"removeEventListener",value:e,listener:r[n]}),!0;return!1},a.Player.prototype.supports=function(e,t){a.assert(a.indexOf(["method","event"],e)>-1,'evtOrMethod needs to be either "event" or "method" got '+e),t=a.isArray(t)?t:[t];for(var r="event"===e?this.events:this.methods,n=0;n-1&&this.eventListeners[t.value].splice(n,1),0===this.eventListeners[t.value].length&&delete this.eventListeners[t.value]}}else this.get(t.method,t.value,r)},a.Receiver.prototype.get=function(e,t,r){var n=this;if(!this.methods.hasOwnProperty(e))return this.emit("error",{code:3,msg:'Method Not Supported"'+e+'"'}),!1;var i=this.methods[e];if("get"===e.substr(0,3)){i.call(this,function(t){n.send(e,t,r)})}else i.call(this,t)},a.Receiver.prototype.on=function(e,t){this.methods[e]=t},a.Receiver.prototype.send=function(e,t,r){if(a.log("Receiver.send",e,t,r),this.reject)return a.log("Receiver.send.reject",e,t,r),!1;var n={context:a.CONTEXT,version:a.VERSION,event:e};a.isNone(t)||(n.value=t),a.isNone(r)||(n.listener=r);var o=JSON.stringify(n);i.parent.postMessage(o,""===this.origin?"*":this.origin)},a.Receiver.prototype.emit=function(e,t){if(!this.eventListeners.hasOwnProperty(e))return!1;a.log("Instance.emit",e,t,this.eventListeners[e]);for(var r=0;r { // webpackBootstrap -/******/ var __webpack_modules__ = ({ - -/***/ "./options/templates/checkbox.ejs" -/*!****************************************!*\ - !*** ./options/templates/checkbox.ejs ***! - \****************************************/ -(module) { - -eval("{module.exports = function(obj) {\nobj || (obj = {});\nvar __t, __p = '', __j = Array.prototype.join;\nfunction print() { __p += __j.call(arguments, '') }\nwith (obj) {\n__p += '
\\n \\n ' +\n((__t = ( label )) == null ? '' : __t) +\n'\\n \\n
\\n';\n\n}\nreturn __p\n}\n\n//# sourceURL=webpack:///./options/templates/checkbox.ejs?\n}"); - -/***/ }, - -/***/ "./options/templates/group.ejs" -/*!*************************************!*\ - !*** ./options/templates/group.ejs ***! - \*************************************/ -(module) { - -eval("{module.exports = function(obj) {\nobj || (obj = {});\nvar __t, __p = '', __e = _.escape;\nwith (obj) {\n__p += '
\\n
\\n ' +\n__e( elementsHtml ) +\n'\\n
\\n
';\n\n}\nreturn __p\n}\n\n//# sourceURL=webpack:///./options/templates/group.ejs?\n}"); - -/***/ }, - -/***/ "./options/templates/radio.ejs" -/*!*************************************!*\ - !*** ./options/templates/radio.ejs ***! - \*************************************/ -(module) { - -eval("{module.exports = function(obj) {\nobj || (obj = {});\nvar __t, __p = '', __j = Array.prototype.join;\nfunction print() { __p += __j.call(arguments, '') }\nwith (obj) {\n__p += '
\\n ';\n if (label) { ;\n__p += '\\n \\n ';\n } ;\n__p += '\\n
\\n ' +\n((__t = ( subContext.label )) == null ? '' : __t) +\n'\\n \\n
\\n ';\n }); ;\n__p += '\\n
\\n';\n\n}\nreturn __p\n}\n\n//# sourceURL=webpack:///./options/templates/radio.ejs?\n}"); - -/***/ }, - -/***/ "./options/templates/range.ejs" -/*!*************************************!*\ - !*** ./options/templates/range.ejs ***! - \*************************************/ -(module) { - -eval("{module.exports = function(obj) {\nobj || (obj = {});\nvar __t, __p = '';\nwith (obj) {\n__p += '
\\n \\n
\\n \\n
\\n
';\n\n}\nreturn __p\n}\n\n//# sourceURL=webpack:///./options/templates/range.ejs?\n}"); - -/***/ }, - -/***/ "./options/templates/select.ejs" -/*!**************************************!*\ - !*** ./options/templates/select.ejs ***! - \**************************************/ -(module) { - -eval("{module.exports = function(obj) {\nobj || (obj = {});\nvar __t, __p = '', __j = Array.prototype.join;\nfunction print() { __p += __j.call(arguments, '') }\nwith (obj) {\n__p += '
\\n \\n
\\n \\n
\\n
';\n\n}\nreturn __p\n}\n\n//# sourceURL=webpack:///./options/templates/select.ejs?\n}"); - -/***/ }, - -/***/ "./options/templates/text.ejs" -/*!************************************!*\ - !*** ./options/templates/text.ejs ***! - \************************************/ -(module) { - -eval("{module.exports = function(obj) {\nobj || (obj = {});\nvar __t, __p = '';\nwith (obj) {\n__p += '
\\n \\n
\\n \\n
\\n
';\n\n}\nreturn __p\n}\n\n//# sourceURL=webpack:///./options/templates/text.ejs?\n}"); - -/***/ }, - -/***/ "./ahref.js" -/*!******************!*\ - !*** ./ahref.js ***! - \******************/ -(__unused_webpack_module, __unused_webpack_exports, __webpack_require__) { - -eval("{var utils = __webpack_require__(/*! ./utils */ \"./utils.js\");\nvar iframely = __webpack_require__(/*! ./iframely */ \"./iframely.js\");\n\niframely.on('load', function(container, href) {\n if (container && container.nodeName && typeof href === 'string') {\n var a = document.createElement('a');\n a.setAttribute('href', href);\n container.appendChild(a);\n iframely.trigger('load', a);\n }\n});\n\niframely.on('load', function(el) {\n\n if (!el && !iframely.import) { \n\n var elements = document.querySelectorAll('a[data-iframely-url]:not([data-import-uri])');\n for(var i = 0; i < elements.length; i++) {\n iframely.trigger('load', elements[i]);\n }\n }\n \n});\n\niframely.on('load', function(el) {\n\n if (el && el.nodeName === 'A' && (el.getAttribute('data-iframely-url') || el.getAttribute('href')) && !el.hasAttribute('data-import-uri')) {\n unfurl(el);\n }\n \n});\n\nfunction unfurl(el) {\n if (!el.getAttribute('data-iframely-url') && !el.getAttribute('href')) {\n return; // isn't valid\n }\n var src;\n\n var dataIframelyUrl = el.getAttribute('data-iframely-url');\n if (dataIframelyUrl && /^((?:https?:)?\\/\\/[^/]+)\\/\\w+/i.test(dataIframelyUrl)) {\n src = utils.getEndpoint(dataIframelyUrl, {\n v: iframely.VERSION,\n app: 1,\n theme: iframely.config.theme\n });\n } else if ((iframely.config.api_key || iframely.config.key) && iframely.CDN) {\n\n if (!el.getAttribute('href')) {\n console.warn('Iframely cannot build embeds: \"href\" attribute missing in', el);\n return;\n }\n\n src = utils.getEndpoint('/api/iframe', {\n url: el.getAttribute('href'),\n v: iframely.VERSION,\n app: 1,\n theme: iframely.config.theme\n }, iframely.SUPPORTED_QUERY_STRING);\n } else {\n console.warn('Iframely cannot build embeds: api key is required as query-string of embed.js');\n }\n\n if (!src) {\n el.removeAttribute('data-iframely-url'); \n } else {\n\n var iframe = document.createElement('iframe');\n\n iframe.setAttribute('allowfullscreen', '');\n iframe.setAttribute('allow', 'autoplay *; encrypted-media *; ch-prefers-color-scheme *');\n\n if (el.hasAttribute('data-img')) {\n iframe.setAttribute('data-img', el.getAttribute('data-img'));\n }\n\n var isLazy = el.hasAttribute('data-lazy') || el.hasAttribute('data-img') || /&lazy=1/.test(src) || iframely.config.lazy;\n\n // support restoring failed links by its text\n var text = el.textContent || el.innerText;\n \n if (text && text !== '') {\n iframe.textContent = text;\n } \n\n var wrapper = utils.getIframeWrapper(el, true);\n \n if (wrapper) {\n\n // Delete all in aspect wrapper.\n while (wrapper.aspectWrapper.lastChild) {\n wrapper.aspectWrapper.removeChild(wrapper.aspectWrapper.lastChild);\n }\n\n } else {\n wrapper = utils.addDefaultWrappers(el);\n\n var parentNode = el.parentNode;\n parentNode.removeChild(el);\n }\n\n wrapper.aspectWrapper.appendChild(iframe);\n\n if (isLazy) {\n \n // send to lazy iframe flow\n iframe.setAttribute('data-iframely-url', src);\n iframely.trigger('load', iframe);\n\n } else {\n\n iframe.setAttribute('src', src);\n iframely.trigger('iframe-ready', iframe);\t\t\t\n }\n\n\n }\n\n\n}\n\n//# sourceURL=webpack:///./ahref.js?\n}"); - -/***/ }, - -/***/ "./const.js" -/*!******************!*\ - !*** ./const.js ***! - \******************/ -(__unused_webpack_module, __unused_webpack_exports, __webpack_require__) { - -eval("{var iframely = __webpack_require__(/*! ./iframely */ \"./iframely.js\");\n\niframely.VERSION = 1;\n\niframely.ASPECT_WRAPPER_CLASS = 'iframely-responsive';\niframely.MAXWIDTH_WRAPPER_CLASS = 'iframely-embed';\niframely.LOADER_CLASS = 'iframely-loader';\n\niframely.DOMAINS = ['cdn.iframe.ly', 'iframe.ly', 'if-cdn.com', 'iframely.net'];\niframely.CDN = iframely.CDN || iframely.DOMAINS[0]; // default domain, user or script src can change CDN\n\niframely.BASE_RE = /^(?:https?:)?\\/\\/[^/]+/i;\niframely.ID_RE = /^(?:https?:)?\\/\\/[^/]+\\/(\\w+-?\\w+)(?:\\?.*)?$/;\niframely.SCRIPT_RE = /^(?:https?:|file:\\/)?\\/\\/[^/]+(?:.+)?\\/(?:embed|iframely)\\.js(?:[^/]+)?$/i;\niframely.CDN_RE = /^(?:https?:)?\\/\\/([^/]+)\\/(?:embed|iframely)\\.js(?:[^/]+)?$/i;\n\niframely.SUPPORTED_QUERY_STRING = ['api_key', 'key', 'iframe', 'html5', 'playerjs', 'align', 'language', 'media', 'maxwidth', 'maxheight', 'lazy', 'import', 'parent', 'shadow', 'click_to_play', 'autoplay', 'mute', 'card', 'consent', 'theme', /^_.+/];\n\niframely.SUPPORTED_THEMES = ['auto', 'light', 'dark'];\n\niframely.LAZY_IFRAME_SHOW_TIMEOUT = 3000;\niframely.LAZY_IFRAME_FADE_TIMEOUT = 200;\niframely.CLEAR_WRAPPER_STYLES_TIMEOUT = 3000;\n\niframely.RECOVER_HREFS_ON_CANCEL = false;\n\niframely.SHADOW = 'iframely-shadow';\n\n//# sourceURL=webpack:///./const.js?\n}"); - -/***/ }, - -/***/ "./deprecated.js" -/*!***********************!*\ - !*** ./deprecated.js ***! - \***********************/ -(__unused_webpack_module, __unused_webpack_exports, __webpack_require__) { - -eval("{var iframely = __webpack_require__(/*! ./iframely */ \"./iframely.js\");\n\n// deprecated. Helper function only, for the reverse compatibility.\niframely.widgets = iframely.widgets || {};\niframely.widgets.load = iframely.load;\n\nif (!iframely.events) {\n iframely.events = {};\n iframely.events.on = iframely.on;\n iframely.events.trigger = iframely.trigger;\n}\n\niframely.on('cancel', function(url, parentNode, text, nextSibling) {\n\n if (iframely.RECOVER_HREFS_ON_CANCEL && !text) {\n text = url;\n }\n\n if (url && parentNode && text && text !== '') {\n var a = document.createElement('a');\n a.setAttribute('href', url);\n a.setAttribute('target', '_blank');\n a.setAttribute('rel', 'noopener');\n a.textContent = text;\n if (nextSibling) {\n parentNode.insertBefore(a, nextSibling);\n } else {\n parentNode.appendChild(a);\n }\n }\n});\n\n//# sourceURL=webpack:///./deprecated.js?\n}"); - -/***/ }, - -/***/ "./dom-ready.js" -/*!**********************!*\ - !*** ./dom-ready.js ***! - \**********************/ -(__unused_webpack_module, __unused_webpack_exports, __webpack_require__) { - -eval("{// TODO: rename core.js to ready.js?\n\nvar iframely = __webpack_require__(/*! ./iframely */ \"./iframely.js\");\n\nvar DOMReady = function(f) {\n if (document.readyState === 'complete' || document.readyState === 'interactive') {\n // Run always (in case of async script).\n setTimeout(f, 0);\n }\n document['addEventListener'] ? document['addEventListener']('DOMContentLoaded', f) : window.attachEvent('onload', f);\n};\n\nDOMReady(function() {\n\n // Called each time on script load\n if (typeof iframely.config.autorun === 'undefined' || iframely.config.autorun !== false) {\n iframely.trigger('load');\n }\n});\n\n\n//# sourceURL=webpack:///./dom-ready.js?\n}"); - -/***/ }, - -/***/ "./events.js" -/*!*******************!*\ - !*** ./events.js ***! - \*******************/ -(__unused_webpack_module, __unused_webpack_exports, __webpack_require__) { - -eval("{var iframely = __webpack_require__(/*! ./iframely */ \"./iframely.js\");\n\nvar nextTick = (function(window, prefixes, i, fnc) {\n while (!fnc && i < prefixes.length) {\n fnc = window[prefixes[i++] + 'equestAnimationFrame'];\n }\n return (fnc && fnc.bind(window)) || window.setImmediate || function(fnc) {window.setTimeout(fnc, 0);};\n})(typeof window !== 'undefined' ? window : __webpack_require__.g, 'r webkitR mozR msR oR'.split(' '), 0);\n\nvar callbacksStack = {};\niframely.on = function(event, cb) {\n var events = callbacksStack[event] = callbacksStack[event] || [];\n events.push(cb);\n};\n\nfunction trigger(event, async, args) {\n var events = callbacksStack[event] || [];\n events.forEach(function(cb) {\n if (async) {\n nextTick(function() {\n cb.apply(iframely, args);\n });\n } else {\n cb.apply(iframely, args);\n }\n });\n\n if (event === 'init') {\n // everything inited, let's clear the callstack, just in case\n // TODO: not good.\n callbacksStack[event] = [];\n }\n}\n\niframely.trigger = function(event) {\n var args = Array.prototype.slice.call(arguments, 1);\n trigger(event, false, args);\n};\n\niframely.triggerAsync = function(event) {\n var args = Array.prototype.slice.call(arguments, 1);\n trigger(event, true, args);\n};\n\n//# sourceURL=webpack:///./events.js?\n}"); - -/***/ }, - -/***/ "./iframely.js" -/*!*********************!*\ - !*** ./iframely.js ***! - \*********************/ -(module) { - -eval("{var iframely = window.iframely = window.iframely || {};\niframely.config = iframely.config || {};\n\nmodule.exports = iframely;\n\n//# sourceURL=webpack:///./iframely.js?\n}"); - -/***/ }, - -/***/ "./import.js" -/*!*******************!*\ - !*** ./import.js ***! - \*******************/ -(__unused_webpack_module, __unused_webpack_exports, __webpack_require__) { - -eval("{var utils = __webpack_require__(/*! ./utils */ \"./utils.js\");\nvar iframely = __webpack_require__(/*! ./iframely */ \"./iframely.js\");\n\n// widgetsCache is used from inside import doc for js callbacks and custom features\nvar widgetsCache = {};\n\niframely.on('load', function(el) {\n\n // load once, if import is not in process and only if query-string from script src has not disabled import\n if (!el && iframely.config.import !== false \n && isImportAble()\n && !iframely.import) {\n\n var elements = document.querySelectorAll('a[data-iframely-url]:not([data-import-uri])');\n if (elements.length > 1) {\n makeImportAPICall(elements);\n }\n }\n\n});\n\niframely.on('load', function(widget, importOptions) {\n\n if (widget && widget.uri && (widget.html || widget.cancel)) {\n\n var els = widgetsCache[widget.uri];\n // alternatively, could as well do querySelectorAll('a[data-iframely-url][data-import=\"' + template.getAttribute('data-uri') + '\"')\n\n if (els) {\n for (var i = 0; i < els.length; i++) {\n loadImportWidget(widget, els[i], importOptions);\n }\n }\n\n delete widgetsCache[widget.uri];\n }\n});\n\nfunction makeImportAPICall(elements) {\n var script = utils.createScript();\n\n var uris = [];\n var ids = [];\n \n var import_options = null; // will be populated from first element; or will remain as null if no params in elements...\n\n // couple helper functions first\n\n function pushElement(uri, el) {\n if (!widgetsCache[uri]) {\n widgetsCache[uri] = [];\n }\n\n widgetsCache[uri].push(el);\n }\n\n function queueElement(el) {\n var src = el.getAttribute('data-iframely-url');\n\n var mId = src.match(iframely.ID_RE);\n var id = mId && mId[1];\n\n var options = utils.parseQueryString(src, iframely.SUPPORTED_QUERY_STRING.concat('url'));\n\n var url = options.url; // can be undefined for IDs\n delete options.url;\n\n // skip import on import=0, playerjs=1\n var skipImport = options.import === '0' || options.import === 'false' \n || options.playerjs === '1' || options.playerjs === 'true';\n\n // or if link's query-string params or CDN are different from the others\n if (!skipImport) {\n var mBase = src.match(iframely.BASE_RE);\n options.CDN = mBase && mBase[0]; // will fall back to iframely.CDN in getEndpoint('/import...' ...)\n\n // set import options from the first el in import\n // that includes api keys \n if (!import_options) {\n import_options = options;\n\n // else check that this el's options are the same as the first one's in import\n } else if (JSON.stringify(options, Object.keys(options).sort()) \n !== JSON.stringify(import_options, Object.keys(import_options).sort())) {\n\n skipImport = true;\n }\n }\n\n\n if (skipImport) {\n // Usual build if no uri and app=1s.\n iframely.trigger('load', el);\n\n } else if (id) {\n el.setAttribute('data-import-uri', id);\n if (ids.indexOf(id) === -1) {\n ids.push(id);\n }\n pushElement(id, el);\n\n } else {\n\n if (!url) {\n url = el.getAttribute('href');\n }\n\n var key = import_options.key || import_options.api_key || iframely.config.api_key || iframely.config.key;\n\n if (key && url) {\n\n el.setAttribute('data-import-uri', url);\n if (uris.indexOf(url) === -1) {\n uris.push(url);\n }\n pushElement(url, el);\n } else {\n // Usual build if no uri.\n iframely.trigger('load', el);\n }\n }\n }\n\n\n // start actual filling up of import request\n\n for(var i = 0; i < elements.length; i++) {\n var el = elements[i];\n if (!el.getAttribute('data-import-uri') && el.hasAttribute('data-iframely-url')) {\n queueElement(el);\n }\n }\n\n if ((uris.length > 0 || ids.length > 0)) {\n\n import_options = import_options || {};\n import_options.touch = iframely.isTouch();\n import_options.flash = hasFlash();\n import_options.app = 1;\n // Do not override imports theme if global theme not set.\n if (iframely.config.theme) {\n import_options.theme = iframely.config.theme;\n }\n\n if (uris.length > 0) {\n import_options.uri = uris;\n }\n\n if (ids.length > 0) {\n import_options.ids = ids.join('&');\n }\n\n import_options.v = iframely.VERSION;\n\n script.src = utils.getEndpoint('/api/import/v2', import_options, iframely.SUPPORTED_QUERY_STRING);\n\n script.onerror = function() {\n // Error loading import. No import this time.\n importReady();\n };\n\n document.head.appendChild(script);\n iframely.import = script;\n\n } else {\n importReady();\n iframely.trigger('load');\n }\n}\n\niframely.buildImportWidgets = function(importOptions) {\n\n iframely.trigger('import-loaded', importOptions);\n\n importOptions.widgets.forEach(function(widget) {\n iframely.trigger('load', widget, importOptions);\n });\n\n importReady();\n};\n\nfunction loadImportWidget(widgetOptions, el, importOptions) {\n\n var needCancelWidget = widgetOptions.cancel;\n var shadow = widgetOptions.shadow;\n var hasRenderedEvent = widgetOptions.renderEvent;\n\n var wrapper = utils.getIframeWrapper(el, true);\n var widget;\n\n if (needCancelWidget) {\n widget = utils.getWidget(el);\n\n iframely.cancelWidget(widget || {\n maxWidthWrapper: el,\n iframe: el,\n url: el.getAttribute('href') \n });\n\n } else {\n\n widget = document.createElement('div');\n widget.innerHTML = widgetOptions.html;\n \n var parent, replacedEl;\n\n if (wrapper && !hasRenderedEvent) {\n // Inline widget will replace 'aspectWrapper' but keep 'maxWidthWrapper' as 'iframely-embed' to fix centering, etc.\n // If has rendered event - keep wrapper and remove attrs later by event.\n parent = wrapper.aspectWrapper.parentNode;\n replacedEl = wrapper.aspectWrapper;\n\n // Clear custom attributes.\n wrapper.maxWidthWrapper.removeAttribute('style');\n } else {\n // No wrapper or keep wrapper for later removal.\n parent = el.parentNode;\n replacedEl = el;\n }\n\n if (shadow) {\n\n var shadowContainer = document.createElement('div');\n var shadowRoot = shadowContainer.attachShadow({mode: 'open'});\n shadowRoot.appendChild(widget);\n\n var shadowWidgetOptions = {\n shadowRoot: shadowRoot,\n shadowContainer: shadowContainer,\n container: parent,\n context: widgetOptions.context,\n stylesIds: widgetOptions.stylesIds,\n stylesDict: importOptions.commonShadowStyles\n };\n \n iframely.trigger('import-shadow-widget-before-render', shadowWidgetOptions);\n \n parent.insertBefore(shadowContainer, replacedEl);\n\n iframely.trigger('import-shadow-widget-after-render', shadowWidgetOptions);\n \n } else {\n\n parent.insertBefore(widget, replacedEl);\n\n exec_body_scripts(widget);\n }\n\n parent.removeChild(replacedEl);\n\n if (hasRenderedEvent) {\n setTimeout(function() {\n clearWrapperStylesAndClass(parent);\n }, iframely.CLEAR_WRAPPER_STYLES_TIMEOUT);\n }\n }\n}\n\n\nfunction importReady() {\n\n delete iframely.import;\n\n // clean up all, let other loaders have a go\n var failed_elements = document.querySelectorAll('a[data-iframely-url][data-import-uri]');\n for(var i = 0; i < failed_elements.length; i++) {\n failed_elements[i].removeAttribute('data-import-uri');\n iframely.trigger('load', failed_elements[i]);\n }\n}\n\niframely.isTouch = function() {\n return 'ontouchstart' in window // works on most browsers\n || navigator.maxTouchPoints; // works on IE10/11 and Surface\n};\n\nfunction hasFlash() {\n\n var _hasFlash = false;\n\n try {\n var fo = new ActiveXObject('ShockwaveFlash.ShockwaveFlash');\n if (fo) {\n _hasFlash = true;\n } else {\n _hasFlash = false;\n }\n } catch (e) {\n if (navigator.mimeTypes\n && navigator.mimeTypes['application/x-shockwave-flash'] != undefined\n && navigator.mimeTypes['application/x-shockwave-flash'].enabledPlugin) {\n _hasFlash = true;\n } else {\n _hasFlash = false;\n }\n }\n\n return _hasFlash;\n}\n\nfunction isImportAble() {\n\n return document.head.attachShadow\n && document.location // Prevent `Cannot read properties of null (reading 'protocol')` for sandbox iframes.\n && (iframely.debug || document.location.protocol === 'http:' || document.location.protocol === 'https:') // Skip import on file:///\n && !iframely.config.playerjs && !iframely.config.lazy;\n // && !navigator.userAgent.toLowerCase().indexOf('firefox') > -1;\n // TODO: test in Firefox 63\n}\n\nfunction clearWrapperStylesAndClass(el) {\n var aspectWrapper = el;\n var parents = 0;\n while(aspectWrapper \n && (!aspectWrapper.getAttribute('class')\n || aspectWrapper.getAttribute('class').split(' ').indexOf(iframely.ASPECT_WRAPPER_CLASS) === -1)) {\n\n aspectWrapper = aspectWrapper.parentNode;\n parents++;\n if (parents > 4) {\n // Do not search further 4 parents.\n aspectWrapper = null;\n }\n }\n\n var maxWidthWrapper = aspectWrapper && aspectWrapper.parentNode;\n if (maxWidthWrapper \n && maxWidthWrapper.getAttribute('class')\n && maxWidthWrapper.getAttribute('class').split(' ').indexOf(iframely.MAXWIDTH_WRAPPER_CLASS) > -1) {\n\n // Remove wrapper specific data. Leave only 'iframely-embed' parent class.\n aspectWrapper.removeAttribute('style');\n aspectWrapper.removeAttribute('class');\n maxWidthWrapper.removeAttribute('style');\n }\n}\n\niframely.on('import-widget-ready', clearWrapperStylesAndClass);\n\n// used in server templates\n\nif (!iframely.addEventListener) {\n iframely.addEventListener = function(elem, type, eventHandle) {\n if (!elem) { return; }\n if ( elem.addEventListener ) {\n elem.addEventListener( type, eventHandle, false );\n } else if ( elem.attachEvent ) {\n elem.attachEvent( 'on' + type, eventHandle );\n } else {\n elem['on' + type] = eventHandle;\n }\n };\n}\n\nfunction exec_body_scripts(body_el) {\n function nodeName(elem, name) {\n return elem.nodeName && elem.nodeName.toUpperCase() ===\n name.toUpperCase();\n }\n\n function evalScript(elem) {\n var data = (elem.text || elem.textContent || elem.innerHTML || '' ),\n script = utils.createScript();\n\n // Copy all script attributes.\n script.type = 'text/javascript';\n for (var i = 0; i < elem.attributes.length; i++) {\n var attr = elem.attributes[i];\n script.setAttribute(attr.name, attr.value);\n }\n try {\n // doesn't work on ie...\n script.appendChild(document.createTextNode(data));\n } catch(e) {\n // IE has funky script nodes\n script.text = data;\n }\n\n body_el.appendChild(script);\n }\n\n // main section of function\n var scripts = [],\n script,\n children_nodes = body_el.childNodes,\n child,\n i;\n\n for (i = 0; children_nodes[i]; i++) {\n child = children_nodes[i];\n if (nodeName(child, 'script' ) &&\n (!child.type || child.type.toLowerCase() === 'text/javascript' || child.type.toLowerCase() === 'application/javascript')) {\n scripts.push(child);\n body_el.removeChild(child);\n } else {\n exec_body_scripts(child);\n }\n }\n\n for (i = 0; scripts[i]; i++) {\n script = scripts[i];\n if (script.parentNode) {script.parentNode.removeChild(script);}\n evalScript(scripts[i]);\n }\n}\n\n//# sourceURL=webpack:///./import.js?\n}"); - -/***/ }, - -/***/ "./index-options.js" -/*!**************************!*\ - !*** ./index-options.js ***! - \**************************/ -(__unused_webpack_module, exports, __webpack_require__) { - -eval("{__webpack_require__(/*! ./dom-ready */ \"./dom-ready.js\");\n\nvar iframely = __webpack_require__(/*! ./iframely */ \"./iframely.js\");\n\nif (!iframely._loaded) {\n\n iframely._loaded = true;\n\n __webpack_require__(/*! ./const */ \"./const.js\");\n __webpack_require__(/*! ./events */ \"./events.js\");\n // require('./utils'); // Loaded by other modules.\n __webpack_require__(/*! ./intersection */ \"./intersection.js\");\n __webpack_require__(/*! ./theme */ \"./theme.js\");\n __webpack_require__(/*! ./import */ \"./import.js\");\n __webpack_require__(/*! ./ahref */ \"./ahref.js\");\n __webpack_require__(/*! ./lazy-img-placeholder */ \"./lazy-img-placeholder.js\");\n __webpack_require__(/*! ./lazy-iframe */ \"./lazy-iframe.js\");\n // require('./messaging'); // Loaded by other modules.\n __webpack_require__(/*! ./widget-cancel */ \"./widget-cancel.js\");\n __webpack_require__(/*! ./widget-resize */ \"./widget-resize.js\");\n __webpack_require__(/*! ./widget-click */ \"./widget-click.js\");\n __webpack_require__(/*! ./widget-options */ \"./widget-options.js\");\n __webpack_require__(/*! ./deprecated */ \"./deprecated.js\");\n __webpack_require__(/*! ./lazy-loading-native */ \"./lazy-loading-native.js\");\n __webpack_require__(/*! ./options */ \"./options/index.js\");\n\n iframely.trigger('init');\n}\n\nexports.iframely = iframely;\n\n\n//# sourceURL=webpack:///./index-options.js?\n}"); - -/***/ }, - -/***/ "./intersection.js" -/*!*************************!*\ - !*** ./intersection.js ***! - \*************************/ -(__unused_webpack_module, __unused_webpack_exports, __webpack_require__) { - -eval("{var messaging = __webpack_require__(/*! ./messaging */ \"./messaging.js\");\nvar iframely = __webpack_require__(/*! ./iframely */ \"./iframely.js\");\n\nvar observers = {};\n\nfunction getObserver(options) {\n var optionsKey = JSON.stringify(options);\n var observer = observers[optionsKey];\n if (!observer) {\n\n observer = new IntersectionObserver(function(entries) {\n\n entries.forEach(function(entry) {\n messaging.postMessage({\n method: 'intersection',\n entry: {\n isIntersecting: entry.isIntersecting\n },\n options: options\n }, '*', entry.target.contentWindow);\n });\n\n }, getObserverOptions(options));\n\n observers[optionsKey] = observer;\n }\n return observer;\n}\n\nfunction getObserverOptions(options) {\n var result = {};\n if (options && options.threshold) {\n result.threshold = options.threshold;\n }\n if (options && options.margin) {\n result.rootMargin = options.margin + 'px ' + options.margin + 'px ' + options.margin + 'px ' + options.margin + 'px';\n }\n return result;\n}\n\nif ('IntersectionObserver' in window &&\n 'IntersectionObserverEntry' in window) {\n\n iframely.on('init', function() {\n\n iframely.extendOptions({\n intersection: 1\n });\n \n });\n\n iframely.on('message', function(widget, message) {\n if (message.method === 'send-intersections' && widget.iframe) {\n\n var options = message.options;\n\n if (!options) {\n options = {\n margin: 1000\n };\n }\n\n getObserver(options).observe(widget.iframe);\n }\n });\n}\n\n\n//# sourceURL=webpack:///./intersection.js?\n}"); - -/***/ }, - -/***/ "./lazy-iframe.js" -/*!************************!*\ - !*** ./lazy-iframe.js ***! - \************************/ -(__unused_webpack_module, __unused_webpack_exports, __webpack_require__) { - -eval("{var utils = __webpack_require__(/*! ./utils */ \"./utils.js\");\nvar iframely = __webpack_require__(/*! ./iframely */ \"./iframely.js\");\n\n// Need 'load' handler here instead of on('init') - we load lazy iframes only when DOM ready.\niframely.on('load', function(el) { \n\n if (!el) { // initial load\n\n var elements = document.querySelectorAll('iframe[data-iframely-url]');\n for(var i = 0; i < elements.length; i++) {\n iframely.trigger('load', elements[i]);\n } \n }\n \n});\n\niframely.on('load', function(el) {\n\n if (el && el.nodeName === 'IFRAME'\n && el.hasAttribute('data-iframely-url')\n && !el.hasAttribute('data-img')\n && !el.getAttribute('src')) {\n\n loadLazyIframe(el);\n }\n \n});\n\n\nfunction loadLazyIframe(el) {\n\n var widget = utils.getWidget(el);\n var src = el.getAttribute('data-iframely-url');\n var dataImg = el.hasAttribute('data-img-created') || el.hasAttribute('data-img');\n var nativeLazyLoad = !dataImg && iframely.SUPPORT_IFRAME_LOADING_ATTR;\n\n if (widget && src) {\n\n var options = {\n v: iframely.VERSION,\n app: 1, // for example, will fall back to summary card if media is not longer available\n theme: iframely.config.theme\n };\n\n if (!nativeLazyLoad && iframely.config.intersection) {\n options.lazy = 1;\n }\n\n src = utils.getEndpoint(src, options);\n\n }\n\n if (nativeLazyLoad) {\n el.setAttribute('loading', 'lazy');\n }\n\n if (dataImg && iframely.SUPPORT_IFRAME_LOADING_ATTR) {\n // Disable lazy load with `data-img`.\n el.setAttribute('loading', 'edge');\n }\n\n el.setAttribute('src', src);\n el.removeAttribute('data-iframely-url');\n\n iframely.trigger('iframe-ready', el);\n}\n\n//# sourceURL=webpack:///./lazy-iframe.js?\n}"); - -/***/ }, - -/***/ "./lazy-img-placeholder.js" -/*!*********************************!*\ - !*** ./lazy-img-placeholder.js ***! - \*********************************/ -(__unused_webpack_module, __unused_webpack_exports, __webpack_require__) { - -eval("{var utils = __webpack_require__(/*! ./utils */ \"./utils.js\");\nvar iframely = __webpack_require__(/*! ./iframely */ \"./iframely.js\");\n\niframely.on('load', function(el) {\n\n if (el && el.nodeName === 'IFRAME'\n && el.hasAttribute('data-iframely-url')\n && el.hasAttribute('data-img')\n && !el.getAttribute('src')) {\n\n var dataImg = el.getAttribute('data-img');\n\n el.removeAttribute('data-img');\n el.setAttribute('data-img-created', '');\n\n var widget = utils.getWidget(el);\n var src = el.getAttribute('data-iframely-url');\n\n addPlaceholderThumbnail(widget, src, dataImg);\n\n src = utils.addQueryString(src, {img: 1});\n el.setAttribute('data-iframely-url', src);\n\n new WaitingWidget(widget);\n\n iframely.trigger('load', el);\n\n }\n});\n\niframely.on('message', function(widget, message) {\n\n var waitingWidget;\n\n if (message.method === 'widgetRendered') {\n hidePlaceholderThumbnail(widget);\n\n waitingWidget = findWaitingWidget(widget);\n waitingWidget && waitingWidget.deactivate();\n }\n\n if (message.method === 'begin-waiting-widget-render') {\n waitingWidget = findWaitingWidget(widget);\n waitingWidget && waitingWidget.clearLoadingTimeout();\n }\n\n if (message.method === 'end-waiting-widget-render') {\n waitingWidget = findWaitingWidget(widget);\n waitingWidget && waitingWidget.registerLoadingTimeout();\n }\n});\n\n\nfunction addPlaceholderThumbnail(widget, href, imageUrl) {\n\n var thumbHref;\n\n if (imageUrl && /^(https?:)?\\/\\//.test(imageUrl)) {\n thumbHref = imageUrl;\n } else {\n\n // Start of image url calculation.\n \n var query = utils.parseQueryString(href);\n \n // Extract widget params to invalidate image cache.\n var _params = {};\n for(var param in query) {\n if (param.indexOf('_') === 0) {\n _params[param] = query[param];\n }\n }\n\n // Force proxy `media` param.\n if (query.media) {\n _params.media = query.media;\n }\n \n // need to run through getEndpoint at least to avoid file:///\n if (href.match(/\\/api\\/iframe/)) {\n thumbHref = utils.getEndpoint(href.match(/^(.+)\\/api\\/iframe/i)[1] + '/api/thumbnail', Object.assign({\n url: query.url,\n api_key: query.api_key,\n key: query.key\n }, _params));\n } else if (href.match(iframely.ID_RE)) {\n // RE copied from `iframely.ID_RE` and modified to replace path part.\n thumbHref = utils.getEndpoint(href.replace(/^((?:https?:)?\\/\\/[^/]+\\/(\\w+-?\\w+))(?:\\?.*)?$/, '$1/thumbnail'), _params);\n } else {\n return;\n }\n }\n\n // End of image url calculation.\n\n var thumb = document.createElement('div');\n // Parent div not always has ASPECT_WRAPPER_CLASS. Need explicit inline styles.\n utils.setStyles(thumb, {\n position: 'absolute',\n width: '100%',\n height: '100%',\n backgroundImage: \"url('\" + thumbHref + \"')\",\n backgroundSize: 'cover',\n backgroundPosition: 'center'\n });\n\n var iframelyLoaderDiv = document.createElement('div');\n iframelyLoaderDiv.setAttribute('class', iframely.LOADER_CLASS);\n thumb.appendChild(iframelyLoaderDiv);\n\n var paddingTop = iframely.getElementComputedStyle(widget.aspectWrapper, 'padding-top');\n var paddingBottom = iframely.getElementComputedStyle(widget.aspectWrapper, 'padding-bottom');\n\n var paddingTopMatch = paddingTop.match(/^(\\d+)px$/);\n var paddingTopInt = paddingTopMatch && parseInt(paddingTopMatch[1]);\n\n if (paddingTopInt && paddingBottom) {\n\n var thumbWrapper = document.createElement('div');\n\n utils.setStyles(thumbWrapper, {\n top: '-' + paddingTop,\n width: '100%',\n height: 0,\n position: 'relative',\n paddingBottom: paddingBottom\n }); \n\n thumbWrapper.appendChild(thumb);\n\n widget.aspectWrapper.appendChild(thumbWrapper);\n\n } else {\n\n widget.aspectWrapper.appendChild(thumb);\n }\n}\n\nfunction getNthNonTextChildNode(nth, element) {\n var count = 0;\n for(var i = 0; i < element.childNodes.length; i++) {\n var el = element.childNodes[i];\n if (el.nodeType === Node.TEXT_NODE) {\n // Nop.\n } else if (el.nodeType === Node.ELEMENT_NODE) {\n if (nth === count) {\n return el;\n }\n count++;\n }\n }\n}\n\nfunction nonTextChildCount(element) {\n var count = 0;\n for(var i = 0; i < element.childNodes.length; i++) {\n var el = element.childNodes[i];\n if (el.nodeType === Node.TEXT_NODE) {\n var text = el.textContent || el.innerText;\n text = text.replace(/\\s|\\n/g, '');\n if (text) {\n // Do not skip text node with text.\n count++;\n }\n } else if (el.nodeType === Node.ELEMENT_NODE) {\n count++;\n }\n }\n return count;\n}\n\nfunction hidePlaceholderThumbnail(widget) {\n var thumb = widget.aspectWrapper && nonTextChildCount(widget.aspectWrapper) > 1 && getNthNonTextChildNode(1, widget.aspectWrapper);\n if (thumb && thumb.nodeName === 'DIV') {\n widget.aspectWrapper.removeChild(thumb);\n }\n}\n\n//===\n\n// Working WaitingWidgets' collection.\n\nvar waitingWidgets = [];\n\nfunction findWaitingWidgetIdx(widget) {\n var i = 0;\n while(i < waitingWidgets.length && waitingWidgets[i].widget.iframe !== widget.iframe) {\n i++;\n }\n if (i < waitingWidgets.length && waitingWidgets[i].widget.iframe === widget.iframe) {\n return i;\n }\n}\n\nfunction findWaitingWidget(widget) {\n var idx = findWaitingWidgetIdx(widget);\n if (idx || idx === 0) {\n return waitingWidgets[idx];\n }\n}\n\nfunction removeWaitingWidget(widget) {\n var idx = findWaitingWidgetIdx(widget);\n if (idx || idx === 0) {\n waitingWidgets.splice(idx, 1);\n }\n}\n\n//===\n\n// WaitingWidget proto.\n\nfunction WaitingWidget(widget) {\n this.widget = widget;\n this.loadCount = 0;\n\n var iframe = widget.iframe;\n\n var that = this;\n function iframeOnLoad() {\n // Bind method to self.\n that.iframeOnLoad();\n }\n\n iframely.addEventListener(iframe, 'load', iframeOnLoad);\n\n this.registerLoadingTimeout();\n\n waitingWidgets.push(this);\n}\n\nWaitingWidget.prototype.iframeOnLoad = function() {\n\n this.loadCount++;\n\n // Skip first load of hosted widget OR timeout call.\n if (this.loadCount !== 2) {\n return;\n }\n\n this.deactivate();\n\n var that = this;\n setTimeout(function() {\n hidePlaceholderThumbnail(that.widget);\n }, iframely.LAZY_IFRAME_FADE_TIMEOUT);\n};\n\nWaitingWidget.prototype.deactivate = function() {\n this.clearLoadingTimeout();\n removeWaitingWidget(this);\n};\n\nWaitingWidget.prototype.clearLoadingTimeout = function() {\n this.timeoutId && clearTimeout(this.timeoutId);\n this.timeoutId = null;\n};\n\nWaitingWidget.prototype.registerLoadingTimeout = function() {\n if (this.timeoutId) {\n return;\n }\n var that = this;\n this.timeoutId = setTimeout(function() {\n that.iframeOnLoad();\n }, iframely.LAZY_IFRAME_SHOW_TIMEOUT);\n};\n\n\n//# sourceURL=webpack:///./lazy-img-placeholder.js?\n}"); - -/***/ }, - -/***/ "./lazy-loading-native.js" -/*!********************************!*\ - !*** ./lazy-loading-native.js ***! - \********************************/ -(__unused_webpack_module, __unused_webpack_exports, __webpack_require__) { - -eval("{function getChromeVersion() { \n var raw = navigator.userAgent.match(/Chrom(e|ium)\\/([0-9]+)\\./);\n\n return raw ? parseInt(raw[2], 10) : false;\n}\nvar chromeVersion = getChromeVersion();\n\nvar iframely = __webpack_require__(/*! ./iframely */ \"./iframely.js\");\niframely.SUPPORT_IFRAME_LOADING_ATTR = chromeVersion && chromeVersion >= 77;\n\n//# sourceURL=webpack:///./lazy-loading-native.js?\n}"); - -/***/ }, - -/***/ "./messaging.js" -/*!**********************!*\ - !*** ./messaging.js ***! - \**********************/ -(__unused_webpack_module, exports, __webpack_require__) { - -eval("{var iframely = __webpack_require__(/*! ./iframely */ \"./iframely.js\");\nvar utils = __webpack_require__(/*! ./utils */ \"./utils.js\");\n\nfunction receiveMessage(callback) {\n\n function cb(e) {\n var message;\n try {\n if (typeof e.data === 'string') {\n message = JSON.parse(e.data);\n } else if (typeof e.data === 'object') {\n message = e.data;\n }\n } catch (ex) {\n if (typeof e.data === 'string') {\n var m = e.data.match(/heightxPYMx(\\d+)/);\n if (m) {\n message = {\n method: 'resize',\n height: parseInt(m[1]) + 1,\n domains: 'all'\n };\n }\n }\n }\n\n callback(e, message);\n }\n\n // browser supports window.postMessage\n if (window['postMessage']) {\n if (window['addEventListener']) {\n window[callback ? 'addEventListener' : 'removeEventListener']('message', cb, !1);\n } else {\n window[callback ? 'attachEvent' : 'detachEvent']('onmessage', cb);\n }\n }\n}\n\nfunction findIframeByContentWindow(iframes, contentWindow) {\n var foundIframe;\n for(var i = 0; i < iframes.length && !foundIframe; i++) {\n var iframe = iframes[i];\n if (iframe.contentWindow === contentWindow) {\n foundIframe = iframe;\n }\n }\n return foundIframe;\n}\n\nfunction findIframeInElement(element, options) {\n var foundIframe, iframes;\n \n if (options.src) {\n iframes = element.querySelectorAll('iframe[src*=\"' + options.src.replace(/^https?:/, '') + '\"]');\n foundIframe = findIframeByContentWindow(iframes, options.contentWindow);\n }\n\n if (!foundIframe) {\n iframes = options.domains ?\n element.querySelectorAll('iframe[src*=\"' + (options.domains || iframely.DOMAINS).join('\"], iframe[src*=\"') + '\"]')\n : element.getElementsByTagName('iframe');\n foundIframe = findIframeByContentWindow(iframes, options.contentWindow);\n }\n\n return foundIframe;\n}\n\nfunction findIframeInShadowRoots(element, options) {\n var foundIframe;\n var className = '.' + (iframely.config.shadow || iframely.SHADOW);\n var shadowRoots = element.querySelectorAll(className);\n for(var i = 0; i < shadowRoots.length && !foundIframe; i++) {\n var shadowRoot = shadowRoots[i].shadowRoot;\n if (shadowRoot) {\n foundIframe = findIframeInElement(shadowRoot, options);\n if (!foundIframe) {\n foundIframe = findIframeInShadowRoots(shadowRoot, options);\n }\n }\n }\n return foundIframe;\n}\n\n// Do not override existing.\nif (!iframely.findIframe) {\n iframely.findIframe = function(options) {\n var foundIframe = findIframeInElement(document, options);\n if (!foundIframe) {\n foundIframe = findIframeInShadowRoots(document, options);\n }\n return foundIframe;\n };\n}\n\n\nreceiveMessage(function(e, message) {\n\n if (message && (message.method || message.type || message.context)) {\n\n var foundIframe = iframely.findIframe({\n contentWindow: e.source,\n src: message.src || message.context,\n domains: message.domains !== 'all' && iframely.DOMAINS.concat(iframely.CDN)\n });\n\n if (foundIframe) {\n var widget = utils.getWidget(foundIframe);\n if (widget && message.url) {\n widget.url = message.url;\n }\n iframely.trigger('message', widget, message);\n }\n }\n \n});\n\n\nexports.postMessage = function(message, target_url, target) {\n if (window['postMessage']) {\n\n if (typeof message === 'object') {\n message.context = document.location.href;\n }\n\n message = JSON.stringify(message);\n\n target_url = target_url || '*';\n\n target = target || window.parent; // default to parent\n\n // the browser supports window.postMessage, so call it with a targetOrigin\n // set appropriately, based on the target_url parameter.\n target['postMessage'](message, target_url.replace( /([^:]+:\\/\\/[^/]+).*/, '$1'));\n }\n};\n\n\n//# sourceURL=webpack:///./messaging.js?\n}"); - -/***/ }, - -/***/ "./options/form-builder.js" -/*!*********************************!*\ - !*** ./options/form-builder.js ***! - \*********************************/ -(module, __unused_webpack_exports, __webpack_require__) { - -eval("{var getFormElements = __webpack_require__(/*! ./form-generator */ \"./options/form-generator.js\");\nvar iframely = __webpack_require__(/*! ../iframely */ \"./iframely.js\");\n\nvar UIelements = {\n checkbox: {\n getValue: function(inputs) {\n var input = inputs[0];\n return input.checked;\n }\n },\n text: {\n getValue: function(inputs) {\n var input = inputs[0];\n var value = input.value;\n if (input.type === 'number') {\n value = parseInt(value);\n if (isNaN(value)) {\n value = '';\n }\n }\n return value;\n },\n customEvents: function(inputs, submitOptionsCb) {\n var input = inputs[0];\n iframely.addEventListener(input, 'click', function() {\n input.select();\n });\n iframely.addEventListener(input, 'blur', submitOptionsCb);\n iframely.addEventListener(input, 'keyup', function(e) {\n // Apply on enter.\n if (e.keyCode === 13) {\n submitOptionsCb();\n }\n });\n }\n },\n radio: {\n getValue: function(inputs) {\n var selectedInput;\n inputs.forEach(function(input) {\n if (input.checked) {\n selectedInput = input;\n }\n });\n return selectedInput.value;\n }\n }\n};\n\nvar defaultQueryById = {};\n\nmodule.exports = function(params) {\n\n var options = params.options;\n var formContainer = params.formContainer;\n\n if (!formContainer) {\n console.warn('No formContainer in form-builder options', params);\n return;\n }\n\n if (!options) {\n formContainer.innerHTML = '';\n return;\n }\n\n var elements = getFormElements(options, params.translator);\n var id = params.id;\n var renderer = params.renderer;\n\n var defaultQuery = defaultQueryById[id] = defaultQueryById[id] || {};\n // Exclude default values.\n Object.keys(options).forEach(function(key) {\n if (!options.query || options.query.indexOf(key) === -1) {\n // Store default value.\n defaultQuery[key] = options[key].value;\n }\n });\n\n function getQueryFromForm() {\n\n var query = {};\n\n var getOptionsFromElements = function(elements) {\n // Get options from all inputs.\n elements.forEach(function(element) {\n\n if (element.context && element.context.elements) {\n\n getOptionsFromElements(element.context.elements);\n\n } else if (element.inputs) {\n\n var elementUI = UIelements[element.type];\n var inputValue;\n if (elementUI && elementUI.getValue) {\n inputValue = elementUI.getValue(element.inputs);\n } else {\n inputValue = element.inputs[0].value;\n }\n Object.assign(query, element.getQuery(inputValue));\n }\n });\n };\n\n getOptionsFromElements(elements);\n \n return query;\n }\n\n function getAndSubmitOptions() {\n var query = getQueryFromForm();\n\n Object.keys(defaultQuery).forEach(function(key) {\n if (defaultQuery[key] === query[key] \n || query[key] === undefined) { // remove undefined so it's not included while JSON.stringify\n delete query[key];\n }\n });\n\n iframely.trigger('options-changed', id, formContainer, query);\n }\n\n // Render form.\n var renderElements = function(elements) {\n var html = '';\n elements.forEach(function(element) {\n if (element.context && element.context.elements) {\n element.context.elementsHtml = renderElements(element.context.elements);\n }\n html += renderer(element.type, element.context || {});\n });\n return html;\n };\n formContainer.innerHTML = renderElements(elements);\n\n // Bind events.\n var bindElements = function(elements) {\n \n elements.forEach(function(element) {\n\n if (element.context && element.context.elements) {\n\n bindElements(element.context.elements);\n\n } else {\n\n var elementUI = UIelements[element.type];\n if (element.context) {\n element.inputs = formContainer.querySelectorAll('[name=\"' + element.context.key + '\"]');\n if (element.inputs.length > 0) {\n if (elementUI && elementUI.customEvents) {\n elementUI.customEvents(element.inputs, getAndSubmitOptions);\n } else {\n element.inputs.forEach(function(input) {\n iframely.addEventListener(input, 'change', getAndSubmitOptions);\n });\n }\n } else {\n console.warn('No inputs found for option', element.key);\n }\n }\n }\n });\n };\n bindElements(elements);\n};\n\n//# sourceURL=webpack:///./options/form-builder.js?\n}"); - -/***/ }, - -/***/ "./options/form-generator.js" -/*!***********************************!*\ - !*** ./options/form-generator.js ***! - \***********************************/ -(module) { - -eval("{var _RE = /^_./;\n\nvar translate = function (label, translator) {\n return translator && typeof translator === 'function' \n ? translator (label) || label\n : label;\n};\n\nmodule.exports = function(options, translator) {\n\n if (!options) {\n return [];\n }\n\n // Remove query key.\n options = Object.assign({}, options);\n delete options.query;\n\n var items = [];\n var keys = Object.keys(options);\n var checkboxCount = 0;\n \n keys.forEach(function(key) {\n \n var context = {};\n\n var getQuery;\n var option = options[key];\n option.key = key;\n\n var forceCheckboxForSingleKeyValue;\n var valuesKeys = option.values && Object.keys(option.values);\n var singleKey, singleLabel;\n if (valuesKeys && valuesKeys.length === 1) {\n forceCheckboxForSingleKeyValue = true;\n singleKey = valuesKeys[0];\n singleLabel = option.values[singleKey];\n }\n\n context.label = translate(singleLabel || option.label, translator);\n context.key = option.key;\n\n if (forceCheckboxForSingleKeyValue || typeof option.value === 'boolean') {\n\n if (forceCheckboxForSingleKeyValue) {\n context.checked = (singleKey === option.value) || (!singleKey && !option.value);\n } else {\n context.checked = option.value;\n }\n\n checkboxCount++;\n\n items.push({\n type: 'checkbox',\n context: context,\n order: _RE.test(key) ? 0 : 1,\n getQuery: function(checked) {\n\n var value;\n if (forceCheckboxForSingleKeyValue) {\n value = checked ? singleKey : '';\n } else {\n value = checked;\n }\n\n var result = {};\n\n if (forceCheckboxForSingleKeyValue) {\n if (value === '') {\n // Empty.\n } else {\n result[option.key] = value;\n }\n } else {\n result[option.key] = checked;\n }\n return result;\n }\n });\n\n } else if ((typeof option.value === 'number' || typeof option.value === 'string') && !option.values) {\n\n var useSlider = option.range && typeof option.range.min === 'number' && typeof option.range.max === 'number';\n var useNumber = typeof option.value === 'number';\n\n context.value = option.value;\n\n getQuery = function(inputValue) {\n var result = {};\n if (inputValue === '') {\n // Empty.\n } else {\n result[option.key] = inputValue;\n }\n return result;\n };\n\n if (useSlider) {\n context.min = option.range.min;\n context.max = option.range.max;\n items.push({\n type: 'range',\n context: context,\n order: 9, // last one\n getQuery: getQuery\n });\n } else {\n context.placeholder = translate(option.placeholder || '', translator);\n context.inputType = useNumber ? 'number' : 'text';\n items.push({\n type: 'text',\n context: context,\n order: /start/i.test(key) ? 7 : 8, // start/end for player timing, ex.: youtube\n getQuery: getQuery\n });\n }\n\n } else if (option.values) {\n\n context.value = option.value + '';\n\n getQuery = function(inputValue) {\n var result = {};\n if (inputValue === '') {\n // Empty.\n } else {\n result[option.key] = inputValue;\n }\n return result;\n };\n\n if (Object.keys(option.values).length <= 3) {\n\n if (option.label) {\n context.label = translate(option.label, translator);\n } else {\n context.label = false;\n }\n\n var i = 0;\n var hasLongLabel = false;\n var values = Object.values(option.values);\n while (i < values.length && !hasLongLabel) {\n var label = values[i];\n hasLongLabel = label.length > 8;\n i++;\n }\n context.inline = !hasLongLabel;\n\n context.items = [];\n\n Object.keys(option.values).forEach(function(key, idx2) {\n context.items.push({\n id: context.key + '-' + idx2,\n value: key,\n label: translate(option.values[key], translator),\n checked: context.value === key\n });\n });\n\n items.push({\n type: 'radio',\n context: context,\n order: hasLongLabel ? -3 : (!/theme/.test(key) ? -2 : -1),\n getQuery: getQuery\n });\n\n } else {\n\n context.items = [];\n\n Object.keys(option.values).forEach(function(key) {\n context.items.push({\n value: key,\n label: translate(option.values[key], translator),\n checked: context.value === key\n });\n });\n\n items.push({\n type: 'select',\n context: context,\n order: 5,\n getQuery: getQuery\n });\n }\n }\n });\n\n items.sort(function(a, b) {\n return a.order - b.order;\n });\n\n items.forEach(function(item) {\n delete item.order;\n });\n\n if (checkboxCount > 0) {\n\n var groupedItems = [];\n var subItems;\n\n items.forEach(function(item, idx) {\n\n if (item.type === 'checkbox') {\n\n // Grouping for checkboxes.\n\n var newCheckboxGroup = \n checkboxCount > 2\n && idx > 0 \n && !_RE.test(item.context.key) \n && items[idx - 1].type === 'checkbox'\n && _RE.test(items[idx - 1].context.key);\n\n if (!subItems // First group.\n || newCheckboxGroup // Second group on _ prefix removed.\n ) {\n\n subItems = [];\n groupedItems.push({\n type: 'group',\n context: {\n elements: subItems\n }\n });\n }\n\n subItems.push(item);\n\n } else {\n // Other items. Just add.\n groupedItems.push(item);\n }\n });\n\n return groupedItems;\n\n } else {\n return items;\n }\n};\n\n//# sourceURL=webpack:///./options/form-generator.js?\n}"); - -/***/ }, - -/***/ "./options/index.js" -/*!**************************!*\ - !*** ./options/index.js ***! - \**************************/ -(__unused_webpack_module, exports, __webpack_require__) { - -eval("{var iframely = __webpack_require__(/*! ../iframely */ \"./iframely.js\");\nvar formBuilder = __webpack_require__(/*! ./form-builder */ \"./options/form-builder.js\");\nvar renderer = __webpack_require__(/*! ./renderer */ \"./options/renderer.js\");\n\niframely.buildOptionsForm = function(id, formContainer, options, translator) {\n formBuilder({\n id: id,\n formContainer: formContainer,\n options: options,\n renderer: renderer,\n translator: translator\n });\n};\n\nexports.iframely = iframely;\n\n//# sourceURL=webpack:///./options/index.js?\n}"); - -/***/ }, - -/***/ "./options/renderer.js" -/*!*****************************!*\ - !*** ./options/renderer.js ***! - \*****************************/ -(module, __unused_webpack_exports, __webpack_require__) { - -eval("{var checkboxTemplate = __webpack_require__(/*! ./templates/checkbox.ejs */ \"./options/templates/checkbox.ejs\");\nvar rangeTemplate = __webpack_require__(/*! ./templates/range.ejs */ \"./options/templates/range.ejs\");\nvar textTemplate = __webpack_require__(/*! ./templates/text.ejs */ \"./options/templates/text.ejs\");\nvar radioTemplate = __webpack_require__(/*! ./templates/radio.ejs */ \"./options/templates/radio.ejs\");\nvar selectTemplate = __webpack_require__(/*! ./templates/select.ejs */ \"./options/templates/select.ejs\");\nvar groupTemplate = __webpack_require__(/*! ./templates/group.ejs */ \"./options/templates/group.ejs\");\n\nvar templates = {\n checkbox: checkboxTemplate,\n range: rangeTemplate,\n text: textTemplate,\n radio: radioTemplate,\n select: selectTemplate,\n group: groupTemplate\n};\n\nmodule.exports = function(type, context) {\n var template = templates[type];\n var renderedTemplate = template(context);\n return renderedTemplate;\n};\n\n//# sourceURL=webpack:///./options/renderer.js?\n}"); - -/***/ }, - -/***/ "./theme.js" -/*!******************!*\ - !*** ./theme.js ***! - \******************/ -(__unused_webpack_module, __unused_webpack_exports, __webpack_require__) { - -eval("{var iframely = __webpack_require__(/*! ./iframely */ \"./iframely.js\");\nvar messaging = __webpack_require__(/*! ./messaging */ \"./messaging.js\");\n\nfunction setThemeInIframe(iframe, theme) {\n messaging.postMessage({\n method: 'setTheme',\n data: theme\n }, '*', iframe.contentWindow);\n}\n\nfunction setThemeInAllIframes(parent, theme) {\n var iframes = parent.getElementsByTagName('iframe');\n for(var i = 0; i < iframes.length; i++) {\n var iframe = iframes[i];\n setThemeInIframe(iframe, theme);\n }\n}\n\niframely.setTheme = function(theme, container) {\n if (theme && iframely.SUPPORTED_THEMES.indexOf(theme) > -1) {\n if (container) {\n if (container.tagName === 'IFRAME') {\n setThemeInIframe(container, theme);\n } else {\n setThemeInAllIframes(container, theme);\n }\n } else {\n // Send get param to next iframes.\n iframely.extendOptions({\n theme: theme\n });\n setThemeInAllIframes(document, theme);\n iframely.trigger('set-theme', theme);\n }\n } else {\n console.warn('Using iframely.setTheme with not supported theme: \"' + theme + '\". Supported themes are: ' + iframely.SUPPORTED_THEMES.join(', '));\n }\n};\n\n//# sourceURL=webpack:///./theme.js?\n}"); - -/***/ }, - -/***/ "./utils.js" -/*!******************!*\ - !*** ./utils.js ***! - \******************/ -(__unused_webpack_module, exports, __webpack_require__) { - -eval("{var iframely = __webpack_require__(/*! ./iframely */ \"./iframely.js\");\nvar messaging = __webpack_require__(/*! ./messaging */ \"./messaging.js\");\n\niframely.on('init', function() {\n\n\n iframely.extendOptions(parseQueryStringFromScriptSrc());\n // if it's hosted from elsewhere - we don't support customizing via query-string.\n // iframely.CDN will be default one unless changed by user (?cdn= or iframely.CDN= )\n\n defineDefaultStyles();\n\n // Set theme for existing iframes.\n if (iframely.config.theme) {\n iframely.setTheme(iframely.config.theme);\n }\n\n requestSizeOfExistingIframes(iframely.DOMAINS.concat(iframely.CDN.replace(/^https?:\\/\\//, '')));\n \n});\n\niframely.load = function() {\n var args = Array.prototype.slice.call(arguments);\n args.unshift('load');\n iframely.trigger.apply(this, args);\n};\n\nvar getIframeWrapper = exports.getIframeWrapper = function(iframe, checkClass) {\n\n var aspectWrapper = iframe.parentNode;\n\n if (!aspectWrapper\n || aspectWrapper.nodeName !== 'DIV'\n || nonTextChildCount(aspectWrapper) > 2 /* 2 is lazy-cover */\n || (checkClass && aspectWrapper.getAttribute('class') !== iframely.ASPECT_WRAPPER_CLASS)\n || (!checkClass && aspectWrapper.style.position !== 'relative' && aspectWrapper.getAttribute('class') !== iframely.ASPECT_WRAPPER_CLASS)) {\n return;\n }\n\n var maxWidthWrapper = aspectWrapper.parentNode;\n\n if (!maxWidthWrapper\n || maxWidthWrapper.nodeName !== 'DIV'\n || nonTextChildCount(maxWidthWrapper) > 1\n || (checkClass && maxWidthWrapper.getAttribute('class') && maxWidthWrapper.getAttribute('class').split(' ').indexOf(iframely.MAXWIDTH_WRAPPER_CLASS) === -1)\n || (!checkClass && maxWidthWrapper.getAttribute('class') && !maxWidthWrapper.getAttribute('class').match(/iframely/i) /* users can modify class */)\n ) {\n return;\n }\n\n return {\n aspectWrapper: aspectWrapper,\n maxWidthWrapper: maxWidthWrapper\n };\n};\n\nexports.addDefaultWrappers = function(el) {\n var parentNode = el.parentNode;\n\n var maxWidthWrapper = document.createElement('div');\n maxWidthWrapper.className = iframely.MAXWIDTH_WRAPPER_CLASS;\n\n var aspectWrapper = document.createElement('div');\n aspectWrapper.className = iframely.ASPECT_WRAPPER_CLASS;\n\n maxWidthWrapper.appendChild(aspectWrapper);\n\n parentNode.insertBefore(maxWidthWrapper, el);\n\n return {\n aspectWrapper: aspectWrapper,\n maxWidthWrapper: maxWidthWrapper\n };\n};\n\nexports.getWidget = function(iframe) {\n var wrapper = getIframeWrapper(iframe);\n if (!wrapper) {\n return;\n }\n var widget = {\n iframe: iframe, // can actually be ahref\n aspectWrapper: wrapper.aspectWrapper,\n maxWidthWrapper: wrapper.maxWidthWrapper\n };\n if (iframe.nodeName === 'A' && iframe.hasAttribute('href')) {\n widget.url = iframe.getAttribute('href');\n } else if (iframe.hasAttribute('src') && /url=/.test(iframe.getAttribute('src'))) {\n var qs = parseQueryString(iframe.getAttribute('src'));\n if (qs.url) {\n widget.url = qs.url;\n }\n }\n return widget;\n};\n\niframely.getElementComputedStyle = function(el, style) {\n return window.getComputedStyle && window.getComputedStyle(el).getPropertyValue(style);\n};\n\nexports.setStyles = function(el, styles) {\n if (el) { // let's check it's still defined, just in case\n Object.keys(styles).forEach(function(key) {\n\n var value = styles[key];\n if (typeof value === 'number' || (typeof value === 'string' && /^(\\d+)?\\.?(\\d+)$/.test(value))) {\n value = value + 'px';\n }\n\n var currentValue = el.style[key];\n\n if (!window.getComputedStyle ||\n // don't change CSS values in pixels, such as height:0\n (\n iframely.getElementComputedStyle(el, key) != value\n // && don't set default aspect ratio if it's defined in CSS anyway\n && !(el.className == 'iframely-responsive' && key === 'paddingBottom' && !currentValue && /^56\\.2\\d+%$/.test(value))\n // && do not change max-width if new value === 'keep'.\n && !(key === 'max-width' && value === 'keep')\n )) {\n\n el.style[key] = value || ''; // remove style that is no longer needed\n }\n });\n }\n};\n\nvar applyNonce = exports.applyNonce = function(element) {\n if (iframely.config.nonce) {\n element.nonce = iframely.config.nonce;\n }\n};\n\nfunction defineDefaultStyles() {\n\n var iframelyStylesId = 'iframely-styles';\n var styles = document.getElementById(iframelyStylesId);\n\n if (!styles) {\n // copy-paste default styles from https://iframely.com/docs/omit-css\n // box-sizing:border-box - need for iOS Safari .\n var iframelyStyles = '.iframely-responsive{top:0;left:0;width:100%;height:0;position:relative;padding-bottom:56.25%;box-sizing:border-box;}.iframely-responsive>*{top:0;left:0;width:100%;height:100%;position:absolute;border:0;box-sizing:border-box;}';\n\n styles = document.createElement('style');\n styles.id = iframelyStylesId;\n styles.type = 'text/css';\n applyNonce(styles);\n\n if (styles.styleSheet) {\n // IE.\n styles.styleSheet.cssText = iframelyStyles;\n } else {\n styles.innerHTML = iframelyStyles;\n }\n document.getElementsByTagName('head')[0].appendChild(styles);\n }\n}\n\n\nvar addQueryString = exports.addQueryString = function(href, options) {\n\n var query_string = '';\n\n Object.keys(options).forEach(function(key) {\n var value = options[key];\n\n // array is used e.g. for import: uris and ids\n if (Object.prototype.toString.call(value) === '[object Array]') {\n\n var values = value.map(function(uri) {\n return key + '=' + encodeURIComponent(uri);\n });\n query_string += '&' + values.join('&'); \n\n } else if (typeof value !== 'undefined' && href.indexOf(key + '=') === -1 ) { // set explicitely in options, skip undefines\n\n // Do not convert boolean for _option.\n if (typeof value === 'boolean' && key.charAt(0) !== '_') {\n value = value ? 1 : 0;\n }\n\n query_string += '&' + key + '=' + encodeURIComponent(value);\n }\n\n });\n\n return href + (query_string !== '' ? (href.indexOf('?') > -1 ? '&' : '?') + query_string.replace(/^&/, '') : '');\n};\n\nexports.getEndpoint = function(src, options, config_params) {\n\n var endpoint = src;\n\n if (!/^(https?:)?\\/\\//i.test(src)) {\n endpoint = (options.CDN || iframely.CDN) + endpoint;\n delete options.CDN;\n }\n\n if (!/^(?:https?:)?\\/\\//i.test(endpoint)) {\n endpoint = '//' + endpoint;\n } \n\n if (options) {\n endpoint = addQueryString(endpoint, options);\n }\n\n // get additional params from config\n if (config_params && config_params.length) {\n\n var more_options = {};\n\n var iframely_config_keys = Object.keys(iframely.config);\n for (var i = 0; i < iframely_config_keys.length; i++) {\n var key = iframely_config_keys[i];\n if (containsString(config_params, key)) {\n more_options[key] = iframely.config[key];\n }\n }\n\n endpoint = addQueryString(endpoint, more_options);\n }\n\n\n if (/^(https?:)?\\/\\//i.test(endpoint) // Path is url.\n && !endpoint.match(/^(https?:)?\\/\\//i)[1] // No http protocol specified.\n && document.location.protocol !== 'http:' // Document in `file:` or other protocol.\n && document.location.protocol !== 'https:') {\n\n endpoint = 'https:' + endpoint;\n }\n\n return endpoint;\n};\n\n// helper method to init more options through js code\niframely.extendOptions = function(options) {\n\n options && Object.keys(options).forEach(function(key) {\n var new_value = (\n options[key] === 0 || options[key] === '0' || options[key] === false || options[key] === 'false'\n ? false : (options[key] === 1 || options[key] === '1' || options[key] === true || options[key] === 'true'\n ? true : options[key]));\n\n if (iframely.config[key] !== false) { // set new value only when undefined or not previously disabled\n iframely.config[key] = new_value;\n }\n });\n\n};\n\nfunction parseQueryStringFromScriptSrc() {\n\n // Extract global iframely params.\n var scripts = document.querySelectorAll('script[src*=\"embed.js\"], script[src*=\"iframely.js\"]');\n\n for(var i = 0; i < scripts.length; i++) {\n var src = scripts[i].getAttribute('src').replace(/&/gi, '&');\n\n if (iframely.SCRIPT_RE.test(src)) { // found the script on custom origin or default Iframely CDN\n\n var options = parseQueryString(src, iframely.SUPPORTED_QUERY_STRING.concat('cdn', 'cancel', 'nonce'));\n\n var m2 = src.match(iframely.CDN_RE);\n if (m2 || options.cdn) { // ignore non-Iframely hosts such as s.imgur.com/min/embed.js\n iframely.CDN = options.cdn || m2[1];\n }\n\n if (options.cancel) {\n if (options.cancel === '0' || options.cancel === 'false') {\n iframely.RECOVER_HREFS_ON_CANCEL = true;\n }\n delete options.cancel;\n }\n\n if (Object.keys(options).length > 0) {\n // give preferrence to CDN from scripts that have query-string. \n // CDN is most critical for embeds with empty data-iframely-url\n // and those should have at least ?api_key... in script src\n\n return options;\n } // or keep searching\n }\n }\n // should have exited by now if any querystring found...\n return {};\n}\n\nfunction requestSizeOfExistingIframes(domains) {\n\n var iframes = document.querySelectorAll('iframe[src*=\"' + (domains || iframely.DOMAINS).join('\"], iframe[src*=\"') + '\"]');\n for(var i = 0; i < iframes.length; i++) {\n var iframe = iframes[i];\n var src = iframe.src;\n if (src.match(/^(https?:)?\\/\\/[^/]+\\/api\\/iframe\\?.+/)\n || src.match(/^(https?:)?\\/\\/[^/]+\\/\\w+(\\?.*)?$/)) {\n messaging.postMessage({\n method: 'getSize'\n }, '*', iframe.contentWindow);\n }\n }\n} \n\nfunction nonTextChildCount(element) {\n var count = 0;\n for(var i = 0; i < element.childNodes.length; i++) {\n var el = element.childNodes[i];\n if (el.nodeType === Node.TEXT_NODE) {\n var text = el.textContent || el.innerText;\n text = text.replace(/\\s|\\n/g, '');\n if (text) {\n // Do not skip text node with text.\n count++;\n }\n } else if (el.nodeType === Node.ELEMENT_NODE) {\n count++;\n }\n }\n return count;\n}\n\nfunction containsString(list, findValue) {\n var value, i = 0;\n while (i < list.length) {\n value = list[i];\n\n if (value == findValue) {\n return true;\n }\n\n if (value && value.test && value.test(findValue)) {\n return true;\n }\n\n i++;\n }\n}\n\nvar parseQueryString = exports.parseQueryString = function(url, allowed_query_string) {\n var query = url.match(/\\?(.+)/i);\n if (query) {\n query = query[1];\n var data = query.split('&');\n var result = {};\n for(var i=0; i= 0;\n }\n return found && el;\n }\n\n var parentNode = widget.maxWidthWrapper && widget.maxWidthWrapper.parentNode;\n var naNode = widget.maxWidthWrapper;\n\n // Try remove by parentClass first.\n if (iframely.config && iframely.config.parent) {\n // Remove by parent class.\n var parentElement = findParent(widget.maxWidthWrapper, iframely.config.parent);\n\n if (parentElement) {\n parentNode = parentElement.parentNode;\n naNode = parentElement;\n }\n }\n\n if (widget.url) {\n var text = widget.iframe && (widget.iframe.textContent || widget.iframe.innerText);\n\n iframely.triggerAsync('cancel', widget.url, parentNode, text, naNode.nextSibling);\n }\n // Re-creating a link if people had it as text is now deprecated (see in deprecated.js)\n // New use: iframely.on('cancel', function(url, parentNode, text) {...} );\n\n parentNode.removeChild(naNode);\n};\n\n//# sourceURL=webpack:///./widget-cancel.js?\n}"); - -/***/ }, - -/***/ "./widget-click.js" -/*!*************************!*\ - !*** ./widget-click.js ***! - \*************************/ -(__unused_webpack_module, __unused_webpack_exports, __webpack_require__) { - -eval("{var iframely = __webpack_require__(/*! ./iframely */ \"./iframely.js\");\n\niframely.on('message', function(widget, message) {\n if (message.method === 'open-href' || message.method === 'click') {\n iframely.trigger(message.method, message.href);\n }\n});\n\n// Do not override user defined handler.\nif (!iframely.openHref) {\n iframely.openHref = function(href) {\n if (href.indexOf(window.location.origin) === 0) {\n // Redirect top on same origin.\n window.location.href = href;\n } else {\n // Open new tab on another origin.\n window.open(href, '_blank', 'noopener');\n }\n };\n}\n\niframely.on('open-href', function(href) {\n iframely.triggerAsync('click', href);\n iframely.openHref(href);\n});\n\n//# sourceURL=webpack:///./widget-click.js?\n}"); - -/***/ }, - -/***/ "./widget-options.js" -/*!***************************!*\ - !*** ./widget-options.js ***! - \***************************/ -(__unused_webpack_module, __unused_webpack_exports, __webpack_require__) { - -eval("{var iframely = __webpack_require__(/*! ./iframely */ \"./iframely.js\");\n\niframely.on('message', function(widget, message) {\n if (message.method === 'setIframelyEmbedOptions') {\n iframely.trigger('options', widget, message.data);\n }\n});\n\n\n//# sourceURL=webpack:///./widget-options.js?\n}"); - -/***/ }, - -/***/ "./widget-resize.js" -/*!**************************!*\ - !*** ./widget-resize.js ***! - \**************************/ -(__unused_webpack_module, __unused_webpack_exports, __webpack_require__) { - -eval("{var utils = __webpack_require__(/*! ./utils */ \"./utils.js\");\nvar iframely = __webpack_require__(/*! ./iframely */ \"./iframely.js\");\n\niframely.on('message', function(widget, message) {\n\n if (message.method === 'setIframelyWidgetSize' \n || message.method === 'resize' \n || message.method === 'setIframelyEmbedData' \n || message.type === 'embed-size'\n || message.context === 'iframe.resize') {\n\n var frame_styles = null;\n\n if (message.data && message.data.media && message.data.media.frame_style) {\n\n message.data.media.frame_style.split(';').forEach(function(str) {\n\n if(str.trim() !== '' && str.indexOf(':') > -1) {\n var props = str.split(':');\n if (props.length === 2) {\n frame_styles = frame_styles || {};\n frame_styles[props[0].trim()] = props[1].trim();\n }\n }\n });\n\n widgetDecorate(widget, frame_styles);\n\n } else if (message.method === 'setIframelyEmbedData') {\n\n // setIframelyEmbedData always sets frame_style. If not - reset.\n // setIframelyEmbedData without message.data resets border.\n widgetDecorate(widget, null);\n }\n\n var media = message.data && message.data.media;\n if (!media && message.height) {\n media = {\n height: message.height,\n 'max-width': 'keep'\n };\n }\n\n widgetResize(widget, media);\n }\n});\n\n// All frame_style attributes.\nvar resetWrapperBorderStyles = {'border': '', 'border-radius': '', 'box-shadow': '', 'overflow': ''};\nvar resetIframeBorderStyles = {'border': '0', 'border-radius': '', 'box-shadow': '', 'overflow': ''};\n\nfunction widgetDecorate(widget, styles) {\n\n if (styles && widget && widget.iframe) {\n\n if (styles['border-radius']) {\n // fix for Chrome?\n styles.overflow = 'hidden';\n utils.setStyles(widget.aspectWrapper, styles);\n } else {\n utils.setStyles(widget.iframe, styles);\n }\n\n } else if (!styles && widget && widget.iframe) {\n\n utils.setStyles(widget.aspectWrapper, resetWrapperBorderStyles);\n utils.setStyles(widget.iframe, resetIframeBorderStyles);\n }\n}\n\nfunction getTotalBorderWidth(widget) {\n\n // Get frame style from iframe or aspect wrapper as in widgetDecorate for Chrome fix.\n var frameStylesBorder = \n (widget.iframe && widget.iframe.style.border) \n || (widget.aspectWrapper && widget.aspectWrapper.style.border);\n\n // Get iframe border width from frame style.\n var borderWidth = frameStylesBorder && frameStylesBorder.match(/(\\d+)px/) || 0;\n if (borderWidth) {\n borderWidth = parseInt(borderWidth[1]);\n // For width and height border size will be 2x.\n borderWidth = borderWidth * 2;\n }\n\n return borderWidth;\n}\n\nfunction widgetResize(widget, media) {\n\n if (media && Object.keys(media).length > 0 && widget) {\n\n var borderWidth = getTotalBorderWidth(widget);\n\n var oldIframeHeight = window.getComputedStyle && window.getComputedStyle(widget.iframe).getPropertyValue('height');\n\n\n var maxWidth = media['max-width'];\n if (typeof maxWidth === 'number') {\n // Can be max-width: 56vh.\n maxWidth += borderWidth;\n }\n\n utils.setStyles(widget.maxWidthWrapper, {\n 'max-width': maxWidth,\n 'min-width': media['min-width'] && (media['min-width'] + borderWidth),\n width: media.width && (media.width + borderWidth)\n });\n\n if (media.scrolling && widget.iframe) {\n widget.iframe.setAttribute('scrolling', media.scrolling);\n }\n\n var aspectRatio = media['aspect-ratio'];\n\n // If no aspect and height - do not change aspect wrapper.\n if (aspectRatio || media.height) {\n utils.setStyles(widget.aspectWrapper, {\n paddingBottom: aspectRatio ? (Math.round(1000 * 100 / aspectRatio) / 1000 + '%') : 0, // if fixed-size, it will get set to 0\n paddingTop: aspectRatio && media['padding-bottom'], // if a fixed-height padding at the bottom of responsive div is required\n height: aspectRatio ? 0 : (media.height && (media.height + borderWidth)) // if defined\n });\n }\n\n\n var currentHeight = window.getComputedStyle && window.getComputedStyle(widget.iframe).getPropertyValue('height');\n\n if (oldIframeHeight && oldIframeHeight !== currentHeight) {\n iframely.triggerAsync('heightChanged', widget.iframe, oldIframeHeight, currentHeight);\n }\n\n }\n}\n\n\n//# sourceURL=webpack:///./widget-resize.js?\n}"); - -/***/ } - -/******/ }); -/************************************************************************/ -/******/ // 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 -/******/ if (!(moduleId in __webpack_modules__)) { -/******/ delete __webpack_module_cache__[moduleId]; -/******/ var e = new Error("Cannot find module '" + moduleId + "'"); -/******/ e.code = 'MODULE_NOT_FOUND'; -/******/ throw e; -/******/ } -/******/ __webpack_modules__[moduleId](module, module.exports, __webpack_require__); -/******/ -/******/ // Return the exports of the module -/******/ return module.exports; -/******/ } -/******/ -/************************************************************************/ -/******/ /* webpack/runtime/global */ -/******/ (() => { -/******/ __webpack_require__.g = (function() { -/******/ if (typeof globalThis === 'object') return globalThis; -/******/ try { -/******/ return this || new Function('return this')(); -/******/ } catch (e) { -/******/ if (typeof window === 'object') return window; -/******/ } -/******/ })(); -/******/ })(); -/******/ -/************************************************************************/ -/******/ -/******/ // startup -/******/ // Load entry module and return exports -/******/ // This entry module can't be inlined because the eval devtool is used. -/******/ var __webpack_exports__ = __webpack_require__("./index-options.js"); -/******/ -/******/ })() -; \ No newline at end of file +(function() { + + +//#region src/iframely.ts + function createServerStub() { + const noop = () => {}; + return { + config: {}, + on: noop, + trigger: noop, + triggerAsync: noop, + load: noop, + unload: noop, + configure: noop, + extendOptions: noop, + setTheme: noop, + cancelWidget: noop, + openHref: noop, + addEventListener: noop, + isTouch: () => false, + findIframe: () => void 0, + getElementComputedStyle: () => void 0, + buildOptionsForm: noop + }; + } + var iframely = typeof window === "undefined" ? createServerStub() : window.iframely = window.iframely || {}; + iframely.config = iframely.config || {}; + +//#endregion +//#region src/dom-ready.ts + var DOMReady = (f) => { + if (document.readyState === "complete" || document.readyState === "interactive") setTimeout(f, 0); + document.addEventListener("DOMContentLoaded", f); + }; + if (typeof document !== "undefined") DOMReady(() => { + if (typeof iframely.config.autorun === "undefined" || iframely.config.autorun !== false) iframely.trigger("load"); + }); + +//#endregion +//#region src/const.ts + function boot$15() { + iframely.VERSION = 1; + iframely.ASPECT_WRAPPER_CLASS = "iframely-responsive"; + iframely.MAXWIDTH_WRAPPER_CLASS = "iframely-embed"; + iframely.LOADER_CLASS = "iframely-loader"; + iframely.DOMAINS = [ + "cdn.iframe.ly", + "iframe.ly", + "if-cdn.com", + "iframely.net" + ]; + iframely.CDN = iframely.CDN || iframely.DOMAINS[0]; + iframely.BASE_RE = /^(?:https?:)?\/\/[^/]+/i; + iframely.ID_RE = /^(?:https?:)?\/\/[^/]+\/(\w+-?\w+)(?:\?.*)?$/; + iframely.SCRIPT_RE = /^(?:https?:|file:\/)?\/\/[^/]+(?:.+)?\/(?:embed|iframely)\.js(?:[^/]+)?$/i; + iframely.CDN_RE = /^(?:https?:)?\/\/([^/]+)\/(?:embed|iframely)\.js(?:[^/]+)?$/i; + iframely.SUPPORTED_QUERY_STRING = [ + "api_key", + "key", + "iframe", + "html5", + "playerjs", + "align", + "language", + "media", + "maxwidth", + "maxheight", + "lazy", + "import", + "parent", + "shadow", + "click_to_play", + "autoplay", + "mute", + "card", + "consent", + "theme", + /^_.+/ + ]; + iframely.SUPPORTED_THEMES = [ + "auto", + "light", + "dark" + ]; + iframely.LAZY_IFRAME_SHOW_TIMEOUT = 3e3; + iframely.LAZY_IFRAME_FADE_TIMEOUT = 200; + iframely.CLEAR_WRAPPER_STYLES_TIMEOUT = 3e3; + iframely.RECOVER_HREFS_ON_CANCEL = false; + iframely.SHADOW = "iframely-shadow"; + iframely.SUPPORT_IFRAME_LOADING_ATTR = true; + } + +//#endregion +//#region src/events.ts + var nextTick = (fn) => { + window.requestAnimationFrame(fn); + }; + var callbacksStack = {}; + function trigger(event, async, args) { + (callbacksStack[event] || []).forEach((cb) => { + if (async) nextTick(() => { + cb.apply(iframely, args); + }); + else cb.apply(iframely, args); + }); + if (event === "init") callbacksStack[event] = []; + } + function boot$14() { + iframely.on = (event, cb) => { + (callbacksStack[event] = callbacksStack[event] || []).push(cb); + }; + iframely.trigger = (event, ...args) => { + trigger(event, false, args); + }; + iframely.triggerAsync = (event, ...args) => { + trigger(event, true, args); + }; + } + +//#endregion +//#region src/messaging.ts + function receiveMessage(callback) { + window.addEventListener("message", (e) => { + let message; + try { + if (typeof e.data === "string") message = JSON.parse(e.data); + else if (typeof e.data === "object") message = e.data; + } catch { + if (typeof e.data === "string") { + const m = e.data.match(/heightxPYMx(\d+)/); + if (m) message = { + method: "resize", + height: parseInt(m[1]) + 1, + domains: "all" + }; + } + } + callback(e, message); + }, false); + } + function findIframeByContentWindow(iframes, contentWindow) { + let foundIframe; + for (let i = 0; i < iframes.length && !foundIframe; i++) { + const iframe = iframes[i]; + if (iframe.contentWindow === contentWindow) foundIframe = iframe; + } + return foundIframe; + } + function findIframeInElement(element, options) { + let foundIframe, iframes; + if (options.src) { + iframes = element.querySelectorAll("iframe[src*=\"" + options.src.replace(/^https?:/, "") + "\"]"); + foundIframe = findIframeByContentWindow(iframes, options.contentWindow); + } + if (!foundIframe) { + iframes = options.domains ? element.querySelectorAll("iframe[src*=\"" + (options.domains || iframely.DOMAINS).join("\"], iframe[src*=\"") + "\"]") : element.querySelectorAll("iframe"); + foundIframe = findIframeByContentWindow(iframes, options.contentWindow); + } + return foundIframe; + } + function findIframeInShadowRoots(element, options) { + let foundIframe; + const className = "." + (iframely.config.shadow || iframely.SHADOW); + const shadowRoots = element.querySelectorAll(className); + for (let i = 0; i < shadowRoots.length && !foundIframe; i++) { + const shadowRoot = shadowRoots[i].shadowRoot; + if (shadowRoot) { + foundIframe = findIframeInElement(shadowRoot, options); + if (!foundIframe) foundIframe = findIframeInShadowRoots(shadowRoot, options); + } + } + return foundIframe; + } + function boot$13() { + if (!iframely.findIframe) iframely.findIframe = (options) => { + let foundIframe = findIframeInElement(document, options); + if (!foundIframe) foundIframe = findIframeInShadowRoots(document, options); + return foundIframe; + }; + receiveMessage((e, message) => { + if (message && (message.method || message.type || message.context)) { + const foundIframe = iframely.findIframe({ + contentWindow: e.source, + src: message.src || message.context, + domains: message.domains !== "all" && iframely.DOMAINS.concat(iframely.CDN) + }); + if (foundIframe) { + const widget = getWidget(foundIframe); + if (widget && message.url) widget.url = message.url; + iframely.trigger("message", widget, message); + } + } + }); + } + function postMessage(message, target_url, target) { + if (typeof message === "object") message.context = document.location.href; + const data = JSON.stringify(message); + target_url = target_url || "*"; + target = target || window.parent; + target.postMessage(data, target_url.replace(/([^:]+:\/\/[^/]+).*/, "$1")); + } + +//#endregion +//#region src/utils.ts + function boot$12() { + iframely.on("init", () => { + iframely.configure(parseQueryStringFromScriptSrc()); + defineDefaultStyles(); + if (iframely.config.theme) iframely.setTheme(iframely.config.theme); + requestSizeOfExistingIframes(iframely.DOMAINS.concat(iframely.CDN.replace(/^https?:\/\//, ""))); + }); + iframely.load = function(...args) { + iframely.trigger("load", ...args); + }; + iframely.unload = (el) => { + const domains = iframely.DOMAINS.concat(iframely.CDN.replace(/^https?:\/\//, "")); + const root = el || document; + const selector = "iframe[src*=\"" + domains.join("\"], iframe[src*=\"") + "\"], iframe[data-iframely-url]"; + const iframes = root.querySelectorAll(selector); + for (let i = 0; i < iframes.length; i++) { + const widget = getWidget(iframes[i]); + if (widget) { + iframely.trigger("unload-widget", widget); + widget.maxWidthWrapper.remove(); + } + } + iframely.trigger("unload", el); + }; + iframely.getElementComputedStyle = (el, style) => { + return window.getComputedStyle(el).getPropertyValue(style); + }; + iframely.configure = (options) => { + if (!options) return; + Object.keys(options).forEach((key) => { + const new_value = options[key] === 0 || options[key] === "0" || options[key] === false || options[key] === "false" ? false : options[key] === 1 || options[key] === "1" || options[key] === true || options[key] === "true" ? true : options[key]; + if (iframely.config[key] !== false) iframely.config[key] = new_value; + }); + }; + } + function getIframeWrapper(iframe, checkClass) { + const aspectWrapper = iframe.parentNode; + if (!aspectWrapper || aspectWrapper.nodeName !== "DIV" || nonTextChildCount$1(aspectWrapper) > 2 || checkClass && aspectWrapper.getAttribute("class") !== iframely.ASPECT_WRAPPER_CLASS || !checkClass && aspectWrapper.style.position !== "relative" && aspectWrapper.getAttribute("class") !== iframely.ASPECT_WRAPPER_CLASS) return; + const maxWidthWrapper = aspectWrapper.parentNode; + if (!maxWidthWrapper || maxWidthWrapper.nodeName !== "DIV" || nonTextChildCount$1(maxWidthWrapper) > 1 || checkClass && maxWidthWrapper.getAttribute("class") && maxWidthWrapper.getAttribute("class").split(" ").indexOf(iframely.MAXWIDTH_WRAPPER_CLASS) === -1 || !checkClass && maxWidthWrapper.getAttribute("class") && !maxWidthWrapper.getAttribute("class").match(/iframely/i)) return; + return { + aspectWrapper, + maxWidthWrapper + }; + } + function addDefaultWrappers(el) { + const parentNode = el.parentNode; + const maxWidthWrapper = document.createElement("div"); + maxWidthWrapper.className = iframely.MAXWIDTH_WRAPPER_CLASS; + const aspectWrapper = document.createElement("div"); + aspectWrapper.className = iframely.ASPECT_WRAPPER_CLASS; + maxWidthWrapper.appendChild(aspectWrapper); + parentNode.insertBefore(maxWidthWrapper, el); + return { + aspectWrapper, + maxWidthWrapper + }; + } + function getWidget(iframe) { + const wrapper = getIframeWrapper(iframe); + if (!wrapper) return; + const widget = { + iframe, + aspectWrapper: wrapper.aspectWrapper, + maxWidthWrapper: wrapper.maxWidthWrapper + }; + const src = iframe.getAttribute("src"); + if (iframe.nodeName === "A" && iframe.hasAttribute("href")) widget.url = iframe.getAttribute("href"); + else if (src && /url=/.test(src)) { + const qs = parseQueryString(src); + if (qs.url) widget.url = qs.url; + } + return widget; + } + function setStyles(el, styles) { + if (el) Object.keys(styles).forEach((key) => { + let value = styles[key]; + if (typeof value === "number" || typeof value === "string" && /^(\d+)?\.?(\d+)$/.test(value)) value = value + "px"; + const elStyle = el.style; + const currentValue = elStyle[key]; + if (iframely.getElementComputedStyle(el, key) != value && !(el.className == "iframely-responsive" && key === "paddingBottom" && !currentValue && /^56\.2\d+%$/.test(value)) && !(key === "max-width" && value === "keep")) elStyle[key] = value || ""; + }); + } + function applyNonce(element) { + if (iframely.config.nonce) element.nonce = iframely.config.nonce; + } + function defineDefaultStyles() { + const iframelyStylesId = "iframely-styles"; + let styles = document.getElementById(iframelyStylesId); + if (!styles) { + const iframelyStyles = ".iframely-responsive{top:0;left:0;width:100%;height:0;position:relative;padding-bottom:56.25%;box-sizing:border-box;}.iframely-responsive>*{top:0;left:0;width:100%;height:100%;position:absolute;border:0;box-sizing:border-box;}"; + styles = document.createElement("style"); + styles.id = iframelyStylesId; + applyNonce(styles); + styles.innerHTML = iframelyStyles; + document.getElementsByTagName("head")[0].appendChild(styles); + } + } + function addQueryString(href, options) { + let query_string = ""; + Object.keys(options).forEach((key) => { + let value = options[key]; + if (Array.isArray(value)) { + const values = value.map((uri) => key + "=" + encodeURIComponent(uri)); + query_string += "&" + values.join("&"); + } else if (typeof value !== "undefined" && href.indexOf(key + "=") === -1) { + if (typeof value === "boolean" && key.charAt(0) !== "_") value = value ? 1 : 0; + query_string += "&" + key + "=" + encodeURIComponent(value); + } + }); + return href + (query_string !== "" ? (href.indexOf("?") > -1 ? "&" : "?") + query_string.replace(/^&/, "") : ""); + } + function getEndpoint(src, options, config_params) { + let endpoint = src; + if (!/^(https?:)?\/\//i.test(src)) { + endpoint = (options && options.CDN || iframely.CDN) + endpoint; + if (options) delete options.CDN; + } + if (!/^(?:https?:)?\/\//i.test(endpoint)) endpoint = "//" + endpoint; + if (options) endpoint = addQueryString(endpoint, options); + if (config_params && config_params.length) { + const more_options = {}; + const iframely_config_keys = Object.keys(iframely.config); + for (let i = 0; i < iframely_config_keys.length; i++) { + const key = iframely_config_keys[i]; + if (containsString(config_params, key)) more_options[key] = iframely.config[key]; + } + endpoint = addQueryString(endpoint, more_options); + } + if (/^(https?:)?\/\//i.test(endpoint) && !endpoint.match(/^(https?:)?\/\//i)[1] && document.location.protocol !== "http:" && document.location.protocol !== "https:") endpoint = "https:" + endpoint; + return endpoint; + } + function parseQueryStringFromScriptSrc() { + const scripts = document.querySelectorAll("script[src*=\"embed.js\"], script[src*=\"iframely.js\"]"); + for (let i = 0; i < scripts.length; i++) { + const src = scripts[i].getAttribute("src").replace(/&/gi, "&"); + if (iframely.SCRIPT_RE.test(src)) { + const options = parseQueryString(src, iframely.SUPPORTED_QUERY_STRING.concat("cdn", "cancel", "nonce")); + const m2 = src.match(iframely.CDN_RE); + if (m2 || options.cdn) iframely.CDN = options.cdn || m2[1]; + if (options.cancel) { + if (options.cancel === "0" || options.cancel === "false") iframely.RECOVER_HREFS_ON_CANCEL = true; + delete options.cancel; + } + if (Object.keys(options).length > 0) return options; + } + } + return {}; + } + function requestSizeOfExistingIframes(domains) { + const iframes = document.querySelectorAll("iframe[src*=\"" + (domains || iframely.DOMAINS).join("\"], iframe[src*=\"") + "\"]"); + for (let i = 0; i < iframes.length; i++) { + const iframe = iframes[i]; + const src = iframe.src; + if (src.match(/^(https?:)?\/\/[^/]+\/api\/iframe\?.+/) || src.match(/^(https?:)?\/\/[^/]+\/\w+(\?.*)?$/)) postMessage({ method: "getSize" }, "*", iframe.contentWindow); + } + } + function nonTextChildCount$1(element) { + let count = 0; + for (let i = 0; i < element.childNodes.length; i++) { + const el = element.childNodes[i]; + if (el.nodeType === Node.TEXT_NODE) { + if ((el.textContent || "").replace(/\s|\n/g, "")) count++; + } else if (el.nodeType === Node.ELEMENT_NODE) count++; + } + return count; + } + function containsString(list, findValue) { + let value, i = 0; + while (i < list.length) { + value = list[i]; + if (value == findValue) return true; + if (value instanceof RegExp && value.test(findValue)) return true; + i++; + } + return false; + } + function parseQueryString(url, allowed_query_string) { + const query = url.match(/\?(.+)/i); + if (query) { + const data = query[1].split("&"); + const result = {}; + for (let i = 0; i < data.length; i++) { + const item = data[i].split("="); + if (!allowed_query_string || containsString(allowed_query_string, item[0])) result[item[0]] = decodeURIComponent(item[1]); + } + return result; + } else return {}; + } + function createScript() { + const script = document.createElement("script"); + applyNonce(script); + return script; + } + +//#endregion +//#region src/intersection.ts + var observers = {}; + function getObserver(options) { + const optionsKey = JSON.stringify(options); + let observer = observers[optionsKey]; + if (!observer) { + observer = new IntersectionObserver((entries) => { + entries.forEach((entry) => { + postMessage({ + method: "intersection", + entry: { isIntersecting: entry.isIntersecting }, + options + }, "*", entry.target.contentWindow); + }); + }, getObserverOptions(options)); + observers[optionsKey] = observer; + } + return observer; + } + function getObserverOptions(options) { + const result = {}; + if (options && options.threshold) result.threshold = options.threshold; + if (options && options.margin) result.rootMargin = options.margin + "px " + options.margin + "px " + options.margin + "px " + options.margin + "px"; + return result; + } + function boot$11() { + iframely.on("init", () => { + iframely.configure({ intersection: 1 }); + }); + iframely.on("message", (widget, message) => { + if (message.method === "send-intersections" && widget.iframe) { + let options = message.options; + if (!options) options = { margin: 1e3 }; + getObserver(options).observe(widget.iframe); + } + }); + iframely.on("unload-widget", (widget) => { + Object.values(observers).forEach((observer) => observer.unobserve(widget.iframe)); + }); + iframely.on("unload", (el) => { + if (!el) Object.keys(observers).forEach((key) => { + observers[key].disconnect(); + delete observers[key]; + }); + }); + } + +//#endregion +//#region src/theme.ts + function setThemeInIframe(iframe, theme) { + postMessage({ + method: "setTheme", + data: theme + }, "*", iframe.contentWindow); + } + function setThemeInAllIframes(parent, theme) { + const iframes = parent.getElementsByTagName("iframe"); + for (let i = 0; i < iframes.length; i++) setThemeInIframe(iframes[i], theme); + } + function boot$10() { + iframely.setTheme = (theme, container) => { + if (theme && iframely.SUPPORTED_THEMES.indexOf(theme) > -1) if (container) if (container.tagName === "IFRAME") setThemeInIframe(container, theme); + else setThemeInAllIframes(container, theme); + else { + iframely.configure({ theme }); + setThemeInAllIframes(document, theme); + iframely.trigger("set-theme", theme); + } + else console.warn("Using iframely.setTheme with not supported theme: \"" + theme + "\". Supported themes are: " + iframely.SUPPORTED_THEMES.join(", ")); + }; + } + +//#endregion +//#region src/import.ts + var widgetsCache = {}; + function boot$9() { + iframely.on("load", (el) => { + if (!el && iframely.config.import !== false && isImportAble() && !iframely.import) { + const elements = document.querySelectorAll("a[data-iframely-url]:not([data-import-uri])"); + if (elements.length > 1) makeImportAPICall(elements); + } + }); + iframely.on("load", (widget, importOptions) => { + if (widget && !(widget instanceof Element) && widget.uri && (widget.html || widget.cancel)) { + const els = widgetsCache[widget.uri]; + if (els) for (let i = 0; i < els.length; i++) loadImportWidget(widget, els[i], importOptions); + delete widgetsCache[widget.uri]; + } + }); + iframely.buildImportWidgets = (importOptions) => { + iframely.trigger("import-loaded", importOptions); + importOptions.widgets.forEach((widget) => { + iframely.trigger("load", widget, importOptions); + }); + importReady(); + }; + iframely.isTouch = () => { + return "ontouchstart" in window || navigator.maxTouchPoints > 0; + }; + iframely.on("import-widget-ready", clearWrapperStylesAndClass); + iframely.on("unload", (el) => { + if (!el) { + delete iframely.import; + Object.keys(widgetsCache).forEach((key) => { + delete widgetsCache[key]; + }); + } + }); + if (!iframely.addEventListener) iframely.addEventListener = (elem, type, eventHandle) => { + if (!elem) return; + elem.addEventListener(type, eventHandle, false); + }; + } + function makeImportAPICall(elements) { + const script = createScript(); + const uris = []; + const ids = []; + let import_options = null; + function pushElement(uri, el) { + if (!widgetsCache[uri]) widgetsCache[uri] = []; + widgetsCache[uri].push(el); + } + function queueElement(el) { + const src = el.getAttribute("data-iframely-url"); + const mId = src.match(iframely.ID_RE); + const id = mId && mId[1]; + const options = parseQueryString(src, iframely.SUPPORTED_QUERY_STRING.concat("url")); + let url = options.url; + delete options.url; + let skipImport = options.import === "0" || options.import === "false" || options.playerjs === "1" || options.playerjs === "true"; + if (!skipImport) { + const mBase = src.match(iframely.BASE_RE); + options.CDN = mBase && mBase[0]; + if (!import_options) import_options = options; + else if (JSON.stringify(options, Object.keys(options).sort()) !== JSON.stringify(import_options, Object.keys(import_options).sort())) skipImport = true; + } + if (skipImport) iframely.trigger("load", el); + else if (id) { + el.setAttribute("data-import-uri", id); + if (ids.indexOf(id) === -1) ids.push(id); + pushElement(id, el); + } else { + if (!url) url = el.getAttribute("href"); + if ((import_options.key || import_options.api_key || iframely.config.api_key || iframely.config.key) && url) { + el.setAttribute("data-import-uri", url); + if (uris.indexOf(url) === -1) uris.push(url); + pushElement(url, el); + } else iframely.trigger("load", el); + } + } + for (let i = 0; i < elements.length; i++) { + const el = elements[i]; + if (!el.getAttribute("data-import-uri") && el.hasAttribute("data-iframely-url")) queueElement(el); + } + if (uris.length > 0 || ids.length > 0) { + import_options = import_options || {}; + import_options.touch = iframely.isTouch(); + import_options.flash = false; + import_options.app = 1; + if (iframely.config.theme) import_options.theme = iframely.config.theme; + if (uris.length > 0) import_options.uri = uris; + if (ids.length > 0) import_options.ids = ids.join("&"); + import_options.v = iframely.VERSION; + script.src = getEndpoint("/api/import/v2", import_options, iframely.SUPPORTED_QUERY_STRING); + script.onerror = () => { + importReady(); + }; + document.head.appendChild(script); + iframely.import = script; + } else { + importReady(); + iframely.trigger("load"); + } + } + function loadImportWidget(widgetOptions, el, importOptions) { + const needCancelWidget = widgetOptions.cancel; + const shadow = widgetOptions.shadow; + const hasRenderedEvent = widgetOptions.renderEvent; + const wrapper = getIframeWrapper(el, true); + if (needCancelWidget) iframely.cancelWidget(getWidget(el) || { + maxWidthWrapper: el, + iframe: el, + url: el.getAttribute("href") + }); + else { + const widget = document.createElement("div"); + widget.innerHTML = widgetOptions.html; + let parent, replacedEl; + if (wrapper && !hasRenderedEvent) { + parent = wrapper.aspectWrapper.parentNode; + replacedEl = wrapper.aspectWrapper; + wrapper.maxWidthWrapper.removeAttribute("style"); + } else { + parent = el.parentNode; + replacedEl = el; + } + if (shadow) { + const shadowContainer = document.createElement("div"); + const shadowRoot = shadowContainer.attachShadow({ mode: "open" }); + shadowRoot.appendChild(widget); + const shadowWidgetOptions = { + shadowRoot, + shadowContainer, + container: parent, + context: widgetOptions.context, + stylesIds: widgetOptions.stylesIds, + stylesDict: importOptions.commonShadowStyles + }; + iframely.trigger("import-shadow-widget-before-render", shadowWidgetOptions); + parent.insertBefore(shadowContainer, replacedEl); + iframely.trigger("import-shadow-widget-after-render", shadowWidgetOptions); + } else { + parent.insertBefore(widget, replacedEl); + exec_body_scripts(widget); + } + parent.removeChild(replacedEl); + if (hasRenderedEvent) setTimeout(() => { + clearWrapperStylesAndClass(parent); + }, iframely.CLEAR_WRAPPER_STYLES_TIMEOUT); + } + } + function importReady() { + delete iframely.import; + const failed_elements = document.querySelectorAll("a[data-iframely-url][data-import-uri]"); + for (let i = 0; i < failed_elements.length; i++) { + failed_elements[i].removeAttribute("data-import-uri"); + iframely.trigger("load", failed_elements[i]); + } + } + function isImportAble() { + return !!(document.location && (iframely.debug || document.location.protocol === "http:" || document.location.protocol === "https:") && !iframely.config.playerjs && !iframely.config.lazy); + } + function clearWrapperStylesAndClass(el) { + let aspectWrapper = el; + let parents = 0; + while (aspectWrapper && (!aspectWrapper.getAttribute("class") || aspectWrapper.getAttribute("class").split(" ").indexOf(iframely.ASPECT_WRAPPER_CLASS) === -1)) { + aspectWrapper = aspectWrapper.parentNode; + parents++; + if (parents > 4) aspectWrapper = null; + } + const maxWidthWrapper = aspectWrapper && aspectWrapper.parentNode; + if (maxWidthWrapper && maxWidthWrapper.getAttribute("class") && maxWidthWrapper.getAttribute("class").split(" ").indexOf(iframely.MAXWIDTH_WRAPPER_CLASS) > -1) { + aspectWrapper.removeAttribute("style"); + aspectWrapper.removeAttribute("class"); + maxWidthWrapper.removeAttribute("style"); + } + } + function exec_body_scripts(body_el) { + function nodeName(elem, name) { + return !!elem.nodeName && elem.nodeName.toUpperCase() === name.toUpperCase(); + } + function evalScript(elem) { + const data = elem.text || elem.textContent || elem.innerHTML || ""; + const script = createScript(); + script.type = "text/javascript"; + for (let i = 0; i < elem.attributes.length; i++) { + const attr = elem.attributes[i]; + script.setAttribute(attr.name, attr.value); + } + script.appendChild(document.createTextNode(data)); + body_el.appendChild(script); + } + const scripts = []; + const children_nodes = body_el.childNodes; + for (let i = 0; children_nodes[i]; i++) { + const child = children_nodes[i]; + if (nodeName(child, "script") && (!child.type || child.type.toLowerCase() === "text/javascript" || child.type.toLowerCase() === "application/javascript")) { + scripts.push(child); + body_el.removeChild(child); + } else if (child.nodeType === Node.ELEMENT_NODE) exec_body_scripts(child); + } + for (let i = 0; i < scripts.length; i++) { + const script = scripts[i]; + if (script.parentNode) script.parentNode.removeChild(script); + evalScript(script); + } + } + +//#endregion +//#region src/ahref.ts + function boot$8() { + iframely.on("load", (container, href) => { + if (container && container.nodeName && typeof href === "string") { + const a = document.createElement("a"); + a.setAttribute("href", href); + container.appendChild(a); + iframely.trigger("load", a); + } + }); + iframely.on("load", (el) => { + if (!el && !iframely.import) { + const elements = document.querySelectorAll("a[data-iframely-url]:not([data-import-uri])"); + for (let i = 0; i < elements.length; i++) iframely.trigger("load", elements[i]); + } + }); + iframely.on("load", (el) => { + if (el && el.nodeName === "A" && (el.getAttribute("data-iframely-url") || el.getAttribute("href")) && !el.hasAttribute("data-import-uri")) unfurl(el); + }); + } + function unfurl(el) { + if (!el.getAttribute("data-iframely-url") && !el.getAttribute("href")) return; + let src; + const dataIframelyUrl = el.getAttribute("data-iframely-url"); + if (dataIframelyUrl && /^((?:https?:)?\/\/[^/]+)\/\w+/i.test(dataIframelyUrl)) src = getEndpoint(dataIframelyUrl, { + v: iframely.VERSION, + app: 1, + theme: iframely.config.theme + }); + else if ((iframely.config.api_key || iframely.config.key) && iframely.CDN) { + if (!el.getAttribute("href")) { + console.warn("Iframely cannot build embeds: \"href\" attribute missing in", el); + return; + } + src = getEndpoint("/api/iframe", { + url: el.getAttribute("href"), + v: iframely.VERSION, + app: 1, + theme: iframely.config.theme + }, iframely.SUPPORTED_QUERY_STRING); + } else console.warn("Iframely cannot build embeds: api key is required as query-string of embed.js"); + if (!src) el.removeAttribute("data-iframely-url"); + else { + const iframe = document.createElement("iframe"); + iframe.setAttribute("allowfullscreen", ""); + iframe.setAttribute("allow", "autoplay *; encrypted-media *; ch-prefers-color-scheme *"); + if (el.hasAttribute("data-img")) iframe.setAttribute("data-img", el.getAttribute("data-img")); + const isLazy = el.hasAttribute("data-lazy") || el.hasAttribute("data-img") || /&lazy=1/.test(src) || iframely.config.lazy; + const text = el.textContent; + if (text && text !== "") iframe.textContent = text; + let wrapper = getIframeWrapper(el, true); + if (wrapper) while (wrapper.aspectWrapper.lastChild) wrapper.aspectWrapper.removeChild(wrapper.aspectWrapper.lastChild); + else { + wrapper = addDefaultWrappers(el); + el.parentNode.removeChild(el); + } + wrapper.aspectWrapper.appendChild(iframe); + if (isLazy) { + iframe.setAttribute("data-iframely-url", src); + iframely.trigger("load", iframe); + } else { + iframe.setAttribute("src", src); + iframely.trigger("iframe-ready", iframe); + } + } + } + +//#endregion +//#region src/lazy-img-placeholder.ts + function boot$7() { + iframely.on("load", (el) => { + if (el && el.nodeName === "IFRAME" && el.hasAttribute("data-iframely-url") && el.hasAttribute("data-img") && !el.getAttribute("src")) { + const dataImg = el.getAttribute("data-img"); + el.removeAttribute("data-img"); + el.setAttribute("data-img-created", ""); + const widget = getWidget(el); + let src = el.getAttribute("data-iframely-url"); + if (widget) { + addPlaceholderThumbnail(widget, src, dataImg); + src = addQueryString(src, { img: 1 }); + el.setAttribute("data-iframely-url", src); + new WaitingWidget(widget); + } + iframely.trigger("load", el); + } + }); + iframely.on("message", (widget, message) => { + if (!widget) return; + let waitingWidget; + if (message.method === "widgetRendered") { + hidePlaceholderThumbnail(widget); + waitingWidget = findWaitingWidget(widget); + waitingWidget?.deactivate(); + } + if (message.method === "begin-waiting-widget-render") { + waitingWidget = findWaitingWidget(widget); + waitingWidget?.clearLoadingTimeout(); + } + if (message.method === "end-waiting-widget-render") { + waitingWidget = findWaitingWidget(widget); + waitingWidget?.registerLoadingTimeout(); + } + }); + iframely.on("unload-widget", (widget) => { + findWaitingWidget(widget)?.deactivate(); + }); + } + function addPlaceholderThumbnail(widget, href, imageUrl) { + let thumbHref; + if (imageUrl && /^(https?:)?\/\//.test(imageUrl)) thumbHref = imageUrl; + else { + const query = parseQueryString(href); + const _params = {}; + for (const param in query) if (param.indexOf("_") === 0) _params[param] = query[param]; + if (query.media) _params.media = query.media; + if (href.match(/\/api\/iframe/)) thumbHref = getEndpoint(href.match(/^(.+)\/api\/iframe/i)[1] + "/api/thumbnail", Object.assign({ + url: query.url, + api_key: query.api_key, + key: query.key + }, _params)); + else if (href.match(iframely.ID_RE)) thumbHref = getEndpoint(href.replace(/^((?:https?:)?\/\/[^/]+\/(\w+-?\w+))(?:\?.*)?$/, "$1/thumbnail"), _params); + else return; + } + const thumb = document.createElement("div"); + setStyles(thumb, { + position: "absolute", + width: "100%", + height: "100%", + backgroundImage: "url('" + thumbHref + "')", + backgroundSize: "cover", + backgroundPosition: "center" + }); + const iframelyLoaderDiv = document.createElement("div"); + iframelyLoaderDiv.setAttribute("class", iframely.LOADER_CLASS); + thumb.appendChild(iframelyLoaderDiv); + const paddingTop = iframely.getElementComputedStyle(widget.aspectWrapper, "padding-top"); + const paddingBottom = iframely.getElementComputedStyle(widget.aspectWrapper, "padding-bottom"); + const paddingTopMatch = paddingTop && paddingTop.match(/^(\d+)px$/); + if (paddingTopMatch && parseInt(paddingTopMatch[1]) && paddingBottom) { + const thumbWrapper = document.createElement("div"); + setStyles(thumbWrapper, { + top: "-" + paddingTop, + width: "100%", + height: 0, + position: "relative", + paddingBottom + }); + thumbWrapper.appendChild(thumb); + widget.aspectWrapper.appendChild(thumbWrapper); + } else widget.aspectWrapper.appendChild(thumb); + } + function getNthNonTextChildNode(nth, element) { + let count = 0; + for (let i = 0; i < element.childNodes.length; i++) { + const el = element.childNodes[i]; + if (el.nodeType === Node.ELEMENT_NODE) { + if (nth === count) return el; + count++; + } + } + } + function nonTextChildCount(element) { + let count = 0; + for (let i = 0; i < element.childNodes.length; i++) { + const el = element.childNodes[i]; + if (el.nodeType === Node.TEXT_NODE) { + if ((el.textContent || "").replace(/\s|\n/g, "")) count++; + } else if (el.nodeType === Node.ELEMENT_NODE) count++; + } + return count; + } + function hidePlaceholderThumbnail(widget) { + const thumb = widget.aspectWrapper && nonTextChildCount(widget.aspectWrapper) > 1 && getNthNonTextChildNode(1, widget.aspectWrapper); + if (thumb && thumb.nodeName === "DIV") widget.aspectWrapper.removeChild(thumb); + } + var waitingWidgets = []; + function findWaitingWidgetIdx(widget) { + let i = 0; + while (i < waitingWidgets.length && waitingWidgets[i].widget.iframe !== widget.iframe) i++; + if (i < waitingWidgets.length && waitingWidgets[i].widget.iframe === widget.iframe) return i; + } + function findWaitingWidget(widget) { + const idx = findWaitingWidgetIdx(widget); + if (idx || idx === 0) return waitingWidgets[idx]; + } + function removeWaitingWidget(widget) { + const idx = findWaitingWidgetIdx(widget); + if (idx || idx === 0) waitingWidgets.splice(idx, 1); + } + var WaitingWidget = class { + widget; + loadCount = 0; + timeoutId = null; + constructor(widget) { + this.widget = widget; + iframely.addEventListener(widget.iframe, "load", () => { + this.iframeOnLoad(); + }); + this.registerLoadingTimeout(); + waitingWidgets.push(this); + } + iframeOnLoad() { + this.loadCount++; + if (this.loadCount !== 2) return; + this.deactivate(); + setTimeout(() => { + hidePlaceholderThumbnail(this.widget); + }, iframely.LAZY_IFRAME_FADE_TIMEOUT); + } + deactivate() { + this.clearLoadingTimeout(); + removeWaitingWidget(this.widget); + } + clearLoadingTimeout() { + if (this.timeoutId) clearTimeout(this.timeoutId); + this.timeoutId = null; + } + registerLoadingTimeout() { + if (this.timeoutId) return; + this.timeoutId = setTimeout(() => { + this.iframeOnLoad(); + }, iframely.LAZY_IFRAME_SHOW_TIMEOUT); + } + }; + +//#endregion +//#region src/lazy-iframe.ts + function boot$6() { + iframely.on("load", (el) => { + if (!el) { + const elements = document.querySelectorAll("iframe[data-iframely-url]"); + for (let i = 0; i < elements.length; i++) iframely.trigger("load", elements[i]); + } + }); + iframely.on("load", (el) => { + if (el && el.nodeName === "IFRAME" && el.hasAttribute("data-iframely-url") && !el.hasAttribute("data-img") && !el.getAttribute("src")) loadLazyIframe(el); + }); + } + function loadLazyIframe(el) { + const widget = getWidget(el); + let src = el.getAttribute("data-iframely-url"); + const dataImg = el.hasAttribute("data-img-created") || el.hasAttribute("data-img"); + const nativeLazyLoad = !dataImg && iframely.SUPPORT_IFRAME_LOADING_ATTR; + if (widget && src) { + const options = { + v: iframely.VERSION, + app: 1, + theme: iframely.config.theme + }; + if (!nativeLazyLoad && iframely.config.intersection) options.lazy = 1; + src = getEndpoint(src, options); + } + if (nativeLazyLoad) el.setAttribute("loading", "lazy"); + if (dataImg && iframely.SUPPORT_IFRAME_LOADING_ATTR) el.setAttribute("loading", "edge"); + el.setAttribute("src", src || ""); + el.removeAttribute("data-iframely-url"); + iframely.trigger("iframe-ready", el); + } + +//#endregion +//#region src/widget-cancel.ts + function boot$5() { + iframely.on("message", (widget, message) => { + if (message.method === "cancelWidget") iframely.cancelWidget(widget); + }); + iframely.cancelWidget = (widget) => { + if (!widget) { + console.warn("iframely.cancelWidget called without widget param"); + return; + } + function findParent(el, className) { + let found = false; + while (!found && el.parentNode) { + el = el.parentNode; + found = !!el.className && typeof el.className === "string" && el.className.split(" ").indexOf(className) >= 0; + } + return found && el; + } + let parentNode = widget.maxWidthWrapper && widget.maxWidthWrapper.parentNode; + let naNode = widget.maxWidthWrapper; + if (iframely.config && iframely.config.parent) { + const parentElement = findParent(widget.maxWidthWrapper, String(iframely.config.parent)); + if (parentElement) { + parentNode = parentElement.parentNode; + naNode = parentElement; + } + } + if (widget.url) { + const text = widget.iframe && widget.iframe.textContent; + iframely.triggerAsync("cancel", widget.url, parentNode, text, naNode.nextSibling); + } + parentNode.removeChild(naNode); + }; + } + +//#endregion +//#region src/widget-resize.ts + var resetWrapperBorderStyles = { + border: "", + "border-radius": "", + "box-shadow": "", + overflow: "" + }; + var resetIframeBorderStyles = { + border: "0", + "border-radius": "", + "box-shadow": "", + overflow: "" + }; + function boot$4() { + iframely.on("message", (widget, message) => { + if (message.method === "setIframelyWidgetSize" || message.method === "resize" || message.method === "setIframelyEmbedData" || message.type === "embed-size" || message.context === "iframe.resize") { + let frame_styles = null; + if (message.data && message.data.media && message.data.media.frame_style) { + message.data.media.frame_style.split(";").forEach((str) => { + if (str.trim() !== "" && str.indexOf(":") > -1) { + const props = str.split(":"); + if (props.length === 2) { + frame_styles = frame_styles || {}; + frame_styles[props[0].trim()] = props[1].trim(); + } + } + }); + widgetDecorate(widget, frame_styles); + } else if (message.method === "setIframelyEmbedData") widgetDecorate(widget, null); + let media = message.data && message.data.media; + if (!media && message.height) media = { + height: message.height, + "max-width": "keep" + }; + widgetResize(widget, media); + } + }); + } + function widgetDecorate(widget, styles) { + if (styles && widget && widget.iframe) if (styles["border-radius"]) { + styles.overflow = "hidden"; + setStyles(widget.aspectWrapper, styles); + } else setStyles(widget.iframe, styles); + else if (!styles && widget && widget.iframe) { + setStyles(widget.aspectWrapper, resetWrapperBorderStyles); + setStyles(widget.iframe, resetIframeBorderStyles); + } + } + function getTotalBorderWidth(widget) { + const frameStylesBorder = widget.iframe && widget.iframe.style.border || widget.aspectWrapper && widget.aspectWrapper.style.border; + const borderMatch = frameStylesBorder && frameStylesBorder.match(/(\d+)px/); + if (borderMatch) return parseInt(borderMatch[1]) * 2; + return 0; + } + function widgetResize(widget, media) { + if (media && Object.keys(media).length > 0 && widget) { + const borderWidth = getTotalBorderWidth(widget); + const oldIframeHeight = window.getComputedStyle(widget.iframe).getPropertyValue("height"); + let maxWidth = media["max-width"]; + if (typeof maxWidth === "number") maxWidth += borderWidth; + setStyles(widget.maxWidthWrapper, { + "max-width": maxWidth, + "min-width": media["min-width"] && media["min-width"] + borderWidth, + width: media.width && media.width + borderWidth + }); + if (media.scrolling && widget.iframe) widget.iframe.setAttribute("scrolling", media.scrolling); + const aspectRatio = media["aspect-ratio"]; + if (aspectRatio || media.height) setStyles(widget.aspectWrapper, { + paddingBottom: aspectRatio ? Math.round(1e3 * 100 / aspectRatio) / 1e3 + "%" : 0, + paddingTop: aspectRatio && media["padding-bottom"], + height: aspectRatio ? 0 : media.height && media.height + borderWidth + }); + const currentHeight = window.getComputedStyle(widget.iframe).getPropertyValue("height"); + if (oldIframeHeight && oldIframeHeight !== currentHeight) iframely.triggerAsync("heightChanged", widget.iframe, oldIframeHeight, currentHeight); + } + } + +//#endregion +//#region src/widget-click.ts + function boot$3() { + iframely.on("message", (widget, message) => { + if (message.method === "open-href" || message.method === "click") iframely.trigger(message.method, message.href); + }); + if (!iframely.openHref) iframely.openHref = (href) => { + if (href.indexOf(window.location.origin) === 0) window.location.href = href; + else window.open(href, "_blank", "noopener"); + }; + iframely.on("open-href", (href) => { + iframely.triggerAsync("click", href); + iframely.openHref(href); + }); + } + +//#endregion +//#region src/widget-options.ts + function boot$2() { + iframely.on("message", (widget, message) => { + if (message.method === "setIframelyEmbedOptions") iframely.trigger("options", widget, message.data); + }); + } + +//#endregion +//#region src/deprecated.ts + function boot$1() { + iframely.widgets = iframely.widgets || {}; + iframely.widgets.load = iframely.load; + iframely.extendOptions = iframely.configure; + if (!iframely.events) { + iframely.events = {}; + iframely.events.on = iframely.on; + iframely.events.trigger = iframely.trigger; + } + iframely.on("cancel", (url, parentNode, text, nextSibling) => { + if (iframely.RECOVER_HREFS_ON_CANCEL && !text) text = url; + if (url && parentNode && text && text !== "") { + const a = document.createElement("a"); + a.setAttribute("href", url); + a.setAttribute("target", "_blank"); + a.setAttribute("rel", "noopener"); + a.textContent = text; + if (nextSibling) parentNode.insertBefore(a, nextSibling); + else parentNode.appendChild(a); + } + }); + } + +//#endregion +//#region src/options/form-generator.ts + var _RE = /^_./; + var translate = (label, translator) => { + return translator && typeof translator === "function" && label ? translator(label) || label : label; + }; + function getFormElements(options, translator) { + if (!options) return []; + options = Object.assign({}, options); + delete options.query; + const items = []; + const keys = Object.keys(options); + let checkboxCount = 0; + keys.forEach((key) => { + const context = {}; + let getQuery; + const option = options[key]; + option.key = key; + let forceCheckboxForSingleKeyValue = false; + const valuesKeys = option.values ? Object.keys(option.values) : void 0; + let singleKey, singleLabel; + if (valuesKeys && valuesKeys.length === 1) { + forceCheckboxForSingleKeyValue = true; + singleKey = valuesKeys[0]; + singleLabel = option.values[singleKey]; + } + context.label = translate(singleLabel || option.label, translator); + context.key = option.key; + if (forceCheckboxForSingleKeyValue || typeof option.value === "boolean") { + if (forceCheckboxForSingleKeyValue) context.checked = singleKey === option.value || !singleKey && !option.value; + else context.checked = option.value; + checkboxCount++; + items.push({ + type: "checkbox", + context, + order: _RE.test(key) ? 0 : 1, + getQuery: (checked) => { + let value; + if (forceCheckboxForSingleKeyValue) value = checked ? singleKey : ""; + else value = checked; + const result = {}; + if (forceCheckboxForSingleKeyValue) if (value === "") {} else result[option.key] = value; + else result[option.key] = checked; + return result; + } + }); + } else if ((typeof option.value === "number" || typeof option.value === "string") && !option.values) { + const useSlider = option.range && typeof option.range.min === "number" && typeof option.range.max === "number"; + const useNumber = typeof option.value === "number"; + context.value = option.value; + getQuery = (inputValue) => { + const result = {}; + if (inputValue === "") {} else result[option.key] = inputValue; + return result; + }; + if (useSlider) { + context.min = option.range.min; + context.max = option.range.max; + items.push({ + type: "range", + context, + order: 9, + getQuery + }); + } else { + context.placeholder = translate(option.placeholder || "", translator); + context.inputType = useNumber ? "number" : "text"; + items.push({ + type: "text", + context, + order: /start/i.test(key) ? 7 : 8, + getQuery + }); + } + } else if (option.values) { + context.value = option.value + ""; + getQuery = (inputValue) => { + const result = {}; + if (inputValue === "") {} else result[option.key] = inputValue; + return result; + }; + if (Object.keys(option.values).length <= 3) { + if (option.label) context.label = translate(option.label, translator); + else context.label = false; + let i = 0; + let hasLongLabel = false; + const values = Object.values(option.values); + while (i < values.length && !hasLongLabel) { + hasLongLabel = values[i].length > 8; + i++; + } + context.inline = !hasLongLabel; + context.items = []; + Object.keys(option.values).forEach((key, idx2) => { + context.items.push({ + id: context.key + "-" + idx2, + value: key, + label: translate(option.values[key], translator), + checked: context.value === key + }); + }); + items.push({ + type: "radio", + context, + order: hasLongLabel ? -3 : !/theme/.test(key) ? -2 : -1, + getQuery + }); + } else { + context.items = []; + Object.keys(option.values).forEach((key) => { + context.items.push({ + value: key, + label: translate(option.values[key], translator), + checked: context.value === key + }); + }); + items.push({ + type: "select", + context, + order: 5, + getQuery + }); + } + } + }); + items.sort((a, b) => a.order - b.order); + items.forEach((item) => { + delete item.order; + }); + if (checkboxCount > 0) { + const groupedItems = []; + let subItems; + items.forEach((item, idx) => { + if (item.type === "checkbox") { + const newCheckboxGroup = checkboxCount > 2 && idx > 0 && !_RE.test(item.context.key) && items[idx - 1].type === "checkbox" && _RE.test(items[idx - 1].context.key); + if (!subItems || newCheckboxGroup) { + subItems = []; + groupedItems.push({ + type: "group", + context: { elements: subItems } + }); + } + subItems.push(item); + } else groupedItems.push(item); + }); + return groupedItems; + } else return items; + } + +//#endregion +//#region src/options/form-builder.ts + var UIelements = { + checkbox: { getValue: (inputs) => { + return inputs[0].checked; + } }, + text: { + getValue: (inputs) => { + const input = inputs[0]; + let value = input.value; + if (input.type === "number") { + value = parseInt(value); + if (isNaN(value)) value = ""; + } + return value; + }, + customEvents: (inputs, submitOptionsCb) => { + const input = inputs[0]; + iframely.addEventListener(input, "click", () => { + input.select(); + }); + iframely.addEventListener(input, "blur", submitOptionsCb); + iframely.addEventListener(input, "keyup", (e) => { + if (e.keyCode === 13) submitOptionsCb(); + }); + } + }, + radio: { getValue: (inputs) => { + let selectedInput; + Array.prototype.forEach.call(inputs, (input) => { + if (input.checked) selectedInput = input; + }); + return selectedInput.value; + } } + }; + var defaultQueryById = {}; + function formBuilder(params) { + const options = params.options; + const formContainer = params.formContainer; + if (!formContainer) { + console.warn("No formContainer in form-builder options", params); + return; + } + if (!options) { + formContainer.innerHTML = ""; + return; + } + const elements = getFormElements(options, params.translator); + const id = params.id; + const renderer = params.renderer; + const defaultQuery = defaultQueryById[id] = defaultQueryById[id] || {}; + Object.keys(options).forEach((key) => { + if (!options.query || options.query.indexOf(key) === -1) defaultQuery[key] = options[key].value; + }); + function getQueryFromForm() { + const query = {}; + const getOptionsFromElements = (elements) => { + elements.forEach((element) => { + if (element.context && element.context.elements) getOptionsFromElements(element.context.elements); + else if (element.inputs) { + const elementUI = UIelements[element.type]; + let inputValue; + if (elementUI && elementUI.getValue) inputValue = elementUI.getValue(element.inputs); + else inputValue = element.inputs[0].value; + Object.assign(query, element.getQuery(inputValue)); + } + }); + }; + getOptionsFromElements(elements); + return query; + } + function getAndSubmitOptions() { + const query = getQueryFromForm(); + Object.keys(defaultQuery).forEach((key) => { + if (defaultQuery[key] === query[key] || query[key] === void 0) delete query[key]; + }); + iframely.trigger("options-changed", id, formContainer, query); + } + const renderElements = (elements) => { + let html = ""; + elements.forEach((element) => { + if (element.context && element.context.elements) element.context.elementsHtml = renderElements(element.context.elements); + html += renderer(element.type, element.context || {}); + }); + return html; + }; + formContainer.innerHTML = renderElements(elements); + const bindElements = (elements) => { + elements.forEach((element) => { + if (element.context && element.context.elements) bindElements(element.context.elements); + else { + const elementUI = UIelements[element.type]; + if (element.context) { + const inputs = formContainer.querySelectorAll("[name=\"" + element.context.key + "\"]"); + element.inputs = inputs; + if (inputs.length > 0) if (elementUI && elementUI.customEvents) elementUI.customEvents(inputs, getAndSubmitOptions); + else inputs.forEach((input) => { + iframely.addEventListener(input, "change", getAndSubmitOptions); + }); + else console.warn("No inputs found for option", element.context.key); + } + } + }); + }; + bindElements(elements); + } + +//#endregion +//#region src/options/renderer.ts + var ESCAPE_MAP = { + "&": "&", + "<": "<", + ">": ">", + "\"": """, + "'": "'" + }; + var esc = (value) => value == null ? "" : String(value).replace(/[&<>"']/g, (c) => ESCAPE_MAP[c]); + var templates = { + checkbox: (ctx) => ` +
+ + +
`, + group: (ctx) => ` +
+
${ctx.elementsHtml ?? ""}
+
`, + radio: (ctx) => ` +
+ ${ctx.label ? `` : ""} +
+ ${(ctx.items || []).map((item) => ` +
+ + +
`).join("")} +
+
`, + range: (ctx) => ` +
+ +
+ +
+
`, + select: (ctx) => ` +
+ +
+ +
+
`, + text: (ctx) => ` +
+ +
+ +
+
` + }; + var render = (type, context) => templates[type](context); + +//#endregion +//#region src/options/index.ts + function boot() { + iframely.buildOptionsForm = (id, formContainer, options, translator) => { + if (typeof iframely.trigger !== "function" || typeof iframely.addEventListener !== "function") { + console.warn("iframely.buildOptionsForm requires embed.js (or embed-options.js) to be loaded"); + return; + } + formBuilder({ + id, + formContainer, + options, + renderer: render, + translator + }); + }; + } + +//#endregion +//#region src/index-options.ts + if (typeof window !== "undefined" && !iframely._loaded) { + iframely._loaded = true; + boot$15(); + boot$14(); + boot$12(); + boot$13(); + boot$11(); + boot$10(); + boot$9(); + boot$8(); + boot$7(); + boot$6(); + boot$5(); + boot$4(); + boot$3(); + boot$2(); + boot$1(); + boot(); + iframely.trigger("init"); + } + +//#endregion +})(); \ No newline at end of file diff --git a/dist/embed-options.min.js b/dist/embed-options.min.js index 0b983c2..8b4eeb9 100644 --- a/dist/embed-options.min.js +++ b/dist/embed-options.min.js @@ -1 +1,38 @@ -(()=>{var __webpack_modules__={530(module){module.exports=function(obj){obj||(obj={});var __t,__p="",__j=Array.prototype.join;function print(){__p+=__j.call(arguments,"")}with(obj)__p+='
\n \n '+(null==(__t=label)?"":__t)+"\n \n
\n";return __p}},30(module){module.exports=function(obj){obj||(obj={});var __t,__p="",__e=_.escape;with(obj)__p+='
\n
\n '+__e(elementsHtml)+"\n
\n
";return __p}},510(module){module.exports=function(obj){obj||(obj={});var __t,__p="",__j=Array.prototype.join;function print(){__p+=__j.call(arguments,"")}with(obj)__p+='
\n ',label&&(__p+='\n \n "),__p+='\n
\n '+(null==(__t=e.label)?"":__t)+"\n \n
\n "}),__p+="\n
\n";return __p}},300(module){module.exports=function(obj){obj||(obj={});var __t,__p="";with(obj)__p+='
\n \n
\n \n
\n
';return __p}},37(module){module.exports=function(obj){obj||(obj={});var __t,__p="",__j=Array.prototype.join;function print(){__p+=__j.call(arguments,"")}with(obj)__p+='
\n \n
\n \n
\n
";return __p}},712(module){module.exports=function(obj){obj||(obj={});var __t,__p="";with(obj)__p+='
\n \n
\n \n
\n
';return __p}},679(e,t,r){var n=r(672),a=r(774);a.on("load",function(e,t){if(e&&e.nodeName&&"string"==typeof t){var r=document.createElement("a");r.setAttribute("href",t),e.appendChild(r),a.trigger("load",r)}}),a.on("load",function(e){if(!e&&!a.import)for(var t=document.querySelectorAll("a[data-iframely-url]:not([data-import-uri])"),r=0;r4&&(t=null);var n=t&&t.parentNode;n&&n.getAttribute("class")&&n.getAttribute("class").split(" ").indexOf(a.MAXWIDTH_WRAPPER_CLASS)>-1&&(t.removeAttribute("style"),t.removeAttribute("class"),n.removeAttribute("style"))}function s(e){function t(e,t){return e.nodeName&&e.nodeName.toUpperCase()===t.toUpperCase()}function r(t){var r=t.text||t.textContent||t.innerHTML||"",a=n.createScript();a.type="text/javascript";for(var i=0;i1&&function(e){var t=n.createScript(),r=[],o=[],c=null;function s(e,t){i[e]||(i[e]=[]),i[e].push(t)}function d(e){var t=e.getAttribute("data-iframely-url"),i=t.match(a.ID_RE),l=i&&i[1],d=n.parseQueryString(t,a.SUPPORTED_QUERY_STRING.concat("url")),u=d.url;delete d.url;var p="0"===d.import||"false"===d.import||"1"===d.playerjs||"true"===d.playerjs;if(!p){var f=t.match(a.BASE_RE);d.CDN=f&&f[0],c?JSON.stringify(d,Object.keys(d).sort())!==JSON.stringify(c,Object.keys(c).sort())&&(p=!0):c=d}p?a.trigger("load",e):l?(e.setAttribute("data-import-uri",l),-1===o.indexOf(l)&&o.push(l),s(l,e)):(u||(u=e.getAttribute("href")),(c.key||c.api_key||a.config.api_key||a.config.key)&&u?(e.setAttribute("data-import-uri",u),-1===r.indexOf(u)&&r.push(u),s(u,e)):a.trigger("load",e))}for(var u=0;u0||o.length>0?((c=c||{}).touch=a.isTouch(),c.flash=function(){var e=!1;try{e=!!new ActiveXObject("ShockwaveFlash.ShockwaveFlash")}catch(t){e=!(!navigator.mimeTypes||null==navigator.mimeTypes["application/x-shockwave-flash"]||!navigator.mimeTypes["application/x-shockwave-flash"].enabledPlugin)}return e}(),c.app=1,a.config.theme&&(c.theme=a.config.theme),r.length>0&&(c.uri=r),o.length>0&&(c.ids=o.join("&")),c.v=a.VERSION,t.src=n.getEndpoint("/api/import/v2",c,a.SUPPORTED_QUERY_STRING),t.onerror=function(){l()},document.head.appendChild(t),a.import=t):(l(),a.trigger("load"))}(t)}}),a.on("load",function(e,t){if(e&&e.uri&&(e.html||e.cancel)){var r=i[e.uri];if(r)for(var n=0;n1&&function(e,t){for(var r=0,n=0;n=77},369(e,t,r){var n=r(774),a=r(672);function i(e,t){for(var r,n=0;n0?t&&t.customEvents?t.customEvents(e.inputs,f):e.inputs.forEach(function(e){a.addEventListener(e,"change",f)}):console.warn("No inputs found for option",e.key))}})};p(l)}else r.innerHTML="";else console.warn("No formContainer in form-builder options",e);function f(){var e=function(){var e={},t=function(r){r.forEach(function(r){if(r.context&&r.context.elements)t(r.context.elements);else if(r.inputs){var n,a=i[r.type];n=a&&a.getValue?a.getValue(r.inputs):r.inputs[0].value,Object.assign(e,r.getQuery(n))}})};return t(l),e}();Object.keys(d).forEach(function(t){d[t]!==e[t]&&void 0!==e[t]||delete e[t]}),a.trigger("options-changed",c,r,e)}}},960(e){var t=/^_./,r=function(e,t){return t&&"function"==typeof t&&t(e)||e};e.exports=function(e,n){if(!e)return[];delete(e=Object.assign({},e)).query;var a=[],i=Object.keys(e),o=0;if(i.forEach(function(i){var l,c,s={},d=e[i];d.key=i;var u,p,f=d.values&&Object.keys(d.values);if(f&&1===f.length&&(c=!0,u=f[0],p=d.values[u]),s.label=r(p||d.label,n),s.key=d.key,c||"boolean"==typeof d.value)s.checked=c?u===d.value||!u&&!d.value:d.value,o++,a.push({type:"checkbox",context:s,order:t.test(i)?0:1,getQuery:function(e){var t;t=c?e?u:"":e;var r={};return c?""===t||(r[d.key]=t):r[d.key]=e,r}});else if("number"!=typeof d.value&&"string"!=typeof d.value||d.values){if(d.values)if(s.value=d.value+"",l=function(e){var t={};return""===e||(t[d.key]=e),t},Object.keys(d.values).length<=3){d.label?s.label=r(d.label,n):s.label=!1;for(var m=0,_=!1,h=Object.values(d.values);m8,m++;s.inline=!_,s.items=[],Object.keys(d.values).forEach(function(e,t){s.items.push({id:s.key+"-"+t,value:e,label:r(d.values[e],n),checked:s.value===e})}),a.push({type:"radio",context:s,order:_?-3:/theme/.test(i)?-1:-2,getQuery:l})}else s.items=[],Object.keys(d.values).forEach(function(e){s.items.push({value:e,label:r(d.values[e],n),checked:s.value===e})}),a.push({type:"select",context:s,order:5,getQuery:l})}else{var g=d.range&&"number"==typeof d.range.min&&"number"==typeof d.range.max,v="number"==typeof d.value;s.value=d.value,l=function(e){var t={};return""===e||(t[d.key]=e),t},g?(s.min=d.range.min,s.max=d.range.max,a.push({type:"range",context:s,order:9,getQuery:l})):(s.placeholder=r(d.placeholder||"",n),s.inputType=v?"number":"text",a.push({type:"text",context:s,order:/start/i.test(i)?7:8,getQuery:l}))}}),a.sort(function(e,t){return e.order-t.order}),a.forEach(function(e){delete e.order}),o>0){var l,c=[];return a.forEach(function(e,r){if("checkbox"===e.type){var n=o>2&&r>0&&!t.test(e.context.key)&&"checkbox"===a[r-1].type&&t.test(a[r-1].context.key);l&&!n||(l=[],c.push({type:"group",context:{elements:l}})),l.push(e)}else c.push(e)}),c}return a}},448(e,t,r){var n=r(774),a=r(410),i=r(505);n.buildOptionsForm=function(e,t,r,n){a({id:e,formContainer:t,options:r,renderer:i,translator:n})},t.iframely=n},505(e,t,r){var n={checkbox:r(530),range:r(300),text:r(712),radio:r(510),select:r(37),group:r(30)};e.exports=function(e,t){return(0,n[e])(t)}},908(e,t,r){var n=r(774),a=r(369);function i(e,t){a.postMessage({method:"setTheme",data:t},"*",e.contentWindow)}function o(e,t){for(var r=e.getElementsByTagName("iframe"),n=0;n-1?t?"IFRAME"===t.tagName?i(t,e):o(t,e):(n.extendOptions({theme:e}),o(document,e),n.trigger("set-theme",e)):console.warn('Using iframely.setTheme with not supported theme: "'+e+'". Supported themes are: '+n.SUPPORTED_THEMES.join(", "))}},672(e,t,r){var n=r(774),a=r(369);n.on("init",function(){n.extendOptions(function(){for(var e=document.querySelectorAll('script[src*="embed.js"], script[src*="iframely.js"]'),t=0;t0)return a}}return{}}()),function(){var e="iframely-styles",t=document.getElementById(e);if(!t){var r=".iframely-responsive{top:0;left:0;width:100%;height:0;position:relative;padding-bottom:56.25%;box-sizing:border-box;}.iframely-responsive>*{top:0;left:0;width:100%;height:100%;position:absolute;border:0;box-sizing:border-box;}";(t=document.createElement("style")).id=e,t.type="text/css",o(t),t.styleSheet?t.styleSheet.cssText=r:t.innerHTML=r,document.getElementsByTagName("head")[0].appendChild(t)}}(),n.config.theme&&n.setTheme(n.config.theme),function(e){for(var t=document.querySelectorAll('iframe[src*="'+(e||n.DOMAINS).join('"], iframe[src*="')+'"]'),r=0;r2||t&&r.getAttribute("class")!==n.ASPECT_WRAPPER_CLASS||!t&&"relative"!==r.style.position&&r.getAttribute("class")!==n.ASPECT_WRAPPER_CLASS)){var a=r.parentNode;if(!(!a||"DIV"!==a.nodeName||c(a)>1||t&&a.getAttribute("class")&&-1===a.getAttribute("class").split(" ").indexOf(n.MAXWIDTH_WRAPPER_CLASS)||!t&&a.getAttribute("class")&&!a.getAttribute("class").match(/iframely/i)))return{aspectWrapper:r,maxWidthWrapper:a}}};t.addDefaultWrappers=function(e){var t=e.parentNode,r=document.createElement("div");r.className=n.MAXWIDTH_WRAPPER_CLASS;var a=document.createElement("div");return a.className=n.ASPECT_WRAPPER_CLASS,r.appendChild(a),t.insertBefore(r,e),{aspectWrapper:a,maxWidthWrapper:r}},t.getWidget=function(e){var t=i(e);if(t){var r={iframe:e,aspectWrapper:t.aspectWrapper,maxWidthWrapper:t.maxWidthWrapper};if("A"===e.nodeName&&e.hasAttribute("href"))r.url=e.getAttribute("href");else if(e.hasAttribute("src")&&/url=/.test(e.getAttribute("src"))){var n=d(e.getAttribute("src"));n.url&&(r.url=n.url)}return r}},n.getElementComputedStyle=function(e,t){return window.getComputedStyle&&window.getComputedStyle(e).getPropertyValue(t)},t.setStyles=function(e,t){e&&Object.keys(t).forEach(function(r){var a=t[r];("number"==typeof a||"string"==typeof a&&/^(\d+)?\.?(\d+)$/.test(a))&&(a+="px");var i=e.style[r];window.getComputedStyle&&(n.getElementComputedStyle(e,r)==a||"iframely-responsive"==e.className&&"paddingBottom"===r&&!i&&/^56\.2\d+%$/.test(a)||"max-width"===r&&"keep"===a)||(e.style[r]=a||"")})};var o=t.applyNonce=function(e){n.config.nonce&&(e.nonce=n.config.nonce)},l=t.addQueryString=function(e,t){var r="";return Object.keys(t).forEach(function(n){var a=t[n];if("[object Array]"===Object.prototype.toString.call(a)){var i=a.map(function(e){return n+"="+encodeURIComponent(e)});r+="&"+i.join("&")}else void 0!==a&&-1===e.indexOf(n+"=")&&("boolean"==typeof a&&"_"!==n.charAt(0)&&(a=a?1:0),r+="&"+n+"="+encodeURIComponent(a))}),e+(""!==r?(e.indexOf("?")>-1?"&":"?")+r.replace(/^&/,""):"")};function c(e){for(var t=0,r=0;r=0;return r&&e}(e.maxWidthWrapper,n.config.parent);a&&(t=a.parentNode,r=a)}if(e.url){var i=e.iframe&&(e.iframe.textContent||e.iframe.innerText);n.triggerAsync("cancel",e.url,t,i,r.nextSibling)}t.removeChild(r)}else console.warn("iframely.cancelWidget called without widget param")}},612(e,t,r){var n=r(774);n.on("message",function(e,t){"open-href"!==t.method&&"click"!==t.method||n.trigger(t.method,t.href)}),n.openHref||(n.openHref=function(e){0===e.indexOf(window.location.origin)?window.location.href=e:window.open(e,"_blank","noopener")}),n.on("open-href",function(e){n.triggerAsync("click",e),n.openHref(e)})},742(e,t,r){var n=r(774);n.on("message",function(e,t){"setIframelyEmbedOptions"===t.method&&n.trigger("options",e,t.data)})},850(e,t,r){var n=r(672),a=r(774);a.on("message",function(e,t){if("setIframelyWidgetSize"===t.method||"resize"===t.method||"setIframelyEmbedData"===t.method||"embed-size"===t.type||"iframe.resize"===t.context){var r=null;t.data&&t.data.media&&t.data.media.frame_style?(t.data.media.frame_style.split(";").forEach(function(e){if(""!==e.trim()&&e.indexOf(":")>-1){var t=e.split(":");2===t.length&&((r=r||{})[t[0].trim()]=t[1].trim())}}),l(e,r)):"setIframelyEmbedData"===t.method&&l(e,null);var i=t.data&&t.data.media;!i&&t.height&&(i={height:t.height,"max-width":"keep"}),function(e,t){if(t&&Object.keys(t).length>0&&e){var r=function(e){var t=e.iframe&&e.iframe.style.border||e.aspectWrapper&&e.aspectWrapper.style.border,r=t&&t.match(/(\d+)px/)||0;return r&&(r=parseInt(r[1]),r*=2),r}(e),i=window.getComputedStyle&&window.getComputedStyle(e.iframe).getPropertyValue("height"),o=t["max-width"];"number"==typeof o&&(o+=r),n.setStyles(e.maxWidthWrapper,{"max-width":o,"min-width":t["min-width"]&&t["min-width"]+r,width:t.width&&t.width+r}),t.scrolling&&e.iframe&&e.iframe.setAttribute("scrolling",t.scrolling);var l=t["aspect-ratio"];(l||t.height)&&n.setStyles(e.aspectWrapper,{paddingBottom:l?Math.round(1e5/l)/1e3+"%":0,paddingTop:l&&t["padding-bottom"],height:l?0:t.height&&t.height+r});var c=window.getComputedStyle&&window.getComputedStyle(e.iframe).getPropertyValue("height");i&&i!==c&&a.triggerAsync("heightChanged",e.iframe,i,c)}}(e,i)}});var i={border:"","border-radius":"","box-shadow":"",overflow:""},o={border:"0","border-radius":"","box-shadow":"",overflow:""};function l(e,t){t&&e&&e.iframe?t["border-radius"]?(t.overflow="hidden",n.setStyles(e.aspectWrapper,t)):n.setStyles(e.iframe,t):!t&&e&&e.iframe&&(n.setStyles(e.aspectWrapper,i),n.setStyles(e.iframe,o))}}},__webpack_module_cache__={};function __webpack_require__(e){var t=__webpack_module_cache__[e];if(void 0!==t)return t.exports;var r=__webpack_module_cache__[e]={exports:{}};return __webpack_modules__[e](r,r.exports,__webpack_require__),r.exports}__webpack_require__.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(e){if("object"==typeof window)return window}}();var __webpack_exports__={};(()=>{__webpack_require__(331);var e=__webpack_require__(774);e._loaded||(e._loaded=!0,__webpack_require__(54),__webpack_require__(912),__webpack_require__(56),__webpack_require__(908),__webpack_require__(472),__webpack_require__(679),__webpack_require__(573),__webpack_require__(324),__webpack_require__(648),__webpack_require__(850),__webpack_require__(612),__webpack_require__(742),__webpack_require__(916),__webpack_require__(291),__webpack_require__(448),e.trigger("init"))})()})(); \ No newline at end of file +(function(){function e(){let e=()=>{};return{config:{},on:e,trigger:e,triggerAsync:e,load:e,unload:e,configure:e,extendOptions:e,setTheme:e,cancelWidget:e,openHref:e,addEventListener:e,isTouch:()=>!1,findIframe:()=>void 0,getElementComputedStyle:()=>void 0,buildOptionsForm:e}}var t=typeof window>`u`?e():window.iframely=window.iframely||{};t.config=t.config||{},typeof document<`u`&&(e=>{(document.readyState===`complete`||document.readyState===`interactive`)&&setTimeout(e,0),document.addEventListener(`DOMContentLoaded`,e)})(()=>{(t.config.autorun===void 0||t.config.autorun!==!1)&&t.trigger(`load`)});function n(){t.VERSION=1,t.ASPECT_WRAPPER_CLASS=`iframely-responsive`,t.MAXWIDTH_WRAPPER_CLASS=`iframely-embed`,t.LOADER_CLASS=`iframely-loader`,t.DOMAINS=[`cdn.iframe.ly`,`iframe.ly`,`if-cdn.com`,`iframely.net`],t.CDN=t.CDN||t.DOMAINS[0],t.BASE_RE=/^(?:https?:)?\/\/[^/]+/i,t.ID_RE=/^(?:https?:)?\/\/[^/]+\/(\w+-?\w+)(?:\?.*)?$/,t.SCRIPT_RE=/^(?:https?:|file:\/)?\/\/[^/]+(?:.+)?\/(?:embed|iframely)\.js(?:[^/]+)?$/i,t.CDN_RE=/^(?:https?:)?\/\/([^/]+)\/(?:embed|iframely)\.js(?:[^/]+)?$/i,t.SUPPORTED_QUERY_STRING=[`api_key`,`key`,`iframe`,`html5`,`playerjs`,`align`,`language`,`media`,`maxwidth`,`maxheight`,`lazy`,`import`,`parent`,`shadow`,`click_to_play`,`autoplay`,`mute`,`card`,`consent`,`theme`,/^_.+/],t.SUPPORTED_THEMES=[`auto`,`light`,`dark`],t.LAZY_IFRAME_SHOW_TIMEOUT=3e3,t.LAZY_IFRAME_FADE_TIMEOUT=200,t.CLEAR_WRAPPER_STYLES_TIMEOUT=3e3,t.RECOVER_HREFS_ON_CANCEL=!1,t.SHADOW=`iframely-shadow`,t.SUPPORT_IFRAME_LOADING_ATTR=!0}var r=e=>{window.requestAnimationFrame(e)},i={};function a(e,n,a){(i[e]||[]).forEach(e=>{n?r(()=>{e.apply(t,a)}):e.apply(t,a)}),e===`init`&&(i[e]=[])}function o(){t.on=(e,t)=>{(i[e]=i[e]||[]).push(t)},t.trigger=(e,...t)=>{a(e,!1,t)},t.triggerAsync=(e,...t)=>{a(e,!0,t)}}function s(e){window.addEventListener(`message`,t=>{let n;try{typeof t.data==`string`?n=JSON.parse(t.data):typeof t.data==`object`&&(n=t.data)}catch{if(typeof t.data==`string`){let e=t.data.match(/heightxPYMx(\d+)/);e&&(n={method:`resize`,height:parseInt(e[1])+1,domains:`all`})}}e(t,n)},!1)}function c(e,t){let n;for(let r=0;r{let t=l(document,e);return t||=u(document,e),t},s((e,n)=>{if(n&&(n.method||n.type||n.context)){let r=t.findIframe({contentWindow:e.source,src:n.src||n.context,domains:n.domains!==`all`&&t.DOMAINS.concat(t.CDN)});if(r){let e=h(r);e&&n.url&&(e.url=n.url),t.trigger(`message`,e,n)}}})}function f(e,t,n){typeof e==`object`&&(e.context=document.location.href);let r=JSON.stringify(e);t||=`*`,n||=window.parent,n.postMessage(r,t.replace(/([^:]+:\/\/[^/]+).*/,`$1`))}function p(){t.on(`init`,()=>{t.configure(x()),v(),t.config.theme&&t.setTheme(t.config.theme),S(t.DOMAINS.concat(t.CDN.replace(/^https?:\/\//,``)))}),t.load=function(...e){t.trigger(`load`,...e)},t.unload=e=>{let n=t.DOMAINS.concat(t.CDN.replace(/^https?:\/\//,``)),r=e||document,i=`iframe[src*="`+n.join(`"], iframe[src*="`)+`"], iframe[data-iframely-url]`,a=r.querySelectorAll(i);for(let e=0;ewindow.getComputedStyle(e).getPropertyValue(t),t.configure=e=>{e&&Object.keys(e).forEach(n=>{let r=e[n]===0||e[n]===`0`||e[n]===!1||e[n]===`false`?!1:e[n]===1||e[n]===`1`||e[n]===!0||e[n]===`true`||e[n];t.config[n]!==!1&&(t.config[n]=r)})}}function m(e,n){let r=e.parentNode;if(!r||r.nodeName!==`DIV`||C(r)>2||n&&r.getAttribute(`class`)!==t.ASPECT_WRAPPER_CLASS||!n&&r.style.position!==`relative`&&r.getAttribute(`class`)!==t.ASPECT_WRAPPER_CLASS)return;let i=r.parentNode;if(!(!i||i.nodeName!==`DIV`||C(i)>1||n&&i.getAttribute(`class`)&&i.getAttribute(`class`).split(` `).indexOf(t.MAXWIDTH_WRAPPER_CLASS)===-1||!n&&i.getAttribute(`class`)&&!i.getAttribute(`class`).match(/iframely/i)))return{aspectWrapper:r,maxWidthWrapper:i}}function ee(e){let n=e.parentNode,r=document.createElement(`div`);r.className=t.MAXWIDTH_WRAPPER_CLASS;let i=document.createElement(`div`);return i.className=t.ASPECT_WRAPPER_CLASS,r.appendChild(i),n.insertBefore(r,e),{aspectWrapper:i,maxWidthWrapper:r}}function h(e){let t=m(e);if(!t)return;let n={iframe:e,aspectWrapper:t.aspectWrapper,maxWidthWrapper:t.maxWidthWrapper},r=e.getAttribute(`src`);if(e.nodeName===`A`&&e.hasAttribute(`href`))n.url=e.getAttribute(`href`);else if(r&&/url=/.test(r)){let e=T(r);e.url&&(n.url=e.url)}return n}function g(e,n){e&&Object.keys(n).forEach(r=>{let i=n[r];(typeof i==`number`||typeof i==`string`&&/^(\d+)?\.?(\d+)$/.test(i))&&(i+=`px`);let a=e.style,o=a[r];t.getElementComputedStyle(e,r)!=i&&!(e.className==`iframely-responsive`&&r===`paddingBottom`&&!o&&/^56\.2\d+%$/.test(i))&&!(r===`max-width`&&i===`keep`)&&(a[r]=i||``)})}function _(e){t.config.nonce&&(e.nonce=t.config.nonce)}function v(){let e=`iframely-styles`,t=document.getElementById(e);t||(t=document.createElement(`style`),t.id=e,_(t),t.innerHTML=`.iframely-responsive{top:0;left:0;width:100%;height:0;position:relative;padding-bottom:56.25%;box-sizing:border-box;}.iframely-responsive>*{top:0;left:0;width:100%;height:100%;position:absolute;border:0;box-sizing:border-box;}`,document.getElementsByTagName(`head`)[0].appendChild(t))}function y(e,t){let n=``;return Object.keys(t).forEach(r=>{let i=t[r];if(Array.isArray(i)){let e=i.map(e=>r+`=`+encodeURIComponent(e));n+=`&`+e.join(`&`)}else i!==void 0&&e.indexOf(r+`=`)===-1&&(typeof i==`boolean`&&r.charAt(0)!==`_`&&(i=+!!i),n+=`&`+r+`=`+encodeURIComponent(i))}),e+(n===``?``:(e.indexOf(`?`)>-1?`&`:`?`)+n.replace(/^&/,``))}function b(e,n,r){let i=e;if(/^(https?:)?\/\//i.test(e)||(i=(n&&n.CDN||t.CDN)+i,n&&delete n.CDN),/^(?:https?:)?\/\//i.test(i)||(i=`//`+i),n&&(i=y(i,n)),r&&r.length){let e={},n=Object.keys(t.config);for(let i=0;i0)return e}}return{}}function S(e){let n=document.querySelectorAll(`iframe[src*="`+(e||t.DOMAINS).join(`"], iframe[src*="`)+`"]`);for(let e=0;e{t.forEach(t=>{f({method:`intersection`,entry:{isIntersecting:t.isIntersecting},options:e},`*`,t.target.contentWindow)})},ne(e)),D[t]=n),n}function ne(e){let t={};return e&&e.threshold&&(t.threshold=e.threshold),e&&e.margin&&(t.rootMargin=e.margin+`px `+e.margin+`px `+e.margin+`px `+e.margin+`px`),t}function O(){t.on(`init`,()=>{t.configure({intersection:1})}),t.on(`message`,(e,t)=>{if(t.method===`send-intersections`&&e.iframe){let n=t.options;n||={margin:1e3},te(n).observe(e.iframe)}}),t.on(`unload-widget`,e=>{Object.values(D).forEach(t=>t.unobserve(e.iframe))}),t.on(`unload`,e=>{e||Object.keys(D).forEach(e=>{D[e].disconnect(),delete D[e]})})}function k(e,t){f({method:`setTheme`,data:t},`*`,e.contentWindow)}function A(e,t){let n=e.getElementsByTagName(`iframe`);for(let e=0;e{e&&t.SUPPORTED_THEMES.indexOf(e)>-1?n?n.tagName===`IFRAME`?k(n,e):A(n,e):(t.configure({theme:e}),A(document,e),t.trigger(`set-theme`,e)):console.warn(`Using iframely.setTheme with not supported theme: "`+e+`". Supported themes are: `+t.SUPPORTED_THEMES.join(`, `))}}var M={};function re(){t.on(`load`,e=>{if(!e&&t.config.import!==!1&&oe()&&!t.import){let e=document.querySelectorAll(`a[data-iframely-url]:not([data-import-uri])`);e.length>1&&ie(e)}}),t.on(`load`,(e,t)=>{if(e&&!(e instanceof Element)&&e.uri&&(e.html||e.cancel)){let n=M[e.uri];if(n)for(let r=0;r{t.trigger(`import-loaded`,e),e.widgets.forEach(n=>{t.trigger(`load`,n,e)}),N()},t.isTouch=()=>`ontouchstart`in window||navigator.maxTouchPoints>0,t.on(`import-widget-ready`,P),t.on(`unload`,e=>{e||(delete t.import,Object.keys(M).forEach(e=>{delete M[e]}))}),t.addEventListener||=(e,t,n)=>{e&&e.addEventListener(t,n,!1)}}function ie(e){let n=E(),r=[],i=[],a=null;function o(e,t){M[e]||(M[e]=[]),M[e].push(t)}function s(e){let n=e.getAttribute(`data-iframely-url`),s=n.match(t.ID_RE),c=s&&s[1],l=T(n,t.SUPPORTED_QUERY_STRING.concat(`url`)),u=l.url;delete l.url;let d=l.import===`0`||l.import===`false`||l.playerjs===`1`||l.playerjs===`true`;if(!d){let e=n.match(t.BASE_RE);l.CDN=e&&e[0],a?JSON.stringify(l,Object.keys(l).sort())!==JSON.stringify(a,Object.keys(a).sort())&&(d=!0):a=l}d?t.trigger(`load`,e):c?(e.setAttribute(`data-import-uri`,c),i.indexOf(c)===-1&&i.push(c),o(c,e)):(u||=e.getAttribute(`href`),(a.key||a.api_key||t.config.api_key||t.config.key)&&u?(e.setAttribute(`data-import-uri`,u),r.indexOf(u)===-1&&r.push(u),o(u,e)):t.trigger(`load`,e))}for(let t=0;t0||i.length>0?(a||={},a.touch=t.isTouch(),a.flash=!1,a.app=1,t.config.theme&&(a.theme=t.config.theme),r.length>0&&(a.uri=r),i.length>0&&(a.ids=i.join(`&`)),a.v=t.VERSION,n.src=b(`/api/import/v2`,a,t.SUPPORTED_QUERY_STRING),n.onerror=()=>{N()},document.head.appendChild(n),t.import=n):(N(),t.trigger(`load`))}function ae(e,n,r){let i=e.cancel,a=e.shadow,o=e.renderEvent,s=m(n,!0);if(i)t.cancelWidget(h(n)||{maxWidthWrapper:n,iframe:n,url:n.getAttribute(`href`)});else{let i=document.createElement(`div`);i.innerHTML=e.html;let c,l;if(s&&!o?(c=s.aspectWrapper.parentNode,l=s.aspectWrapper,s.maxWidthWrapper.removeAttribute(`style`)):(c=n.parentNode,l=n),a){let n=document.createElement(`div`),a=n.attachShadow({mode:`open`});a.appendChild(i);let o={shadowRoot:a,shadowContainer:n,container:c,context:e.context,stylesIds:e.stylesIds,stylesDict:r.commonShadowStyles};t.trigger(`import-shadow-widget-before-render`,o),c.insertBefore(n,l),t.trigger(`import-shadow-widget-after-render`,o)}else c.insertBefore(i,l),F(i);c.removeChild(l),o&&setTimeout(()=>{P(c)},t.CLEAR_WRAPPER_STYLES_TIMEOUT)}}function N(){delete t.import;let e=document.querySelectorAll(`a[data-iframely-url][data-import-uri]`);for(let n=0;n4&&(n=null);let i=n&&n.parentNode;i&&i.getAttribute(`class`)&&i.getAttribute(`class`).split(` `).indexOf(t.MAXWIDTH_WRAPPER_CLASS)>-1&&(n.removeAttribute(`style`),n.removeAttribute(`class`),i.removeAttribute(`style`))}function F(e){function t(e,t){return!!e.nodeName&&e.nodeName.toUpperCase()===t.toUpperCase()}function n(t){let n=t.text||t.textContent||t.innerHTML||``,r=E();r.type=`text/javascript`;for(let e=0;e{if(e&&e.nodeName&&typeof n==`string`){let r=document.createElement(`a`);r.setAttribute(`href`,n),e.appendChild(r),t.trigger(`load`,r)}}),t.on(`load`,e=>{if(!e&&!t.import){let e=document.querySelectorAll(`a[data-iframely-url]:not([data-import-uri])`);for(let n=0;n{e&&e.nodeName===`A`&&(e.getAttribute(`data-iframely-url`)||e.getAttribute(`href`))&&!e.hasAttribute(`data-import-uri`)&&L(e)})}function L(e){if(!e.getAttribute(`data-iframely-url`)&&!e.getAttribute(`href`))return;let n,r=e.getAttribute(`data-iframely-url`);if(r&&/^((?:https?:)?\/\/[^/]+)\/\w+/i.test(r))n=b(r,{v:t.VERSION,app:1,theme:t.config.theme});else if((t.config.api_key||t.config.key)&&t.CDN){if(!e.getAttribute(`href`)){console.warn(`Iframely cannot build embeds: "href" attribute missing in`,e);return}n=b(`/api/iframe`,{url:e.getAttribute(`href`),v:t.VERSION,app:1,theme:t.config.theme},t.SUPPORTED_QUERY_STRING)}else console.warn(`Iframely cannot build embeds: api key is required as query-string of embed.js`);if(!n)e.removeAttribute(`data-iframely-url`);else{let r=document.createElement(`iframe`);r.setAttribute(`allowfullscreen`,``),r.setAttribute(`allow`,`autoplay *; encrypted-media *; ch-prefers-color-scheme *`),e.hasAttribute(`data-img`)&&r.setAttribute(`data-img`,e.getAttribute(`data-img`));let i=e.hasAttribute(`data-lazy`)||e.hasAttribute(`data-img`)||/&lazy=1/.test(n)||t.config.lazy,a=e.textContent;a&&a!==``&&(r.textContent=a);let o=m(e,!0);if(o)for(;o.aspectWrapper.lastChild;)o.aspectWrapper.removeChild(o.aspectWrapper.lastChild);else o=ee(e),e.parentNode.removeChild(e);o.aspectWrapper.appendChild(r),i?(r.setAttribute(`data-iframely-url`,n),t.trigger(`load`,r)):(r.setAttribute(`src`,n),t.trigger(`iframe-ready`,r))}}function R(){t.on(`load`,e=>{if(e&&e.nodeName===`IFRAME`&&e.hasAttribute(`data-iframely-url`)&&e.hasAttribute(`data-img`)&&!e.getAttribute(`src`)){let n=e.getAttribute(`data-img`);e.removeAttribute(`data-img`),e.setAttribute(`data-img-created`,``);let r=h(e),i=e.getAttribute(`data-iframely-url`);r&&(z(r,i,n),i=y(i,{img:1}),e.setAttribute(`data-iframely-url`,i),new q(r)),t.trigger(`load`,e)}}),t.on(`message`,(e,t)=>{if(!e)return;let n;t.method===`widgetRendered`&&(H(e),n=G(e),n?.deactivate()),t.method===`begin-waiting-widget-render`&&(n=G(e),n?.clearLoadingTimeout()),t.method===`end-waiting-widget-render`&&(n=G(e),n?.registerLoadingTimeout())}),t.on(`unload-widget`,e=>{G(e)?.deactivate()})}function z(e,n,r){let i;if(r&&/^(https?:)?\/\//.test(r))i=r;else{let e=T(n),r={};for(let t in e)t.indexOf(`_`)===0&&(r[t]=e[t]);if(e.media&&(r.media=e.media),n.match(/\/api\/iframe/))i=b(n.match(/^(.+)\/api\/iframe/i)[1]+`/api/thumbnail`,Object.assign({url:e.url,api_key:e.api_key,key:e.key},r));else if(n.match(t.ID_RE))i=b(n.replace(/^((?:https?:)?\/\/[^/]+\/(\w+-?\w+))(?:\?.*)?$/,`$1/thumbnail`),r);else return}let a=document.createElement(`div`);g(a,{position:`absolute`,width:`100%`,height:`100%`,backgroundImage:`url('`+i+`')`,backgroundSize:`cover`,backgroundPosition:`center`});let o=document.createElement(`div`);o.setAttribute(`class`,t.LOADER_CLASS),a.appendChild(o);let s=t.getElementComputedStyle(e.aspectWrapper,`padding-top`),c=t.getElementComputedStyle(e.aspectWrapper,`padding-bottom`),l=s&&s.match(/^(\d+)px$/);if(l&&parseInt(l[1])&&c){let t=document.createElement(`div`);g(t,{top:`-`+s,width:`100%`,height:0,position:`relative`,paddingBottom:c}),t.appendChild(a),e.aspectWrapper.appendChild(t)}else e.aspectWrapper.appendChild(a)}function B(e,t){let n=0;for(let r=0;r1&&B(1,e.aspectWrapper);t&&t.nodeName===`DIV`&&e.aspectWrapper.removeChild(t)}var U=[];function W(e){let t=0;for(;t{this.iframeOnLoad()}),this.registerLoadingTimeout(),U.push(this)}iframeOnLoad(){this.loadCount++,this.loadCount===2&&(this.deactivate(),setTimeout(()=>{H(this.widget)},t.LAZY_IFRAME_FADE_TIMEOUT))}deactivate(){this.clearLoadingTimeout(),K(this.widget)}clearLoadingTimeout(){this.timeoutId&&clearTimeout(this.timeoutId),this.timeoutId=null}registerLoadingTimeout(){this.timeoutId||=setTimeout(()=>{this.iframeOnLoad()},t.LAZY_IFRAME_SHOW_TIMEOUT)}};function se(){t.on(`load`,e=>{if(!e){let e=document.querySelectorAll(`iframe[data-iframely-url]`);for(let n=0;n{e&&e.nodeName===`IFRAME`&&e.hasAttribute(`data-iframely-url`)&&!e.hasAttribute(`data-img`)&&!e.getAttribute(`src`)&&ce(e)})}function ce(e){let n=h(e),r=e.getAttribute(`data-iframely-url`),i=e.hasAttribute(`data-img-created`)||e.hasAttribute(`data-img`),a=!i&&t.SUPPORT_IFRAME_LOADING_ATTR;if(n&&r){let e={v:t.VERSION,app:1,theme:t.config.theme};!a&&t.config.intersection&&(e.lazy=1),r=b(r,e)}a&&e.setAttribute(`loading`,`lazy`),i&&t.SUPPORT_IFRAME_LOADING_ATTR&&e.setAttribute(`loading`,`edge`),e.setAttribute(`src`,r||``),e.removeAttribute(`data-iframely-url`),t.trigger(`iframe-ready`,e)}function le(){t.on(`message`,(e,n)=>{n.method===`cancelWidget`&&t.cancelWidget(e)}),t.cancelWidget=e=>{if(!e){console.warn(`iframely.cancelWidget called without widget param`);return}function n(e,t){let n=!1;for(;!n&&e.parentNode;)e=e.parentNode,n=!!e.className&&typeof e.className==`string`&&e.className.split(` `).indexOf(t)>=0;return n&&e}let r=e.maxWidthWrapper&&e.maxWidthWrapper.parentNode,i=e.maxWidthWrapper;if(t.config&&t.config.parent){let a=n(e.maxWidthWrapper,String(t.config.parent));a&&(r=a.parentNode,i=a)}if(e.url){let n=e.iframe&&e.iframe.textContent;t.triggerAsync(`cancel`,e.url,r,n,i.nextSibling)}r.removeChild(i)}}var ue={border:``,"border-radius":``,"box-shadow":``,overflow:``},de={border:`0`,"border-radius":``,"box-shadow":``,overflow:``};function fe(){t.on(`message`,(e,t)=>{if(t.method===`setIframelyWidgetSize`||t.method===`resize`||t.method===`setIframelyEmbedData`||t.type===`embed-size`||t.context===`iframe.resize`){let n=null;t.data&&t.data.media&&t.data.media.frame_style?(t.data.media.frame_style.split(`;`).forEach(e=>{if(e.trim()!==``&&e.indexOf(`:`)>-1){let t=e.split(`:`);t.length===2&&(n||={},n[t[0].trim()]=t[1].trim())}}),J(e,n)):t.method===`setIframelyEmbedData`&&J(e,null);let r=t.data&&t.data.media;!r&&t.height&&(r={height:t.height,"max-width":`keep`}),me(e,r)}})}function J(e,t){t&&e&&e.iframe?t[`border-radius`]?(t.overflow=`hidden`,g(e.aspectWrapper,t)):g(e.iframe,t):!t&&e&&e.iframe&&(g(e.aspectWrapper,ue),g(e.iframe,de))}function pe(e){let t=e.iframe&&e.iframe.style.border||e.aspectWrapper&&e.aspectWrapper.style.border,n=t&&t.match(/(\d+)px/);return n?parseInt(n[1])*2:0}function me(e,n){if(n&&Object.keys(n).length>0&&e){let r=pe(e),i=window.getComputedStyle(e.iframe).getPropertyValue(`height`),a=n[`max-width`];typeof a==`number`&&(a+=r),g(e.maxWidthWrapper,{"max-width":a,"min-width":n[`min-width`]&&n[`min-width`]+r,width:n.width&&n.width+r}),n.scrolling&&e.iframe&&e.iframe.setAttribute(`scrolling`,n.scrolling);let o=n[`aspect-ratio`];(o||n.height)&&g(e.aspectWrapper,{paddingBottom:o?Math.round(1e3*100/o)/1e3+`%`:0,paddingTop:o&&n[`padding-bottom`],height:o?0:n.height&&n.height+r});let s=window.getComputedStyle(e.iframe).getPropertyValue(`height`);i&&i!==s&&t.triggerAsync(`heightChanged`,e.iframe,i,s)}}function he(){t.on(`message`,(e,n)=>{(n.method===`open-href`||n.method===`click`)&&t.trigger(n.method,n.href)}),t.openHref||=e=>{e.indexOf(window.location.origin)===0?window.location.href=e:window.open(e,`_blank`,`noopener`)},t.on(`open-href`,e=>{t.triggerAsync(`click`,e),t.openHref(e)})}function ge(){t.on(`message`,(e,n)=>{n.method===`setIframelyEmbedOptions`&&t.trigger(`options`,e,n.data)})}function _e(){t.widgets=t.widgets||{},t.widgets.load=t.load,t.extendOptions=t.configure,t.events||(t.events={},t.events.on=t.on,t.events.trigger=t.trigger),t.on(`cancel`,(e,n,r,i)=>{if(t.RECOVER_HREFS_ON_CANCEL&&!r&&(r=e),e&&n&&r&&r!==``){let t=document.createElement(`a`);t.setAttribute(`href`,e),t.setAttribute(`target`,`_blank`),t.setAttribute(`rel`,`noopener`),t.textContent=r,i?n.insertBefore(t,i):n.appendChild(t)}})}var Y=/^_./,X=(e,t)=>t&&typeof t==`function`&&e&&t(e)||e;function ve(e,t){if(!e)return[];e=Object.assign({},e),delete e.query;let n=[],r=Object.keys(e),i=0;if(r.forEach(r=>{let a={},o,s=e[r];s.key=r;let c=!1,l=s.values?Object.keys(s.values):void 0,u,d;if(l&&l.length===1&&(c=!0,u=l[0],d=s.values[u]),a.label=X(d||s.label,t),a.key=s.key,c||typeof s.value==`boolean`)c?a.checked=u===s.value||!u&&!s.value:a.checked=s.value,i++,n.push({type:`checkbox`,context:a,order:+!Y.test(r),getQuery:e=>{let t;t=c?e?u:``:e;let n={};return c?t===``||(n[s.key]=t):n[s.key]=e,n}});else if((typeof s.value==`number`||typeof s.value==`string`)&&!s.values){let e=s.range&&typeof s.range.min==`number`&&typeof s.range.max==`number`,i=typeof s.value==`number`;a.value=s.value,o=e=>{let t={};return e===``||(t[s.key]=e),t},e?(a.min=s.range.min,a.max=s.range.max,n.push({type:`range`,context:a,order:9,getQuery:o})):(a.placeholder=X(s.placeholder||``,t),a.inputType=i?`number`:`text`,n.push({type:`text`,context:a,order:/start/i.test(r)?7:8,getQuery:o}))}else if(s.values)if(a.value=s.value+``,o=e=>{let t={};return e===``||(t[s.key]=e),t},Object.keys(s.values).length<=3){s.label?a.label=X(s.label,t):a.label=!1;let e=0,i=!1,c=Object.values(s.values);for(;e8,e++;a.inline=!i,a.items=[],Object.keys(s.values).forEach((e,n)=>{a.items.push({id:a.key+`-`+n,value:e,label:X(s.values[e],t),checked:a.value===e})}),n.push({type:`radio`,context:a,order:i?-3:/theme/.test(r)?-1:-2,getQuery:o})}else a.items=[],Object.keys(s.values).forEach(e=>{a.items.push({value:e,label:X(s.values[e],t),checked:a.value===e})}),n.push({type:`select`,context:a,order:5,getQuery:o})}),n.sort((e,t)=>e.order-t.order),n.forEach(e=>{delete e.order}),i>0){let e=[],t;return n.forEach((r,a)=>{if(r.type===`checkbox`){let o=i>2&&a>0&&!Y.test(r.context.key)&&n[a-1].type===`checkbox`&&Y.test(n[a-1].context.key);(!t||o)&&(t=[],e.push({type:`group`,context:{elements:t}})),t.push(r)}else e.push(r)}),e}else return n}var Z={checkbox:{getValue:e=>e[0].checked},text:{getValue:e=>{let t=e[0],n=t.value;return t.type===`number`&&(n=parseInt(n),isNaN(n)&&(n=``)),n},customEvents:(e,n)=>{let r=e[0];t.addEventListener(r,`click`,()=>{r.select()}),t.addEventListener(r,`blur`,n),t.addEventListener(r,`keyup`,e=>{e.keyCode===13&&n()})}},radio:{getValue:e=>{let t;return Array.prototype.forEach.call(e,e=>{e.checked&&(t=e)}),t.value}}},Q={};function ye(e){let n=e.options,r=e.formContainer;if(!r){console.warn(`No formContainer in form-builder options`,e);return}if(!n){r.innerHTML=``;return}let i=ve(n,e.translator),a=e.id,o=e.renderer,s=Q[a]=Q[a]||{};Object.keys(n).forEach(e=>{(!n.query||n.query.indexOf(e)===-1)&&(s[e]=n[e].value)});function c(){let e={},t=n=>{n.forEach(n=>{if(n.context&&n.context.elements)t(n.context.elements);else if(n.inputs){let t=Z[n.type],r;r=t&&t.getValue?t.getValue(n.inputs):n.inputs[0].value,Object.assign(e,n.getQuery(r))}})};return t(i),e}function l(){let e=c();Object.keys(s).forEach(t=>{(s[t]===e[t]||e[t]===void 0)&&delete e[t]}),t.trigger(`options-changed`,a,r,e)}let u=e=>{let t=``;return e.forEach(e=>{e.context&&e.context.elements&&(e.context.elementsHtml=u(e.context.elements)),t+=o(e.type,e.context||{})}),t};r.innerHTML=u(i);let d=e=>{e.forEach(e=>{if(e.context&&e.context.elements)d(e.context.elements);else{let n=Z[e.type];if(e.context){let i=r.querySelectorAll(`[name="`+e.context.key+`"]`);e.inputs=i,i.length>0?n&&n.customEvents?n.customEvents(i,l):i.forEach(e=>{t.addEventListener(e,`change`,l)}):console.warn(`No inputs found for option`,e.context.key)}}})};d(i)}var be={"&":`&`,"<":`<`,">":`>`,'"':`"`,"'":`'`},$=e=>e==null?``:String(e).replace(/[&<>"']/g,e=>be[e]),xe={checkbox:e=>` +
+ + +
`,group:e=>` +
+
${e.elementsHtml??``}
+
`,radio:e=>` +
+ ${e.label?``:``} +
+ ${(e.items||[]).map(t=>` +
+ + +
`).join(``)} +
+
`,range:e=>` +
+ +
+ +
+
`,select:e=>` +
+ +
+ +
+
`,text:e=>` +
+ +
+ +
+
`},Se=(e,t)=>xe[e](t);function Ce(){t.buildOptionsForm=(e,n,r,i)=>{if(typeof t.trigger!=`function`||typeof t.addEventListener!=`function`){console.warn(`iframely.buildOptionsForm requires embed.js (or embed-options.js) to be loaded`);return}ye({id:e,formContainer:n,options:r,renderer:Se,translator:i})}}typeof window<`u`&&!t._loaded&&(t._loaded=!0,n(),o(),p(),d(),O(),j(),re(),I(),R(),se(),le(),fe(),he(),ge(),_e(),Ce(),t.trigger(`init`))})(); \ No newline at end of file diff --git a/dist/embed.js b/dist/embed.js index 75718c6..6a32172 100644 --- a/dist/embed.js +++ b/dist/embed.js @@ -1,255 +1,1125 @@ -/* - * ATTENTION: The "eval" devtool has been used (maybe by default in mode: "development"). - * This devtool is neither made for production nor for readable output files. - * It uses "eval()" calls to create a separate source file in the browser devtools. - * If you are trying to read the output file, select a different devtool (https://webpack.js.org/configuration/devtool/) - * or disable the default devtool with "devtool: false". - * If you are looking for production-ready output files, see mode: "production" (https://webpack.js.org/configuration/mode/). - */ -/******/ (() => { // webpackBootstrap -/******/ var __webpack_modules__ = ({ +(function() { -/***/ "./ahref.js" -/*!******************!*\ - !*** ./ahref.js ***! - \******************/ -(__unused_webpack_module, __unused_webpack_exports, __webpack_require__) { -eval("{var utils = __webpack_require__(/*! ./utils */ \"./utils.js\");\nvar iframely = __webpack_require__(/*! ./iframely */ \"./iframely.js\");\n\niframely.on('load', function(container, href) {\n if (container && container.nodeName && typeof href === 'string') {\n var a = document.createElement('a');\n a.setAttribute('href', href);\n container.appendChild(a);\n iframely.trigger('load', a);\n }\n});\n\niframely.on('load', function(el) {\n\n if (!el && !iframely.import) { \n\n var elements = document.querySelectorAll('a[data-iframely-url]:not([data-import-uri])');\n for(var i = 0; i < elements.length; i++) {\n iframely.trigger('load', elements[i]);\n }\n }\n \n});\n\niframely.on('load', function(el) {\n\n if (el && el.nodeName === 'A' && (el.getAttribute('data-iframely-url') || el.getAttribute('href')) && !el.hasAttribute('data-import-uri')) {\n unfurl(el);\n }\n \n});\n\nfunction unfurl(el) {\n if (!el.getAttribute('data-iframely-url') && !el.getAttribute('href')) {\n return; // isn't valid\n }\n var src;\n\n var dataIframelyUrl = el.getAttribute('data-iframely-url');\n if (dataIframelyUrl && /^((?:https?:)?\\/\\/[^/]+)\\/\\w+/i.test(dataIframelyUrl)) {\n src = utils.getEndpoint(dataIframelyUrl, {\n v: iframely.VERSION,\n app: 1,\n theme: iframely.config.theme\n });\n } else if ((iframely.config.api_key || iframely.config.key) && iframely.CDN) {\n\n if (!el.getAttribute('href')) {\n console.warn('Iframely cannot build embeds: \"href\" attribute missing in', el);\n return;\n }\n\n src = utils.getEndpoint('/api/iframe', {\n url: el.getAttribute('href'),\n v: iframely.VERSION,\n app: 1,\n theme: iframely.config.theme\n }, iframely.SUPPORTED_QUERY_STRING);\n } else {\n console.warn('Iframely cannot build embeds: api key is required as query-string of embed.js');\n }\n\n if (!src) {\n el.removeAttribute('data-iframely-url'); \n } else {\n\n var iframe = document.createElement('iframe');\n\n iframe.setAttribute('allowfullscreen', '');\n iframe.setAttribute('allow', 'autoplay *; encrypted-media *; ch-prefers-color-scheme *');\n\n if (el.hasAttribute('data-img')) {\n iframe.setAttribute('data-img', el.getAttribute('data-img'));\n }\n\n var isLazy = el.hasAttribute('data-lazy') || el.hasAttribute('data-img') || /&lazy=1/.test(src) || iframely.config.lazy;\n\n // support restoring failed links by its text\n var text = el.textContent || el.innerText;\n \n if (text && text !== '') {\n iframe.textContent = text;\n } \n\n var wrapper = utils.getIframeWrapper(el, true);\n \n if (wrapper) {\n\n // Delete all in aspect wrapper.\n while (wrapper.aspectWrapper.lastChild) {\n wrapper.aspectWrapper.removeChild(wrapper.aspectWrapper.lastChild);\n }\n\n } else {\n wrapper = utils.addDefaultWrappers(el);\n\n var parentNode = el.parentNode;\n parentNode.removeChild(el);\n }\n\n wrapper.aspectWrapper.appendChild(iframe);\n\n if (isLazy) {\n \n // send to lazy iframe flow\n iframe.setAttribute('data-iframely-url', src);\n iframely.trigger('load', iframe);\n\n } else {\n\n iframe.setAttribute('src', src);\n iframely.trigger('iframe-ready', iframe);\t\t\t\n }\n\n\n }\n\n\n}\n\n//# sourceURL=webpack:///./ahref.js?\n}"); +//#region src/iframely.ts + function createServerStub() { + const noop = () => {}; + return { + config: {}, + on: noop, + trigger: noop, + triggerAsync: noop, + load: noop, + unload: noop, + configure: noop, + extendOptions: noop, + setTheme: noop, + cancelWidget: noop, + openHref: noop, + addEventListener: noop, + isTouch: () => false, + findIframe: () => void 0, + getElementComputedStyle: () => void 0, + buildOptionsForm: noop + }; + } + var iframely = typeof window === "undefined" ? createServerStub() : window.iframely = window.iframely || {}; + iframely.config = iframely.config || {}; -/***/ }, +//#endregion +//#region src/dom-ready.ts + var DOMReady = (f) => { + if (document.readyState === "complete" || document.readyState === "interactive") setTimeout(f, 0); + document.addEventListener("DOMContentLoaded", f); + }; + if (typeof document !== "undefined") DOMReady(() => { + if (typeof iframely.config.autorun === "undefined" || iframely.config.autorun !== false) iframely.trigger("load"); + }); -/***/ "./const.js" -/*!******************!*\ - !*** ./const.js ***! - \******************/ -(__unused_webpack_module, __unused_webpack_exports, __webpack_require__) { +//#endregion +//#region src/const.ts + function boot$14() { + iframely.VERSION = 1; + iframely.ASPECT_WRAPPER_CLASS = "iframely-responsive"; + iframely.MAXWIDTH_WRAPPER_CLASS = "iframely-embed"; + iframely.LOADER_CLASS = "iframely-loader"; + iframely.DOMAINS = [ + "cdn.iframe.ly", + "iframe.ly", + "if-cdn.com", + "iframely.net" + ]; + iframely.CDN = iframely.CDN || iframely.DOMAINS[0]; + iframely.BASE_RE = /^(?:https?:)?\/\/[^/]+/i; + iframely.ID_RE = /^(?:https?:)?\/\/[^/]+\/(\w+-?\w+)(?:\?.*)?$/; + iframely.SCRIPT_RE = /^(?:https?:|file:\/)?\/\/[^/]+(?:.+)?\/(?:embed|iframely)\.js(?:[^/]+)?$/i; + iframely.CDN_RE = /^(?:https?:)?\/\/([^/]+)\/(?:embed|iframely)\.js(?:[^/]+)?$/i; + iframely.SUPPORTED_QUERY_STRING = [ + "api_key", + "key", + "iframe", + "html5", + "playerjs", + "align", + "language", + "media", + "maxwidth", + "maxheight", + "lazy", + "import", + "parent", + "shadow", + "click_to_play", + "autoplay", + "mute", + "card", + "consent", + "theme", + /^_.+/ + ]; + iframely.SUPPORTED_THEMES = [ + "auto", + "light", + "dark" + ]; + iframely.LAZY_IFRAME_SHOW_TIMEOUT = 3e3; + iframely.LAZY_IFRAME_FADE_TIMEOUT = 200; + iframely.CLEAR_WRAPPER_STYLES_TIMEOUT = 3e3; + iframely.RECOVER_HREFS_ON_CANCEL = false; + iframely.SHADOW = "iframely-shadow"; + iframely.SUPPORT_IFRAME_LOADING_ATTR = true; + } -eval("{var iframely = __webpack_require__(/*! ./iframely */ \"./iframely.js\");\n\niframely.VERSION = 1;\n\niframely.ASPECT_WRAPPER_CLASS = 'iframely-responsive';\niframely.MAXWIDTH_WRAPPER_CLASS = 'iframely-embed';\niframely.LOADER_CLASS = 'iframely-loader';\n\niframely.DOMAINS = ['cdn.iframe.ly', 'iframe.ly', 'if-cdn.com', 'iframely.net'];\niframely.CDN = iframely.CDN || iframely.DOMAINS[0]; // default domain, user or script src can change CDN\n\niframely.BASE_RE = /^(?:https?:)?\\/\\/[^/]+/i;\niframely.ID_RE = /^(?:https?:)?\\/\\/[^/]+\\/(\\w+-?\\w+)(?:\\?.*)?$/;\niframely.SCRIPT_RE = /^(?:https?:|file:\\/)?\\/\\/[^/]+(?:.+)?\\/(?:embed|iframely)\\.js(?:[^/]+)?$/i;\niframely.CDN_RE = /^(?:https?:)?\\/\\/([^/]+)\\/(?:embed|iframely)\\.js(?:[^/]+)?$/i;\n\niframely.SUPPORTED_QUERY_STRING = ['api_key', 'key', 'iframe', 'html5', 'playerjs', 'align', 'language', 'media', 'maxwidth', 'maxheight', 'lazy', 'import', 'parent', 'shadow', 'click_to_play', 'autoplay', 'mute', 'card', 'consent', 'theme', /^_.+/];\n\niframely.SUPPORTED_THEMES = ['auto', 'light', 'dark'];\n\niframely.LAZY_IFRAME_SHOW_TIMEOUT = 3000;\niframely.LAZY_IFRAME_FADE_TIMEOUT = 200;\niframely.CLEAR_WRAPPER_STYLES_TIMEOUT = 3000;\n\niframely.RECOVER_HREFS_ON_CANCEL = false;\n\niframely.SHADOW = 'iframely-shadow';\n\n//# sourceURL=webpack:///./const.js?\n}"); +//#endregion +//#region src/events.ts + var nextTick = (fn) => { + window.requestAnimationFrame(fn); + }; + var callbacksStack = {}; + function trigger(event, async, args) { + (callbacksStack[event] || []).forEach((cb) => { + if (async) nextTick(() => { + cb.apply(iframely, args); + }); + else cb.apply(iframely, args); + }); + if (event === "init") callbacksStack[event] = []; + } + function boot$13() { + iframely.on = (event, cb) => { + (callbacksStack[event] = callbacksStack[event] || []).push(cb); + }; + iframely.trigger = (event, ...args) => { + trigger(event, false, args); + }; + iframely.triggerAsync = (event, ...args) => { + trigger(event, true, args); + }; + } -/***/ }, +//#endregion +//#region src/messaging.ts + function receiveMessage(callback) { + window.addEventListener("message", (e) => { + let message; + try { + if (typeof e.data === "string") message = JSON.parse(e.data); + else if (typeof e.data === "object") message = e.data; + } catch { + if (typeof e.data === "string") { + const m = e.data.match(/heightxPYMx(\d+)/); + if (m) message = { + method: "resize", + height: parseInt(m[1]) + 1, + domains: "all" + }; + } + } + callback(e, message); + }, false); + } + function findIframeByContentWindow(iframes, contentWindow) { + let foundIframe; + for (let i = 0; i < iframes.length && !foundIframe; i++) { + const iframe = iframes[i]; + if (iframe.contentWindow === contentWindow) foundIframe = iframe; + } + return foundIframe; + } + function findIframeInElement(element, options) { + let foundIframe, iframes; + if (options.src) { + iframes = element.querySelectorAll("iframe[src*=\"" + options.src.replace(/^https?:/, "") + "\"]"); + foundIframe = findIframeByContentWindow(iframes, options.contentWindow); + } + if (!foundIframe) { + iframes = options.domains ? element.querySelectorAll("iframe[src*=\"" + (options.domains || iframely.DOMAINS).join("\"], iframe[src*=\"") + "\"]") : element.querySelectorAll("iframe"); + foundIframe = findIframeByContentWindow(iframes, options.contentWindow); + } + return foundIframe; + } + function findIframeInShadowRoots(element, options) { + let foundIframe; + const className = "." + (iframely.config.shadow || iframely.SHADOW); + const shadowRoots = element.querySelectorAll(className); + for (let i = 0; i < shadowRoots.length && !foundIframe; i++) { + const shadowRoot = shadowRoots[i].shadowRoot; + if (shadowRoot) { + foundIframe = findIframeInElement(shadowRoot, options); + if (!foundIframe) foundIframe = findIframeInShadowRoots(shadowRoot, options); + } + } + return foundIframe; + } + function boot$12() { + if (!iframely.findIframe) iframely.findIframe = (options) => { + let foundIframe = findIframeInElement(document, options); + if (!foundIframe) foundIframe = findIframeInShadowRoots(document, options); + return foundIframe; + }; + receiveMessage((e, message) => { + if (message && (message.method || message.type || message.context)) { + const foundIframe = iframely.findIframe({ + contentWindow: e.source, + src: message.src || message.context, + domains: message.domains !== "all" && iframely.DOMAINS.concat(iframely.CDN) + }); + if (foundIframe) { + const widget = getWidget(foundIframe); + if (widget && message.url) widget.url = message.url; + iframely.trigger("message", widget, message); + } + } + }); + } + function postMessage(message, target_url, target) { + if (typeof message === "object") message.context = document.location.href; + const data = JSON.stringify(message); + target_url = target_url || "*"; + target = target || window.parent; + target.postMessage(data, target_url.replace(/([^:]+:\/\/[^/]+).*/, "$1")); + } -/***/ "./deprecated.js" -/*!***********************!*\ - !*** ./deprecated.js ***! - \***********************/ -(__unused_webpack_module, __unused_webpack_exports, __webpack_require__) { +//#endregion +//#region src/utils.ts + function boot$11() { + iframely.on("init", () => { + iframely.configure(parseQueryStringFromScriptSrc()); + defineDefaultStyles(); + if (iframely.config.theme) iframely.setTheme(iframely.config.theme); + requestSizeOfExistingIframes(iframely.DOMAINS.concat(iframely.CDN.replace(/^https?:\/\//, ""))); + }); + iframely.load = function(...args) { + iframely.trigger("load", ...args); + }; + iframely.unload = (el) => { + const domains = iframely.DOMAINS.concat(iframely.CDN.replace(/^https?:\/\//, "")); + const root = el || document; + const selector = "iframe[src*=\"" + domains.join("\"], iframe[src*=\"") + "\"], iframe[data-iframely-url]"; + const iframes = root.querySelectorAll(selector); + for (let i = 0; i < iframes.length; i++) { + const widget = getWidget(iframes[i]); + if (widget) { + iframely.trigger("unload-widget", widget); + widget.maxWidthWrapper.remove(); + } + } + iframely.trigger("unload", el); + }; + iframely.getElementComputedStyle = (el, style) => { + return window.getComputedStyle(el).getPropertyValue(style); + }; + iframely.configure = (options) => { + if (!options) return; + Object.keys(options).forEach((key) => { + const new_value = options[key] === 0 || options[key] === "0" || options[key] === false || options[key] === "false" ? false : options[key] === 1 || options[key] === "1" || options[key] === true || options[key] === "true" ? true : options[key]; + if (iframely.config[key] !== false) iframely.config[key] = new_value; + }); + }; + } + function getIframeWrapper(iframe, checkClass) { + const aspectWrapper = iframe.parentNode; + if (!aspectWrapper || aspectWrapper.nodeName !== "DIV" || nonTextChildCount$1(aspectWrapper) > 2 || checkClass && aspectWrapper.getAttribute("class") !== iframely.ASPECT_WRAPPER_CLASS || !checkClass && aspectWrapper.style.position !== "relative" && aspectWrapper.getAttribute("class") !== iframely.ASPECT_WRAPPER_CLASS) return; + const maxWidthWrapper = aspectWrapper.parentNode; + if (!maxWidthWrapper || maxWidthWrapper.nodeName !== "DIV" || nonTextChildCount$1(maxWidthWrapper) > 1 || checkClass && maxWidthWrapper.getAttribute("class") && maxWidthWrapper.getAttribute("class").split(" ").indexOf(iframely.MAXWIDTH_WRAPPER_CLASS) === -1 || !checkClass && maxWidthWrapper.getAttribute("class") && !maxWidthWrapper.getAttribute("class").match(/iframely/i)) return; + return { + aspectWrapper, + maxWidthWrapper + }; + } + function addDefaultWrappers(el) { + const parentNode = el.parentNode; + const maxWidthWrapper = document.createElement("div"); + maxWidthWrapper.className = iframely.MAXWIDTH_WRAPPER_CLASS; + const aspectWrapper = document.createElement("div"); + aspectWrapper.className = iframely.ASPECT_WRAPPER_CLASS; + maxWidthWrapper.appendChild(aspectWrapper); + parentNode.insertBefore(maxWidthWrapper, el); + return { + aspectWrapper, + maxWidthWrapper + }; + } + function getWidget(iframe) { + const wrapper = getIframeWrapper(iframe); + if (!wrapper) return; + const widget = { + iframe, + aspectWrapper: wrapper.aspectWrapper, + maxWidthWrapper: wrapper.maxWidthWrapper + }; + const src = iframe.getAttribute("src"); + if (iframe.nodeName === "A" && iframe.hasAttribute("href")) widget.url = iframe.getAttribute("href"); + else if (src && /url=/.test(src)) { + const qs = parseQueryString(src); + if (qs.url) widget.url = qs.url; + } + return widget; + } + function setStyles(el, styles) { + if (el) Object.keys(styles).forEach((key) => { + let value = styles[key]; + if (typeof value === "number" || typeof value === "string" && /^(\d+)?\.?(\d+)$/.test(value)) value = value + "px"; + const elStyle = el.style; + const currentValue = elStyle[key]; + if (iframely.getElementComputedStyle(el, key) != value && !(el.className == "iframely-responsive" && key === "paddingBottom" && !currentValue && /^56\.2\d+%$/.test(value)) && !(key === "max-width" && value === "keep")) elStyle[key] = value || ""; + }); + } + function applyNonce(element) { + if (iframely.config.nonce) element.nonce = iframely.config.nonce; + } + function defineDefaultStyles() { + const iframelyStylesId = "iframely-styles"; + let styles = document.getElementById(iframelyStylesId); + if (!styles) { + const iframelyStyles = ".iframely-responsive{top:0;left:0;width:100%;height:0;position:relative;padding-bottom:56.25%;box-sizing:border-box;}.iframely-responsive>*{top:0;left:0;width:100%;height:100%;position:absolute;border:0;box-sizing:border-box;}"; + styles = document.createElement("style"); + styles.id = iframelyStylesId; + applyNonce(styles); + styles.innerHTML = iframelyStyles; + document.getElementsByTagName("head")[0].appendChild(styles); + } + } + function addQueryString(href, options) { + let query_string = ""; + Object.keys(options).forEach((key) => { + let value = options[key]; + if (Array.isArray(value)) { + const values = value.map((uri) => key + "=" + encodeURIComponent(uri)); + query_string += "&" + values.join("&"); + } else if (typeof value !== "undefined" && href.indexOf(key + "=") === -1) { + if (typeof value === "boolean" && key.charAt(0) !== "_") value = value ? 1 : 0; + query_string += "&" + key + "=" + encodeURIComponent(value); + } + }); + return href + (query_string !== "" ? (href.indexOf("?") > -1 ? "&" : "?") + query_string.replace(/^&/, "") : ""); + } + function getEndpoint(src, options, config_params) { + let endpoint = src; + if (!/^(https?:)?\/\//i.test(src)) { + endpoint = (options && options.CDN || iframely.CDN) + endpoint; + if (options) delete options.CDN; + } + if (!/^(?:https?:)?\/\//i.test(endpoint)) endpoint = "//" + endpoint; + if (options) endpoint = addQueryString(endpoint, options); + if (config_params && config_params.length) { + const more_options = {}; + const iframely_config_keys = Object.keys(iframely.config); + for (let i = 0; i < iframely_config_keys.length; i++) { + const key = iframely_config_keys[i]; + if (containsString(config_params, key)) more_options[key] = iframely.config[key]; + } + endpoint = addQueryString(endpoint, more_options); + } + if (/^(https?:)?\/\//i.test(endpoint) && !endpoint.match(/^(https?:)?\/\//i)[1] && document.location.protocol !== "http:" && document.location.protocol !== "https:") endpoint = "https:" + endpoint; + return endpoint; + } + function parseQueryStringFromScriptSrc() { + const scripts = document.querySelectorAll("script[src*=\"embed.js\"], script[src*=\"iframely.js\"]"); + for (let i = 0; i < scripts.length; i++) { + const src = scripts[i].getAttribute("src").replace(/&/gi, "&"); + if (iframely.SCRIPT_RE.test(src)) { + const options = parseQueryString(src, iframely.SUPPORTED_QUERY_STRING.concat("cdn", "cancel", "nonce")); + const m2 = src.match(iframely.CDN_RE); + if (m2 || options.cdn) iframely.CDN = options.cdn || m2[1]; + if (options.cancel) { + if (options.cancel === "0" || options.cancel === "false") iframely.RECOVER_HREFS_ON_CANCEL = true; + delete options.cancel; + } + if (Object.keys(options).length > 0) return options; + } + } + return {}; + } + function requestSizeOfExistingIframes(domains) { + const iframes = document.querySelectorAll("iframe[src*=\"" + (domains || iframely.DOMAINS).join("\"], iframe[src*=\"") + "\"]"); + for (let i = 0; i < iframes.length; i++) { + const iframe = iframes[i]; + const src = iframe.src; + if (src.match(/^(https?:)?\/\/[^/]+\/api\/iframe\?.+/) || src.match(/^(https?:)?\/\/[^/]+\/\w+(\?.*)?$/)) postMessage({ method: "getSize" }, "*", iframe.contentWindow); + } + } + function nonTextChildCount$1(element) { + let count = 0; + for (let i = 0; i < element.childNodes.length; i++) { + const el = element.childNodes[i]; + if (el.nodeType === Node.TEXT_NODE) { + if ((el.textContent || "").replace(/\s|\n/g, "")) count++; + } else if (el.nodeType === Node.ELEMENT_NODE) count++; + } + return count; + } + function containsString(list, findValue) { + let value, i = 0; + while (i < list.length) { + value = list[i]; + if (value == findValue) return true; + if (value instanceof RegExp && value.test(findValue)) return true; + i++; + } + return false; + } + function parseQueryString(url, allowed_query_string) { + const query = url.match(/\?(.+)/i); + if (query) { + const data = query[1].split("&"); + const result = {}; + for (let i = 0; i < data.length; i++) { + const item = data[i].split("="); + if (!allowed_query_string || containsString(allowed_query_string, item[0])) result[item[0]] = decodeURIComponent(item[1]); + } + return result; + } else return {}; + } + function createScript() { + const script = document.createElement("script"); + applyNonce(script); + return script; + } -eval("{var iframely = __webpack_require__(/*! ./iframely */ \"./iframely.js\");\n\n// deprecated. Helper function only, for the reverse compatibility.\niframely.widgets = iframely.widgets || {};\niframely.widgets.load = iframely.load;\n\nif (!iframely.events) {\n iframely.events = {};\n iframely.events.on = iframely.on;\n iframely.events.trigger = iframely.trigger;\n}\n\niframely.on('cancel', function(url, parentNode, text, nextSibling) {\n\n if (iframely.RECOVER_HREFS_ON_CANCEL && !text) {\n text = url;\n }\n\n if (url && parentNode && text && text !== '') {\n var a = document.createElement('a');\n a.setAttribute('href', url);\n a.setAttribute('target', '_blank');\n a.setAttribute('rel', 'noopener');\n a.textContent = text;\n if (nextSibling) {\n parentNode.insertBefore(a, nextSibling);\n } else {\n parentNode.appendChild(a);\n }\n }\n});\n\n//# sourceURL=webpack:///./deprecated.js?\n}"); +//#endregion +//#region src/intersection.ts + var observers = {}; + function getObserver(options) { + const optionsKey = JSON.stringify(options); + let observer = observers[optionsKey]; + if (!observer) { + observer = new IntersectionObserver((entries) => { + entries.forEach((entry) => { + postMessage({ + method: "intersection", + entry: { isIntersecting: entry.isIntersecting }, + options + }, "*", entry.target.contentWindow); + }); + }, getObserverOptions(options)); + observers[optionsKey] = observer; + } + return observer; + } + function getObserverOptions(options) { + const result = {}; + if (options && options.threshold) result.threshold = options.threshold; + if (options && options.margin) result.rootMargin = options.margin + "px " + options.margin + "px " + options.margin + "px " + options.margin + "px"; + return result; + } + function boot$10() { + iframely.on("init", () => { + iframely.configure({ intersection: 1 }); + }); + iframely.on("message", (widget, message) => { + if (message.method === "send-intersections" && widget.iframe) { + let options = message.options; + if (!options) options = { margin: 1e3 }; + getObserver(options).observe(widget.iframe); + } + }); + iframely.on("unload-widget", (widget) => { + Object.values(observers).forEach((observer) => observer.unobserve(widget.iframe)); + }); + iframely.on("unload", (el) => { + if (!el) Object.keys(observers).forEach((key) => { + observers[key].disconnect(); + delete observers[key]; + }); + }); + } -/***/ }, +//#endregion +//#region src/theme.ts + function setThemeInIframe(iframe, theme) { + postMessage({ + method: "setTheme", + data: theme + }, "*", iframe.contentWindow); + } + function setThemeInAllIframes(parent, theme) { + const iframes = parent.getElementsByTagName("iframe"); + for (let i = 0; i < iframes.length; i++) setThemeInIframe(iframes[i], theme); + } + function boot$9() { + iframely.setTheme = (theme, container) => { + if (theme && iframely.SUPPORTED_THEMES.indexOf(theme) > -1) if (container) if (container.tagName === "IFRAME") setThemeInIframe(container, theme); + else setThemeInAllIframes(container, theme); + else { + iframely.configure({ theme }); + setThemeInAllIframes(document, theme); + iframely.trigger("set-theme", theme); + } + else console.warn("Using iframely.setTheme with not supported theme: \"" + theme + "\". Supported themes are: " + iframely.SUPPORTED_THEMES.join(", ")); + }; + } -/***/ "./dom-ready.js" -/*!**********************!*\ - !*** ./dom-ready.js ***! - \**********************/ -(__unused_webpack_module, __unused_webpack_exports, __webpack_require__) { +//#endregion +//#region src/import.ts + var widgetsCache = {}; + function boot$8() { + iframely.on("load", (el) => { + if (!el && iframely.config.import !== false && isImportAble() && !iframely.import) { + const elements = document.querySelectorAll("a[data-iframely-url]:not([data-import-uri])"); + if (elements.length > 1) makeImportAPICall(elements); + } + }); + iframely.on("load", (widget, importOptions) => { + if (widget && !(widget instanceof Element) && widget.uri && (widget.html || widget.cancel)) { + const els = widgetsCache[widget.uri]; + if (els) for (let i = 0; i < els.length; i++) loadImportWidget(widget, els[i], importOptions); + delete widgetsCache[widget.uri]; + } + }); + iframely.buildImportWidgets = (importOptions) => { + iframely.trigger("import-loaded", importOptions); + importOptions.widgets.forEach((widget) => { + iframely.trigger("load", widget, importOptions); + }); + importReady(); + }; + iframely.isTouch = () => { + return "ontouchstart" in window || navigator.maxTouchPoints > 0; + }; + iframely.on("import-widget-ready", clearWrapperStylesAndClass); + iframely.on("unload", (el) => { + if (!el) { + delete iframely.import; + Object.keys(widgetsCache).forEach((key) => { + delete widgetsCache[key]; + }); + } + }); + if (!iframely.addEventListener) iframely.addEventListener = (elem, type, eventHandle) => { + if (!elem) return; + elem.addEventListener(type, eventHandle, false); + }; + } + function makeImportAPICall(elements) { + const script = createScript(); + const uris = []; + const ids = []; + let import_options = null; + function pushElement(uri, el) { + if (!widgetsCache[uri]) widgetsCache[uri] = []; + widgetsCache[uri].push(el); + } + function queueElement(el) { + const src = el.getAttribute("data-iframely-url"); + const mId = src.match(iframely.ID_RE); + const id = mId && mId[1]; + const options = parseQueryString(src, iframely.SUPPORTED_QUERY_STRING.concat("url")); + let url = options.url; + delete options.url; + let skipImport = options.import === "0" || options.import === "false" || options.playerjs === "1" || options.playerjs === "true"; + if (!skipImport) { + const mBase = src.match(iframely.BASE_RE); + options.CDN = mBase && mBase[0]; + if (!import_options) import_options = options; + else if (JSON.stringify(options, Object.keys(options).sort()) !== JSON.stringify(import_options, Object.keys(import_options).sort())) skipImport = true; + } + if (skipImport) iframely.trigger("load", el); + else if (id) { + el.setAttribute("data-import-uri", id); + if (ids.indexOf(id) === -1) ids.push(id); + pushElement(id, el); + } else { + if (!url) url = el.getAttribute("href"); + if ((import_options.key || import_options.api_key || iframely.config.api_key || iframely.config.key) && url) { + el.setAttribute("data-import-uri", url); + if (uris.indexOf(url) === -1) uris.push(url); + pushElement(url, el); + } else iframely.trigger("load", el); + } + } + for (let i = 0; i < elements.length; i++) { + const el = elements[i]; + if (!el.getAttribute("data-import-uri") && el.hasAttribute("data-iframely-url")) queueElement(el); + } + if (uris.length > 0 || ids.length > 0) { + import_options = import_options || {}; + import_options.touch = iframely.isTouch(); + import_options.flash = false; + import_options.app = 1; + if (iframely.config.theme) import_options.theme = iframely.config.theme; + if (uris.length > 0) import_options.uri = uris; + if (ids.length > 0) import_options.ids = ids.join("&"); + import_options.v = iframely.VERSION; + script.src = getEndpoint("/api/import/v2", import_options, iframely.SUPPORTED_QUERY_STRING); + script.onerror = () => { + importReady(); + }; + document.head.appendChild(script); + iframely.import = script; + } else { + importReady(); + iframely.trigger("load"); + } + } + function loadImportWidget(widgetOptions, el, importOptions) { + const needCancelWidget = widgetOptions.cancel; + const shadow = widgetOptions.shadow; + const hasRenderedEvent = widgetOptions.renderEvent; + const wrapper = getIframeWrapper(el, true); + if (needCancelWidget) iframely.cancelWidget(getWidget(el) || { + maxWidthWrapper: el, + iframe: el, + url: el.getAttribute("href") + }); + else { + const widget = document.createElement("div"); + widget.innerHTML = widgetOptions.html; + let parent, replacedEl; + if (wrapper && !hasRenderedEvent) { + parent = wrapper.aspectWrapper.parentNode; + replacedEl = wrapper.aspectWrapper; + wrapper.maxWidthWrapper.removeAttribute("style"); + } else { + parent = el.parentNode; + replacedEl = el; + } + if (shadow) { + const shadowContainer = document.createElement("div"); + const shadowRoot = shadowContainer.attachShadow({ mode: "open" }); + shadowRoot.appendChild(widget); + const shadowWidgetOptions = { + shadowRoot, + shadowContainer, + container: parent, + context: widgetOptions.context, + stylesIds: widgetOptions.stylesIds, + stylesDict: importOptions.commonShadowStyles + }; + iframely.trigger("import-shadow-widget-before-render", shadowWidgetOptions); + parent.insertBefore(shadowContainer, replacedEl); + iframely.trigger("import-shadow-widget-after-render", shadowWidgetOptions); + } else { + parent.insertBefore(widget, replacedEl); + exec_body_scripts(widget); + } + parent.removeChild(replacedEl); + if (hasRenderedEvent) setTimeout(() => { + clearWrapperStylesAndClass(parent); + }, iframely.CLEAR_WRAPPER_STYLES_TIMEOUT); + } + } + function importReady() { + delete iframely.import; + const failed_elements = document.querySelectorAll("a[data-iframely-url][data-import-uri]"); + for (let i = 0; i < failed_elements.length; i++) { + failed_elements[i].removeAttribute("data-import-uri"); + iframely.trigger("load", failed_elements[i]); + } + } + function isImportAble() { + return !!(document.location && (iframely.debug || document.location.protocol === "http:" || document.location.protocol === "https:") && !iframely.config.playerjs && !iframely.config.lazy); + } + function clearWrapperStylesAndClass(el) { + let aspectWrapper = el; + let parents = 0; + while (aspectWrapper && (!aspectWrapper.getAttribute("class") || aspectWrapper.getAttribute("class").split(" ").indexOf(iframely.ASPECT_WRAPPER_CLASS) === -1)) { + aspectWrapper = aspectWrapper.parentNode; + parents++; + if (parents > 4) aspectWrapper = null; + } + const maxWidthWrapper = aspectWrapper && aspectWrapper.parentNode; + if (maxWidthWrapper && maxWidthWrapper.getAttribute("class") && maxWidthWrapper.getAttribute("class").split(" ").indexOf(iframely.MAXWIDTH_WRAPPER_CLASS) > -1) { + aspectWrapper.removeAttribute("style"); + aspectWrapper.removeAttribute("class"); + maxWidthWrapper.removeAttribute("style"); + } + } + function exec_body_scripts(body_el) { + function nodeName(elem, name) { + return !!elem.nodeName && elem.nodeName.toUpperCase() === name.toUpperCase(); + } + function evalScript(elem) { + const data = elem.text || elem.textContent || elem.innerHTML || ""; + const script = createScript(); + script.type = "text/javascript"; + for (let i = 0; i < elem.attributes.length; i++) { + const attr = elem.attributes[i]; + script.setAttribute(attr.name, attr.value); + } + script.appendChild(document.createTextNode(data)); + body_el.appendChild(script); + } + const scripts = []; + const children_nodes = body_el.childNodes; + for (let i = 0; children_nodes[i]; i++) { + const child = children_nodes[i]; + if (nodeName(child, "script") && (!child.type || child.type.toLowerCase() === "text/javascript" || child.type.toLowerCase() === "application/javascript")) { + scripts.push(child); + body_el.removeChild(child); + } else if (child.nodeType === Node.ELEMENT_NODE) exec_body_scripts(child); + } + for (let i = 0; i < scripts.length; i++) { + const script = scripts[i]; + if (script.parentNode) script.parentNode.removeChild(script); + evalScript(script); + } + } -eval("{// TODO: rename core.js to ready.js?\n\nvar iframely = __webpack_require__(/*! ./iframely */ \"./iframely.js\");\n\nvar DOMReady = function(f) {\n if (document.readyState === 'complete' || document.readyState === 'interactive') {\n // Run always (in case of async script).\n setTimeout(f, 0);\n }\n document['addEventListener'] ? document['addEventListener']('DOMContentLoaded', f) : window.attachEvent('onload', f);\n};\n\nDOMReady(function() {\n\n // Called each time on script load\n if (typeof iframely.config.autorun === 'undefined' || iframely.config.autorun !== false) {\n iframely.trigger('load');\n }\n});\n\n\n//# sourceURL=webpack:///./dom-ready.js?\n}"); +//#endregion +//#region src/ahref.ts + function boot$7() { + iframely.on("load", (container, href) => { + if (container && container.nodeName && typeof href === "string") { + const a = document.createElement("a"); + a.setAttribute("href", href); + container.appendChild(a); + iframely.trigger("load", a); + } + }); + iframely.on("load", (el) => { + if (!el && !iframely.import) { + const elements = document.querySelectorAll("a[data-iframely-url]:not([data-import-uri])"); + for (let i = 0; i < elements.length; i++) iframely.trigger("load", elements[i]); + } + }); + iframely.on("load", (el) => { + if (el && el.nodeName === "A" && (el.getAttribute("data-iframely-url") || el.getAttribute("href")) && !el.hasAttribute("data-import-uri")) unfurl(el); + }); + } + function unfurl(el) { + if (!el.getAttribute("data-iframely-url") && !el.getAttribute("href")) return; + let src; + const dataIframelyUrl = el.getAttribute("data-iframely-url"); + if (dataIframelyUrl && /^((?:https?:)?\/\/[^/]+)\/\w+/i.test(dataIframelyUrl)) src = getEndpoint(dataIframelyUrl, { + v: iframely.VERSION, + app: 1, + theme: iframely.config.theme + }); + else if ((iframely.config.api_key || iframely.config.key) && iframely.CDN) { + if (!el.getAttribute("href")) { + console.warn("Iframely cannot build embeds: \"href\" attribute missing in", el); + return; + } + src = getEndpoint("/api/iframe", { + url: el.getAttribute("href"), + v: iframely.VERSION, + app: 1, + theme: iframely.config.theme + }, iframely.SUPPORTED_QUERY_STRING); + } else console.warn("Iframely cannot build embeds: api key is required as query-string of embed.js"); + if (!src) el.removeAttribute("data-iframely-url"); + else { + const iframe = document.createElement("iframe"); + iframe.setAttribute("allowfullscreen", ""); + iframe.setAttribute("allow", "autoplay *; encrypted-media *; ch-prefers-color-scheme *"); + if (el.hasAttribute("data-img")) iframe.setAttribute("data-img", el.getAttribute("data-img")); + const isLazy = el.hasAttribute("data-lazy") || el.hasAttribute("data-img") || /&lazy=1/.test(src) || iframely.config.lazy; + const text = el.textContent; + if (text && text !== "") iframe.textContent = text; + let wrapper = getIframeWrapper(el, true); + if (wrapper) while (wrapper.aspectWrapper.lastChild) wrapper.aspectWrapper.removeChild(wrapper.aspectWrapper.lastChild); + else { + wrapper = addDefaultWrappers(el); + el.parentNode.removeChild(el); + } + wrapper.aspectWrapper.appendChild(iframe); + if (isLazy) { + iframe.setAttribute("data-iframely-url", src); + iframely.trigger("load", iframe); + } else { + iframe.setAttribute("src", src); + iframely.trigger("iframe-ready", iframe); + } + } + } -/***/ }, +//#endregion +//#region src/lazy-img-placeholder.ts + function boot$6() { + iframely.on("load", (el) => { + if (el && el.nodeName === "IFRAME" && el.hasAttribute("data-iframely-url") && el.hasAttribute("data-img") && !el.getAttribute("src")) { + const dataImg = el.getAttribute("data-img"); + el.removeAttribute("data-img"); + el.setAttribute("data-img-created", ""); + const widget = getWidget(el); + let src = el.getAttribute("data-iframely-url"); + if (widget) { + addPlaceholderThumbnail(widget, src, dataImg); + src = addQueryString(src, { img: 1 }); + el.setAttribute("data-iframely-url", src); + new WaitingWidget(widget); + } + iframely.trigger("load", el); + } + }); + iframely.on("message", (widget, message) => { + if (!widget) return; + let waitingWidget; + if (message.method === "widgetRendered") { + hidePlaceholderThumbnail(widget); + waitingWidget = findWaitingWidget(widget); + waitingWidget?.deactivate(); + } + if (message.method === "begin-waiting-widget-render") { + waitingWidget = findWaitingWidget(widget); + waitingWidget?.clearLoadingTimeout(); + } + if (message.method === "end-waiting-widget-render") { + waitingWidget = findWaitingWidget(widget); + waitingWidget?.registerLoadingTimeout(); + } + }); + iframely.on("unload-widget", (widget) => { + findWaitingWidget(widget)?.deactivate(); + }); + } + function addPlaceholderThumbnail(widget, href, imageUrl) { + let thumbHref; + if (imageUrl && /^(https?:)?\/\//.test(imageUrl)) thumbHref = imageUrl; + else { + const query = parseQueryString(href); + const _params = {}; + for (const param in query) if (param.indexOf("_") === 0) _params[param] = query[param]; + if (query.media) _params.media = query.media; + if (href.match(/\/api\/iframe/)) thumbHref = getEndpoint(href.match(/^(.+)\/api\/iframe/i)[1] + "/api/thumbnail", Object.assign({ + url: query.url, + api_key: query.api_key, + key: query.key + }, _params)); + else if (href.match(iframely.ID_RE)) thumbHref = getEndpoint(href.replace(/^((?:https?:)?\/\/[^/]+\/(\w+-?\w+))(?:\?.*)?$/, "$1/thumbnail"), _params); + else return; + } + const thumb = document.createElement("div"); + setStyles(thumb, { + position: "absolute", + width: "100%", + height: "100%", + backgroundImage: "url('" + thumbHref + "')", + backgroundSize: "cover", + backgroundPosition: "center" + }); + const iframelyLoaderDiv = document.createElement("div"); + iframelyLoaderDiv.setAttribute("class", iframely.LOADER_CLASS); + thumb.appendChild(iframelyLoaderDiv); + const paddingTop = iframely.getElementComputedStyle(widget.aspectWrapper, "padding-top"); + const paddingBottom = iframely.getElementComputedStyle(widget.aspectWrapper, "padding-bottom"); + const paddingTopMatch = paddingTop && paddingTop.match(/^(\d+)px$/); + if (paddingTopMatch && parseInt(paddingTopMatch[1]) && paddingBottom) { + const thumbWrapper = document.createElement("div"); + setStyles(thumbWrapper, { + top: "-" + paddingTop, + width: "100%", + height: 0, + position: "relative", + paddingBottom + }); + thumbWrapper.appendChild(thumb); + widget.aspectWrapper.appendChild(thumbWrapper); + } else widget.aspectWrapper.appendChild(thumb); + } + function getNthNonTextChildNode(nth, element) { + let count = 0; + for (let i = 0; i < element.childNodes.length; i++) { + const el = element.childNodes[i]; + if (el.nodeType === Node.ELEMENT_NODE) { + if (nth === count) return el; + count++; + } + } + } + function nonTextChildCount(element) { + let count = 0; + for (let i = 0; i < element.childNodes.length; i++) { + const el = element.childNodes[i]; + if (el.nodeType === Node.TEXT_NODE) { + if ((el.textContent || "").replace(/\s|\n/g, "")) count++; + } else if (el.nodeType === Node.ELEMENT_NODE) count++; + } + return count; + } + function hidePlaceholderThumbnail(widget) { + const thumb = widget.aspectWrapper && nonTextChildCount(widget.aspectWrapper) > 1 && getNthNonTextChildNode(1, widget.aspectWrapper); + if (thumb && thumb.nodeName === "DIV") widget.aspectWrapper.removeChild(thumb); + } + var waitingWidgets = []; + function findWaitingWidgetIdx(widget) { + let i = 0; + while (i < waitingWidgets.length && waitingWidgets[i].widget.iframe !== widget.iframe) i++; + if (i < waitingWidgets.length && waitingWidgets[i].widget.iframe === widget.iframe) return i; + } + function findWaitingWidget(widget) { + const idx = findWaitingWidgetIdx(widget); + if (idx || idx === 0) return waitingWidgets[idx]; + } + function removeWaitingWidget(widget) { + const idx = findWaitingWidgetIdx(widget); + if (idx || idx === 0) waitingWidgets.splice(idx, 1); + } + var WaitingWidget = class { + widget; + loadCount = 0; + timeoutId = null; + constructor(widget) { + this.widget = widget; + iframely.addEventListener(widget.iframe, "load", () => { + this.iframeOnLoad(); + }); + this.registerLoadingTimeout(); + waitingWidgets.push(this); + } + iframeOnLoad() { + this.loadCount++; + if (this.loadCount !== 2) return; + this.deactivate(); + setTimeout(() => { + hidePlaceholderThumbnail(this.widget); + }, iframely.LAZY_IFRAME_FADE_TIMEOUT); + } + deactivate() { + this.clearLoadingTimeout(); + removeWaitingWidget(this.widget); + } + clearLoadingTimeout() { + if (this.timeoutId) clearTimeout(this.timeoutId); + this.timeoutId = null; + } + registerLoadingTimeout() { + if (this.timeoutId) return; + this.timeoutId = setTimeout(() => { + this.iframeOnLoad(); + }, iframely.LAZY_IFRAME_SHOW_TIMEOUT); + } + }; -/***/ "./events.js" -/*!*******************!*\ - !*** ./events.js ***! - \*******************/ -(__unused_webpack_module, __unused_webpack_exports, __webpack_require__) { +//#endregion +//#region src/lazy-iframe.ts + function boot$5() { + iframely.on("load", (el) => { + if (!el) { + const elements = document.querySelectorAll("iframe[data-iframely-url]"); + for (let i = 0; i < elements.length; i++) iframely.trigger("load", elements[i]); + } + }); + iframely.on("load", (el) => { + if (el && el.nodeName === "IFRAME" && el.hasAttribute("data-iframely-url") && !el.hasAttribute("data-img") && !el.getAttribute("src")) loadLazyIframe(el); + }); + } + function loadLazyIframe(el) { + const widget = getWidget(el); + let src = el.getAttribute("data-iframely-url"); + const dataImg = el.hasAttribute("data-img-created") || el.hasAttribute("data-img"); + const nativeLazyLoad = !dataImg && iframely.SUPPORT_IFRAME_LOADING_ATTR; + if (widget && src) { + const options = { + v: iframely.VERSION, + app: 1, + theme: iframely.config.theme + }; + if (!nativeLazyLoad && iframely.config.intersection) options.lazy = 1; + src = getEndpoint(src, options); + } + if (nativeLazyLoad) el.setAttribute("loading", "lazy"); + if (dataImg && iframely.SUPPORT_IFRAME_LOADING_ATTR) el.setAttribute("loading", "edge"); + el.setAttribute("src", src || ""); + el.removeAttribute("data-iframely-url"); + iframely.trigger("iframe-ready", el); + } -eval("{var iframely = __webpack_require__(/*! ./iframely */ \"./iframely.js\");\n\nvar nextTick = (function(window, prefixes, i, fnc) {\n while (!fnc && i < prefixes.length) {\n fnc = window[prefixes[i++] + 'equestAnimationFrame'];\n }\n return (fnc && fnc.bind(window)) || window.setImmediate || function(fnc) {window.setTimeout(fnc, 0);};\n})(typeof window !== 'undefined' ? window : __webpack_require__.g, 'r webkitR mozR msR oR'.split(' '), 0);\n\nvar callbacksStack = {};\niframely.on = function(event, cb) {\n var events = callbacksStack[event] = callbacksStack[event] || [];\n events.push(cb);\n};\n\nfunction trigger(event, async, args) {\n var events = callbacksStack[event] || [];\n events.forEach(function(cb) {\n if (async) {\n nextTick(function() {\n cb.apply(iframely, args);\n });\n } else {\n cb.apply(iframely, args);\n }\n });\n\n if (event === 'init') {\n // everything inited, let's clear the callstack, just in case\n // TODO: not good.\n callbacksStack[event] = [];\n }\n}\n\niframely.trigger = function(event) {\n var args = Array.prototype.slice.call(arguments, 1);\n trigger(event, false, args);\n};\n\niframely.triggerAsync = function(event) {\n var args = Array.prototype.slice.call(arguments, 1);\n trigger(event, true, args);\n};\n\n//# sourceURL=webpack:///./events.js?\n}"); +//#endregion +//#region src/widget-cancel.ts + function boot$4() { + iframely.on("message", (widget, message) => { + if (message.method === "cancelWidget") iframely.cancelWidget(widget); + }); + iframely.cancelWidget = (widget) => { + if (!widget) { + console.warn("iframely.cancelWidget called without widget param"); + return; + } + function findParent(el, className) { + let found = false; + while (!found && el.parentNode) { + el = el.parentNode; + found = !!el.className && typeof el.className === "string" && el.className.split(" ").indexOf(className) >= 0; + } + return found && el; + } + let parentNode = widget.maxWidthWrapper && widget.maxWidthWrapper.parentNode; + let naNode = widget.maxWidthWrapper; + if (iframely.config && iframely.config.parent) { + const parentElement = findParent(widget.maxWidthWrapper, String(iframely.config.parent)); + if (parentElement) { + parentNode = parentElement.parentNode; + naNode = parentElement; + } + } + if (widget.url) { + const text = widget.iframe && widget.iframe.textContent; + iframely.triggerAsync("cancel", widget.url, parentNode, text, naNode.nextSibling); + } + parentNode.removeChild(naNode); + }; + } -/***/ }, +//#endregion +//#region src/widget-resize.ts + var resetWrapperBorderStyles = { + border: "", + "border-radius": "", + "box-shadow": "", + overflow: "" + }; + var resetIframeBorderStyles = { + border: "0", + "border-radius": "", + "box-shadow": "", + overflow: "" + }; + function boot$3() { + iframely.on("message", (widget, message) => { + if (message.method === "setIframelyWidgetSize" || message.method === "resize" || message.method === "setIframelyEmbedData" || message.type === "embed-size" || message.context === "iframe.resize") { + let frame_styles = null; + if (message.data && message.data.media && message.data.media.frame_style) { + message.data.media.frame_style.split(";").forEach((str) => { + if (str.trim() !== "" && str.indexOf(":") > -1) { + const props = str.split(":"); + if (props.length === 2) { + frame_styles = frame_styles || {}; + frame_styles[props[0].trim()] = props[1].trim(); + } + } + }); + widgetDecorate(widget, frame_styles); + } else if (message.method === "setIframelyEmbedData") widgetDecorate(widget, null); + let media = message.data && message.data.media; + if (!media && message.height) media = { + height: message.height, + "max-width": "keep" + }; + widgetResize(widget, media); + } + }); + } + function widgetDecorate(widget, styles) { + if (styles && widget && widget.iframe) if (styles["border-radius"]) { + styles.overflow = "hidden"; + setStyles(widget.aspectWrapper, styles); + } else setStyles(widget.iframe, styles); + else if (!styles && widget && widget.iframe) { + setStyles(widget.aspectWrapper, resetWrapperBorderStyles); + setStyles(widget.iframe, resetIframeBorderStyles); + } + } + function getTotalBorderWidth(widget) { + const frameStylesBorder = widget.iframe && widget.iframe.style.border || widget.aspectWrapper && widget.aspectWrapper.style.border; + const borderMatch = frameStylesBorder && frameStylesBorder.match(/(\d+)px/); + if (borderMatch) return parseInt(borderMatch[1]) * 2; + return 0; + } + function widgetResize(widget, media) { + if (media && Object.keys(media).length > 0 && widget) { + const borderWidth = getTotalBorderWidth(widget); + const oldIframeHeight = window.getComputedStyle(widget.iframe).getPropertyValue("height"); + let maxWidth = media["max-width"]; + if (typeof maxWidth === "number") maxWidth += borderWidth; + setStyles(widget.maxWidthWrapper, { + "max-width": maxWidth, + "min-width": media["min-width"] && media["min-width"] + borderWidth, + width: media.width && media.width + borderWidth + }); + if (media.scrolling && widget.iframe) widget.iframe.setAttribute("scrolling", media.scrolling); + const aspectRatio = media["aspect-ratio"]; + if (aspectRatio || media.height) setStyles(widget.aspectWrapper, { + paddingBottom: aspectRatio ? Math.round(1e3 * 100 / aspectRatio) / 1e3 + "%" : 0, + paddingTop: aspectRatio && media["padding-bottom"], + height: aspectRatio ? 0 : media.height && media.height + borderWidth + }); + const currentHeight = window.getComputedStyle(widget.iframe).getPropertyValue("height"); + if (oldIframeHeight && oldIframeHeight !== currentHeight) iframely.triggerAsync("heightChanged", widget.iframe, oldIframeHeight, currentHeight); + } + } -/***/ "./iframely.js" -/*!*********************!*\ - !*** ./iframely.js ***! - \*********************/ -(module) { +//#endregion +//#region src/widget-click.ts + function boot$2() { + iframely.on("message", (widget, message) => { + if (message.method === "open-href" || message.method === "click") iframely.trigger(message.method, message.href); + }); + if (!iframely.openHref) iframely.openHref = (href) => { + if (href.indexOf(window.location.origin) === 0) window.location.href = href; + else window.open(href, "_blank", "noopener"); + }; + iframely.on("open-href", (href) => { + iframely.triggerAsync("click", href); + iframely.openHref(href); + }); + } -eval("{var iframely = window.iframely = window.iframely || {};\niframely.config = iframely.config || {};\n\nmodule.exports = iframely;\n\n//# sourceURL=webpack:///./iframely.js?\n}"); +//#endregion +//#region src/widget-options.ts + function boot$1() { + iframely.on("message", (widget, message) => { + if (message.method === "setIframelyEmbedOptions") iframely.trigger("options", widget, message.data); + }); + } -/***/ }, +//#endregion +//#region src/deprecated.ts + function boot() { + iframely.widgets = iframely.widgets || {}; + iframely.widgets.load = iframely.load; + iframely.extendOptions = iframely.configure; + if (!iframely.events) { + iframely.events = {}; + iframely.events.on = iframely.on; + iframely.events.trigger = iframely.trigger; + } + iframely.on("cancel", (url, parentNode, text, nextSibling) => { + if (iframely.RECOVER_HREFS_ON_CANCEL && !text) text = url; + if (url && parentNode && text && text !== "") { + const a = document.createElement("a"); + a.setAttribute("href", url); + a.setAttribute("target", "_blank"); + a.setAttribute("rel", "noopener"); + a.textContent = text; + if (nextSibling) parentNode.insertBefore(a, nextSibling); + else parentNode.appendChild(a); + } + }); + } -/***/ "./import.js" -/*!*******************!*\ - !*** ./import.js ***! - \*******************/ -(__unused_webpack_module, __unused_webpack_exports, __webpack_require__) { +//#endregion +//#region src/index.ts + if (typeof window !== "undefined" && !iframely._loaded) { + iframely._loaded = true; + boot$14(); + boot$13(); + boot$11(); + boot$12(); + boot$10(); + boot$9(); + boot$8(); + boot$7(); + boot$6(); + boot$5(); + boot$4(); + boot$3(); + boot$2(); + boot$1(); + boot(); + iframely.trigger("init"); + } -eval("{var utils = __webpack_require__(/*! ./utils */ \"./utils.js\");\nvar iframely = __webpack_require__(/*! ./iframely */ \"./iframely.js\");\n\n// widgetsCache is used from inside import doc for js callbacks and custom features\nvar widgetsCache = {};\n\niframely.on('load', function(el) {\n\n // load once, if import is not in process and only if query-string from script src has not disabled import\n if (!el && iframely.config.import !== false \n && isImportAble()\n && !iframely.import) {\n\n var elements = document.querySelectorAll('a[data-iframely-url]:not([data-import-uri])');\n if (elements.length > 1) {\n makeImportAPICall(elements);\n }\n }\n\n});\n\niframely.on('load', function(widget, importOptions) {\n\n if (widget && widget.uri && (widget.html || widget.cancel)) {\n\n var els = widgetsCache[widget.uri];\n // alternatively, could as well do querySelectorAll('a[data-iframely-url][data-import=\"' + template.getAttribute('data-uri') + '\"')\n\n if (els) {\n for (var i = 0; i < els.length; i++) {\n loadImportWidget(widget, els[i], importOptions);\n }\n }\n\n delete widgetsCache[widget.uri];\n }\n});\n\nfunction makeImportAPICall(elements) {\n var script = utils.createScript();\n\n var uris = [];\n var ids = [];\n \n var import_options = null; // will be populated from first element; or will remain as null if no params in elements...\n\n // couple helper functions first\n\n function pushElement(uri, el) {\n if (!widgetsCache[uri]) {\n widgetsCache[uri] = [];\n }\n\n widgetsCache[uri].push(el);\n }\n\n function queueElement(el) {\n var src = el.getAttribute('data-iframely-url');\n\n var mId = src.match(iframely.ID_RE);\n var id = mId && mId[1];\n\n var options = utils.parseQueryString(src, iframely.SUPPORTED_QUERY_STRING.concat('url'));\n\n var url = options.url; // can be undefined for IDs\n delete options.url;\n\n // skip import on import=0, playerjs=1\n var skipImport = options.import === '0' || options.import === 'false' \n || options.playerjs === '1' || options.playerjs === 'true';\n\n // or if link's query-string params or CDN are different from the others\n if (!skipImport) {\n var mBase = src.match(iframely.BASE_RE);\n options.CDN = mBase && mBase[0]; // will fall back to iframely.CDN in getEndpoint('/import...' ...)\n\n // set import options from the first el in import\n // that includes api keys \n if (!import_options) {\n import_options = options;\n\n // else check that this el's options are the same as the first one's in import\n } else if (JSON.stringify(options, Object.keys(options).sort()) \n !== JSON.stringify(import_options, Object.keys(import_options).sort())) {\n\n skipImport = true;\n }\n }\n\n\n if (skipImport) {\n // Usual build if no uri and app=1s.\n iframely.trigger('load', el);\n\n } else if (id) {\n el.setAttribute('data-import-uri', id);\n if (ids.indexOf(id) === -1) {\n ids.push(id);\n }\n pushElement(id, el);\n\n } else {\n\n if (!url) {\n url = el.getAttribute('href');\n }\n\n var key = import_options.key || import_options.api_key || iframely.config.api_key || iframely.config.key;\n\n if (key && url) {\n\n el.setAttribute('data-import-uri', url);\n if (uris.indexOf(url) === -1) {\n uris.push(url);\n }\n pushElement(url, el);\n } else {\n // Usual build if no uri.\n iframely.trigger('load', el);\n }\n }\n }\n\n\n // start actual filling up of import request\n\n for(var i = 0; i < elements.length; i++) {\n var el = elements[i];\n if (!el.getAttribute('data-import-uri') && el.hasAttribute('data-iframely-url')) {\n queueElement(el);\n }\n }\n\n if ((uris.length > 0 || ids.length > 0)) {\n\n import_options = import_options || {};\n import_options.touch = iframely.isTouch();\n import_options.flash = hasFlash();\n import_options.app = 1;\n // Do not override imports theme if global theme not set.\n if (iframely.config.theme) {\n import_options.theme = iframely.config.theme;\n }\n\n if (uris.length > 0) {\n import_options.uri = uris;\n }\n\n if (ids.length > 0) {\n import_options.ids = ids.join('&');\n }\n\n import_options.v = iframely.VERSION;\n\n script.src = utils.getEndpoint('/api/import/v2', import_options, iframely.SUPPORTED_QUERY_STRING);\n\n script.onerror = function() {\n // Error loading import. No import this time.\n importReady();\n };\n\n document.head.appendChild(script);\n iframely.import = script;\n\n } else {\n importReady();\n iframely.trigger('load');\n }\n}\n\niframely.buildImportWidgets = function(importOptions) {\n\n iframely.trigger('import-loaded', importOptions);\n\n importOptions.widgets.forEach(function(widget) {\n iframely.trigger('load', widget, importOptions);\n });\n\n importReady();\n};\n\nfunction loadImportWidget(widgetOptions, el, importOptions) {\n\n var needCancelWidget = widgetOptions.cancel;\n var shadow = widgetOptions.shadow;\n var hasRenderedEvent = widgetOptions.renderEvent;\n\n var wrapper = utils.getIframeWrapper(el, true);\n var widget;\n\n if (needCancelWidget) {\n widget = utils.getWidget(el);\n\n iframely.cancelWidget(widget || {\n maxWidthWrapper: el,\n iframe: el,\n url: el.getAttribute('href') \n });\n\n } else {\n\n widget = document.createElement('div');\n widget.innerHTML = widgetOptions.html;\n \n var parent, replacedEl;\n\n if (wrapper && !hasRenderedEvent) {\n // Inline widget will replace 'aspectWrapper' but keep 'maxWidthWrapper' as 'iframely-embed' to fix centering, etc.\n // If has rendered event - keep wrapper and remove attrs later by event.\n parent = wrapper.aspectWrapper.parentNode;\n replacedEl = wrapper.aspectWrapper;\n\n // Clear custom attributes.\n wrapper.maxWidthWrapper.removeAttribute('style');\n } else {\n // No wrapper or keep wrapper for later removal.\n parent = el.parentNode;\n replacedEl = el;\n }\n\n if (shadow) {\n\n var shadowContainer = document.createElement('div');\n var shadowRoot = shadowContainer.attachShadow({mode: 'open'});\n shadowRoot.appendChild(widget);\n\n var shadowWidgetOptions = {\n shadowRoot: shadowRoot,\n shadowContainer: shadowContainer,\n container: parent,\n context: widgetOptions.context,\n stylesIds: widgetOptions.stylesIds,\n stylesDict: importOptions.commonShadowStyles\n };\n \n iframely.trigger('import-shadow-widget-before-render', shadowWidgetOptions);\n \n parent.insertBefore(shadowContainer, replacedEl);\n\n iframely.trigger('import-shadow-widget-after-render', shadowWidgetOptions);\n \n } else {\n\n parent.insertBefore(widget, replacedEl);\n\n exec_body_scripts(widget);\n }\n\n parent.removeChild(replacedEl);\n\n if (hasRenderedEvent) {\n setTimeout(function() {\n clearWrapperStylesAndClass(parent);\n }, iframely.CLEAR_WRAPPER_STYLES_TIMEOUT);\n }\n }\n}\n\n\nfunction importReady() {\n\n delete iframely.import;\n\n // clean up all, let other loaders have a go\n var failed_elements = document.querySelectorAll('a[data-iframely-url][data-import-uri]');\n for(var i = 0; i < failed_elements.length; i++) {\n failed_elements[i].removeAttribute('data-import-uri');\n iframely.trigger('load', failed_elements[i]);\n }\n}\n\niframely.isTouch = function() {\n return 'ontouchstart' in window // works on most browsers\n || navigator.maxTouchPoints; // works on IE10/11 and Surface\n};\n\nfunction hasFlash() {\n\n var _hasFlash = false;\n\n try {\n var fo = new ActiveXObject('ShockwaveFlash.ShockwaveFlash');\n if (fo) {\n _hasFlash = true;\n } else {\n _hasFlash = false;\n }\n } catch (e) {\n if (navigator.mimeTypes\n && navigator.mimeTypes['application/x-shockwave-flash'] != undefined\n && navigator.mimeTypes['application/x-shockwave-flash'].enabledPlugin) {\n _hasFlash = true;\n } else {\n _hasFlash = false;\n }\n }\n\n return _hasFlash;\n}\n\nfunction isImportAble() {\n\n return document.head.attachShadow\n && document.location // Prevent `Cannot read properties of null (reading 'protocol')` for sandbox iframes.\n && (iframely.debug || document.location.protocol === 'http:' || document.location.protocol === 'https:') // Skip import on file:///\n && !iframely.config.playerjs && !iframely.config.lazy;\n // && !navigator.userAgent.toLowerCase().indexOf('firefox') > -1;\n // TODO: test in Firefox 63\n}\n\nfunction clearWrapperStylesAndClass(el) {\n var aspectWrapper = el;\n var parents = 0;\n while(aspectWrapper \n && (!aspectWrapper.getAttribute('class')\n || aspectWrapper.getAttribute('class').split(' ').indexOf(iframely.ASPECT_WRAPPER_CLASS) === -1)) {\n\n aspectWrapper = aspectWrapper.parentNode;\n parents++;\n if (parents > 4) {\n // Do not search further 4 parents.\n aspectWrapper = null;\n }\n }\n\n var maxWidthWrapper = aspectWrapper && aspectWrapper.parentNode;\n if (maxWidthWrapper \n && maxWidthWrapper.getAttribute('class')\n && maxWidthWrapper.getAttribute('class').split(' ').indexOf(iframely.MAXWIDTH_WRAPPER_CLASS) > -1) {\n\n // Remove wrapper specific data. Leave only 'iframely-embed' parent class.\n aspectWrapper.removeAttribute('style');\n aspectWrapper.removeAttribute('class');\n maxWidthWrapper.removeAttribute('style');\n }\n}\n\niframely.on('import-widget-ready', clearWrapperStylesAndClass);\n\n// used in server templates\n\nif (!iframely.addEventListener) {\n iframely.addEventListener = function(elem, type, eventHandle) {\n if (!elem) { return; }\n if ( elem.addEventListener ) {\n elem.addEventListener( type, eventHandle, false );\n } else if ( elem.attachEvent ) {\n elem.attachEvent( 'on' + type, eventHandle );\n } else {\n elem['on' + type] = eventHandle;\n }\n };\n}\n\nfunction exec_body_scripts(body_el) {\n function nodeName(elem, name) {\n return elem.nodeName && elem.nodeName.toUpperCase() ===\n name.toUpperCase();\n }\n\n function evalScript(elem) {\n var data = (elem.text || elem.textContent || elem.innerHTML || '' ),\n script = utils.createScript();\n\n // Copy all script attributes.\n script.type = 'text/javascript';\n for (var i = 0; i < elem.attributes.length; i++) {\n var attr = elem.attributes[i];\n script.setAttribute(attr.name, attr.value);\n }\n try {\n // doesn't work on ie...\n script.appendChild(document.createTextNode(data));\n } catch(e) {\n // IE has funky script nodes\n script.text = data;\n }\n\n body_el.appendChild(script);\n }\n\n // main section of function\n var scripts = [],\n script,\n children_nodes = body_el.childNodes,\n child,\n i;\n\n for (i = 0; children_nodes[i]; i++) {\n child = children_nodes[i];\n if (nodeName(child, 'script' ) &&\n (!child.type || child.type.toLowerCase() === 'text/javascript' || child.type.toLowerCase() === 'application/javascript')) {\n scripts.push(child);\n body_el.removeChild(child);\n } else {\n exec_body_scripts(child);\n }\n }\n\n for (i = 0; scripts[i]; i++) {\n script = scripts[i];\n if (script.parentNode) {script.parentNode.removeChild(script);}\n evalScript(scripts[i]);\n }\n}\n\n//# sourceURL=webpack:///./import.js?\n}"); - -/***/ }, - -/***/ "./index.js" -/*!******************!*\ - !*** ./index.js ***! - \******************/ -(__unused_webpack_module, exports, __webpack_require__) { - -eval("{__webpack_require__(/*! ./dom-ready */ \"./dom-ready.js\");\n\nvar iframely = __webpack_require__(/*! ./iframely */ \"./iframely.js\");\n\nif (!iframely._loaded) {\n\n iframely._loaded = true;\n\n __webpack_require__(/*! ./const */ \"./const.js\");\n __webpack_require__(/*! ./events */ \"./events.js\");\n // require('./utils'); // Loaded by other modules.\n __webpack_require__(/*! ./intersection */ \"./intersection.js\");\n __webpack_require__(/*! ./theme */ \"./theme.js\");\n __webpack_require__(/*! ./import */ \"./import.js\");\n __webpack_require__(/*! ./ahref */ \"./ahref.js\");\n __webpack_require__(/*! ./lazy-img-placeholder */ \"./lazy-img-placeholder.js\");\n __webpack_require__(/*! ./lazy-iframe */ \"./lazy-iframe.js\");\n // require('./messaging'); // Loaded by other modules.\n __webpack_require__(/*! ./widget-cancel */ \"./widget-cancel.js\");\n __webpack_require__(/*! ./widget-resize */ \"./widget-resize.js\");\n __webpack_require__(/*! ./widget-click */ \"./widget-click.js\");\n __webpack_require__(/*! ./widget-options */ \"./widget-options.js\");\n __webpack_require__(/*! ./deprecated */ \"./deprecated.js\");\n __webpack_require__(/*! ./lazy-loading-native */ \"./lazy-loading-native.js\");\n\n iframely.trigger('init'); \n}\n\nexports.iframely = iframely;\n\n//# sourceURL=webpack:///./index.js?\n}"); - -/***/ }, - -/***/ "./intersection.js" -/*!*************************!*\ - !*** ./intersection.js ***! - \*************************/ -(__unused_webpack_module, __unused_webpack_exports, __webpack_require__) { - -eval("{var messaging = __webpack_require__(/*! ./messaging */ \"./messaging.js\");\nvar iframely = __webpack_require__(/*! ./iframely */ \"./iframely.js\");\n\nvar observers = {};\n\nfunction getObserver(options) {\n var optionsKey = JSON.stringify(options);\n var observer = observers[optionsKey];\n if (!observer) {\n\n observer = new IntersectionObserver(function(entries) {\n\n entries.forEach(function(entry) {\n messaging.postMessage({\n method: 'intersection',\n entry: {\n isIntersecting: entry.isIntersecting\n },\n options: options\n }, '*', entry.target.contentWindow);\n });\n\n }, getObserverOptions(options));\n\n observers[optionsKey] = observer;\n }\n return observer;\n}\n\nfunction getObserverOptions(options) {\n var result = {};\n if (options && options.threshold) {\n result.threshold = options.threshold;\n }\n if (options && options.margin) {\n result.rootMargin = options.margin + 'px ' + options.margin + 'px ' + options.margin + 'px ' + options.margin + 'px';\n }\n return result;\n}\n\nif ('IntersectionObserver' in window &&\n 'IntersectionObserverEntry' in window) {\n\n iframely.on('init', function() {\n\n iframely.extendOptions({\n intersection: 1\n });\n \n });\n\n iframely.on('message', function(widget, message) {\n if (message.method === 'send-intersections' && widget.iframe) {\n\n var options = message.options;\n\n if (!options) {\n options = {\n margin: 1000\n };\n }\n\n getObserver(options).observe(widget.iframe);\n }\n });\n}\n\n\n//# sourceURL=webpack:///./intersection.js?\n}"); - -/***/ }, - -/***/ "./lazy-iframe.js" -/*!************************!*\ - !*** ./lazy-iframe.js ***! - \************************/ -(__unused_webpack_module, __unused_webpack_exports, __webpack_require__) { - -eval("{var utils = __webpack_require__(/*! ./utils */ \"./utils.js\");\nvar iframely = __webpack_require__(/*! ./iframely */ \"./iframely.js\");\n\n// Need 'load' handler here instead of on('init') - we load lazy iframes only when DOM ready.\niframely.on('load', function(el) { \n\n if (!el) { // initial load\n\n var elements = document.querySelectorAll('iframe[data-iframely-url]');\n for(var i = 0; i < elements.length; i++) {\n iframely.trigger('load', elements[i]);\n } \n }\n \n});\n\niframely.on('load', function(el) {\n\n if (el && el.nodeName === 'IFRAME'\n && el.hasAttribute('data-iframely-url')\n && !el.hasAttribute('data-img')\n && !el.getAttribute('src')) {\n\n loadLazyIframe(el);\n }\n \n});\n\n\nfunction loadLazyIframe(el) {\n\n var widget = utils.getWidget(el);\n var src = el.getAttribute('data-iframely-url');\n var dataImg = el.hasAttribute('data-img-created') || el.hasAttribute('data-img');\n var nativeLazyLoad = !dataImg && iframely.SUPPORT_IFRAME_LOADING_ATTR;\n\n if (widget && src) {\n\n var options = {\n v: iframely.VERSION,\n app: 1, // for example, will fall back to summary card if media is not longer available\n theme: iframely.config.theme\n };\n\n if (!nativeLazyLoad && iframely.config.intersection) {\n options.lazy = 1;\n }\n\n src = utils.getEndpoint(src, options);\n\n }\n\n if (nativeLazyLoad) {\n el.setAttribute('loading', 'lazy');\n }\n\n if (dataImg && iframely.SUPPORT_IFRAME_LOADING_ATTR) {\n // Disable lazy load with `data-img`.\n el.setAttribute('loading', 'edge');\n }\n\n el.setAttribute('src', src);\n el.removeAttribute('data-iframely-url');\n\n iframely.trigger('iframe-ready', el);\n}\n\n//# sourceURL=webpack:///./lazy-iframe.js?\n}"); - -/***/ }, - -/***/ "./lazy-img-placeholder.js" -/*!*********************************!*\ - !*** ./lazy-img-placeholder.js ***! - \*********************************/ -(__unused_webpack_module, __unused_webpack_exports, __webpack_require__) { - -eval("{var utils = __webpack_require__(/*! ./utils */ \"./utils.js\");\nvar iframely = __webpack_require__(/*! ./iframely */ \"./iframely.js\");\n\niframely.on('load', function(el) {\n\n if (el && el.nodeName === 'IFRAME'\n && el.hasAttribute('data-iframely-url')\n && el.hasAttribute('data-img')\n && !el.getAttribute('src')) {\n\n var dataImg = el.getAttribute('data-img');\n\n el.removeAttribute('data-img');\n el.setAttribute('data-img-created', '');\n\n var widget = utils.getWidget(el);\n var src = el.getAttribute('data-iframely-url');\n\n addPlaceholderThumbnail(widget, src, dataImg);\n\n src = utils.addQueryString(src, {img: 1});\n el.setAttribute('data-iframely-url', src);\n\n new WaitingWidget(widget);\n\n iframely.trigger('load', el);\n\n }\n});\n\niframely.on('message', function(widget, message) {\n\n var waitingWidget;\n\n if (message.method === 'widgetRendered') {\n hidePlaceholderThumbnail(widget);\n\n waitingWidget = findWaitingWidget(widget);\n waitingWidget && waitingWidget.deactivate();\n }\n\n if (message.method === 'begin-waiting-widget-render') {\n waitingWidget = findWaitingWidget(widget);\n waitingWidget && waitingWidget.clearLoadingTimeout();\n }\n\n if (message.method === 'end-waiting-widget-render') {\n waitingWidget = findWaitingWidget(widget);\n waitingWidget && waitingWidget.registerLoadingTimeout();\n }\n});\n\n\nfunction addPlaceholderThumbnail(widget, href, imageUrl) {\n\n var thumbHref;\n\n if (imageUrl && /^(https?:)?\\/\\//.test(imageUrl)) {\n thumbHref = imageUrl;\n } else {\n\n // Start of image url calculation.\n \n var query = utils.parseQueryString(href);\n \n // Extract widget params to invalidate image cache.\n var _params = {};\n for(var param in query) {\n if (param.indexOf('_') === 0) {\n _params[param] = query[param];\n }\n }\n\n // Force proxy `media` param.\n if (query.media) {\n _params.media = query.media;\n }\n \n // need to run through getEndpoint at least to avoid file:///\n if (href.match(/\\/api\\/iframe/)) {\n thumbHref = utils.getEndpoint(href.match(/^(.+)\\/api\\/iframe/i)[1] + '/api/thumbnail', Object.assign({\n url: query.url,\n api_key: query.api_key,\n key: query.key\n }, _params));\n } else if (href.match(iframely.ID_RE)) {\n // RE copied from `iframely.ID_RE` and modified to replace path part.\n thumbHref = utils.getEndpoint(href.replace(/^((?:https?:)?\\/\\/[^/]+\\/(\\w+-?\\w+))(?:\\?.*)?$/, '$1/thumbnail'), _params);\n } else {\n return;\n }\n }\n\n // End of image url calculation.\n\n var thumb = document.createElement('div');\n // Parent div not always has ASPECT_WRAPPER_CLASS. Need explicit inline styles.\n utils.setStyles(thumb, {\n position: 'absolute',\n width: '100%',\n height: '100%',\n backgroundImage: \"url('\" + thumbHref + \"')\",\n backgroundSize: 'cover',\n backgroundPosition: 'center'\n });\n\n var iframelyLoaderDiv = document.createElement('div');\n iframelyLoaderDiv.setAttribute('class', iframely.LOADER_CLASS);\n thumb.appendChild(iframelyLoaderDiv);\n\n var paddingTop = iframely.getElementComputedStyle(widget.aspectWrapper, 'padding-top');\n var paddingBottom = iframely.getElementComputedStyle(widget.aspectWrapper, 'padding-bottom');\n\n var paddingTopMatch = paddingTop.match(/^(\\d+)px$/);\n var paddingTopInt = paddingTopMatch && parseInt(paddingTopMatch[1]);\n\n if (paddingTopInt && paddingBottom) {\n\n var thumbWrapper = document.createElement('div');\n\n utils.setStyles(thumbWrapper, {\n top: '-' + paddingTop,\n width: '100%',\n height: 0,\n position: 'relative',\n paddingBottom: paddingBottom\n }); \n\n thumbWrapper.appendChild(thumb);\n\n widget.aspectWrapper.appendChild(thumbWrapper);\n\n } else {\n\n widget.aspectWrapper.appendChild(thumb);\n }\n}\n\nfunction getNthNonTextChildNode(nth, element) {\n var count = 0;\n for(var i = 0; i < element.childNodes.length; i++) {\n var el = element.childNodes[i];\n if (el.nodeType === Node.TEXT_NODE) {\n // Nop.\n } else if (el.nodeType === Node.ELEMENT_NODE) {\n if (nth === count) {\n return el;\n }\n count++;\n }\n }\n}\n\nfunction nonTextChildCount(element) {\n var count = 0;\n for(var i = 0; i < element.childNodes.length; i++) {\n var el = element.childNodes[i];\n if (el.nodeType === Node.TEXT_NODE) {\n var text = el.textContent || el.innerText;\n text = text.replace(/\\s|\\n/g, '');\n if (text) {\n // Do not skip text node with text.\n count++;\n }\n } else if (el.nodeType === Node.ELEMENT_NODE) {\n count++;\n }\n }\n return count;\n}\n\nfunction hidePlaceholderThumbnail(widget) {\n var thumb = widget.aspectWrapper && nonTextChildCount(widget.aspectWrapper) > 1 && getNthNonTextChildNode(1, widget.aspectWrapper);\n if (thumb && thumb.nodeName === 'DIV') {\n widget.aspectWrapper.removeChild(thumb);\n }\n}\n\n//===\n\n// Working WaitingWidgets' collection.\n\nvar waitingWidgets = [];\n\nfunction findWaitingWidgetIdx(widget) {\n var i = 0;\n while(i < waitingWidgets.length && waitingWidgets[i].widget.iframe !== widget.iframe) {\n i++;\n }\n if (i < waitingWidgets.length && waitingWidgets[i].widget.iframe === widget.iframe) {\n return i;\n }\n}\n\nfunction findWaitingWidget(widget) {\n var idx = findWaitingWidgetIdx(widget);\n if (idx || idx === 0) {\n return waitingWidgets[idx];\n }\n}\n\nfunction removeWaitingWidget(widget) {\n var idx = findWaitingWidgetIdx(widget);\n if (idx || idx === 0) {\n waitingWidgets.splice(idx, 1);\n }\n}\n\n//===\n\n// WaitingWidget proto.\n\nfunction WaitingWidget(widget) {\n this.widget = widget;\n this.loadCount = 0;\n\n var iframe = widget.iframe;\n\n var that = this;\n function iframeOnLoad() {\n // Bind method to self.\n that.iframeOnLoad();\n }\n\n iframely.addEventListener(iframe, 'load', iframeOnLoad);\n\n this.registerLoadingTimeout();\n\n waitingWidgets.push(this);\n}\n\nWaitingWidget.prototype.iframeOnLoad = function() {\n\n this.loadCount++;\n\n // Skip first load of hosted widget OR timeout call.\n if (this.loadCount !== 2) {\n return;\n }\n\n this.deactivate();\n\n var that = this;\n setTimeout(function() {\n hidePlaceholderThumbnail(that.widget);\n }, iframely.LAZY_IFRAME_FADE_TIMEOUT);\n};\n\nWaitingWidget.prototype.deactivate = function() {\n this.clearLoadingTimeout();\n removeWaitingWidget(this);\n};\n\nWaitingWidget.prototype.clearLoadingTimeout = function() {\n this.timeoutId && clearTimeout(this.timeoutId);\n this.timeoutId = null;\n};\n\nWaitingWidget.prototype.registerLoadingTimeout = function() {\n if (this.timeoutId) {\n return;\n }\n var that = this;\n this.timeoutId = setTimeout(function() {\n that.iframeOnLoad();\n }, iframely.LAZY_IFRAME_SHOW_TIMEOUT);\n};\n\n\n//# sourceURL=webpack:///./lazy-img-placeholder.js?\n}"); - -/***/ }, - -/***/ "./lazy-loading-native.js" -/*!********************************!*\ - !*** ./lazy-loading-native.js ***! - \********************************/ -(__unused_webpack_module, __unused_webpack_exports, __webpack_require__) { - -eval("{function getChromeVersion() { \n var raw = navigator.userAgent.match(/Chrom(e|ium)\\/([0-9]+)\\./);\n\n return raw ? parseInt(raw[2], 10) : false;\n}\nvar chromeVersion = getChromeVersion();\n\nvar iframely = __webpack_require__(/*! ./iframely */ \"./iframely.js\");\niframely.SUPPORT_IFRAME_LOADING_ATTR = chromeVersion && chromeVersion >= 77;\n\n//# sourceURL=webpack:///./lazy-loading-native.js?\n}"); - -/***/ }, - -/***/ "./messaging.js" -/*!**********************!*\ - !*** ./messaging.js ***! - \**********************/ -(__unused_webpack_module, exports, __webpack_require__) { - -eval("{var iframely = __webpack_require__(/*! ./iframely */ \"./iframely.js\");\nvar utils = __webpack_require__(/*! ./utils */ \"./utils.js\");\n\nfunction receiveMessage(callback) {\n\n function cb(e) {\n var message;\n try {\n if (typeof e.data === 'string') {\n message = JSON.parse(e.data);\n } else if (typeof e.data === 'object') {\n message = e.data;\n }\n } catch (ex) {\n if (typeof e.data === 'string') {\n var m = e.data.match(/heightxPYMx(\\d+)/);\n if (m) {\n message = {\n method: 'resize',\n height: parseInt(m[1]) + 1,\n domains: 'all'\n };\n }\n }\n }\n\n callback(e, message);\n }\n\n // browser supports window.postMessage\n if (window['postMessage']) {\n if (window['addEventListener']) {\n window[callback ? 'addEventListener' : 'removeEventListener']('message', cb, !1);\n } else {\n window[callback ? 'attachEvent' : 'detachEvent']('onmessage', cb);\n }\n }\n}\n\nfunction findIframeByContentWindow(iframes, contentWindow) {\n var foundIframe;\n for(var i = 0; i < iframes.length && !foundIframe; i++) {\n var iframe = iframes[i];\n if (iframe.contentWindow === contentWindow) {\n foundIframe = iframe;\n }\n }\n return foundIframe;\n}\n\nfunction findIframeInElement(element, options) {\n var foundIframe, iframes;\n \n if (options.src) {\n iframes = element.querySelectorAll('iframe[src*=\"' + options.src.replace(/^https?:/, '') + '\"]');\n foundIframe = findIframeByContentWindow(iframes, options.contentWindow);\n }\n\n if (!foundIframe) {\n iframes = options.domains ?\n element.querySelectorAll('iframe[src*=\"' + (options.domains || iframely.DOMAINS).join('\"], iframe[src*=\"') + '\"]')\n : element.getElementsByTagName('iframe');\n foundIframe = findIframeByContentWindow(iframes, options.contentWindow);\n }\n\n return foundIframe;\n}\n\nfunction findIframeInShadowRoots(element, options) {\n var foundIframe;\n var className = '.' + (iframely.config.shadow || iframely.SHADOW);\n var shadowRoots = element.querySelectorAll(className);\n for(var i = 0; i < shadowRoots.length && !foundIframe; i++) {\n var shadowRoot = shadowRoots[i].shadowRoot;\n if (shadowRoot) {\n foundIframe = findIframeInElement(shadowRoot, options);\n if (!foundIframe) {\n foundIframe = findIframeInShadowRoots(shadowRoot, options);\n }\n }\n }\n return foundIframe;\n}\n\n// Do not override existing.\nif (!iframely.findIframe) {\n iframely.findIframe = function(options) {\n var foundIframe = findIframeInElement(document, options);\n if (!foundIframe) {\n foundIframe = findIframeInShadowRoots(document, options);\n }\n return foundIframe;\n };\n}\n\n\nreceiveMessage(function(e, message) {\n\n if (message && (message.method || message.type || message.context)) {\n\n var foundIframe = iframely.findIframe({\n contentWindow: e.source,\n src: message.src || message.context,\n domains: message.domains !== 'all' && iframely.DOMAINS.concat(iframely.CDN)\n });\n\n if (foundIframe) {\n var widget = utils.getWidget(foundIframe);\n if (widget && message.url) {\n widget.url = message.url;\n }\n iframely.trigger('message', widget, message);\n }\n }\n \n});\n\n\nexports.postMessage = function(message, target_url, target) {\n if (window['postMessage']) {\n\n if (typeof message === 'object') {\n message.context = document.location.href;\n }\n\n message = JSON.stringify(message);\n\n target_url = target_url || '*';\n\n target = target || window.parent; // default to parent\n\n // the browser supports window.postMessage, so call it with a targetOrigin\n // set appropriately, based on the target_url parameter.\n target['postMessage'](message, target_url.replace( /([^:]+:\\/\\/[^/]+).*/, '$1'));\n }\n};\n\n\n//# sourceURL=webpack:///./messaging.js?\n}"); - -/***/ }, - -/***/ "./theme.js" -/*!******************!*\ - !*** ./theme.js ***! - \******************/ -(__unused_webpack_module, __unused_webpack_exports, __webpack_require__) { - -eval("{var iframely = __webpack_require__(/*! ./iframely */ \"./iframely.js\");\nvar messaging = __webpack_require__(/*! ./messaging */ \"./messaging.js\");\n\nfunction setThemeInIframe(iframe, theme) {\n messaging.postMessage({\n method: 'setTheme',\n data: theme\n }, '*', iframe.contentWindow);\n}\n\nfunction setThemeInAllIframes(parent, theme) {\n var iframes = parent.getElementsByTagName('iframe');\n for(var i = 0; i < iframes.length; i++) {\n var iframe = iframes[i];\n setThemeInIframe(iframe, theme);\n }\n}\n\niframely.setTheme = function(theme, container) {\n if (theme && iframely.SUPPORTED_THEMES.indexOf(theme) > -1) {\n if (container) {\n if (container.tagName === 'IFRAME') {\n setThemeInIframe(container, theme);\n } else {\n setThemeInAllIframes(container, theme);\n }\n } else {\n // Send get param to next iframes.\n iframely.extendOptions({\n theme: theme\n });\n setThemeInAllIframes(document, theme);\n iframely.trigger('set-theme', theme);\n }\n } else {\n console.warn('Using iframely.setTheme with not supported theme: \"' + theme + '\". Supported themes are: ' + iframely.SUPPORTED_THEMES.join(', '));\n }\n};\n\n//# sourceURL=webpack:///./theme.js?\n}"); - -/***/ }, - -/***/ "./utils.js" -/*!******************!*\ - !*** ./utils.js ***! - \******************/ -(__unused_webpack_module, exports, __webpack_require__) { - -eval("{var iframely = __webpack_require__(/*! ./iframely */ \"./iframely.js\");\nvar messaging = __webpack_require__(/*! ./messaging */ \"./messaging.js\");\n\niframely.on('init', function() {\n\n\n iframely.extendOptions(parseQueryStringFromScriptSrc());\n // if it's hosted from elsewhere - we don't support customizing via query-string.\n // iframely.CDN will be default one unless changed by user (?cdn= or iframely.CDN= )\n\n defineDefaultStyles();\n\n // Set theme for existing iframes.\n if (iframely.config.theme) {\n iframely.setTheme(iframely.config.theme);\n }\n\n requestSizeOfExistingIframes(iframely.DOMAINS.concat(iframely.CDN.replace(/^https?:\\/\\//, '')));\n \n});\n\niframely.load = function() {\n var args = Array.prototype.slice.call(arguments);\n args.unshift('load');\n iframely.trigger.apply(this, args);\n};\n\nvar getIframeWrapper = exports.getIframeWrapper = function(iframe, checkClass) {\n\n var aspectWrapper = iframe.parentNode;\n\n if (!aspectWrapper\n || aspectWrapper.nodeName !== 'DIV'\n || nonTextChildCount(aspectWrapper) > 2 /* 2 is lazy-cover */\n || (checkClass && aspectWrapper.getAttribute('class') !== iframely.ASPECT_WRAPPER_CLASS)\n || (!checkClass && aspectWrapper.style.position !== 'relative' && aspectWrapper.getAttribute('class') !== iframely.ASPECT_WRAPPER_CLASS)) {\n return;\n }\n\n var maxWidthWrapper = aspectWrapper.parentNode;\n\n if (!maxWidthWrapper\n || maxWidthWrapper.nodeName !== 'DIV'\n || nonTextChildCount(maxWidthWrapper) > 1\n || (checkClass && maxWidthWrapper.getAttribute('class') && maxWidthWrapper.getAttribute('class').split(' ').indexOf(iframely.MAXWIDTH_WRAPPER_CLASS) === -1)\n || (!checkClass && maxWidthWrapper.getAttribute('class') && !maxWidthWrapper.getAttribute('class').match(/iframely/i) /* users can modify class */)\n ) {\n return;\n }\n\n return {\n aspectWrapper: aspectWrapper,\n maxWidthWrapper: maxWidthWrapper\n };\n};\n\nexports.addDefaultWrappers = function(el) {\n var parentNode = el.parentNode;\n\n var maxWidthWrapper = document.createElement('div');\n maxWidthWrapper.className = iframely.MAXWIDTH_WRAPPER_CLASS;\n\n var aspectWrapper = document.createElement('div');\n aspectWrapper.className = iframely.ASPECT_WRAPPER_CLASS;\n\n maxWidthWrapper.appendChild(aspectWrapper);\n\n parentNode.insertBefore(maxWidthWrapper, el);\n\n return {\n aspectWrapper: aspectWrapper,\n maxWidthWrapper: maxWidthWrapper\n };\n};\n\nexports.getWidget = function(iframe) {\n var wrapper = getIframeWrapper(iframe);\n if (!wrapper) {\n return;\n }\n var widget = {\n iframe: iframe, // can actually be ahref\n aspectWrapper: wrapper.aspectWrapper,\n maxWidthWrapper: wrapper.maxWidthWrapper\n };\n if (iframe.nodeName === 'A' && iframe.hasAttribute('href')) {\n widget.url = iframe.getAttribute('href');\n } else if (iframe.hasAttribute('src') && /url=/.test(iframe.getAttribute('src'))) {\n var qs = parseQueryString(iframe.getAttribute('src'));\n if (qs.url) {\n widget.url = qs.url;\n }\n }\n return widget;\n};\n\niframely.getElementComputedStyle = function(el, style) {\n return window.getComputedStyle && window.getComputedStyle(el).getPropertyValue(style);\n};\n\nexports.setStyles = function(el, styles) {\n if (el) { // let's check it's still defined, just in case\n Object.keys(styles).forEach(function(key) {\n\n var value = styles[key];\n if (typeof value === 'number' || (typeof value === 'string' && /^(\\d+)?\\.?(\\d+)$/.test(value))) {\n value = value + 'px';\n }\n\n var currentValue = el.style[key];\n\n if (!window.getComputedStyle ||\n // don't change CSS values in pixels, such as height:0\n (\n iframely.getElementComputedStyle(el, key) != value\n // && don't set default aspect ratio if it's defined in CSS anyway\n && !(el.className == 'iframely-responsive' && key === 'paddingBottom' && !currentValue && /^56\\.2\\d+%$/.test(value))\n // && do not change max-width if new value === 'keep'.\n && !(key === 'max-width' && value === 'keep')\n )) {\n\n el.style[key] = value || ''; // remove style that is no longer needed\n }\n });\n }\n};\n\nvar applyNonce = exports.applyNonce = function(element) {\n if (iframely.config.nonce) {\n element.nonce = iframely.config.nonce;\n }\n};\n\nfunction defineDefaultStyles() {\n\n var iframelyStylesId = 'iframely-styles';\n var styles = document.getElementById(iframelyStylesId);\n\n if (!styles) {\n // copy-paste default styles from https://iframely.com/docs/omit-css\n // box-sizing:border-box - need for iOS Safari .\n var iframelyStyles = '.iframely-responsive{top:0;left:0;width:100%;height:0;position:relative;padding-bottom:56.25%;box-sizing:border-box;}.iframely-responsive>*{top:0;left:0;width:100%;height:100%;position:absolute;border:0;box-sizing:border-box;}';\n\n styles = document.createElement('style');\n styles.id = iframelyStylesId;\n styles.type = 'text/css';\n applyNonce(styles);\n\n if (styles.styleSheet) {\n // IE.\n styles.styleSheet.cssText = iframelyStyles;\n } else {\n styles.innerHTML = iframelyStyles;\n }\n document.getElementsByTagName('head')[0].appendChild(styles);\n }\n}\n\n\nvar addQueryString = exports.addQueryString = function(href, options) {\n\n var query_string = '';\n\n Object.keys(options).forEach(function(key) {\n var value = options[key];\n\n // array is used e.g. for import: uris and ids\n if (Object.prototype.toString.call(value) === '[object Array]') {\n\n var values = value.map(function(uri) {\n return key + '=' + encodeURIComponent(uri);\n });\n query_string += '&' + values.join('&'); \n\n } else if (typeof value !== 'undefined' && href.indexOf(key + '=') === -1 ) { // set explicitely in options, skip undefines\n\n // Do not convert boolean for _option.\n if (typeof value === 'boolean' && key.charAt(0) !== '_') {\n value = value ? 1 : 0;\n }\n\n query_string += '&' + key + '=' + encodeURIComponent(value);\n }\n\n });\n\n return href + (query_string !== '' ? (href.indexOf('?') > -1 ? '&' : '?') + query_string.replace(/^&/, '') : '');\n};\n\nexports.getEndpoint = function(src, options, config_params) {\n\n var endpoint = src;\n\n if (!/^(https?:)?\\/\\//i.test(src)) {\n endpoint = (options.CDN || iframely.CDN) + endpoint;\n delete options.CDN;\n }\n\n if (!/^(?:https?:)?\\/\\//i.test(endpoint)) {\n endpoint = '//' + endpoint;\n } \n\n if (options) {\n endpoint = addQueryString(endpoint, options);\n }\n\n // get additional params from config\n if (config_params && config_params.length) {\n\n var more_options = {};\n\n var iframely_config_keys = Object.keys(iframely.config);\n for (var i = 0; i < iframely_config_keys.length; i++) {\n var key = iframely_config_keys[i];\n if (containsString(config_params, key)) {\n more_options[key] = iframely.config[key];\n }\n }\n\n endpoint = addQueryString(endpoint, more_options);\n }\n\n\n if (/^(https?:)?\\/\\//i.test(endpoint) // Path is url.\n && !endpoint.match(/^(https?:)?\\/\\//i)[1] // No http protocol specified.\n && document.location.protocol !== 'http:' // Document in `file:` or other protocol.\n && document.location.protocol !== 'https:') {\n\n endpoint = 'https:' + endpoint;\n }\n\n return endpoint;\n};\n\n// helper method to init more options through js code\niframely.extendOptions = function(options) {\n\n options && Object.keys(options).forEach(function(key) {\n var new_value = (\n options[key] === 0 || options[key] === '0' || options[key] === false || options[key] === 'false'\n ? false : (options[key] === 1 || options[key] === '1' || options[key] === true || options[key] === 'true'\n ? true : options[key]));\n\n if (iframely.config[key] !== false) { // set new value only when undefined or not previously disabled\n iframely.config[key] = new_value;\n }\n });\n\n};\n\nfunction parseQueryStringFromScriptSrc() {\n\n // Extract global iframely params.\n var scripts = document.querySelectorAll('script[src*=\"embed.js\"], script[src*=\"iframely.js\"]');\n\n for(var i = 0; i < scripts.length; i++) {\n var src = scripts[i].getAttribute('src').replace(/&/gi, '&');\n\n if (iframely.SCRIPT_RE.test(src)) { // found the script on custom origin or default Iframely CDN\n\n var options = parseQueryString(src, iframely.SUPPORTED_QUERY_STRING.concat('cdn', 'cancel', 'nonce'));\n\n var m2 = src.match(iframely.CDN_RE);\n if (m2 || options.cdn) { // ignore non-Iframely hosts such as s.imgur.com/min/embed.js\n iframely.CDN = options.cdn || m2[1];\n }\n\n if (options.cancel) {\n if (options.cancel === '0' || options.cancel === 'false') {\n iframely.RECOVER_HREFS_ON_CANCEL = true;\n }\n delete options.cancel;\n }\n\n if (Object.keys(options).length > 0) {\n // give preferrence to CDN from scripts that have query-string. \n // CDN is most critical for embeds with empty data-iframely-url\n // and those should have at least ?api_key... in script src\n\n return options;\n } // or keep searching\n }\n }\n // should have exited by now if any querystring found...\n return {};\n}\n\nfunction requestSizeOfExistingIframes(domains) {\n\n var iframes = document.querySelectorAll('iframe[src*=\"' + (domains || iframely.DOMAINS).join('\"], iframe[src*=\"') + '\"]');\n for(var i = 0; i < iframes.length; i++) {\n var iframe = iframes[i];\n var src = iframe.src;\n if (src.match(/^(https?:)?\\/\\/[^/]+\\/api\\/iframe\\?.+/)\n || src.match(/^(https?:)?\\/\\/[^/]+\\/\\w+(\\?.*)?$/)) {\n messaging.postMessage({\n method: 'getSize'\n }, '*', iframe.contentWindow);\n }\n }\n} \n\nfunction nonTextChildCount(element) {\n var count = 0;\n for(var i = 0; i < element.childNodes.length; i++) {\n var el = element.childNodes[i];\n if (el.nodeType === Node.TEXT_NODE) {\n var text = el.textContent || el.innerText;\n text = text.replace(/\\s|\\n/g, '');\n if (text) {\n // Do not skip text node with text.\n count++;\n }\n } else if (el.nodeType === Node.ELEMENT_NODE) {\n count++;\n }\n }\n return count;\n}\n\nfunction containsString(list, findValue) {\n var value, i = 0;\n while (i < list.length) {\n value = list[i];\n\n if (value == findValue) {\n return true;\n }\n\n if (value && value.test && value.test(findValue)) {\n return true;\n }\n\n i++;\n }\n}\n\nvar parseQueryString = exports.parseQueryString = function(url, allowed_query_string) {\n var query = url.match(/\\?(.+)/i);\n if (query) {\n query = query[1];\n var data = query.split('&');\n var result = {};\n for(var i=0; i= 0;\n }\n return found && el;\n }\n\n var parentNode = widget.maxWidthWrapper && widget.maxWidthWrapper.parentNode;\n var naNode = widget.maxWidthWrapper;\n\n // Try remove by parentClass first.\n if (iframely.config && iframely.config.parent) {\n // Remove by parent class.\n var parentElement = findParent(widget.maxWidthWrapper, iframely.config.parent);\n\n if (parentElement) {\n parentNode = parentElement.parentNode;\n naNode = parentElement;\n }\n }\n\n if (widget.url) {\n var text = widget.iframe && (widget.iframe.textContent || widget.iframe.innerText);\n\n iframely.triggerAsync('cancel', widget.url, parentNode, text, naNode.nextSibling);\n }\n // Re-creating a link if people had it as text is now deprecated (see in deprecated.js)\n // New use: iframely.on('cancel', function(url, parentNode, text) {...} );\n\n parentNode.removeChild(naNode);\n};\n\n//# sourceURL=webpack:///./widget-cancel.js?\n}"); - -/***/ }, - -/***/ "./widget-click.js" -/*!*************************!*\ - !*** ./widget-click.js ***! - \*************************/ -(__unused_webpack_module, __unused_webpack_exports, __webpack_require__) { - -eval("{var iframely = __webpack_require__(/*! ./iframely */ \"./iframely.js\");\n\niframely.on('message', function(widget, message) {\n if (message.method === 'open-href' || message.method === 'click') {\n iframely.trigger(message.method, message.href);\n }\n});\n\n// Do not override user defined handler.\nif (!iframely.openHref) {\n iframely.openHref = function(href) {\n if (href.indexOf(window.location.origin) === 0) {\n // Redirect top on same origin.\n window.location.href = href;\n } else {\n // Open new tab on another origin.\n window.open(href, '_blank', 'noopener');\n }\n };\n}\n\niframely.on('open-href', function(href) {\n iframely.triggerAsync('click', href);\n iframely.openHref(href);\n});\n\n//# sourceURL=webpack:///./widget-click.js?\n}"); - -/***/ }, - -/***/ "./widget-options.js" -/*!***************************!*\ - !*** ./widget-options.js ***! - \***************************/ -(__unused_webpack_module, __unused_webpack_exports, __webpack_require__) { - -eval("{var iframely = __webpack_require__(/*! ./iframely */ \"./iframely.js\");\n\niframely.on('message', function(widget, message) {\n if (message.method === 'setIframelyEmbedOptions') {\n iframely.trigger('options', widget, message.data);\n }\n});\n\n\n//# sourceURL=webpack:///./widget-options.js?\n}"); - -/***/ }, - -/***/ "./widget-resize.js" -/*!**************************!*\ - !*** ./widget-resize.js ***! - \**************************/ -(__unused_webpack_module, __unused_webpack_exports, __webpack_require__) { - -eval("{var utils = __webpack_require__(/*! ./utils */ \"./utils.js\");\nvar iframely = __webpack_require__(/*! ./iframely */ \"./iframely.js\");\n\niframely.on('message', function(widget, message) {\n\n if (message.method === 'setIframelyWidgetSize' \n || message.method === 'resize' \n || message.method === 'setIframelyEmbedData' \n || message.type === 'embed-size'\n || message.context === 'iframe.resize') {\n\n var frame_styles = null;\n\n if (message.data && message.data.media && message.data.media.frame_style) {\n\n message.data.media.frame_style.split(';').forEach(function(str) {\n\n if(str.trim() !== '' && str.indexOf(':') > -1) {\n var props = str.split(':');\n if (props.length === 2) {\n frame_styles = frame_styles || {};\n frame_styles[props[0].trim()] = props[1].trim();\n }\n }\n });\n\n widgetDecorate(widget, frame_styles);\n\n } else if (message.method === 'setIframelyEmbedData') {\n\n // setIframelyEmbedData always sets frame_style. If not - reset.\n // setIframelyEmbedData without message.data resets border.\n widgetDecorate(widget, null);\n }\n\n var media = message.data && message.data.media;\n if (!media && message.height) {\n media = {\n height: message.height,\n 'max-width': 'keep'\n };\n }\n\n widgetResize(widget, media);\n }\n});\n\n// All frame_style attributes.\nvar resetWrapperBorderStyles = {'border': '', 'border-radius': '', 'box-shadow': '', 'overflow': ''};\nvar resetIframeBorderStyles = {'border': '0', 'border-radius': '', 'box-shadow': '', 'overflow': ''};\n\nfunction widgetDecorate(widget, styles) {\n\n if (styles && widget && widget.iframe) {\n\n if (styles['border-radius']) {\n // fix for Chrome?\n styles.overflow = 'hidden';\n utils.setStyles(widget.aspectWrapper, styles);\n } else {\n utils.setStyles(widget.iframe, styles);\n }\n\n } else if (!styles && widget && widget.iframe) {\n\n utils.setStyles(widget.aspectWrapper, resetWrapperBorderStyles);\n utils.setStyles(widget.iframe, resetIframeBorderStyles);\n }\n}\n\nfunction getTotalBorderWidth(widget) {\n\n // Get frame style from iframe or aspect wrapper as in widgetDecorate for Chrome fix.\n var frameStylesBorder = \n (widget.iframe && widget.iframe.style.border) \n || (widget.aspectWrapper && widget.aspectWrapper.style.border);\n\n // Get iframe border width from frame style.\n var borderWidth = frameStylesBorder && frameStylesBorder.match(/(\\d+)px/) || 0;\n if (borderWidth) {\n borderWidth = parseInt(borderWidth[1]);\n // For width and height border size will be 2x.\n borderWidth = borderWidth * 2;\n }\n\n return borderWidth;\n}\n\nfunction widgetResize(widget, media) {\n\n if (media && Object.keys(media).length > 0 && widget) {\n\n var borderWidth = getTotalBorderWidth(widget);\n\n var oldIframeHeight = window.getComputedStyle && window.getComputedStyle(widget.iframe).getPropertyValue('height');\n\n\n var maxWidth = media['max-width'];\n if (typeof maxWidth === 'number') {\n // Can be max-width: 56vh.\n maxWidth += borderWidth;\n }\n\n utils.setStyles(widget.maxWidthWrapper, {\n 'max-width': maxWidth,\n 'min-width': media['min-width'] && (media['min-width'] + borderWidth),\n width: media.width && (media.width + borderWidth)\n });\n\n if (media.scrolling && widget.iframe) {\n widget.iframe.setAttribute('scrolling', media.scrolling);\n }\n\n var aspectRatio = media['aspect-ratio'];\n\n // If no aspect and height - do not change aspect wrapper.\n if (aspectRatio || media.height) {\n utils.setStyles(widget.aspectWrapper, {\n paddingBottom: aspectRatio ? (Math.round(1000 * 100 / aspectRatio) / 1000 + '%') : 0, // if fixed-size, it will get set to 0\n paddingTop: aspectRatio && media['padding-bottom'], // if a fixed-height padding at the bottom of responsive div is required\n height: aspectRatio ? 0 : (media.height && (media.height + borderWidth)) // if defined\n });\n }\n\n\n var currentHeight = window.getComputedStyle && window.getComputedStyle(widget.iframe).getPropertyValue('height');\n\n if (oldIframeHeight && oldIframeHeight !== currentHeight) {\n iframely.triggerAsync('heightChanged', widget.iframe, oldIframeHeight, currentHeight);\n }\n\n }\n}\n\n\n//# sourceURL=webpack:///./widget-resize.js?\n}"); - -/***/ } - -/******/ }); -/************************************************************************/ -/******/ // 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 -/******/ if (!(moduleId in __webpack_modules__)) { -/******/ delete __webpack_module_cache__[moduleId]; -/******/ var e = new Error("Cannot find module '" + moduleId + "'"); -/******/ e.code = 'MODULE_NOT_FOUND'; -/******/ throw e; -/******/ } -/******/ __webpack_modules__[moduleId](module, module.exports, __webpack_require__); -/******/ -/******/ // Return the exports of the module -/******/ return module.exports; -/******/ } -/******/ -/************************************************************************/ -/******/ /* webpack/runtime/global */ -/******/ (() => { -/******/ __webpack_require__.g = (function() { -/******/ if (typeof globalThis === 'object') return globalThis; -/******/ try { -/******/ return this || new Function('return this')(); -/******/ } catch (e) { -/******/ if (typeof window === 'object') return window; -/******/ } -/******/ })(); -/******/ })(); -/******/ -/************************************************************************/ -/******/ -/******/ // startup -/******/ // Load entry module and return exports -/******/ // This entry module can't be inlined because the eval devtool is used. -/******/ var __webpack_exports__ = __webpack_require__("./index.js"); -/******/ -/******/ })() -; \ No newline at end of file +//#endregion +})(); \ No newline at end of file diff --git a/dist/embed.min.js b/dist/embed.min.js index efcca27..e7c4932 100644 --- a/dist/embed.min.js +++ b/dist/embed.min.js @@ -1 +1 @@ -(()=>{var e={679(e,t,r){var i=r(672),a=r(774);a.on("load",function(e,t){if(e&&e.nodeName&&"string"==typeof t){var r=document.createElement("a");r.setAttribute("href",t),e.appendChild(r),a.trigger("load",r)}}),a.on("load",function(e){if(!e&&!a.import)for(var t=document.querySelectorAll("a[data-iframely-url]:not([data-import-uri])"),r=0;r4&&(t=null);var i=t&&t.parentNode;i&&i.getAttribute("class")&&i.getAttribute("class").split(" ").indexOf(a.MAXWIDTH_WRAPPER_CLASS)>-1&&(t.removeAttribute("style"),t.removeAttribute("class"),i.removeAttribute("style"))}function c(e){function t(e,t){return e.nodeName&&e.nodeName.toUpperCase()===t.toUpperCase()}function r(t){var r=t.text||t.textContent||t.innerHTML||"",a=i.createScript();a.type="text/javascript";for(var n=0;n1&&function(e){var t=i.createScript(),r=[],o=[],s=null;function c(e,t){n[e]||(n[e]=[]),n[e].push(t)}function l(e){var t=e.getAttribute("data-iframely-url"),n=t.match(a.ID_RE),d=n&&n[1],l=i.parseQueryString(t,a.SUPPORTED_QUERY_STRING.concat("url")),p=l.url;delete l.url;var u="0"===l.import||"false"===l.import||"1"===l.playerjs||"true"===l.playerjs;if(!u){var m=t.match(a.BASE_RE);l.CDN=m&&m[0],s?JSON.stringify(l,Object.keys(l).sort())!==JSON.stringify(s,Object.keys(s).sort())&&(u=!0):s=l}u?a.trigger("load",e):d?(e.setAttribute("data-import-uri",d),-1===o.indexOf(d)&&o.push(d),c(d,e)):(p||(p=e.getAttribute("href")),(s.key||s.api_key||a.config.api_key||a.config.key)&&p?(e.setAttribute("data-import-uri",p),-1===r.indexOf(p)&&r.push(p),c(p,e)):a.trigger("load",e))}for(var p=0;p0||o.length>0?((s=s||{}).touch=a.isTouch(),s.flash=function(){var e=!1;try{e=!!new ActiveXObject("ShockwaveFlash.ShockwaveFlash")}catch(t){e=!(!navigator.mimeTypes||null==navigator.mimeTypes["application/x-shockwave-flash"]||!navigator.mimeTypes["application/x-shockwave-flash"].enabledPlugin)}return e}(),s.app=1,a.config.theme&&(s.theme=a.config.theme),r.length>0&&(s.uri=r),o.length>0&&(s.ids=o.join("&")),s.v=a.VERSION,t.src=i.getEndpoint("/api/import/v2",s,a.SUPPORTED_QUERY_STRING),t.onerror=function(){d()},document.head.appendChild(t),a.import=t):(d(),a.trigger("load"))}(t)}}),a.on("load",function(e,t){if(e&&e.uri&&(e.html||e.cancel)){var r=n[e.uri];if(r)for(var i=0;i1&&function(e,t){for(var r=0,i=0;i=77},369(e,t,r){var i=r(774),a=r(672);function n(e,t){for(var r,i=0;i-1?t?"IFRAME"===t.tagName?n(t,e):o(t,e):(i.extendOptions({theme:e}),o(document,e),i.trigger("set-theme",e)):console.warn('Using iframely.setTheme with not supported theme: "'+e+'". Supported themes are: '+i.SUPPORTED_THEMES.join(", "))}},672(e,t,r){var i=r(774),a=r(369);i.on("init",function(){i.extendOptions(function(){for(var e=document.querySelectorAll('script[src*="embed.js"], script[src*="iframely.js"]'),t=0;t0)return a}}return{}}()),function(){var e="iframely-styles",t=document.getElementById(e);if(!t){var r=".iframely-responsive{top:0;left:0;width:100%;height:0;position:relative;padding-bottom:56.25%;box-sizing:border-box;}.iframely-responsive>*{top:0;left:0;width:100%;height:100%;position:absolute;border:0;box-sizing:border-box;}";(t=document.createElement("style")).id=e,t.type="text/css",o(t),t.styleSheet?t.styleSheet.cssText=r:t.innerHTML=r,document.getElementsByTagName("head")[0].appendChild(t)}}(),i.config.theme&&i.setTheme(i.config.theme),function(e){for(var t=document.querySelectorAll('iframe[src*="'+(e||i.DOMAINS).join('"], iframe[src*="')+'"]'),r=0;r2||t&&r.getAttribute("class")!==i.ASPECT_WRAPPER_CLASS||!t&&"relative"!==r.style.position&&r.getAttribute("class")!==i.ASPECT_WRAPPER_CLASS)){var a=r.parentNode;if(!(!a||"DIV"!==a.nodeName||s(a)>1||t&&a.getAttribute("class")&&-1===a.getAttribute("class").split(" ").indexOf(i.MAXWIDTH_WRAPPER_CLASS)||!t&&a.getAttribute("class")&&!a.getAttribute("class").match(/iframely/i)))return{aspectWrapper:r,maxWidthWrapper:a}}};t.addDefaultWrappers=function(e){var t=e.parentNode,r=document.createElement("div");r.className=i.MAXWIDTH_WRAPPER_CLASS;var a=document.createElement("div");return a.className=i.ASPECT_WRAPPER_CLASS,r.appendChild(a),t.insertBefore(r,e),{aspectWrapper:a,maxWidthWrapper:r}},t.getWidget=function(e){var t=n(e);if(t){var r={iframe:e,aspectWrapper:t.aspectWrapper,maxWidthWrapper:t.maxWidthWrapper};if("A"===e.nodeName&&e.hasAttribute("href"))r.url=e.getAttribute("href");else if(e.hasAttribute("src")&&/url=/.test(e.getAttribute("src"))){var i=l(e.getAttribute("src"));i.url&&(r.url=i.url)}return r}},i.getElementComputedStyle=function(e,t){return window.getComputedStyle&&window.getComputedStyle(e).getPropertyValue(t)},t.setStyles=function(e,t){e&&Object.keys(t).forEach(function(r){var a=t[r];("number"==typeof a||"string"==typeof a&&/^(\d+)?\.?(\d+)$/.test(a))&&(a+="px");var n=e.style[r];window.getComputedStyle&&(i.getElementComputedStyle(e,r)==a||"iframely-responsive"==e.className&&"paddingBottom"===r&&!n&&/^56\.2\d+%$/.test(a)||"max-width"===r&&"keep"===a)||(e.style[r]=a||"")})};var o=t.applyNonce=function(e){i.config.nonce&&(e.nonce=i.config.nonce)},d=t.addQueryString=function(e,t){var r="";return Object.keys(t).forEach(function(i){var a=t[i];if("[object Array]"===Object.prototype.toString.call(a)){var n=a.map(function(e){return i+"="+encodeURIComponent(e)});r+="&"+n.join("&")}else void 0!==a&&-1===e.indexOf(i+"=")&&("boolean"==typeof a&&"_"!==i.charAt(0)&&(a=a?1:0),r+="&"+i+"="+encodeURIComponent(a))}),e+(""!==r?(e.indexOf("?")>-1?"&":"?")+r.replace(/^&/,""):"")};function s(e){for(var t=0,r=0;r=0;return r&&e}(e.maxWidthWrapper,i.config.parent);a&&(t=a.parentNode,r=a)}if(e.url){var n=e.iframe&&(e.iframe.textContent||e.iframe.innerText);i.triggerAsync("cancel",e.url,t,n,r.nextSibling)}t.removeChild(r)}else console.warn("iframely.cancelWidget called without widget param")}},612(e,t,r){var i=r(774);i.on("message",function(e,t){"open-href"!==t.method&&"click"!==t.method||i.trigger(t.method,t.href)}),i.openHref||(i.openHref=function(e){0===e.indexOf(window.location.origin)?window.location.href=e:window.open(e,"_blank","noopener")}),i.on("open-href",function(e){i.triggerAsync("click",e),i.openHref(e)})},742(e,t,r){var i=r(774);i.on("message",function(e,t){"setIframelyEmbedOptions"===t.method&&i.trigger("options",e,t.data)})},850(e,t,r){var i=r(672),a=r(774);a.on("message",function(e,t){if("setIframelyWidgetSize"===t.method||"resize"===t.method||"setIframelyEmbedData"===t.method||"embed-size"===t.type||"iframe.resize"===t.context){var r=null;t.data&&t.data.media&&t.data.media.frame_style?(t.data.media.frame_style.split(";").forEach(function(e){if(""!==e.trim()&&e.indexOf(":")>-1){var t=e.split(":");2===t.length&&((r=r||{})[t[0].trim()]=t[1].trim())}}),d(e,r)):"setIframelyEmbedData"===t.method&&d(e,null);var n=t.data&&t.data.media;!n&&t.height&&(n={height:t.height,"max-width":"keep"}),function(e,t){if(t&&Object.keys(t).length>0&&e){var r=function(e){var t=e.iframe&&e.iframe.style.border||e.aspectWrapper&&e.aspectWrapper.style.border,r=t&&t.match(/(\d+)px/)||0;return r&&(r=parseInt(r[1]),r*=2),r}(e),n=window.getComputedStyle&&window.getComputedStyle(e.iframe).getPropertyValue("height"),o=t["max-width"];"number"==typeof o&&(o+=r),i.setStyles(e.maxWidthWrapper,{"max-width":o,"min-width":t["min-width"]&&t["min-width"]+r,width:t.width&&t.width+r}),t.scrolling&&e.iframe&&e.iframe.setAttribute("scrolling",t.scrolling);var d=t["aspect-ratio"];(d||t.height)&&i.setStyles(e.aspectWrapper,{paddingBottom:d?Math.round(1e5/d)/1e3+"%":0,paddingTop:d&&t["padding-bottom"],height:d?0:t.height&&t.height+r});var s=window.getComputedStyle&&window.getComputedStyle(e.iframe).getPropertyValue("height");n&&n!==s&&a.triggerAsync("heightChanged",e.iframe,n,s)}}(e,n)}});var n={border:"","border-radius":"","box-shadow":"",overflow:""},o={border:"0","border-radius":"","box-shadow":"",overflow:""};function d(e,t){t&&e&&e.iframe?t["border-radius"]?(t.overflow="hidden",i.setStyles(e.aspectWrapper,t)):i.setStyles(e.iframe,t):!t&&e&&e.iframe&&(i.setStyles(e.aspectWrapper,n),i.setStyles(e.iframe,o))}}},t={};function r(i){var a=t[i];if(void 0!==a)return a.exports;var n=t[i]={exports:{}};return e[i](n,n.exports,r),n.exports}r.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(e){if("object"==typeof window)return window}}(),(()=>{r(331);var e=r(774);e._loaded||(e._loaded=!0,r(54),r(912),r(56),r(908),r(472),r(679),r(573),r(324),r(648),r(850),r(612),r(742),r(916),r(291),e.trigger("init"))})()})(); \ No newline at end of file +(function(){function e(){let e=()=>{};return{config:{},on:e,trigger:e,triggerAsync:e,load:e,unload:e,configure:e,extendOptions:e,setTheme:e,cancelWidget:e,openHref:e,addEventListener:e,isTouch:()=>!1,findIframe:()=>void 0,getElementComputedStyle:()=>void 0,buildOptionsForm:e}}var t=typeof window>`u`?e():window.iframely=window.iframely||{};t.config=t.config||{},typeof document<`u`&&(e=>{(document.readyState===`complete`||document.readyState===`interactive`)&&setTimeout(e,0),document.addEventListener(`DOMContentLoaded`,e)})(()=>{(t.config.autorun===void 0||t.config.autorun!==!1)&&t.trigger(`load`)});function n(){t.VERSION=1,t.ASPECT_WRAPPER_CLASS=`iframely-responsive`,t.MAXWIDTH_WRAPPER_CLASS=`iframely-embed`,t.LOADER_CLASS=`iframely-loader`,t.DOMAINS=[`cdn.iframe.ly`,`iframe.ly`,`if-cdn.com`,`iframely.net`],t.CDN=t.CDN||t.DOMAINS[0],t.BASE_RE=/^(?:https?:)?\/\/[^/]+/i,t.ID_RE=/^(?:https?:)?\/\/[^/]+\/(\w+-?\w+)(?:\?.*)?$/,t.SCRIPT_RE=/^(?:https?:|file:\/)?\/\/[^/]+(?:.+)?\/(?:embed|iframely)\.js(?:[^/]+)?$/i,t.CDN_RE=/^(?:https?:)?\/\/([^/]+)\/(?:embed|iframely)\.js(?:[^/]+)?$/i,t.SUPPORTED_QUERY_STRING=[`api_key`,`key`,`iframe`,`html5`,`playerjs`,`align`,`language`,`media`,`maxwidth`,`maxheight`,`lazy`,`import`,`parent`,`shadow`,`click_to_play`,`autoplay`,`mute`,`card`,`consent`,`theme`,/^_.+/],t.SUPPORTED_THEMES=[`auto`,`light`,`dark`],t.LAZY_IFRAME_SHOW_TIMEOUT=3e3,t.LAZY_IFRAME_FADE_TIMEOUT=200,t.CLEAR_WRAPPER_STYLES_TIMEOUT=3e3,t.RECOVER_HREFS_ON_CANCEL=!1,t.SHADOW=`iframely-shadow`,t.SUPPORT_IFRAME_LOADING_ATTR=!0}var r=e=>{window.requestAnimationFrame(e)},i={};function a(e,n,a){(i[e]||[]).forEach(e=>{n?r(()=>{e.apply(t,a)}):e.apply(t,a)}),e===`init`&&(i[e]=[])}function o(){t.on=(e,t)=>{(i[e]=i[e]||[]).push(t)},t.trigger=(e,...t)=>{a(e,!1,t)},t.triggerAsync=(e,...t)=>{a(e,!0,t)}}function s(e){window.addEventListener(`message`,t=>{let n;try{typeof t.data==`string`?n=JSON.parse(t.data):typeof t.data==`object`&&(n=t.data)}catch{if(typeof t.data==`string`){let e=t.data.match(/heightxPYMx(\d+)/);e&&(n={method:`resize`,height:parseInt(e[1])+1,domains:`all`})}}e(t,n)},!1)}function c(e,t){let n;for(let r=0;r{let t=l(document,e);return t||=u(document,e),t},s((e,n)=>{if(n&&(n.method||n.type||n.context)){let r=t.findIframe({contentWindow:e.source,src:n.src||n.context,domains:n.domains!==`all`&&t.DOMAINS.concat(t.CDN)});if(r){let e=h(r);e&&n.url&&(e.url=n.url),t.trigger(`message`,e,n)}}})}function f(e,t,n){typeof e==`object`&&(e.context=document.location.href);let r=JSON.stringify(e);t||=`*`,n||=window.parent,n.postMessage(r,t.replace(/([^:]+:\/\/[^/]+).*/,`$1`))}function p(){t.on(`init`,()=>{t.configure(x()),v(),t.config.theme&&t.setTheme(t.config.theme),S(t.DOMAINS.concat(t.CDN.replace(/^https?:\/\//,``)))}),t.load=function(...e){t.trigger(`load`,...e)},t.unload=e=>{let n=t.DOMAINS.concat(t.CDN.replace(/^https?:\/\//,``)),r=e||document,i=`iframe[src*="`+n.join(`"], iframe[src*="`)+`"], iframe[data-iframely-url]`,a=r.querySelectorAll(i);for(let e=0;ewindow.getComputedStyle(e).getPropertyValue(t),t.configure=e=>{e&&Object.keys(e).forEach(n=>{let r=e[n]===0||e[n]===`0`||e[n]===!1||e[n]===`false`?!1:e[n]===1||e[n]===`1`||e[n]===!0||e[n]===`true`||e[n];t.config[n]!==!1&&(t.config[n]=r)})}}function m(e,n){let r=e.parentNode;if(!r||r.nodeName!==`DIV`||C(r)>2||n&&r.getAttribute(`class`)!==t.ASPECT_WRAPPER_CLASS||!n&&r.style.position!==`relative`&&r.getAttribute(`class`)!==t.ASPECT_WRAPPER_CLASS)return;let i=r.parentNode;if(!(!i||i.nodeName!==`DIV`||C(i)>1||n&&i.getAttribute(`class`)&&i.getAttribute(`class`).split(` `).indexOf(t.MAXWIDTH_WRAPPER_CLASS)===-1||!n&&i.getAttribute(`class`)&&!i.getAttribute(`class`).match(/iframely/i)))return{aspectWrapper:r,maxWidthWrapper:i}}function ee(e){let n=e.parentNode,r=document.createElement(`div`);r.className=t.MAXWIDTH_WRAPPER_CLASS;let i=document.createElement(`div`);return i.className=t.ASPECT_WRAPPER_CLASS,r.appendChild(i),n.insertBefore(r,e),{aspectWrapper:i,maxWidthWrapper:r}}function h(e){let t=m(e);if(!t)return;let n={iframe:e,aspectWrapper:t.aspectWrapper,maxWidthWrapper:t.maxWidthWrapper},r=e.getAttribute(`src`);if(e.nodeName===`A`&&e.hasAttribute(`href`))n.url=e.getAttribute(`href`);else if(r&&/url=/.test(r)){let e=T(r);e.url&&(n.url=e.url)}return n}function g(e,n){e&&Object.keys(n).forEach(r=>{let i=n[r];(typeof i==`number`||typeof i==`string`&&/^(\d+)?\.?(\d+)$/.test(i))&&(i+=`px`);let a=e.style,o=a[r];t.getElementComputedStyle(e,r)!=i&&!(e.className==`iframely-responsive`&&r===`paddingBottom`&&!o&&/^56\.2\d+%$/.test(i))&&!(r===`max-width`&&i===`keep`)&&(a[r]=i||``)})}function _(e){t.config.nonce&&(e.nonce=t.config.nonce)}function v(){let e=`iframely-styles`,t=document.getElementById(e);t||(t=document.createElement(`style`),t.id=e,_(t),t.innerHTML=`.iframely-responsive{top:0;left:0;width:100%;height:0;position:relative;padding-bottom:56.25%;box-sizing:border-box;}.iframely-responsive>*{top:0;left:0;width:100%;height:100%;position:absolute;border:0;box-sizing:border-box;}`,document.getElementsByTagName(`head`)[0].appendChild(t))}function y(e,t){let n=``;return Object.keys(t).forEach(r=>{let i=t[r];if(Array.isArray(i)){let e=i.map(e=>r+`=`+encodeURIComponent(e));n+=`&`+e.join(`&`)}else i!==void 0&&e.indexOf(r+`=`)===-1&&(typeof i==`boolean`&&r.charAt(0)!==`_`&&(i=+!!i),n+=`&`+r+`=`+encodeURIComponent(i))}),e+(n===``?``:(e.indexOf(`?`)>-1?`&`:`?`)+n.replace(/^&/,``))}function b(e,n,r){let i=e;if(/^(https?:)?\/\//i.test(e)||(i=(n&&n.CDN||t.CDN)+i,n&&delete n.CDN),/^(?:https?:)?\/\//i.test(i)||(i=`//`+i),n&&(i=y(i,n)),r&&r.length){let e={},n=Object.keys(t.config);for(let i=0;i0)return e}}return{}}function S(e){let n=document.querySelectorAll(`iframe[src*="`+(e||t.DOMAINS).join(`"], iframe[src*="`)+`"]`);for(let e=0;e{t.forEach(t=>{f({method:`intersection`,entry:{isIntersecting:t.isIntersecting},options:e},`*`,t.target.contentWindow)})},k(e)),D[t]=n),n}function k(e){let t={};return e&&e.threshold&&(t.threshold=e.threshold),e&&e.margin&&(t.rootMargin=e.margin+`px `+e.margin+`px `+e.margin+`px `+e.margin+`px`),t}function A(){t.on(`init`,()=>{t.configure({intersection:1})}),t.on(`message`,(e,t)=>{if(t.method===`send-intersections`&&e.iframe){let n=t.options;n||={margin:1e3},O(n).observe(e.iframe)}}),t.on(`unload-widget`,e=>{Object.values(D).forEach(t=>t.unobserve(e.iframe))}),t.on(`unload`,e=>{e||Object.keys(D).forEach(e=>{D[e].disconnect(),delete D[e]})})}function j(e,t){f({method:`setTheme`,data:t},`*`,e.contentWindow)}function M(e,t){let n=e.getElementsByTagName(`iframe`);for(let e=0;e{e&&t.SUPPORTED_THEMES.indexOf(e)>-1?n?n.tagName===`IFRAME`?j(n,e):M(n,e):(t.configure({theme:e}),M(document,e),t.trigger(`set-theme`,e)):console.warn(`Using iframely.setTheme with not supported theme: "`+e+`". Supported themes are: `+t.SUPPORTED_THEMES.join(`, `))}}var N={};function P(){t.on(`load`,e=>{if(!e&&t.config.import!==!1&&R()&&!t.import){let e=document.querySelectorAll(`a[data-iframely-url]:not([data-import-uri])`);e.length>1&&F(e)}}),t.on(`load`,(e,t)=>{if(e&&!(e instanceof Element)&&e.uri&&(e.html||e.cancel)){let n=N[e.uri];if(n)for(let r=0;r{t.trigger(`import-loaded`,e),e.widgets.forEach(n=>{t.trigger(`load`,n,e)}),L()},t.isTouch=()=>`ontouchstart`in window||navigator.maxTouchPoints>0,t.on(`import-widget-ready`,z),t.on(`unload`,e=>{e||(delete t.import,Object.keys(N).forEach(e=>{delete N[e]}))}),t.addEventListener||=(e,t,n)=>{e&&e.addEventListener(t,n,!1)}}function F(e){let n=E(),r=[],i=[],a=null;function o(e,t){N[e]||(N[e]=[]),N[e].push(t)}function s(e){let n=e.getAttribute(`data-iframely-url`),s=n.match(t.ID_RE),c=s&&s[1],l=T(n,t.SUPPORTED_QUERY_STRING.concat(`url`)),u=l.url;delete l.url;let d=l.import===`0`||l.import===`false`||l.playerjs===`1`||l.playerjs===`true`;if(!d){let e=n.match(t.BASE_RE);l.CDN=e&&e[0],a?JSON.stringify(l,Object.keys(l).sort())!==JSON.stringify(a,Object.keys(a).sort())&&(d=!0):a=l}d?t.trigger(`load`,e):c?(e.setAttribute(`data-import-uri`,c),i.indexOf(c)===-1&&i.push(c),o(c,e)):(u||=e.getAttribute(`href`),(a.key||a.api_key||t.config.api_key||t.config.key)&&u?(e.setAttribute(`data-import-uri`,u),r.indexOf(u)===-1&&r.push(u),o(u,e)):t.trigger(`load`,e))}for(let t=0;t0||i.length>0?(a||={},a.touch=t.isTouch(),a.flash=!1,a.app=1,t.config.theme&&(a.theme=t.config.theme),r.length>0&&(a.uri=r),i.length>0&&(a.ids=i.join(`&`)),a.v=t.VERSION,n.src=b(`/api/import/v2`,a,t.SUPPORTED_QUERY_STRING),n.onerror=()=>{L()},document.head.appendChild(n),t.import=n):(L(),t.trigger(`load`))}function I(e,n,r){let i=e.cancel,a=e.shadow,o=e.renderEvent,s=m(n,!0);if(i)t.cancelWidget(h(n)||{maxWidthWrapper:n,iframe:n,url:n.getAttribute(`href`)});else{let i=document.createElement(`div`);i.innerHTML=e.html;let c,l;if(s&&!o?(c=s.aspectWrapper.parentNode,l=s.aspectWrapper,s.maxWidthWrapper.removeAttribute(`style`)):(c=n.parentNode,l=n),a){let n=document.createElement(`div`),a=n.attachShadow({mode:`open`});a.appendChild(i);let o={shadowRoot:a,shadowContainer:n,container:c,context:e.context,stylesIds:e.stylesIds,stylesDict:r.commonShadowStyles};t.trigger(`import-shadow-widget-before-render`,o),c.insertBefore(n,l),t.trigger(`import-shadow-widget-after-render`,o)}else c.insertBefore(i,l),B(i);c.removeChild(l),o&&setTimeout(()=>{z(c)},t.CLEAR_WRAPPER_STYLES_TIMEOUT)}}function L(){delete t.import;let e=document.querySelectorAll(`a[data-iframely-url][data-import-uri]`);for(let n=0;n4&&(n=null);let i=n&&n.parentNode;i&&i.getAttribute(`class`)&&i.getAttribute(`class`).split(` `).indexOf(t.MAXWIDTH_WRAPPER_CLASS)>-1&&(n.removeAttribute(`style`),n.removeAttribute(`class`),i.removeAttribute(`style`))}function B(e){function t(e,t){return!!e.nodeName&&e.nodeName.toUpperCase()===t.toUpperCase()}function n(t){let n=t.text||t.textContent||t.innerHTML||``,r=E();r.type=`text/javascript`;for(let e=0;e{if(e&&e.nodeName&&typeof n==`string`){let r=document.createElement(`a`);r.setAttribute(`href`,n),e.appendChild(r),t.trigger(`load`,r)}}),t.on(`load`,e=>{if(!e&&!t.import){let e=document.querySelectorAll(`a[data-iframely-url]:not([data-import-uri])`);for(let n=0;n{e&&e.nodeName===`A`&&(e.getAttribute(`data-iframely-url`)||e.getAttribute(`href`))&&!e.hasAttribute(`data-import-uri`)&&H(e)})}function H(e){if(!e.getAttribute(`data-iframely-url`)&&!e.getAttribute(`href`))return;let n,r=e.getAttribute(`data-iframely-url`);if(r&&/^((?:https?:)?\/\/[^/]+)\/\w+/i.test(r))n=b(r,{v:t.VERSION,app:1,theme:t.config.theme});else if((t.config.api_key||t.config.key)&&t.CDN){if(!e.getAttribute(`href`)){console.warn(`Iframely cannot build embeds: "href" attribute missing in`,e);return}n=b(`/api/iframe`,{url:e.getAttribute(`href`),v:t.VERSION,app:1,theme:t.config.theme},t.SUPPORTED_QUERY_STRING)}else console.warn(`Iframely cannot build embeds: api key is required as query-string of embed.js`);if(!n)e.removeAttribute(`data-iframely-url`);else{let r=document.createElement(`iframe`);r.setAttribute(`allowfullscreen`,``),r.setAttribute(`allow`,`autoplay *; encrypted-media *; ch-prefers-color-scheme *`),e.hasAttribute(`data-img`)&&r.setAttribute(`data-img`,e.getAttribute(`data-img`));let i=e.hasAttribute(`data-lazy`)||e.hasAttribute(`data-img`)||/&lazy=1/.test(n)||t.config.lazy,a=e.textContent;a&&a!==``&&(r.textContent=a);let o=m(e,!0);if(o)for(;o.aspectWrapper.lastChild;)o.aspectWrapper.removeChild(o.aspectWrapper.lastChild);else o=ee(e),e.parentNode.removeChild(e);o.aspectWrapper.appendChild(r),i?(r.setAttribute(`data-iframely-url`,n),t.trigger(`load`,r)):(r.setAttribute(`src`,n),t.trigger(`iframe-ready`,r))}}function U(){t.on(`load`,e=>{if(e&&e.nodeName===`IFRAME`&&e.hasAttribute(`data-iframely-url`)&&e.hasAttribute(`data-img`)&&!e.getAttribute(`src`)){let n=e.getAttribute(`data-img`);e.removeAttribute(`data-img`),e.setAttribute(`data-img-created`,``);let r=h(e),i=e.getAttribute(`data-iframely-url`);r&&(W(r,i,n),i=y(i,{img:1}),e.setAttribute(`data-iframely-url`,i),new ne(r)),t.trigger(`load`,e)}}),t.on(`message`,(e,t)=>{if(!e)return;let n;t.method===`widgetRendered`&&(q(e),n=X(e),n?.deactivate()),t.method===`begin-waiting-widget-render`&&(n=X(e),n?.clearLoadingTimeout()),t.method===`end-waiting-widget-render`&&(n=X(e),n?.registerLoadingTimeout())}),t.on(`unload-widget`,e=>{X(e)?.deactivate()})}function W(e,n,r){let i;if(r&&/^(https?:)?\/\//.test(r))i=r;else{let e=T(n),r={};for(let t in e)t.indexOf(`_`)===0&&(r[t]=e[t]);if(e.media&&(r.media=e.media),n.match(/\/api\/iframe/))i=b(n.match(/^(.+)\/api\/iframe/i)[1]+`/api/thumbnail`,Object.assign({url:e.url,api_key:e.api_key,key:e.key},r));else if(n.match(t.ID_RE))i=b(n.replace(/^((?:https?:)?\/\/[^/]+\/(\w+-?\w+))(?:\?.*)?$/,`$1/thumbnail`),r);else return}let a=document.createElement(`div`);g(a,{position:`absolute`,width:`100%`,height:`100%`,backgroundImage:`url('`+i+`')`,backgroundSize:`cover`,backgroundPosition:`center`});let o=document.createElement(`div`);o.setAttribute(`class`,t.LOADER_CLASS),a.appendChild(o);let s=t.getElementComputedStyle(e.aspectWrapper,`padding-top`),c=t.getElementComputedStyle(e.aspectWrapper,`padding-bottom`),l=s&&s.match(/^(\d+)px$/);if(l&&parseInt(l[1])&&c){let t=document.createElement(`div`);g(t,{top:`-`+s,width:`100%`,height:0,position:`relative`,paddingBottom:c}),t.appendChild(a),e.aspectWrapper.appendChild(t)}else e.aspectWrapper.appendChild(a)}function G(e,t){let n=0;for(let r=0;r1&&G(1,e.aspectWrapper);t&&t.nodeName===`DIV`&&e.aspectWrapper.removeChild(t)}var J=[];function Y(e){let t=0;for(;t{this.iframeOnLoad()}),this.registerLoadingTimeout(),J.push(this)}iframeOnLoad(){this.loadCount++,this.loadCount===2&&(this.deactivate(),setTimeout(()=>{q(this.widget)},t.LAZY_IFRAME_FADE_TIMEOUT))}deactivate(){this.clearLoadingTimeout(),Z(this.widget)}clearLoadingTimeout(){this.timeoutId&&clearTimeout(this.timeoutId),this.timeoutId=null}registerLoadingTimeout(){this.timeoutId||=setTimeout(()=>{this.iframeOnLoad()},t.LAZY_IFRAME_SHOW_TIMEOUT)}};function re(){t.on(`load`,e=>{if(!e){let e=document.querySelectorAll(`iframe[data-iframely-url]`);for(let n=0;n{e&&e.nodeName===`IFRAME`&&e.hasAttribute(`data-iframely-url`)&&!e.hasAttribute(`data-img`)&&!e.getAttribute(`src`)&&ie(e)})}function ie(e){let n=h(e),r=e.getAttribute(`data-iframely-url`),i=e.hasAttribute(`data-img-created`)||e.hasAttribute(`data-img`),a=!i&&t.SUPPORT_IFRAME_LOADING_ATTR;if(n&&r){let e={v:t.VERSION,app:1,theme:t.config.theme};!a&&t.config.intersection&&(e.lazy=1),r=b(r,e)}a&&e.setAttribute(`loading`,`lazy`),i&&t.SUPPORT_IFRAME_LOADING_ATTR&&e.setAttribute(`loading`,`edge`),e.setAttribute(`src`,r||``),e.removeAttribute(`data-iframely-url`),t.trigger(`iframe-ready`,e)}function ae(){t.on(`message`,(e,n)=>{n.method===`cancelWidget`&&t.cancelWidget(e)}),t.cancelWidget=e=>{if(!e){console.warn(`iframely.cancelWidget called without widget param`);return}function n(e,t){let n=!1;for(;!n&&e.parentNode;)e=e.parentNode,n=!!e.className&&typeof e.className==`string`&&e.className.split(` `).indexOf(t)>=0;return n&&e}let r=e.maxWidthWrapper&&e.maxWidthWrapper.parentNode,i=e.maxWidthWrapper;if(t.config&&t.config.parent){let a=n(e.maxWidthWrapper,String(t.config.parent));a&&(r=a.parentNode,i=a)}if(e.url){let n=e.iframe&&e.iframe.textContent;t.triggerAsync(`cancel`,e.url,r,n,i.nextSibling)}r.removeChild(i)}}var oe={border:``,"border-radius":``,"box-shadow":``,overflow:``},se={border:`0`,"border-radius":``,"box-shadow":``,overflow:``};function Q(){t.on(`message`,(e,t)=>{if(t.method===`setIframelyWidgetSize`||t.method===`resize`||t.method===`setIframelyEmbedData`||t.type===`embed-size`||t.context===`iframe.resize`){let n=null;t.data&&t.data.media&&t.data.media.frame_style?(t.data.media.frame_style.split(`;`).forEach(e=>{if(e.trim()!==``&&e.indexOf(`:`)>-1){let t=e.split(`:`);t.length===2&&(n||={},n[t[0].trim()]=t[1].trim())}}),$(e,n)):t.method===`setIframelyEmbedData`&&$(e,null);let r=t.data&&t.data.media;!r&&t.height&&(r={height:t.height,"max-width":`keep`}),le(e,r)}})}function $(e,t){t&&e&&e.iframe?t[`border-radius`]?(t.overflow=`hidden`,g(e.aspectWrapper,t)):g(e.iframe,t):!t&&e&&e.iframe&&(g(e.aspectWrapper,oe),g(e.iframe,se))}function ce(e){let t=e.iframe&&e.iframe.style.border||e.aspectWrapper&&e.aspectWrapper.style.border,n=t&&t.match(/(\d+)px/);return n?parseInt(n[1])*2:0}function le(e,n){if(n&&Object.keys(n).length>0&&e){let r=ce(e),i=window.getComputedStyle(e.iframe).getPropertyValue(`height`),a=n[`max-width`];typeof a==`number`&&(a+=r),g(e.maxWidthWrapper,{"max-width":a,"min-width":n[`min-width`]&&n[`min-width`]+r,width:n.width&&n.width+r}),n.scrolling&&e.iframe&&e.iframe.setAttribute(`scrolling`,n.scrolling);let o=n[`aspect-ratio`];(o||n.height)&&g(e.aspectWrapper,{paddingBottom:o?Math.round(1e3*100/o)/1e3+`%`:0,paddingTop:o&&n[`padding-bottom`],height:o?0:n.height&&n.height+r});let s=window.getComputedStyle(e.iframe).getPropertyValue(`height`);i&&i!==s&&t.triggerAsync(`heightChanged`,e.iframe,i,s)}}function ue(){t.on(`message`,(e,n)=>{(n.method===`open-href`||n.method===`click`)&&t.trigger(n.method,n.href)}),t.openHref||=e=>{e.indexOf(window.location.origin)===0?window.location.href=e:window.open(e,`_blank`,`noopener`)},t.on(`open-href`,e=>{t.triggerAsync(`click`,e),t.openHref(e)})}function de(){t.on(`message`,(e,n)=>{n.method===`setIframelyEmbedOptions`&&t.trigger(`options`,e,n.data)})}function fe(){t.widgets=t.widgets||{},t.widgets.load=t.load,t.extendOptions=t.configure,t.events||(t.events={},t.events.on=t.on,t.events.trigger=t.trigger),t.on(`cancel`,(e,n,r,i)=>{if(t.RECOVER_HREFS_ON_CANCEL&&!r&&(r=e),e&&n&&r&&r!==``){let t=document.createElement(`a`);t.setAttribute(`href`,e),t.setAttribute(`target`,`_blank`),t.setAttribute(`rel`,`noopener`),t.textContent=r,i?n.insertBefore(t,i):n.appendChild(t)}})}typeof window<`u`&&!t._loaded&&(t._loaded=!0,n(),o(),p(),d(),A(),te(),P(),V(),U(),re(),ae(),Q(),ue(),de(),fe(),t.trigger(`init`))})(); \ No newline at end of file diff --git a/dist/esm/chunks/deprecated.js b/dist/esm/chunks/deprecated.js new file mode 100644 index 0000000..c0ecb1b --- /dev/null +++ b/dist/esm/chunks/deprecated.js @@ -0,0 +1,1059 @@ +import { t as iframely } from "./iframely.js"; +//#region src/dom-ready.ts +var DOMReady = (f) => { + if (document.readyState === "complete" || document.readyState === "interactive") setTimeout(f, 0); + document.addEventListener("DOMContentLoaded", f); +}; +if (typeof document !== "undefined") DOMReady(() => { + if (typeof iframely.config.autorun === "undefined" || iframely.config.autorun !== false) iframely.trigger("load"); +}); +//#endregion +//#region src/const.ts +function boot$14() { + iframely.VERSION = 1; + iframely.ASPECT_WRAPPER_CLASS = "iframely-responsive"; + iframely.MAXWIDTH_WRAPPER_CLASS = "iframely-embed"; + iframely.LOADER_CLASS = "iframely-loader"; + iframely.DOMAINS = [ + "cdn.iframe.ly", + "iframe.ly", + "if-cdn.com", + "iframely.net" + ]; + iframely.CDN = iframely.CDN || iframely.DOMAINS[0]; + iframely.BASE_RE = /^(?:https?:)?\/\/[^/]+/i; + iframely.ID_RE = /^(?:https?:)?\/\/[^/]+\/(\w+-?\w+)(?:\?.*)?$/; + iframely.SCRIPT_RE = /^(?:https?:|file:\/)?\/\/[^/]+(?:.+)?\/(?:embed|iframely)\.js(?:[^/]+)?$/i; + iframely.CDN_RE = /^(?:https?:)?\/\/([^/]+)\/(?:embed|iframely)\.js(?:[^/]+)?$/i; + iframely.SUPPORTED_QUERY_STRING = [ + "api_key", + "key", + "iframe", + "html5", + "playerjs", + "align", + "language", + "media", + "maxwidth", + "maxheight", + "lazy", + "import", + "parent", + "shadow", + "click_to_play", + "autoplay", + "mute", + "card", + "consent", + "theme", + /^_.+/ + ]; + iframely.SUPPORTED_THEMES = [ + "auto", + "light", + "dark" + ]; + iframely.LAZY_IFRAME_SHOW_TIMEOUT = 3e3; + iframely.LAZY_IFRAME_FADE_TIMEOUT = 200; + iframely.CLEAR_WRAPPER_STYLES_TIMEOUT = 3e3; + iframely.RECOVER_HREFS_ON_CANCEL = false; + iframely.SHADOW = "iframely-shadow"; + iframely.SUPPORT_IFRAME_LOADING_ATTR = true; +} +//#endregion +//#region src/events.ts +var nextTick = (fn) => { + window.requestAnimationFrame(fn); +}; +var callbacksStack = {}; +function trigger(event, async, args) { + (callbacksStack[event] || []).forEach((cb) => { + if (async) nextTick(() => { + cb.apply(iframely, args); + }); + else cb.apply(iframely, args); + }); + if (event === "init") callbacksStack[event] = []; +} +function boot$13() { + iframely.on = (event, cb) => { + (callbacksStack[event] = callbacksStack[event] || []).push(cb); + }; + iframely.trigger = (event, ...args) => { + trigger(event, false, args); + }; + iframely.triggerAsync = (event, ...args) => { + trigger(event, true, args); + }; +} +//#endregion +//#region src/messaging.ts +function receiveMessage(callback) { + window.addEventListener("message", (e) => { + let message; + try { + if (typeof e.data === "string") message = JSON.parse(e.data); + else if (typeof e.data === "object") message = e.data; + } catch { + if (typeof e.data === "string") { + const m = e.data.match(/heightxPYMx(\d+)/); + if (m) message = { + method: "resize", + height: parseInt(m[1]) + 1, + domains: "all" + }; + } + } + callback(e, message); + }, false); +} +function findIframeByContentWindow(iframes, contentWindow) { + let foundIframe; + for (let i = 0; i < iframes.length && !foundIframe; i++) { + const iframe = iframes[i]; + if (iframe.contentWindow === contentWindow) foundIframe = iframe; + } + return foundIframe; +} +function findIframeInElement(element, options) { + let foundIframe, iframes; + if (options.src) { + iframes = element.querySelectorAll("iframe[src*=\"" + options.src.replace(/^https?:/, "") + "\"]"); + foundIframe = findIframeByContentWindow(iframes, options.contentWindow); + } + if (!foundIframe) { + iframes = options.domains ? element.querySelectorAll("iframe[src*=\"" + (options.domains || iframely.DOMAINS).join("\"], iframe[src*=\"") + "\"]") : element.querySelectorAll("iframe"); + foundIframe = findIframeByContentWindow(iframes, options.contentWindow); + } + return foundIframe; +} +function findIframeInShadowRoots(element, options) { + let foundIframe; + const className = "." + (iframely.config.shadow || iframely.SHADOW); + const shadowRoots = element.querySelectorAll(className); + for (let i = 0; i < shadowRoots.length && !foundIframe; i++) { + const shadowRoot = shadowRoots[i].shadowRoot; + if (shadowRoot) { + foundIframe = findIframeInElement(shadowRoot, options); + if (!foundIframe) foundIframe = findIframeInShadowRoots(shadowRoot, options); + } + } + return foundIframe; +} +function boot$12() { + if (!iframely.findIframe) iframely.findIframe = (options) => { + let foundIframe = findIframeInElement(document, options); + if (!foundIframe) foundIframe = findIframeInShadowRoots(document, options); + return foundIframe; + }; + receiveMessage((e, message) => { + if (message && (message.method || message.type || message.context)) { + const foundIframe = iframely.findIframe({ + contentWindow: e.source, + src: message.src || message.context, + domains: message.domains !== "all" && iframely.DOMAINS.concat(iframely.CDN) + }); + if (foundIframe) { + const widget = getWidget(foundIframe); + if (widget && message.url) widget.url = message.url; + iframely.trigger("message", widget, message); + } + } + }); +} +function postMessage(message, target_url, target) { + if (typeof message === "object") message.context = document.location.href; + const data = JSON.stringify(message); + target_url = target_url || "*"; + target = target || window.parent; + target.postMessage(data, target_url.replace(/([^:]+:\/\/[^/]+).*/, "$1")); +} +//#endregion +//#region src/utils.ts +function boot$11() { + iframely.on("init", () => { + iframely.configure(parseQueryStringFromScriptSrc()); + defineDefaultStyles(); + if (iframely.config.theme) iframely.setTheme(iframely.config.theme); + requestSizeOfExistingIframes(iframely.DOMAINS.concat(iframely.CDN.replace(/^https?:\/\//, ""))); + }); + iframely.load = function(...args) { + iframely.trigger("load", ...args); + }; + iframely.unload = (el) => { + const domains = iframely.DOMAINS.concat(iframely.CDN.replace(/^https?:\/\//, "")); + const root = el || document; + const selector = "iframe[src*=\"" + domains.join("\"], iframe[src*=\"") + "\"], iframe[data-iframely-url]"; + const iframes = root.querySelectorAll(selector); + for (let i = 0; i < iframes.length; i++) { + const widget = getWidget(iframes[i]); + if (widget) { + iframely.trigger("unload-widget", widget); + widget.maxWidthWrapper.remove(); + } + } + iframely.trigger("unload", el); + }; + iframely.getElementComputedStyle = (el, style) => { + return window.getComputedStyle(el).getPropertyValue(style); + }; + iframely.configure = (options) => { + if (!options) return; + Object.keys(options).forEach((key) => { + const new_value = options[key] === 0 || options[key] === "0" || options[key] === false || options[key] === "false" ? false : options[key] === 1 || options[key] === "1" || options[key] === true || options[key] === "true" ? true : options[key]; + if (iframely.config[key] !== false) iframely.config[key] = new_value; + }); + }; +} +function getIframeWrapper(iframe, checkClass) { + const aspectWrapper = iframe.parentNode; + if (!aspectWrapper || aspectWrapper.nodeName !== "DIV" || nonTextChildCount$1(aspectWrapper) > 2 || checkClass && aspectWrapper.getAttribute("class") !== iframely.ASPECT_WRAPPER_CLASS || !checkClass && aspectWrapper.style.position !== "relative" && aspectWrapper.getAttribute("class") !== iframely.ASPECT_WRAPPER_CLASS) return; + const maxWidthWrapper = aspectWrapper.parentNode; + if (!maxWidthWrapper || maxWidthWrapper.nodeName !== "DIV" || nonTextChildCount$1(maxWidthWrapper) > 1 || checkClass && maxWidthWrapper.getAttribute("class") && maxWidthWrapper.getAttribute("class").split(" ").indexOf(iframely.MAXWIDTH_WRAPPER_CLASS) === -1 || !checkClass && maxWidthWrapper.getAttribute("class") && !maxWidthWrapper.getAttribute("class").match(/iframely/i)) return; + return { + aspectWrapper, + maxWidthWrapper + }; +} +function addDefaultWrappers(el) { + const parentNode = el.parentNode; + const maxWidthWrapper = document.createElement("div"); + maxWidthWrapper.className = iframely.MAXWIDTH_WRAPPER_CLASS; + const aspectWrapper = document.createElement("div"); + aspectWrapper.className = iframely.ASPECT_WRAPPER_CLASS; + maxWidthWrapper.appendChild(aspectWrapper); + parentNode.insertBefore(maxWidthWrapper, el); + return { + aspectWrapper, + maxWidthWrapper + }; +} +function getWidget(iframe) { + const wrapper = getIframeWrapper(iframe); + if (!wrapper) return; + const widget = { + iframe, + aspectWrapper: wrapper.aspectWrapper, + maxWidthWrapper: wrapper.maxWidthWrapper + }; + const src = iframe.getAttribute("src"); + if (iframe.nodeName === "A" && iframe.hasAttribute("href")) widget.url = iframe.getAttribute("href"); + else if (src && /url=/.test(src)) { + const qs = parseQueryString(src); + if (qs.url) widget.url = qs.url; + } + return widget; +} +function setStyles(el, styles) { + if (el) Object.keys(styles).forEach((key) => { + let value = styles[key]; + if (typeof value === "number" || typeof value === "string" && /^(\d+)?\.?(\d+)$/.test(value)) value = value + "px"; + const elStyle = el.style; + const currentValue = elStyle[key]; + if (iframely.getElementComputedStyle(el, key) != value && !(el.className == "iframely-responsive" && key === "paddingBottom" && !currentValue && /^56\.2\d+%$/.test(value)) && !(key === "max-width" && value === "keep")) elStyle[key] = value || ""; + }); +} +function applyNonce(element) { + if (iframely.config.nonce) element.nonce = iframely.config.nonce; +} +function defineDefaultStyles() { + const iframelyStylesId = "iframely-styles"; + let styles = document.getElementById(iframelyStylesId); + if (!styles) { + const iframelyStyles = ".iframely-responsive{top:0;left:0;width:100%;height:0;position:relative;padding-bottom:56.25%;box-sizing:border-box;}.iframely-responsive>*{top:0;left:0;width:100%;height:100%;position:absolute;border:0;box-sizing:border-box;}"; + styles = document.createElement("style"); + styles.id = iframelyStylesId; + applyNonce(styles); + styles.innerHTML = iframelyStyles; + document.getElementsByTagName("head")[0].appendChild(styles); + } +} +function addQueryString(href, options) { + let query_string = ""; + Object.keys(options).forEach((key) => { + let value = options[key]; + if (Array.isArray(value)) { + const values = value.map((uri) => key + "=" + encodeURIComponent(uri)); + query_string += "&" + values.join("&"); + } else if (typeof value !== "undefined" && href.indexOf(key + "=") === -1) { + if (typeof value === "boolean" && key.charAt(0) !== "_") value = value ? 1 : 0; + query_string += "&" + key + "=" + encodeURIComponent(value); + } + }); + return href + (query_string !== "" ? (href.indexOf("?") > -1 ? "&" : "?") + query_string.replace(/^&/, "") : ""); +} +function getEndpoint(src, options, config_params) { + let endpoint = src; + if (!/^(https?:)?\/\//i.test(src)) { + endpoint = (options && options.CDN || iframely.CDN) + endpoint; + if (options) delete options.CDN; + } + if (!/^(?:https?:)?\/\//i.test(endpoint)) endpoint = "//" + endpoint; + if (options) endpoint = addQueryString(endpoint, options); + if (config_params && config_params.length) { + const more_options = {}; + const iframely_config_keys = Object.keys(iframely.config); + for (let i = 0; i < iframely_config_keys.length; i++) { + const key = iframely_config_keys[i]; + if (containsString(config_params, key)) more_options[key] = iframely.config[key]; + } + endpoint = addQueryString(endpoint, more_options); + } + if (/^(https?:)?\/\//i.test(endpoint) && !endpoint.match(/^(https?:)?\/\//i)[1] && document.location.protocol !== "http:" && document.location.protocol !== "https:") endpoint = "https:" + endpoint; + return endpoint; +} +function parseQueryStringFromScriptSrc() { + const scripts = document.querySelectorAll("script[src*=\"embed.js\"], script[src*=\"iframely.js\"]"); + for (let i = 0; i < scripts.length; i++) { + const src = scripts[i].getAttribute("src").replace(/&/gi, "&"); + if (iframely.SCRIPT_RE.test(src)) { + const options = parseQueryString(src, iframely.SUPPORTED_QUERY_STRING.concat("cdn", "cancel", "nonce")); + const m2 = src.match(iframely.CDN_RE); + if (m2 || options.cdn) iframely.CDN = options.cdn || m2[1]; + if (options.cancel) { + if (options.cancel === "0" || options.cancel === "false") iframely.RECOVER_HREFS_ON_CANCEL = true; + delete options.cancel; + } + if (Object.keys(options).length > 0) return options; + } + } + return {}; +} +function requestSizeOfExistingIframes(domains) { + const iframes = document.querySelectorAll("iframe[src*=\"" + (domains || iframely.DOMAINS).join("\"], iframe[src*=\"") + "\"]"); + for (let i = 0; i < iframes.length; i++) { + const iframe = iframes[i]; + const src = iframe.src; + if (src.match(/^(https?:)?\/\/[^/]+\/api\/iframe\?.+/) || src.match(/^(https?:)?\/\/[^/]+\/\w+(\?.*)?$/)) postMessage({ method: "getSize" }, "*", iframe.contentWindow); + } +} +function nonTextChildCount$1(element) { + let count = 0; + for (let i = 0; i < element.childNodes.length; i++) { + const el = element.childNodes[i]; + if (el.nodeType === Node.TEXT_NODE) { + if ((el.textContent || "").replace(/\s|\n/g, "")) count++; + } else if (el.nodeType === Node.ELEMENT_NODE) count++; + } + return count; +} +function containsString(list, findValue) { + let value, i = 0; + while (i < list.length) { + value = list[i]; + if (value == findValue) return true; + if (value instanceof RegExp && value.test(findValue)) return true; + i++; + } + return false; +} +function parseQueryString(url, allowed_query_string) { + const query = url.match(/\?(.+)/i); + if (query) { + const data = query[1].split("&"); + const result = {}; + for (let i = 0; i < data.length; i++) { + const item = data[i].split("="); + if (!allowed_query_string || containsString(allowed_query_string, item[0])) result[item[0]] = decodeURIComponent(item[1]); + } + return result; + } else return {}; +} +function createScript() { + const script = document.createElement("script"); + applyNonce(script); + return script; +} +//#endregion +//#region src/intersection.ts +var observers = {}; +function getObserver(options) { + const optionsKey = JSON.stringify(options); + let observer = observers[optionsKey]; + if (!observer) { + observer = new IntersectionObserver((entries) => { + entries.forEach((entry) => { + postMessage({ + method: "intersection", + entry: { isIntersecting: entry.isIntersecting }, + options + }, "*", entry.target.contentWindow); + }); + }, getObserverOptions(options)); + observers[optionsKey] = observer; + } + return observer; +} +function getObserverOptions(options) { + const result = {}; + if (options && options.threshold) result.threshold = options.threshold; + if (options && options.margin) result.rootMargin = options.margin + "px " + options.margin + "px " + options.margin + "px " + options.margin + "px"; + return result; +} +function boot$10() { + iframely.on("init", () => { + iframely.configure({ intersection: 1 }); + }); + iframely.on("message", (widget, message) => { + if (message.method === "send-intersections" && widget.iframe) { + let options = message.options; + if (!options) options = { margin: 1e3 }; + getObserver(options).observe(widget.iframe); + } + }); + iframely.on("unload-widget", (widget) => { + Object.values(observers).forEach((observer) => observer.unobserve(widget.iframe)); + }); + iframely.on("unload", (el) => { + if (!el) Object.keys(observers).forEach((key) => { + observers[key].disconnect(); + delete observers[key]; + }); + }); +} +//#endregion +//#region src/theme.ts +function setThemeInIframe(iframe, theme) { + postMessage({ + method: "setTheme", + data: theme + }, "*", iframe.contentWindow); +} +function setThemeInAllIframes(parent, theme) { + const iframes = parent.getElementsByTagName("iframe"); + for (let i = 0; i < iframes.length; i++) setThemeInIframe(iframes[i], theme); +} +function boot$9() { + iframely.setTheme = (theme, container) => { + if (theme && iframely.SUPPORTED_THEMES.indexOf(theme) > -1) if (container) if (container.tagName === "IFRAME") setThemeInIframe(container, theme); + else setThemeInAllIframes(container, theme); + else { + iframely.configure({ theme }); + setThemeInAllIframes(document, theme); + iframely.trigger("set-theme", theme); + } + else console.warn("Using iframely.setTheme with not supported theme: \"" + theme + "\". Supported themes are: " + iframely.SUPPORTED_THEMES.join(", ")); + }; +} +//#endregion +//#region src/import.ts +var widgetsCache = {}; +function boot$8() { + iframely.on("load", (el) => { + if (!el && iframely.config.import !== false && isImportAble() && !iframely.import) { + const elements = document.querySelectorAll("a[data-iframely-url]:not([data-import-uri])"); + if (elements.length > 1) makeImportAPICall(elements); + } + }); + iframely.on("load", (widget, importOptions) => { + if (widget && !(widget instanceof Element) && widget.uri && (widget.html || widget.cancel)) { + const els = widgetsCache[widget.uri]; + if (els) for (let i = 0; i < els.length; i++) loadImportWidget(widget, els[i], importOptions); + delete widgetsCache[widget.uri]; + } + }); + iframely.buildImportWidgets = (importOptions) => { + iframely.trigger("import-loaded", importOptions); + importOptions.widgets.forEach((widget) => { + iframely.trigger("load", widget, importOptions); + }); + importReady(); + }; + iframely.isTouch = () => { + return "ontouchstart" in window || navigator.maxTouchPoints > 0; + }; + iframely.on("import-widget-ready", clearWrapperStylesAndClass); + iframely.on("unload", (el) => { + if (!el) { + delete iframely.import; + Object.keys(widgetsCache).forEach((key) => { + delete widgetsCache[key]; + }); + } + }); + if (!iframely.addEventListener) iframely.addEventListener = (elem, type, eventHandle) => { + if (!elem) return; + elem.addEventListener(type, eventHandle, false); + }; +} +function makeImportAPICall(elements) { + const script = createScript(); + const uris = []; + const ids = []; + let import_options = null; + function pushElement(uri, el) { + if (!widgetsCache[uri]) widgetsCache[uri] = []; + widgetsCache[uri].push(el); + } + function queueElement(el) { + const src = el.getAttribute("data-iframely-url"); + const mId = src.match(iframely.ID_RE); + const id = mId && mId[1]; + const options = parseQueryString(src, iframely.SUPPORTED_QUERY_STRING.concat("url")); + let url = options.url; + delete options.url; + let skipImport = options.import === "0" || options.import === "false" || options.playerjs === "1" || options.playerjs === "true"; + if (!skipImport) { + const mBase = src.match(iframely.BASE_RE); + options.CDN = mBase && mBase[0]; + if (!import_options) import_options = options; + else if (JSON.stringify(options, Object.keys(options).sort()) !== JSON.stringify(import_options, Object.keys(import_options).sort())) skipImport = true; + } + if (skipImport) iframely.trigger("load", el); + else if (id) { + el.setAttribute("data-import-uri", id); + if (ids.indexOf(id) === -1) ids.push(id); + pushElement(id, el); + } else { + if (!url) url = el.getAttribute("href"); + if ((import_options.key || import_options.api_key || iframely.config.api_key || iframely.config.key) && url) { + el.setAttribute("data-import-uri", url); + if (uris.indexOf(url) === -1) uris.push(url); + pushElement(url, el); + } else iframely.trigger("load", el); + } + } + for (let i = 0; i < elements.length; i++) { + const el = elements[i]; + if (!el.getAttribute("data-import-uri") && el.hasAttribute("data-iframely-url")) queueElement(el); + } + if (uris.length > 0 || ids.length > 0) { + import_options = import_options || {}; + import_options.touch = iframely.isTouch(); + import_options.flash = false; + import_options.app = 1; + if (iframely.config.theme) import_options.theme = iframely.config.theme; + if (uris.length > 0) import_options.uri = uris; + if (ids.length > 0) import_options.ids = ids.join("&"); + import_options.v = iframely.VERSION; + script.src = getEndpoint("/api/import/v2", import_options, iframely.SUPPORTED_QUERY_STRING); + script.onerror = () => { + importReady(); + }; + document.head.appendChild(script); + iframely.import = script; + } else { + importReady(); + iframely.trigger("load"); + } +} +function loadImportWidget(widgetOptions, el, importOptions) { + const needCancelWidget = widgetOptions.cancel; + const shadow = widgetOptions.shadow; + const hasRenderedEvent = widgetOptions.renderEvent; + const wrapper = getIframeWrapper(el, true); + if (needCancelWidget) iframely.cancelWidget(getWidget(el) || { + maxWidthWrapper: el, + iframe: el, + url: el.getAttribute("href") + }); + else { + const widget = document.createElement("div"); + widget.innerHTML = widgetOptions.html; + let parent, replacedEl; + if (wrapper && !hasRenderedEvent) { + parent = wrapper.aspectWrapper.parentNode; + replacedEl = wrapper.aspectWrapper; + wrapper.maxWidthWrapper.removeAttribute("style"); + } else { + parent = el.parentNode; + replacedEl = el; + } + if (shadow) { + const shadowContainer = document.createElement("div"); + const shadowRoot = shadowContainer.attachShadow({ mode: "open" }); + shadowRoot.appendChild(widget); + const shadowWidgetOptions = { + shadowRoot, + shadowContainer, + container: parent, + context: widgetOptions.context, + stylesIds: widgetOptions.stylesIds, + stylesDict: importOptions.commonShadowStyles + }; + iframely.trigger("import-shadow-widget-before-render", shadowWidgetOptions); + parent.insertBefore(shadowContainer, replacedEl); + iframely.trigger("import-shadow-widget-after-render", shadowWidgetOptions); + } else { + parent.insertBefore(widget, replacedEl); + exec_body_scripts(widget); + } + parent.removeChild(replacedEl); + if (hasRenderedEvent) setTimeout(() => { + clearWrapperStylesAndClass(parent); + }, iframely.CLEAR_WRAPPER_STYLES_TIMEOUT); + } +} +function importReady() { + delete iframely.import; + const failed_elements = document.querySelectorAll("a[data-iframely-url][data-import-uri]"); + for (let i = 0; i < failed_elements.length; i++) { + failed_elements[i].removeAttribute("data-import-uri"); + iframely.trigger("load", failed_elements[i]); + } +} +function isImportAble() { + return !!(document.location && (iframely.debug || document.location.protocol === "http:" || document.location.protocol === "https:") && !iframely.config.playerjs && !iframely.config.lazy); +} +function clearWrapperStylesAndClass(el) { + let aspectWrapper = el; + let parents = 0; + while (aspectWrapper && (!aspectWrapper.getAttribute("class") || aspectWrapper.getAttribute("class").split(" ").indexOf(iframely.ASPECT_WRAPPER_CLASS) === -1)) { + aspectWrapper = aspectWrapper.parentNode; + parents++; + if (parents > 4) aspectWrapper = null; + } + const maxWidthWrapper = aspectWrapper && aspectWrapper.parentNode; + if (maxWidthWrapper && maxWidthWrapper.getAttribute("class") && maxWidthWrapper.getAttribute("class").split(" ").indexOf(iframely.MAXWIDTH_WRAPPER_CLASS) > -1) { + aspectWrapper.removeAttribute("style"); + aspectWrapper.removeAttribute("class"); + maxWidthWrapper.removeAttribute("style"); + } +} +function exec_body_scripts(body_el) { + function nodeName(elem, name) { + return !!elem.nodeName && elem.nodeName.toUpperCase() === name.toUpperCase(); + } + function evalScript(elem) { + const data = elem.text || elem.textContent || elem.innerHTML || ""; + const script = createScript(); + script.type = "text/javascript"; + for (let i = 0; i < elem.attributes.length; i++) { + const attr = elem.attributes[i]; + script.setAttribute(attr.name, attr.value); + } + script.appendChild(document.createTextNode(data)); + body_el.appendChild(script); + } + const scripts = []; + const children_nodes = body_el.childNodes; + for (let i = 0; children_nodes[i]; i++) { + const child = children_nodes[i]; + if (nodeName(child, "script") && (!child.type || child.type.toLowerCase() === "text/javascript" || child.type.toLowerCase() === "application/javascript")) { + scripts.push(child); + body_el.removeChild(child); + } else if (child.nodeType === Node.ELEMENT_NODE) exec_body_scripts(child); + } + for (let i = 0; i < scripts.length; i++) { + const script = scripts[i]; + if (script.parentNode) script.parentNode.removeChild(script); + evalScript(script); + } +} +//#endregion +//#region src/ahref.ts +function boot$7() { + iframely.on("load", (container, href) => { + if (container && container.nodeName && typeof href === "string") { + const a = document.createElement("a"); + a.setAttribute("href", href); + container.appendChild(a); + iframely.trigger("load", a); + } + }); + iframely.on("load", (el) => { + if (!el && !iframely.import) { + const elements = document.querySelectorAll("a[data-iframely-url]:not([data-import-uri])"); + for (let i = 0; i < elements.length; i++) iframely.trigger("load", elements[i]); + } + }); + iframely.on("load", (el) => { + if (el && el.nodeName === "A" && (el.getAttribute("data-iframely-url") || el.getAttribute("href")) && !el.hasAttribute("data-import-uri")) unfurl(el); + }); +} +function unfurl(el) { + if (!el.getAttribute("data-iframely-url") && !el.getAttribute("href")) return; + let src; + const dataIframelyUrl = el.getAttribute("data-iframely-url"); + if (dataIframelyUrl && /^((?:https?:)?\/\/[^/]+)\/\w+/i.test(dataIframelyUrl)) src = getEndpoint(dataIframelyUrl, { + v: iframely.VERSION, + app: 1, + theme: iframely.config.theme + }); + else if ((iframely.config.api_key || iframely.config.key) && iframely.CDN) { + if (!el.getAttribute("href")) { + console.warn("Iframely cannot build embeds: \"href\" attribute missing in", el); + return; + } + src = getEndpoint("/api/iframe", { + url: el.getAttribute("href"), + v: iframely.VERSION, + app: 1, + theme: iframely.config.theme + }, iframely.SUPPORTED_QUERY_STRING); + } else console.warn("Iframely cannot build embeds: api key is required as query-string of embed.js"); + if (!src) el.removeAttribute("data-iframely-url"); + else { + const iframe = document.createElement("iframe"); + iframe.setAttribute("allowfullscreen", ""); + iframe.setAttribute("allow", "autoplay *; encrypted-media *; ch-prefers-color-scheme *"); + if (el.hasAttribute("data-img")) iframe.setAttribute("data-img", el.getAttribute("data-img")); + const isLazy = el.hasAttribute("data-lazy") || el.hasAttribute("data-img") || /&lazy=1/.test(src) || iframely.config.lazy; + const text = el.textContent; + if (text && text !== "") iframe.textContent = text; + let wrapper = getIframeWrapper(el, true); + if (wrapper) while (wrapper.aspectWrapper.lastChild) wrapper.aspectWrapper.removeChild(wrapper.aspectWrapper.lastChild); + else { + wrapper = addDefaultWrappers(el); + el.parentNode.removeChild(el); + } + wrapper.aspectWrapper.appendChild(iframe); + if (isLazy) { + iframe.setAttribute("data-iframely-url", src); + iframely.trigger("load", iframe); + } else { + iframe.setAttribute("src", src); + iframely.trigger("iframe-ready", iframe); + } + } +} +//#endregion +//#region src/lazy-img-placeholder.ts +function boot$6() { + iframely.on("load", (el) => { + if (el && el.nodeName === "IFRAME" && el.hasAttribute("data-iframely-url") && el.hasAttribute("data-img") && !el.getAttribute("src")) { + const dataImg = el.getAttribute("data-img"); + el.removeAttribute("data-img"); + el.setAttribute("data-img-created", ""); + const widget = getWidget(el); + let src = el.getAttribute("data-iframely-url"); + if (widget) { + addPlaceholderThumbnail(widget, src, dataImg); + src = addQueryString(src, { img: 1 }); + el.setAttribute("data-iframely-url", src); + new WaitingWidget(widget); + } + iframely.trigger("load", el); + } + }); + iframely.on("message", (widget, message) => { + if (!widget) return; + let waitingWidget; + if (message.method === "widgetRendered") { + hidePlaceholderThumbnail(widget); + waitingWidget = findWaitingWidget(widget); + waitingWidget?.deactivate(); + } + if (message.method === "begin-waiting-widget-render") { + waitingWidget = findWaitingWidget(widget); + waitingWidget?.clearLoadingTimeout(); + } + if (message.method === "end-waiting-widget-render") { + waitingWidget = findWaitingWidget(widget); + waitingWidget?.registerLoadingTimeout(); + } + }); + iframely.on("unload-widget", (widget) => { + findWaitingWidget(widget)?.deactivate(); + }); +} +function addPlaceholderThumbnail(widget, href, imageUrl) { + let thumbHref; + if (imageUrl && /^(https?:)?\/\//.test(imageUrl)) thumbHref = imageUrl; + else { + const query = parseQueryString(href); + const _params = {}; + for (const param in query) if (param.indexOf("_") === 0) _params[param] = query[param]; + if (query.media) _params.media = query.media; + if (href.match(/\/api\/iframe/)) thumbHref = getEndpoint(href.match(/^(.+)\/api\/iframe/i)[1] + "/api/thumbnail", Object.assign({ + url: query.url, + api_key: query.api_key, + key: query.key + }, _params)); + else if (href.match(iframely.ID_RE)) thumbHref = getEndpoint(href.replace(/^((?:https?:)?\/\/[^/]+\/(\w+-?\w+))(?:\?.*)?$/, "$1/thumbnail"), _params); + else return; + } + const thumb = document.createElement("div"); + setStyles(thumb, { + position: "absolute", + width: "100%", + height: "100%", + backgroundImage: "url('" + thumbHref + "')", + backgroundSize: "cover", + backgroundPosition: "center" + }); + const iframelyLoaderDiv = document.createElement("div"); + iframelyLoaderDiv.setAttribute("class", iframely.LOADER_CLASS); + thumb.appendChild(iframelyLoaderDiv); + const paddingTop = iframely.getElementComputedStyle(widget.aspectWrapper, "padding-top"); + const paddingBottom = iframely.getElementComputedStyle(widget.aspectWrapper, "padding-bottom"); + const paddingTopMatch = paddingTop && paddingTop.match(/^(\d+)px$/); + if (paddingTopMatch && parseInt(paddingTopMatch[1]) && paddingBottom) { + const thumbWrapper = document.createElement("div"); + setStyles(thumbWrapper, { + top: "-" + paddingTop, + width: "100%", + height: 0, + position: "relative", + paddingBottom + }); + thumbWrapper.appendChild(thumb); + widget.aspectWrapper.appendChild(thumbWrapper); + } else widget.aspectWrapper.appendChild(thumb); +} +function getNthNonTextChildNode(nth, element) { + let count = 0; + for (let i = 0; i < element.childNodes.length; i++) { + const el = element.childNodes[i]; + if (el.nodeType === Node.ELEMENT_NODE) { + if (nth === count) return el; + count++; + } + } +} +function nonTextChildCount(element) { + let count = 0; + for (let i = 0; i < element.childNodes.length; i++) { + const el = element.childNodes[i]; + if (el.nodeType === Node.TEXT_NODE) { + if ((el.textContent || "").replace(/\s|\n/g, "")) count++; + } else if (el.nodeType === Node.ELEMENT_NODE) count++; + } + return count; +} +function hidePlaceholderThumbnail(widget) { + const thumb = widget.aspectWrapper && nonTextChildCount(widget.aspectWrapper) > 1 && getNthNonTextChildNode(1, widget.aspectWrapper); + if (thumb && thumb.nodeName === "DIV") widget.aspectWrapper.removeChild(thumb); +} +var waitingWidgets = []; +function findWaitingWidgetIdx(widget) { + let i = 0; + while (i < waitingWidgets.length && waitingWidgets[i].widget.iframe !== widget.iframe) i++; + if (i < waitingWidgets.length && waitingWidgets[i].widget.iframe === widget.iframe) return i; +} +function findWaitingWidget(widget) { + const idx = findWaitingWidgetIdx(widget); + if (idx || idx === 0) return waitingWidgets[idx]; +} +function removeWaitingWidget(widget) { + const idx = findWaitingWidgetIdx(widget); + if (idx || idx === 0) waitingWidgets.splice(idx, 1); +} +var WaitingWidget = class { + widget; + loadCount = 0; + timeoutId = null; + constructor(widget) { + this.widget = widget; + iframely.addEventListener(widget.iframe, "load", () => { + this.iframeOnLoad(); + }); + this.registerLoadingTimeout(); + waitingWidgets.push(this); + } + iframeOnLoad() { + this.loadCount++; + if (this.loadCount !== 2) return; + this.deactivate(); + setTimeout(() => { + hidePlaceholderThumbnail(this.widget); + }, iframely.LAZY_IFRAME_FADE_TIMEOUT); + } + deactivate() { + this.clearLoadingTimeout(); + removeWaitingWidget(this.widget); + } + clearLoadingTimeout() { + if (this.timeoutId) clearTimeout(this.timeoutId); + this.timeoutId = null; + } + registerLoadingTimeout() { + if (this.timeoutId) return; + this.timeoutId = setTimeout(() => { + this.iframeOnLoad(); + }, iframely.LAZY_IFRAME_SHOW_TIMEOUT); + } +}; +//#endregion +//#region src/lazy-iframe.ts +function boot$5() { + iframely.on("load", (el) => { + if (!el) { + const elements = document.querySelectorAll("iframe[data-iframely-url]"); + for (let i = 0; i < elements.length; i++) iframely.trigger("load", elements[i]); + } + }); + iframely.on("load", (el) => { + if (el && el.nodeName === "IFRAME" && el.hasAttribute("data-iframely-url") && !el.hasAttribute("data-img") && !el.getAttribute("src")) loadLazyIframe(el); + }); +} +function loadLazyIframe(el) { + const widget = getWidget(el); + let src = el.getAttribute("data-iframely-url"); + const dataImg = el.hasAttribute("data-img-created") || el.hasAttribute("data-img"); + const nativeLazyLoad = !dataImg && iframely.SUPPORT_IFRAME_LOADING_ATTR; + if (widget && src) { + const options = { + v: iframely.VERSION, + app: 1, + theme: iframely.config.theme + }; + if (!nativeLazyLoad && iframely.config.intersection) options.lazy = 1; + src = getEndpoint(src, options); + } + if (nativeLazyLoad) el.setAttribute("loading", "lazy"); + if (dataImg && iframely.SUPPORT_IFRAME_LOADING_ATTR) el.setAttribute("loading", "edge"); + el.setAttribute("src", src || ""); + el.removeAttribute("data-iframely-url"); + iframely.trigger("iframe-ready", el); +} +//#endregion +//#region src/widget-cancel.ts +function boot$4() { + iframely.on("message", (widget, message) => { + if (message.method === "cancelWidget") iframely.cancelWidget(widget); + }); + iframely.cancelWidget = (widget) => { + if (!widget) { + console.warn("iframely.cancelWidget called without widget param"); + return; + } + function findParent(el, className) { + let found = false; + while (!found && el.parentNode) { + el = el.parentNode; + found = !!el.className && typeof el.className === "string" && el.className.split(" ").indexOf(className) >= 0; + } + return found && el; + } + let parentNode = widget.maxWidthWrapper && widget.maxWidthWrapper.parentNode; + let naNode = widget.maxWidthWrapper; + if (iframely.config && iframely.config.parent) { + const parentElement = findParent(widget.maxWidthWrapper, String(iframely.config.parent)); + if (parentElement) { + parentNode = parentElement.parentNode; + naNode = parentElement; + } + } + if (widget.url) { + const text = widget.iframe && widget.iframe.textContent; + iframely.triggerAsync("cancel", widget.url, parentNode, text, naNode.nextSibling); + } + parentNode.removeChild(naNode); + }; +} +//#endregion +//#region src/widget-resize.ts +var resetWrapperBorderStyles = { + border: "", + "border-radius": "", + "box-shadow": "", + overflow: "" +}; +var resetIframeBorderStyles = { + border: "0", + "border-radius": "", + "box-shadow": "", + overflow: "" +}; +function boot$3() { + iframely.on("message", (widget, message) => { + if (message.method === "setIframelyWidgetSize" || message.method === "resize" || message.method === "setIframelyEmbedData" || message.type === "embed-size" || message.context === "iframe.resize") { + let frame_styles = null; + if (message.data && message.data.media && message.data.media.frame_style) { + message.data.media.frame_style.split(";").forEach((str) => { + if (str.trim() !== "" && str.indexOf(":") > -1) { + const props = str.split(":"); + if (props.length === 2) { + frame_styles = frame_styles || {}; + frame_styles[props[0].trim()] = props[1].trim(); + } + } + }); + widgetDecorate(widget, frame_styles); + } else if (message.method === "setIframelyEmbedData") widgetDecorate(widget, null); + let media = message.data && message.data.media; + if (!media && message.height) media = { + height: message.height, + "max-width": "keep" + }; + widgetResize(widget, media); + } + }); +} +function widgetDecorate(widget, styles) { + if (styles && widget && widget.iframe) if (styles["border-radius"]) { + styles.overflow = "hidden"; + setStyles(widget.aspectWrapper, styles); + } else setStyles(widget.iframe, styles); + else if (!styles && widget && widget.iframe) { + setStyles(widget.aspectWrapper, resetWrapperBorderStyles); + setStyles(widget.iframe, resetIframeBorderStyles); + } +} +function getTotalBorderWidth(widget) { + const frameStylesBorder = widget.iframe && widget.iframe.style.border || widget.aspectWrapper && widget.aspectWrapper.style.border; + const borderMatch = frameStylesBorder && frameStylesBorder.match(/(\d+)px/); + if (borderMatch) return parseInt(borderMatch[1]) * 2; + return 0; +} +function widgetResize(widget, media) { + if (media && Object.keys(media).length > 0 && widget) { + const borderWidth = getTotalBorderWidth(widget); + const oldIframeHeight = window.getComputedStyle(widget.iframe).getPropertyValue("height"); + let maxWidth = media["max-width"]; + if (typeof maxWidth === "number") maxWidth += borderWidth; + setStyles(widget.maxWidthWrapper, { + "max-width": maxWidth, + "min-width": media["min-width"] && media["min-width"] + borderWidth, + width: media.width && media.width + borderWidth + }); + if (media.scrolling && widget.iframe) widget.iframe.setAttribute("scrolling", media.scrolling); + const aspectRatio = media["aspect-ratio"]; + if (aspectRatio || media.height) setStyles(widget.aspectWrapper, { + paddingBottom: aspectRatio ? Math.round(1e3 * 100 / aspectRatio) / 1e3 + "%" : 0, + paddingTop: aspectRatio && media["padding-bottom"], + height: aspectRatio ? 0 : media.height && media.height + borderWidth + }); + const currentHeight = window.getComputedStyle(widget.iframe).getPropertyValue("height"); + if (oldIframeHeight && oldIframeHeight !== currentHeight) iframely.triggerAsync("heightChanged", widget.iframe, oldIframeHeight, currentHeight); + } +} +//#endregion +//#region src/widget-click.ts +function boot$2() { + iframely.on("message", (widget, message) => { + if (message.method === "open-href" || message.method === "click") iframely.trigger(message.method, message.href); + }); + if (!iframely.openHref) iframely.openHref = (href) => { + if (href.indexOf(window.location.origin) === 0) window.location.href = href; + else window.open(href, "_blank", "noopener"); + }; + iframely.on("open-href", (href) => { + iframely.triggerAsync("click", href); + iframely.openHref(href); + }); +} +//#endregion +//#region src/widget-options.ts +function boot$1() { + iframely.on("message", (widget, message) => { + if (message.method === "setIframelyEmbedOptions") iframely.trigger("options", widget, message.data); + }); +} +//#endregion +//#region src/deprecated.ts +function boot() { + iframely.widgets = iframely.widgets || {}; + iframely.widgets.load = iframely.load; + iframely.extendOptions = iframely.configure; + if (!iframely.events) { + iframely.events = {}; + iframely.events.on = iframely.on; + iframely.events.trigger = iframely.trigger; + } + iframely.on("cancel", (url, parentNode, text, nextSibling) => { + if (iframely.RECOVER_HREFS_ON_CANCEL && !text) text = url; + if (url && parentNode && text && text !== "") { + const a = document.createElement("a"); + a.setAttribute("href", url); + a.setAttribute("target", "_blank"); + a.setAttribute("rel", "noopener"); + a.textContent = text; + if (nextSibling) parentNode.insertBefore(a, nextSibling); + else parentNode.appendChild(a); + } + }); +} +//#endregion +export { boot$4 as a, boot$7 as c, boot$10 as d, boot$11 as f, boot$14 as h, boot$3 as i, boot$8 as l, boot$13 as m, boot$1 as n, boot$5 as o, boot$12 as p, boot$2 as r, boot$6 as s, boot as t, boot$9 as u }; diff --git a/dist/esm/chunks/iframely.js b/dist/esm/chunks/iframely.js new file mode 100644 index 0000000..cb72551 --- /dev/null +++ b/dist/esm/chunks/iframely.js @@ -0,0 +1,26 @@ +//#region src/iframely.ts +function createServerStub() { + const noop = () => {}; + return { + config: {}, + on: noop, + trigger: noop, + triggerAsync: noop, + load: noop, + unload: noop, + configure: noop, + extendOptions: noop, + setTheme: noop, + cancelWidget: noop, + openHref: noop, + addEventListener: noop, + isTouch: () => false, + findIframe: () => void 0, + getElementComputedStyle: () => void 0, + buildOptionsForm: noop + }; +} +var iframely = typeof window === "undefined" ? createServerStub() : window.iframely = window.iframely || {}; +iframely.config = iframely.config || {}; +//#endregion +export { iframely as t }; diff --git a/dist/esm/chunks/translator.js b/dist/esm/chunks/translator.js new file mode 100644 index 0000000..b910890 --- /dev/null +++ b/dist/esm/chunks/translator.js @@ -0,0 +1,14 @@ +import { t as iframely } from "./iframely.js"; +//#region src/options/translator.ts +var langs = {}; +function registerLabels(lang, labels) { + const existingLabels = langs[lang] = langs[lang] || {}; + Object.assign(existingLabels, labels); +} +iframely.optionsTranslator = (lang) => { + return (label) => { + return langs[lang] && langs[lang][label] && langs[lang][label] !== "" ? langs[lang][label] : label; + }; +}; +//#endregion +export { registerLabels as t }; diff --git a/dist/esm/i18n.de.js b/dist/esm/i18n.de.js new file mode 100644 index 0000000..8e58bf6 --- /dev/null +++ b/dist/esm/i18n.de.js @@ -0,0 +1,70 @@ +import { t as registerLabels } from "./chunks/translator.js"; +//#region src/options/lang/labels.de.ts +registerLabels("de", { + "Slimmer horizontal player": "Schlanker horizontaler Player", + "Include playlist": "Wiedergabeliste anzeigen", + "Hide artwork": "Artwork ausblenden", + "Theme color": "Theme Farbe", + Light: "Hell", + Dark: "Dunkel", + Auto: "Automatisch", + Default: "Standard", + "Adjust height": "Höhe einstellen", + "Active page": "Aktive Seite", + "Use click-to-load": "Verwende click-to-load", + "ex.: 600, in px": "Z.B. 600, in px", + "Hide timed comments": "Kommentare ausblenden", + "Let Iframely optimize player for the artwork": "Optimierung des Players durch IFramely", + "Show as slideshow": "Als Slideshow zeigen", + "Start from": "Start ab", + "ex.: 11, 1m10s": "z.B. 11, 1m10s", + "End on": "Ende an", + "Closed captions": "Untertitel", + "Include up to 20 tweets": "Bis zu 20 Tweets anzeigen", + "Hide photos, videos, and cards": "Verberge Fotos, Videos und Cards", + "Hide previous Tweet in conversation thread": "Verberge den vorigen Tweet in der Konversation", + "Use dark theme": "Verwende dunkles Farbschema", + "Adjust width": "Breite anpassen", + "Hide description": "Beschreibung verbergen", + "Widget style": "Widget-Style", + Mini: "Mini", + Classic: "Klassisch", + Picture: "Bild", + Zoom: "Zoom", + "Map orientation": "Karten-Ausrichtung", + Album: "Album", + Portrait: "Portrait", + Square: "Quadratisch", + "Show context slideshow": "Als Slideshow anzeigen", + "Show description footer": "Fußzeile anzeigen", + "Show user header": "Kopfbereich anzeigen", + "Show author's text caption": "Beschriftung des Autors anzeigen", + "Hide author's text caption": "Beschriftung des Autors verbergen", + "Include parent comment (if url is a reply)": "Ursprünglichen Kommentar einschließen (wenn die Url eine Antwort ist)", + "Show recent posts": "Neueste Beiträge anzeigen", + "Show profile photos when friends like this": "Profilfotos anzeigen, wenn Freunde dies mögen", + "Use the small header instead": "Kleine Kopfzeile stattdessen verwenden", + Artwork: "Artwork", + Small: "klein", + Big: "groß", + None: "Keines", + Layout: "Layout", + Slim: "Schlank", + "Artwork-only": "Nur Artwork", + Standard: "Standard", + "Size & style": "Größe & Stil", + "Wide image": "Breite Darstellung", + "Wide simple": "Breite Darstellung (Einfach)", + "Text language (ignored if no captions)": "Sprache der Untertitel (wird ignoriert, wenn keine Untertitel vorhanden)", + "Two letters: en, fr, es, de...": "Zwei Buchstaben: en, fr, es, de...", + "Don't include attached player": "Player nicht integrieren", + "Attached player only, no card": "Nur Player, keine Card", + "Hold load & play until clicked": "Klicken zum Abspielen", + "Make it a small card": "Kleine Card verwenden", + "Keep using full media card": "Verwende weiterhin vollständige Media-Cards", + "Don't include player": "Player nicht hinzufügen", + "Player only, no card": "Nur Player, keine Card", + "Just the player": "Nur Player", + "Just the image": "Nur Bild" +}); +//#endregion diff --git a/dist/esm/i18n.fr.js b/dist/esm/i18n.fr.js new file mode 100644 index 0000000..8778df6 --- /dev/null +++ b/dist/esm/i18n.fr.js @@ -0,0 +1,63 @@ +import { t as registerLabels } from "./chunks/translator.js"; +//#region src/options/lang/labels.fr.ts +registerLabels("fr", { + "Slimmer horizontal player": "Joueur de audio classique", + "Include playlist": "Inclure la playlist", + "Hide artwork": "Masquer la illustration", + "Theme color": "Couleur du thème", + Light: "Lumière", + Dark: "Sombre", + Auto: "", + Default: "Défaut", + "Adjust height": "Height", + "Active page": "Page active", + "Use click-to-load": "Utilisez click-to-load", + "ex.: 600, in px": "", + "Hide timed comments": "Masquer les commentaires", + "Let Iframely optimize player for the artwork": "Optimiser le lecteur pour l'illustration", + "Show as slideshow": "Montrer en diaporama", + "Start from": "Commencer", + "ex.: 11, 1m10s": "", + "End on": "Fin sur", + "Include up to 20 tweets": "Incluez jusqu'à 20 tweets", + "Hide photos, videos, and cards": "Masquer les photos, les vidéos et les cartes", + "Hide previous Tweet in conversation thread": "Masquer le tweet parent", + "Hide description": "Masquer la description", + "Widget style": "Style de widget", + Mini: "", + Classic: "Classique", + Picture: "Image", + Zoom: "", + "Map orientation": "Orientation de la carte", + Album: "", + Portrait: "", + Square: "Carré", + "Show context slideshow": "Afficher le diaporama contextuel", + "Show description footer": "Afficher la description pied de page", + "Show user header": "Afficher l'en-tête de l'utilisateur", + "Show author's text caption": "Afficher la description de l'auteur", + "Hide author's text caption": "Masquer la description de l'auteur", + "Include parent comment (if url is a reply)": "", + "Show recent posts": "Afficher les messages récents", + "Show profile photos when friends like this": "", + "Use the small header instead": "Utilisez plutôt le petit en-tête", + Artwork: "Ouvrages d'art", + Small: "Petite", + Big: "Grosse", + None: "Aucune", + Layout: "Disposition", + Slim: "Svelte", + "Artwork-only": "Oeuvre seule", + Standard: "Standard", + "Size & style": "Style", + "Wide image": "Image large", + "Wide simple": "Large simple", + "Hold load & play until clicked": "Click-to-play", + "Make it a small card": "Carte compacte", + "Keep using full media card": "Continuez à utiliser la carte média complète", + "Don't include player": "Ne pas inclure la vidéo", + "Player only, no card": "La vidéo seulement, pas de carte", + "Just the player": "Seulement la vidéo", + "Just the image": "Seulement l'image" +}); +//#endregion diff --git a/dist/esm/main-options.js b/dist/esm/main-options.js new file mode 100644 index 0000000..d830792 --- /dev/null +++ b/dist/esm/main-options.js @@ -0,0 +1,355 @@ +import { t as iframely } from "./chunks/iframely.js"; +import { a as boot$11, c as boot$8, d as boot$5, f as boot$3, h as boot$1, i as boot$12, l as boot$7, m as boot$2, n as boot$14, o as boot$10, p as boot$4, r as boot$13, s as boot$9, t as boot$15, u as boot$6 } from "./chunks/deprecated.js"; +//#region src/options/form-generator.ts +var _RE = /^_./; +var translate = (label, translator) => { + return translator && typeof translator === "function" && label ? translator(label) || label : label; +}; +function getFormElements(options, translator) { + if (!options) return []; + options = Object.assign({}, options); + delete options.query; + const items = []; + const keys = Object.keys(options); + let checkboxCount = 0; + keys.forEach((key) => { + const context = {}; + let getQuery; + const option = options[key]; + option.key = key; + let forceCheckboxForSingleKeyValue = false; + const valuesKeys = option.values ? Object.keys(option.values) : void 0; + let singleKey, singleLabel; + if (valuesKeys && valuesKeys.length === 1) { + forceCheckboxForSingleKeyValue = true; + singleKey = valuesKeys[0]; + singleLabel = option.values[singleKey]; + } + context.label = translate(singleLabel || option.label, translator); + context.key = option.key; + if (forceCheckboxForSingleKeyValue || typeof option.value === "boolean") { + if (forceCheckboxForSingleKeyValue) context.checked = singleKey === option.value || !singleKey && !option.value; + else context.checked = option.value; + checkboxCount++; + items.push({ + type: "checkbox", + context, + order: _RE.test(key) ? 0 : 1, + getQuery: (checked) => { + let value; + if (forceCheckboxForSingleKeyValue) value = checked ? singleKey : ""; + else value = checked; + const result = {}; + if (forceCheckboxForSingleKeyValue) if (value === "") {} else result[option.key] = value; + else result[option.key] = checked; + return result; + } + }); + } else if ((typeof option.value === "number" || typeof option.value === "string") && !option.values) { + const useSlider = option.range && typeof option.range.min === "number" && typeof option.range.max === "number"; + const useNumber = typeof option.value === "number"; + context.value = option.value; + getQuery = (inputValue) => { + const result = {}; + if (inputValue === "") {} else result[option.key] = inputValue; + return result; + }; + if (useSlider) { + context.min = option.range.min; + context.max = option.range.max; + items.push({ + type: "range", + context, + order: 9, + getQuery + }); + } else { + context.placeholder = translate(option.placeholder || "", translator); + context.inputType = useNumber ? "number" : "text"; + items.push({ + type: "text", + context, + order: /start/i.test(key) ? 7 : 8, + getQuery + }); + } + } else if (option.values) { + context.value = option.value + ""; + getQuery = (inputValue) => { + const result = {}; + if (inputValue === "") {} else result[option.key] = inputValue; + return result; + }; + if (Object.keys(option.values).length <= 3) { + if (option.label) context.label = translate(option.label, translator); + else context.label = false; + let i = 0; + let hasLongLabel = false; + const values = Object.values(option.values); + while (i < values.length && !hasLongLabel) { + hasLongLabel = values[i].length > 8; + i++; + } + context.inline = !hasLongLabel; + context.items = []; + Object.keys(option.values).forEach((key, idx2) => { + context.items.push({ + id: context.key + "-" + idx2, + value: key, + label: translate(option.values[key], translator), + checked: context.value === key + }); + }); + items.push({ + type: "radio", + context, + order: hasLongLabel ? -3 : !/theme/.test(key) ? -2 : -1, + getQuery + }); + } else { + context.items = []; + Object.keys(option.values).forEach((key) => { + context.items.push({ + value: key, + label: translate(option.values[key], translator), + checked: context.value === key + }); + }); + items.push({ + type: "select", + context, + order: 5, + getQuery + }); + } + } + }); + items.sort((a, b) => a.order - b.order); + items.forEach((item) => { + delete item.order; + }); + if (checkboxCount > 0) { + const groupedItems = []; + let subItems; + items.forEach((item, idx) => { + if (item.type === "checkbox") { + const newCheckboxGroup = checkboxCount > 2 && idx > 0 && !_RE.test(item.context.key) && items[idx - 1].type === "checkbox" && _RE.test(items[idx - 1].context.key); + if (!subItems || newCheckboxGroup) { + subItems = []; + groupedItems.push({ + type: "group", + context: { elements: subItems } + }); + } + subItems.push(item); + } else groupedItems.push(item); + }); + return groupedItems; + } else return items; +} +//#endregion +//#region src/options/form-builder.ts +var UIelements = { + checkbox: { getValue: (inputs) => { + return inputs[0].checked; + } }, + text: { + getValue: (inputs) => { + const input = inputs[0]; + let value = input.value; + if (input.type === "number") { + value = parseInt(value); + if (isNaN(value)) value = ""; + } + return value; + }, + customEvents: (inputs, submitOptionsCb) => { + const input = inputs[0]; + iframely.addEventListener(input, "click", () => { + input.select(); + }); + iframely.addEventListener(input, "blur", submitOptionsCb); + iframely.addEventListener(input, "keyup", (e) => { + if (e.keyCode === 13) submitOptionsCb(); + }); + } + }, + radio: { getValue: (inputs) => { + let selectedInput; + Array.prototype.forEach.call(inputs, (input) => { + if (input.checked) selectedInput = input; + }); + return selectedInput.value; + } } +}; +var defaultQueryById = {}; +function formBuilder(params) { + const options = params.options; + const formContainer = params.formContainer; + if (!formContainer) { + console.warn("No formContainer in form-builder options", params); + return; + } + if (!options) { + formContainer.innerHTML = ""; + return; + } + const elements = getFormElements(options, params.translator); + const id = params.id; + const renderer = params.renderer; + const defaultQuery = defaultQueryById[id] = defaultQueryById[id] || {}; + Object.keys(options).forEach((key) => { + if (!options.query || options.query.indexOf(key) === -1) defaultQuery[key] = options[key].value; + }); + function getQueryFromForm() { + const query = {}; + const getOptionsFromElements = (elements) => { + elements.forEach((element) => { + if (element.context && element.context.elements) getOptionsFromElements(element.context.elements); + else if (element.inputs) { + const elementUI = UIelements[element.type]; + let inputValue; + if (elementUI && elementUI.getValue) inputValue = elementUI.getValue(element.inputs); + else inputValue = element.inputs[0].value; + Object.assign(query, element.getQuery(inputValue)); + } + }); + }; + getOptionsFromElements(elements); + return query; + } + function getAndSubmitOptions() { + const query = getQueryFromForm(); + Object.keys(defaultQuery).forEach((key) => { + if (defaultQuery[key] === query[key] || query[key] === void 0) delete query[key]; + }); + iframely.trigger("options-changed", id, formContainer, query); + } + const renderElements = (elements) => { + let html = ""; + elements.forEach((element) => { + if (element.context && element.context.elements) element.context.elementsHtml = renderElements(element.context.elements); + html += renderer(element.type, element.context || {}); + }); + return html; + }; + formContainer.innerHTML = renderElements(elements); + const bindElements = (elements) => { + elements.forEach((element) => { + if (element.context && element.context.elements) bindElements(element.context.elements); + else { + const elementUI = UIelements[element.type]; + if (element.context) { + const inputs = formContainer.querySelectorAll("[name=\"" + element.context.key + "\"]"); + element.inputs = inputs; + if (inputs.length > 0) if (elementUI && elementUI.customEvents) elementUI.customEvents(inputs, getAndSubmitOptions); + else inputs.forEach((input) => { + iframely.addEventListener(input, "change", getAndSubmitOptions); + }); + else console.warn("No inputs found for option", element.context.key); + } + } + }); + }; + bindElements(elements); +} +//#endregion +//#region src/options/renderer.ts +var ESCAPE_MAP = { + "&": "&", + "<": "<", + ">": ">", + "\"": """, + "'": "'" +}; +var esc = (value) => value == null ? "" : String(value).replace(/[&<>"']/g, (c) => ESCAPE_MAP[c]); +var templates = { + checkbox: (ctx) => ` +
+ + +
`, + group: (ctx) => ` +
+
${ctx.elementsHtml ?? ""}
+
`, + radio: (ctx) => ` +
+ ${ctx.label ? `` : ""} +
+ ${(ctx.items || []).map((item) => ` +
+ + +
`).join("")} +
+
`, + range: (ctx) => ` +
+ +
+ +
+
`, + select: (ctx) => ` +
+ +
+ +
+
`, + text: (ctx) => ` +
+ +
+ +
+
` +}; +var render = (type, context) => templates[type](context); +//#endregion +//#region src/options/index.ts +function boot() { + iframely.buildOptionsForm = (id, formContainer, options, translator) => { + if (typeof iframely.trigger !== "function" || typeof iframely.addEventListener !== "function") { + console.warn("iframely.buildOptionsForm requires embed.js (or embed-options.js) to be loaded"); + return; + } + formBuilder({ + id, + formContainer, + options, + renderer: render, + translator + }); + }; +} +//#endregion +//#region src/index-options.ts +if (typeof window !== "undefined" && !iframely._loaded) { + iframely._loaded = true; + boot$1(); + boot$2(); + boot$3(); + boot$4(); + boot$5(); + boot$6(); + boot$7(); + boot$8(); + boot$9(); + boot$10(); + boot$11(); + boot$12(); + boot$13(); + boot$14(); + boot$15(); + boot(); + iframely.trigger("init"); +} +//#endregion +//#region src/main-options.ts +if (typeof window !== "undefined") iframely.config.autorun = iframely.config.autorun ?? false; +//#endregion +export { iframely }; diff --git a/dist/esm/main.js b/dist/esm/main.js new file mode 100644 index 0000000..6ff1e9f --- /dev/null +++ b/dist/esm/main.js @@ -0,0 +1,27 @@ +import { t as iframely } from "./chunks/iframely.js"; +import { a as boot$10, c as boot$7, d as boot$4, f as boot$2, h as boot, i as boot$11, l as boot$6, m as boot$1, n as boot$13, o as boot$9, p as boot$3, r as boot$12, s as boot$8, t as boot$14, u as boot$5 } from "./chunks/deprecated.js"; +//#region src/index.ts +if (typeof window !== "undefined" && !iframely._loaded) { + iframely._loaded = true; + boot(); + boot$1(); + boot$2(); + boot$3(); + boot$4(); + boot$5(); + boot$6(); + boot$7(); + boot$8(); + boot$9(); + boot$10(); + boot$11(); + boot$12(); + boot$13(); + boot$14(); + iframely.trigger("init"); +} +//#endregion +//#region src/main.ts +if (typeof window !== "undefined") iframely.config.autorun = iframely.config.autorun ?? false; +//#endregion +export { iframely }; diff --git a/dist/options.i18n.de.js b/dist/options.i18n.de.js index 814415b..c22f029 100644 --- a/dist/options.i18n.de.js +++ b/dist/options.i18n.de.js @@ -1,82 +1,113 @@ -/* - * ATTENTION: The "eval" devtool has been used (maybe by default in mode: "development"). - * This devtool is neither made for production nor for readable output files. - * It uses "eval()" calls to create a separate source file in the browser devtools. - * If you are trying to read the output file, select a different devtool (https://webpack.js.org/configuration/devtool/) - * or disable the default devtool with "devtool: false". - * If you are looking for production-ready output files, see mode: "production" (https://webpack.js.org/configuration/mode/). - */ -/******/ (() => { // webpackBootstrap -/******/ var __webpack_modules__ = ({ +(function() { -/***/ "./iframely.js" -/*!*********************!*\ - !*** ./iframely.js ***! - \*********************/ -(module) { -eval("{var iframely = window.iframely = window.iframely || {};\niframely.config = iframely.config || {};\n\nmodule.exports = iframely;\n\n//# sourceURL=webpack:///./iframely.js?\n}"); +//#region src/iframely.ts + function createServerStub() { + const noop = () => {}; + return { + config: {}, + on: noop, + trigger: noop, + triggerAsync: noop, + load: noop, + unload: noop, + configure: noop, + extendOptions: noop, + setTheme: noop, + cancelWidget: noop, + openHref: noop, + addEventListener: noop, + isTouch: () => false, + findIframe: () => void 0, + getElementComputedStyle: () => void 0, + buildOptionsForm: noop + }; + } + var iframely = typeof window === "undefined" ? createServerStub() : window.iframely = window.iframely || {}; + iframely.config = iframely.config || {}; -/***/ }, +//#endregion +//#region src/options/translator.ts + var langs = {}; + function registerLabels(lang, labels) { + const existingLabels = langs[lang] = langs[lang] || {}; + Object.assign(existingLabels, labels); + } + iframely.optionsTranslator = (lang) => { + return (label) => { + return langs[lang] && langs[lang][label] && langs[lang][label] !== "" ? langs[lang][label] : label; + }; + }; -/***/ "./options/lang/labels.de.js" -/*!***********************************!*\ - !*** ./options/lang/labels.de.js ***! - \***********************************/ -(__unused_webpack_module, __unused_webpack_exports, __webpack_require__) { +//#endregion +//#region src/options/lang/labels.de.ts + registerLabels("de", { + "Slimmer horizontal player": "Schlanker horizontaler Player", + "Include playlist": "Wiedergabeliste anzeigen", + "Hide artwork": "Artwork ausblenden", + "Theme color": "Theme Farbe", + Light: "Hell", + Dark: "Dunkel", + Auto: "Automatisch", + Default: "Standard", + "Adjust height": "Höhe einstellen", + "Active page": "Aktive Seite", + "Use click-to-load": "Verwende click-to-load", + "ex.: 600, in px": "Z.B. 600, in px", + "Hide timed comments": "Kommentare ausblenden", + "Let Iframely optimize player for the artwork": "Optimierung des Players durch IFramely", + "Show as slideshow": "Als Slideshow zeigen", + "Start from": "Start ab", + "ex.: 11, 1m10s": "z.B. 11, 1m10s", + "End on": "Ende an", + "Closed captions": "Untertitel", + "Include up to 20 tweets": "Bis zu 20 Tweets anzeigen", + "Hide photos, videos, and cards": "Verberge Fotos, Videos und Cards", + "Hide previous Tweet in conversation thread": "Verberge den vorigen Tweet in der Konversation", + "Use dark theme": "Verwende dunkles Farbschema", + "Adjust width": "Breite anpassen", + "Hide description": "Beschreibung verbergen", + "Widget style": "Widget-Style", + Mini: "Mini", + Classic: "Klassisch", + Picture: "Bild", + Zoom: "Zoom", + "Map orientation": "Karten-Ausrichtung", + Album: "Album", + Portrait: "Portrait", + Square: "Quadratisch", + "Show context slideshow": "Als Slideshow anzeigen", + "Show description footer": "Fußzeile anzeigen", + "Show user header": "Kopfbereich anzeigen", + "Show author's text caption": "Beschriftung des Autors anzeigen", + "Hide author's text caption": "Beschriftung des Autors verbergen", + "Include parent comment (if url is a reply)": "Ursprünglichen Kommentar einschließen (wenn die Url eine Antwort ist)", + "Show recent posts": "Neueste Beiträge anzeigen", + "Show profile photos when friends like this": "Profilfotos anzeigen, wenn Freunde dies mögen", + "Use the small header instead": "Kleine Kopfzeile stattdessen verwenden", + Artwork: "Artwork", + Small: "klein", + Big: "groß", + None: "Keines", + Layout: "Layout", + Slim: "Schlank", + "Artwork-only": "Nur Artwork", + Standard: "Standard", + "Size & style": "Größe & Stil", + "Wide image": "Breite Darstellung", + "Wide simple": "Breite Darstellung (Einfach)", + "Text language (ignored if no captions)": "Sprache der Untertitel (wird ignoriert, wenn keine Untertitel vorhanden)", + "Two letters: en, fr, es, de...": "Zwei Buchstaben: en, fr, es, de...", + "Don't include attached player": "Player nicht integrieren", + "Attached player only, no card": "Nur Player, keine Card", + "Hold load & play until clicked": "Klicken zum Abspielen", + "Make it a small card": "Kleine Card verwenden", + "Keep using full media card": "Verwende weiterhin vollständige Media-Cards", + "Don't include player": "Player nicht hinzufügen", + "Player only, no card": "Nur Player, keine Card", + "Just the player": "Nur Player", + "Just the image": "Nur Bild" + }); -eval("{var translator = __webpack_require__(/*! ../translator */ \"./options/translator.js\");\n\nvar lang ='de';\n\nvar labels = {\n // general options\n 'Slimmer horizontal player': 'Schlanker horizontaler Player',\n 'Include playlist': 'Wiedergabeliste anzeigen',\n 'Hide artwork': 'Artwork ausblenden',\n 'Theme color': 'Theme Farbe',\n 'Light': 'Hell',\n 'Dark': 'Dunkel',\n 'Auto': 'Automatisch',\n 'Default': 'Standard',\n 'Adjust height': 'Höhe einstellen',\n 'Active page': 'Aktive Seite',\n\n // Codepen\n 'Use click-to-load': 'Verwende click-to-load',\n 'ex.: 600, in px': 'Z.B. 600, in px',\n\n //Instagram\n 'Hide timed comments': 'Kommentare ausblenden',\n\n //Soundcloud\n 'Let Iframely optimize player for the artwork': 'Optimierung des Players durch IFramely',\n\n // scribd\n 'Show as slideshow': 'Als Slideshow zeigen',\n\n // youtube\n 'Start from': 'Start ab',\n 'ex.: 11, 1m10s': 'z.B. 11, 1m10s',\n 'End on': 'Ende an',\n 'Closed captions': 'Untertitel',\n\n // twitter\n 'Include up to 20 tweets': 'Bis zu 20 Tweets anzeigen',\n 'Hide photos, videos, and cards': 'Verberge Fotos, Videos und Cards',\n 'Hide previous Tweet in conversation thread': 'Verberge den vorigen Tweet in der Konversation',\n 'Use dark theme': 'Verwende dunkles Farbschema',\n 'Adjust width': 'Breite anpassen',\n\n // pinterest\n 'Hide description': 'Beschreibung verbergen',\n\n //mixcloud\n 'Widget style': 'Widget-Style',\n 'Mini': 'Mini',\n 'Classic': 'Klassisch',\n 'Picture': 'Bild',\n\n //google maps\n 'Zoom': 'Zoom',\n 'Map orientation': 'Karten-Ausrichtung',\n 'Album': 'Album',\n 'Portrait': 'Portrait',\n 'Square': 'Quadratisch',\n\n // Flickr\n 'Show context slideshow': 'Als Slideshow anzeigen',\n 'Show description footer': 'Fußzeile anzeigen',\n 'Show user header': 'Kopfbereich anzeigen',\n\n //facebook\n 'Show author\\'s text caption': 'Beschriftung des Autors anzeigen',\n 'Hide author\\'s text caption': 'Beschriftung des Autors verbergen',\n 'Include parent comment (if url is a reply)': 'Ursprünglichen Kommentar einschließen (wenn die Url eine Antwort ist)',\n\n 'Show recent posts': 'Neueste Beiträge anzeigen',\n 'Show profile photos when friends like this': 'Profilfotos anzeigen, wenn Freunde dies mögen',\n 'Use the small header instead': 'Kleine Kopfzeile stattdessen verwenden',\n\n //bandcamp\n 'Artwork': 'Artwork',\n 'Small': 'klein',\n 'Big': 'groß',\n 'None': 'Keines',\n\n 'Layout': 'Layout',\n 'Slim': 'Schlank',\n 'Artwork-only': 'Nur Artwork',\n 'Standard': 'Standard',\n\n //omny.fm\n 'Size & style': 'Größe & Stil',\n 'Wide image': 'Breite Darstellung',\n 'Wide simple': 'Breite Darstellung (Einfach)',\n\n // Vimeo\n 'Text language (ignored if no captions)': 'Sprache der Untertitel (wird ignoriert, wenn keine Untertitel vorhanden)',\n 'Two letters: en, fr, es, de...': 'Zwei Buchstaben: en, fr, es, de...',\n \n // Kickstarter\n 'Don\\'t include attached player': 'Player nicht integrieren',\n 'Attached player only, no card': 'Nur Player, keine Card',\n\n //iframely options\n 'Hold load & play until clicked': 'Klicken zum Abspielen',\n 'Make it a small card': 'Kleine Card verwenden',\n //iframely media cards\n 'Keep using full media card': 'Verwende weiterhin vollständige Media-Cards',\n 'Don\\'t include player': 'Player nicht hinzufügen',\n 'Player only, no card': 'Nur Player, keine Card',\n //iframely media=1\n 'Just the player': 'Nur Player',\n 'Just the image': 'Nur Bild'\n};\n\ntranslator.registerLabels(lang, labels);\n\n\n//# sourceURL=webpack:///./options/lang/labels.de.js?\n}"); - -/***/ }, - -/***/ "./options/translator.js" -/*!*******************************!*\ - !*** ./options/translator.js ***! - \*******************************/ -(__unused_webpack_module, exports, __webpack_require__) { - -eval("{/*\nTo add more languages to the translator -\nsee ./lang/labels.LAN.example.js\n\n - use the template for the list of currently available labels\n - save it as labels.LAN.js // replace LAN with your actual value, e.g. es, de, ru, etc.\n - fill in the labels translations\n - add to webpack config options as \n\t'options.i18n.fr': './options/lang/labels.fr.js' \n\t(see webpack.common.js as example)\n\nYou can then call iframely.optionsTranslator('LAN') - with your chosen language - to build the options form\n\nYou don't need to translate all the labels. The ones without a translation will be left as-is\n*/\n\nvar iframely = __webpack_require__(/*! ../iframely */ \"./iframely.js\");\n\nvar langs = {};\n\nexports.registerLabels = function(lang, labels) {\n var existingLabels = langs[lang] = langs[lang] || {};\n Object.assign(existingLabels, labels);\n};\n\niframely.optionsTranslator = function(lang) {\n return function (label) {\n return langs[lang] && langs[lang][label] && langs[lang][label] !== '' ? langs[lang][label] : label;\n };\n};\n\n//# sourceURL=webpack:///./options/translator.js?\n}"); - -/***/ } - -/******/ }); -/************************************************************************/ -/******/ // 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 -/******/ if (!(moduleId in __webpack_modules__)) { -/******/ delete __webpack_module_cache__[moduleId]; -/******/ var e = new Error("Cannot find module '" + moduleId + "'"); -/******/ e.code = 'MODULE_NOT_FOUND'; -/******/ throw e; -/******/ } -/******/ __webpack_modules__[moduleId](module, module.exports, __webpack_require__); -/******/ -/******/ // Return the exports of the module -/******/ return module.exports; -/******/ } -/******/ -/************************************************************************/ -/******/ -/******/ // startup -/******/ // Load entry module and return exports -/******/ // This entry module can't be inlined because the eval devtool is used. -/******/ var __webpack_exports__ = __webpack_require__("./options/lang/labels.de.js"); -/******/ -/******/ })() -; \ No newline at end of file +//#endregion +})(); \ No newline at end of file diff --git a/dist/options.i18n.de.min.js b/dist/options.i18n.de.min.js index 1eb6778..d194d02 100644 --- a/dist/options.i18n.de.min.js +++ b/dist/options.i18n.de.min.js @@ -1 +1 @@ -(()=>{var e={774(e){var r=window.iframely=window.iframely||{};r.config=r.config||{},e.exports=r},132(e,r,n){var i=n(774),t={};r.registerLabels=function(e,r){var n=t[e]=t[e]||{};Object.assign(n,r)},i.optionsTranslator=function(e){return function(r){return t[e]&&t[e][r]&&""!==t[e][r]?t[e][r]:r}}}},r={};(function n(i){var t=r[i];if(void 0!==t)return t.exports;var a=r[i]={exports:{}};return e[i](a,a.exports,n),a.exports})(132).registerLabels("de",{"Slimmer horizontal player":"Schlanker horizontaler Player","Include playlist":"Wiedergabeliste anzeigen","Hide artwork":"Artwork ausblenden","Theme color":"Theme Farbe",Light:"Hell",Dark:"Dunkel",Auto:"Automatisch",Default:"Standard","Adjust height":"Höhe einstellen","Active page":"Aktive Seite","Use click-to-load":"Verwende click-to-load","ex.: 600, in px":"Z.B. 600, in px","Hide timed comments":"Kommentare ausblenden","Let Iframely optimize player for the artwork":"Optimierung des Players durch IFramely","Show as slideshow":"Als Slideshow zeigen","Start from":"Start ab","ex.: 11, 1m10s":"z.B. 11, 1m10s","End on":"Ende an","Closed captions":"Untertitel","Include up to 20 tweets":"Bis zu 20 Tweets anzeigen","Hide photos, videos, and cards":"Verberge Fotos, Videos und Cards","Hide previous Tweet in conversation thread":"Verberge den vorigen Tweet in der Konversation","Use dark theme":"Verwende dunkles Farbschema","Adjust width":"Breite anpassen","Hide description":"Beschreibung verbergen","Widget style":"Widget-Style",Mini:"Mini",Classic:"Klassisch",Picture:"Bild",Zoom:"Zoom","Map orientation":"Karten-Ausrichtung",Album:"Album",Portrait:"Portrait",Square:"Quadratisch","Show context slideshow":"Als Slideshow anzeigen","Show description footer":"Fußzeile anzeigen","Show user header":"Kopfbereich anzeigen","Show author's text caption":"Beschriftung des Autors anzeigen","Hide author's text caption":"Beschriftung des Autors verbergen","Include parent comment (if url is a reply)":"Ursprünglichen Kommentar einschließen (wenn die Url eine Antwort ist)","Show recent posts":"Neueste Beiträge anzeigen","Show profile photos when friends like this":"Profilfotos anzeigen, wenn Freunde dies mögen","Use the small header instead":"Kleine Kopfzeile stattdessen verwenden",Artwork:"Artwork",Small:"klein",Big:"groß",None:"Keines",Layout:"Layout",Slim:"Schlank","Artwork-only":"Nur Artwork",Standard:"Standard","Size & style":"Größe & Stil","Wide image":"Breite Darstellung","Wide simple":"Breite Darstellung (Einfach)","Text language (ignored if no captions)":"Sprache der Untertitel (wird ignoriert, wenn keine Untertitel vorhanden)","Two letters: en, fr, es, de...":"Zwei Buchstaben: en, fr, es, de...","Don't include attached player":"Player nicht integrieren","Attached player only, no card":"Nur Player, keine Card","Hold load & play until clicked":"Klicken zum Abspielen","Make it a small card":"Kleine Card verwenden","Keep using full media card":"Verwende weiterhin vollständige Media-Cards","Don't include player":"Player nicht hinzufügen","Player only, no card":"Nur Player, keine Card","Just the player":"Nur Player","Just the image":"Nur Bild"})})(); \ No newline at end of file +(function(){function e(){let e=()=>{};return{config:{},on:e,trigger:e,triggerAsync:e,load:e,unload:e,configure:e,extendOptions:e,setTheme:e,cancelWidget:e,openHref:e,addEventListener:e,isTouch:()=>!1,findIframe:()=>void 0,getElementComputedStyle:()=>void 0,buildOptionsForm:e}}var t=typeof window>`u`?e():window.iframely=window.iframely||{};t.config=t.config||{};var n={};function r(e,t){let r=n[e]=n[e]||{};Object.assign(r,t)}t.optionsTranslator=e=>t=>n[e]&&n[e][t]&&n[e][t]!==``?n[e][t]:t,r(`de`,{"Slimmer horizontal player":`Schlanker horizontaler Player`,"Include playlist":`Wiedergabeliste anzeigen`,"Hide artwork":`Artwork ausblenden`,"Theme color":`Theme Farbe`,Light:`Hell`,Dark:`Dunkel`,Auto:`Automatisch`,Default:`Standard`,"Adjust height":`Höhe einstellen`,"Active page":`Aktive Seite`,"Use click-to-load":`Verwende click-to-load`,"ex.: 600, in px":`Z.B. 600, in px`,"Hide timed comments":`Kommentare ausblenden`,"Let Iframely optimize player for the artwork":`Optimierung des Players durch IFramely`,"Show as slideshow":`Als Slideshow zeigen`,"Start from":`Start ab`,"ex.: 11, 1m10s":`z.B. 11, 1m10s`,"End on":`Ende an`,"Closed captions":`Untertitel`,"Include up to 20 tweets":`Bis zu 20 Tweets anzeigen`,"Hide photos, videos, and cards":`Verberge Fotos, Videos und Cards`,"Hide previous Tweet in conversation thread":`Verberge den vorigen Tweet in der Konversation`,"Use dark theme":`Verwende dunkles Farbschema`,"Adjust width":`Breite anpassen`,"Hide description":`Beschreibung verbergen`,"Widget style":`Widget-Style`,Mini:`Mini`,Classic:`Klassisch`,Picture:`Bild`,Zoom:`Zoom`,"Map orientation":`Karten-Ausrichtung`,Album:`Album`,Portrait:`Portrait`,Square:`Quadratisch`,"Show context slideshow":`Als Slideshow anzeigen`,"Show description footer":`Fußzeile anzeigen`,"Show user header":`Kopfbereich anzeigen`,"Show author's text caption":`Beschriftung des Autors anzeigen`,"Hide author's text caption":`Beschriftung des Autors verbergen`,"Include parent comment (if url is a reply)":`Ursprünglichen Kommentar einschließen (wenn die Url eine Antwort ist)`,"Show recent posts":`Neueste Beiträge anzeigen`,"Show profile photos when friends like this":`Profilfotos anzeigen, wenn Freunde dies mögen`,"Use the small header instead":`Kleine Kopfzeile stattdessen verwenden`,Artwork:`Artwork`,Small:`klein`,Big:`groß`,None:`Keines`,Layout:`Layout`,Slim:`Schlank`,"Artwork-only":`Nur Artwork`,Standard:`Standard`,"Size & style":`Größe & Stil`,"Wide image":`Breite Darstellung`,"Wide simple":`Breite Darstellung (Einfach)`,"Text language (ignored if no captions)":`Sprache der Untertitel (wird ignoriert, wenn keine Untertitel vorhanden)`,"Two letters: en, fr, es, de...":`Zwei Buchstaben: en, fr, es, de...`,"Don't include attached player":`Player nicht integrieren`,"Attached player only, no card":`Nur Player, keine Card`,"Hold load & play until clicked":`Klicken zum Abspielen`,"Make it a small card":`Kleine Card verwenden`,"Keep using full media card":`Verwende weiterhin vollständige Media-Cards`,"Don't include player":`Player nicht hinzufügen`,"Player only, no card":`Nur Player, keine Card`,"Just the player":`Nur Player`,"Just the image":`Nur Bild`})})(); \ No newline at end of file diff --git a/dist/options.i18n.fr.js b/dist/options.i18n.fr.js index 2caa881..4265414 100644 --- a/dist/options.i18n.fr.js +++ b/dist/options.i18n.fr.js @@ -1,82 +1,106 @@ -/* - * ATTENTION: The "eval" devtool has been used (maybe by default in mode: "development"). - * This devtool is neither made for production nor for readable output files. - * It uses "eval()" calls to create a separate source file in the browser devtools. - * If you are trying to read the output file, select a different devtool (https://webpack.js.org/configuration/devtool/) - * or disable the default devtool with "devtool: false". - * If you are looking for production-ready output files, see mode: "production" (https://webpack.js.org/configuration/mode/). - */ -/******/ (() => { // webpackBootstrap -/******/ var __webpack_modules__ = ({ +(function() { -/***/ "./iframely.js" -/*!*********************!*\ - !*** ./iframely.js ***! - \*********************/ -(module) { -eval("{var iframely = window.iframely = window.iframely || {};\niframely.config = iframely.config || {};\n\nmodule.exports = iframely;\n\n//# sourceURL=webpack:///./iframely.js?\n}"); +//#region src/iframely.ts + function createServerStub() { + const noop = () => {}; + return { + config: {}, + on: noop, + trigger: noop, + triggerAsync: noop, + load: noop, + unload: noop, + configure: noop, + extendOptions: noop, + setTheme: noop, + cancelWidget: noop, + openHref: noop, + addEventListener: noop, + isTouch: () => false, + findIframe: () => void 0, + getElementComputedStyle: () => void 0, + buildOptionsForm: noop + }; + } + var iframely = typeof window === "undefined" ? createServerStub() : window.iframely = window.iframely || {}; + iframely.config = iframely.config || {}; -/***/ }, +//#endregion +//#region src/options/translator.ts + var langs = {}; + function registerLabels(lang, labels) { + const existingLabels = langs[lang] = langs[lang] || {}; + Object.assign(existingLabels, labels); + } + iframely.optionsTranslator = (lang) => { + return (label) => { + return langs[lang] && langs[lang][label] && langs[lang][label] !== "" ? langs[lang][label] : label; + }; + }; -/***/ "./options/lang/labels.fr.js" -/*!***********************************!*\ - !*** ./options/lang/labels.fr.js ***! - \***********************************/ -(__unused_webpack_module, __unused_webpack_exports, __webpack_require__) { +//#endregion +//#region src/options/lang/labels.fr.ts + registerLabels("fr", { + "Slimmer horizontal player": "Joueur de audio classique", + "Include playlist": "Inclure la playlist", + "Hide artwork": "Masquer la illustration", + "Theme color": "Couleur du thème", + Light: "Lumière", + Dark: "Sombre", + Auto: "", + Default: "Défaut", + "Adjust height": "Height", + "Active page": "Page active", + "Use click-to-load": "Utilisez click-to-load", + "ex.: 600, in px": "", + "Hide timed comments": "Masquer les commentaires", + "Let Iframely optimize player for the artwork": "Optimiser le lecteur pour l'illustration", + "Show as slideshow": "Montrer en diaporama", + "Start from": "Commencer", + "ex.: 11, 1m10s": "", + "End on": "Fin sur", + "Include up to 20 tweets": "Incluez jusqu'à 20 tweets", + "Hide photos, videos, and cards": "Masquer les photos, les vidéos et les cartes", + "Hide previous Tweet in conversation thread": "Masquer le tweet parent", + "Hide description": "Masquer la description", + "Widget style": "Style de widget", + Mini: "", + Classic: "Classique", + Picture: "Image", + Zoom: "", + "Map orientation": "Orientation de la carte", + Album: "", + Portrait: "", + Square: "Carré", + "Show context slideshow": "Afficher le diaporama contextuel", + "Show description footer": "Afficher la description pied de page", + "Show user header": "Afficher l'en-tête de l'utilisateur", + "Show author's text caption": "Afficher la description de l'auteur", + "Hide author's text caption": "Masquer la description de l'auteur", + "Include parent comment (if url is a reply)": "", + "Show recent posts": "Afficher les messages récents", + "Show profile photos when friends like this": "", + "Use the small header instead": "Utilisez plutôt le petit en-tête", + Artwork: "Ouvrages d'art", + Small: "Petite", + Big: "Grosse", + None: "Aucune", + Layout: "Disposition", + Slim: "Svelte", + "Artwork-only": "Oeuvre seule", + Standard: "Standard", + "Size & style": "Style", + "Wide image": "Image large", + "Wide simple": "Large simple", + "Hold load & play until clicked": "Click-to-play", + "Make it a small card": "Carte compacte", + "Keep using full media card": "Continuez à utiliser la carte média complète", + "Don't include player": "Ne pas inclure la vidéo", + "Player only, no card": "La vidéo seulement, pas de carte", + "Just the player": "Seulement la vidéo", + "Just the image": "Seulement l'image" + }); -eval("{var translator = __webpack_require__(/*! ../translator */ \"./options/translator.js\");\n\nvar lang ='fr';\n\nvar labels = {\n // general options\n 'Slimmer horizontal player': 'Joueur de audio classique',\n 'Include playlist': 'Inclure la playlist',\n 'Hide artwork': 'Masquer la illustration',\n 'Theme color': 'Couleur du thème',\n 'Light': 'Lumière',\n 'Dark': 'Sombre',\n 'Auto': '',\n 'Default': 'Défaut',\n 'Adjust height': 'Height',\n 'Active page': 'Page active',\n\n // Codepen\n 'Use click-to-load': 'Utilisez click-to-load',\n 'ex.: 600, in px': '',\n\n //Instagram\n 'Hide timed comments': 'Masquer les commentaires',\n\n //Soundcloud\n 'Let Iframely optimize player for the artwork': 'Optimiser le lecteur pour l\\'illustration',\n\n // scribd\n 'Show as slideshow': 'Montrer en diaporama',\n\n // youtube\n 'Start from': 'Commencer',\n 'ex.: 11, 1m10s': '',\n 'End on': 'Fin sur',\n\n // twitter\n 'Include up to 20 tweets': 'Incluez jusqu\\'à 20 tweets',\n 'Hide photos, videos, and cards': 'Masquer les photos, les vidéos et les cartes',\n 'Hide previous Tweet in conversation thread': 'Masquer le tweet parent',\n\n // pinterest\n 'Hide description': 'Masquer la description',\n\n //mixcloud\n 'Widget style': 'Style de widget',\n 'Mini': '', // can leave empty - will remain as is\n 'Classic': 'Classique',\n 'Picture': 'Image',\n\n //google maps\n 'Zoom': '',\n 'Map orientation': 'Orientation de la carte',\n 'Album': '',\n 'Portrait': '',\n 'Square': 'Carré',\n\n // Flickr\n 'Show context slideshow': 'Afficher le diaporama contextuel',\n 'Show description footer': 'Afficher la description pied de page',\n 'Show user header': 'Afficher l\\'en-tête de l\\'utilisateur',\n\n //facebook\n 'Show author\\'s text caption': 'Afficher la description de l\\'auteur',\n 'Hide author\\'s text caption': 'Masquer la description de l\\'auteur',\n 'Include parent comment (if url is a reply)': '',\n\n 'Show recent posts': 'Afficher les messages récents',\n 'Show profile photos when friends like this': '',\n 'Use the small header instead': 'Utilisez plutôt le petit en-tête',\n\n //bandcamp\n 'Artwork': 'Ouvrages d\\'art',\n 'Small': 'Petite',\n 'Big': 'Grosse',\n 'None': 'Aucune',\n\n 'Layout': 'Disposition',\n 'Slim': 'Svelte',\n 'Artwork-only': 'Oeuvre seule',\n 'Standard': 'Standard',\n\n //omny.fm\n 'Size & style': 'Style',\n 'Wide image': 'Image large',\n 'Wide simple': 'Large simple',\n\n\n //iframely options\n 'Hold load & play until clicked': 'Click-to-play',\n 'Make it a small card': 'Carte compacte',\n //iframely media cards\n 'Keep using full media card': 'Continuez à utiliser la carte média complète',\n 'Don\\'t include player': 'Ne pas inclure la vidéo',\n 'Player only, no card': 'La vidéo seulement, pas de carte',\n //iframely media=1\n 'Just the player': 'Seulement la vidéo',\n 'Just the image': 'Seulement l\\'image'\n};\n\ntranslator.registerLabels(lang, labels);\n\n//# sourceURL=webpack:///./options/lang/labels.fr.js?\n}"); - -/***/ }, - -/***/ "./options/translator.js" -/*!*******************************!*\ - !*** ./options/translator.js ***! - \*******************************/ -(__unused_webpack_module, exports, __webpack_require__) { - -eval("{/*\nTo add more languages to the translator -\nsee ./lang/labels.LAN.example.js\n\n - use the template for the list of currently available labels\n - save it as labels.LAN.js // replace LAN with your actual value, e.g. es, de, ru, etc.\n - fill in the labels translations\n - add to webpack config options as \n\t'options.i18n.fr': './options/lang/labels.fr.js' \n\t(see webpack.common.js as example)\n\nYou can then call iframely.optionsTranslator('LAN') - with your chosen language - to build the options form\n\nYou don't need to translate all the labels. The ones without a translation will be left as-is\n*/\n\nvar iframely = __webpack_require__(/*! ../iframely */ \"./iframely.js\");\n\nvar langs = {};\n\nexports.registerLabels = function(lang, labels) {\n var existingLabels = langs[lang] = langs[lang] || {};\n Object.assign(existingLabels, labels);\n};\n\niframely.optionsTranslator = function(lang) {\n return function (label) {\n return langs[lang] && langs[lang][label] && langs[lang][label] !== '' ? langs[lang][label] : label;\n };\n};\n\n//# sourceURL=webpack:///./options/translator.js?\n}"); - -/***/ } - -/******/ }); -/************************************************************************/ -/******/ // 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 -/******/ if (!(moduleId in __webpack_modules__)) { -/******/ delete __webpack_module_cache__[moduleId]; -/******/ var e = new Error("Cannot find module '" + moduleId + "'"); -/******/ e.code = 'MODULE_NOT_FOUND'; -/******/ throw e; -/******/ } -/******/ __webpack_modules__[moduleId](module, module.exports, __webpack_require__); -/******/ -/******/ // Return the exports of the module -/******/ return module.exports; -/******/ } -/******/ -/************************************************************************/ -/******/ -/******/ // startup -/******/ // Load entry module and return exports -/******/ // This entry module can't be inlined because the eval devtool is used. -/******/ var __webpack_exports__ = __webpack_require__("./options/lang/labels.fr.js"); -/******/ -/******/ })() -; \ No newline at end of file +//#endregion +})(); \ No newline at end of file diff --git a/dist/options.i18n.fr.min.js b/dist/options.i18n.fr.min.js index 486b022..5c20eca 100644 --- a/dist/options.i18n.fr.min.js +++ b/dist/options.i18n.fr.min.js @@ -1 +1 @@ -(()=>{var e={774(e){var t=window.iframely=window.iframely||{};t.config=t.config||{},e.exports=t},132(e,t,i){var r=i(774),a={};t.registerLabels=function(e,t){var i=a[e]=a[e]||{};Object.assign(i,t)},r.optionsTranslator=function(e){return function(t){return a[e]&&a[e][t]&&""!==a[e][t]?a[e][t]:t}}}},t={};(function i(r){var a=t[r];if(void 0!==a)return a.exports;var o=t[r]={exports:{}};return e[r](o,o.exports,i),o.exports})(132).registerLabels("fr",{"Slimmer horizontal player":"Joueur de audio classique","Include playlist":"Inclure la playlist","Hide artwork":"Masquer la illustration","Theme color":"Couleur du thème",Light:"Lumière",Dark:"Sombre",Auto:"",Default:"Défaut","Adjust height":"Height","Active page":"Page active","Use click-to-load":"Utilisez click-to-load","ex.: 600, in px":"","Hide timed comments":"Masquer les commentaires","Let Iframely optimize player for the artwork":"Optimiser le lecteur pour l'illustration","Show as slideshow":"Montrer en diaporama","Start from":"Commencer","ex.: 11, 1m10s":"","End on":"Fin sur","Include up to 20 tweets":"Incluez jusqu'à 20 tweets","Hide photos, videos, and cards":"Masquer les photos, les vidéos et les cartes","Hide previous Tweet in conversation thread":"Masquer le tweet parent","Hide description":"Masquer la description","Widget style":"Style de widget",Mini:"",Classic:"Classique",Picture:"Image",Zoom:"","Map orientation":"Orientation de la carte",Album:"",Portrait:"",Square:"Carré","Show context slideshow":"Afficher le diaporama contextuel","Show description footer":"Afficher la description pied de page","Show user header":"Afficher l'en-tête de l'utilisateur","Show author's text caption":"Afficher la description de l'auteur","Hide author's text caption":"Masquer la description de l'auteur","Include parent comment (if url is a reply)":"","Show recent posts":"Afficher les messages récents","Show profile photos when friends like this":"","Use the small header instead":"Utilisez plutôt le petit en-tête",Artwork:"Ouvrages d'art",Small:"Petite",Big:"Grosse",None:"Aucune",Layout:"Disposition",Slim:"Svelte","Artwork-only":"Oeuvre seule",Standard:"Standard","Size & style":"Style","Wide image":"Image large","Wide simple":"Large simple","Hold load & play until clicked":"Click-to-play","Make it a small card":"Carte compacte","Keep using full media card":"Continuez à utiliser la carte média complète","Don't include player":"Ne pas inclure la vidéo","Player only, no card":"La vidéo seulement, pas de carte","Just the player":"Seulement la vidéo","Just the image":"Seulement l'image"})})(); \ No newline at end of file +(function(){function e(){let e=()=>{};return{config:{},on:e,trigger:e,triggerAsync:e,load:e,unload:e,configure:e,extendOptions:e,setTheme:e,cancelWidget:e,openHref:e,addEventListener:e,isTouch:()=>!1,findIframe:()=>void 0,getElementComputedStyle:()=>void 0,buildOptionsForm:e}}var t=typeof window>`u`?e():window.iframely=window.iframely||{};t.config=t.config||{};var n={};function r(e,t){let r=n[e]=n[e]||{};Object.assign(r,t)}t.optionsTranslator=e=>t=>n[e]&&n[e][t]&&n[e][t]!==``?n[e][t]:t,r(`fr`,{"Slimmer horizontal player":`Joueur de audio classique`,"Include playlist":`Inclure la playlist`,"Hide artwork":`Masquer la illustration`,"Theme color":`Couleur du thème`,Light:`Lumière`,Dark:`Sombre`,Auto:``,Default:`Défaut`,"Adjust height":`Height`,"Active page":`Page active`,"Use click-to-load":`Utilisez click-to-load`,"ex.: 600, in px":``,"Hide timed comments":`Masquer les commentaires`,"Let Iframely optimize player for the artwork":`Optimiser le lecteur pour l'illustration`,"Show as slideshow":`Montrer en diaporama`,"Start from":`Commencer`,"ex.: 11, 1m10s":``,"End on":`Fin sur`,"Include up to 20 tweets":`Incluez jusqu'à 20 tweets`,"Hide photos, videos, and cards":`Masquer les photos, les vidéos et les cartes`,"Hide previous Tweet in conversation thread":`Masquer le tweet parent`,"Hide description":`Masquer la description`,"Widget style":`Style de widget`,Mini:``,Classic:`Classique`,Picture:`Image`,Zoom:``,"Map orientation":`Orientation de la carte`,Album:``,Portrait:``,Square:`Carré`,"Show context slideshow":`Afficher le diaporama contextuel`,"Show description footer":`Afficher la description pied de page`,"Show user header":`Afficher l'en-tête de l'utilisateur`,"Show author's text caption":`Afficher la description de l'auteur`,"Hide author's text caption":`Masquer la description de l'auteur`,"Include parent comment (if url is a reply)":``,"Show recent posts":`Afficher les messages récents`,"Show profile photos when friends like this":``,"Use the small header instead":`Utilisez plutôt le petit en-tête`,Artwork:`Ouvrages d'art`,Small:`Petite`,Big:`Grosse`,None:`Aucune`,Layout:`Disposition`,Slim:`Svelte`,"Artwork-only":`Oeuvre seule`,Standard:`Standard`,"Size & style":`Style`,"Wide image":`Image large`,"Wide simple":`Large simple`,"Hold load & play until clicked":`Click-to-play`,"Make it a small card":`Carte compacte`,"Keep using full media card":`Continuez à utiliser la carte média complète`,"Don't include player":`Ne pas inclure la vidéo`,"Player only, no card":`La vidéo seulement, pas de carte`,"Just the player":`Seulement la vidéo`,"Just the image":`Seulement l'image`})})(); \ No newline at end of file diff --git a/dist/options.js b/dist/options.js index 98d463b..f993dc7 100644 --- a/dist/options.js +++ b/dist/options.js @@ -1,162 +1,365 @@ -/* - * ATTENTION: The "eval" devtool has been used (maybe by default in mode: "development"). - * This devtool is neither made for production nor for readable output files. - * It uses "eval()" calls to create a separate source file in the browser devtools. - * If you are trying to read the output file, select a different devtool (https://webpack.js.org/configuration/devtool/) - * or disable the default devtool with "devtool: false". - * If you are looking for production-ready output files, see mode: "production" (https://webpack.js.org/configuration/mode/). - */ -/******/ (() => { // webpackBootstrap -/******/ var __webpack_modules__ = ({ - -/***/ "./options/templates/checkbox.ejs" -/*!****************************************!*\ - !*** ./options/templates/checkbox.ejs ***! - \****************************************/ -(module) { - -eval("{module.exports = function(obj) {\nobj || (obj = {});\nvar __t, __p = '', __j = Array.prototype.join;\nfunction print() { __p += __j.call(arguments, '') }\nwith (obj) {\n__p += '
\\n \\n ' +\n((__t = ( label )) == null ? '' : __t) +\n'\\n \\n
\\n';\n\n}\nreturn __p\n}\n\n//# sourceURL=webpack:///./options/templates/checkbox.ejs?\n}"); - -/***/ }, - -/***/ "./options/templates/group.ejs" -/*!*************************************!*\ - !*** ./options/templates/group.ejs ***! - \*************************************/ -(module) { - -eval("{module.exports = function(obj) {\nobj || (obj = {});\nvar __t, __p = '', __e = _.escape;\nwith (obj) {\n__p += '
\\n
\\n ' +\n__e( elementsHtml ) +\n'\\n
\\n
';\n\n}\nreturn __p\n}\n\n//# sourceURL=webpack:///./options/templates/group.ejs?\n}"); - -/***/ }, - -/***/ "./options/templates/radio.ejs" -/*!*************************************!*\ - !*** ./options/templates/radio.ejs ***! - \*************************************/ -(module) { - -eval("{module.exports = function(obj) {\nobj || (obj = {});\nvar __t, __p = '', __j = Array.prototype.join;\nfunction print() { __p += __j.call(arguments, '') }\nwith (obj) {\n__p += '
\\n ';\n if (label) { ;\n__p += '\\n \\n ';\n } ;\n__p += '\\n
\\n ' +\n((__t = ( subContext.label )) == null ? '' : __t) +\n'\\n \\n
\\n ';\n }); ;\n__p += '\\n
\\n';\n\n}\nreturn __p\n}\n\n//# sourceURL=webpack:///./options/templates/radio.ejs?\n}"); - -/***/ }, - -/***/ "./options/templates/range.ejs" -/*!*************************************!*\ - !*** ./options/templates/range.ejs ***! - \*************************************/ -(module) { - -eval("{module.exports = function(obj) {\nobj || (obj = {});\nvar __t, __p = '';\nwith (obj) {\n__p += '
\\n \\n
\\n \\n
\\n
';\n\n}\nreturn __p\n}\n\n//# sourceURL=webpack:///./options/templates/range.ejs?\n}"); - -/***/ }, - -/***/ "./options/templates/select.ejs" -/*!**************************************!*\ - !*** ./options/templates/select.ejs ***! - \**************************************/ -(module) { - -eval("{module.exports = function(obj) {\nobj || (obj = {});\nvar __t, __p = '', __j = Array.prototype.join;\nfunction print() { __p += __j.call(arguments, '') }\nwith (obj) {\n__p += '
\\n \\n
\\n \\n
\\n
';\n\n}\nreturn __p\n}\n\n//# sourceURL=webpack:///./options/templates/select.ejs?\n}"); - -/***/ }, - -/***/ "./options/templates/text.ejs" -/*!************************************!*\ - !*** ./options/templates/text.ejs ***! - \************************************/ -(module) { - -eval("{module.exports = function(obj) {\nobj || (obj = {});\nvar __t, __p = '';\nwith (obj) {\n__p += '
\\n \\n
\\n \\n
\\n
';\n\n}\nreturn __p\n}\n\n//# sourceURL=webpack:///./options/templates/text.ejs?\n}"); - -/***/ }, - -/***/ "./iframely.js" -/*!*********************!*\ - !*** ./iframely.js ***! - \*********************/ -(module) { - -eval("{var iframely = window.iframely = window.iframely || {};\niframely.config = iframely.config || {};\n\nmodule.exports = iframely;\n\n//# sourceURL=webpack:///./iframely.js?\n}"); - -/***/ }, - -/***/ "./options/form-builder.js" -/*!*********************************!*\ - !*** ./options/form-builder.js ***! - \*********************************/ -(module, __unused_webpack_exports, __webpack_require__) { - -eval("{var getFormElements = __webpack_require__(/*! ./form-generator */ \"./options/form-generator.js\");\nvar iframely = __webpack_require__(/*! ../iframely */ \"./iframely.js\");\n\nvar UIelements = {\n checkbox: {\n getValue: function(inputs) {\n var input = inputs[0];\n return input.checked;\n }\n },\n text: {\n getValue: function(inputs) {\n var input = inputs[0];\n var value = input.value;\n if (input.type === 'number') {\n value = parseInt(value);\n if (isNaN(value)) {\n value = '';\n }\n }\n return value;\n },\n customEvents: function(inputs, submitOptionsCb) {\n var input = inputs[0];\n iframely.addEventListener(input, 'click', function() {\n input.select();\n });\n iframely.addEventListener(input, 'blur', submitOptionsCb);\n iframely.addEventListener(input, 'keyup', function(e) {\n // Apply on enter.\n if (e.keyCode === 13) {\n submitOptionsCb();\n }\n });\n }\n },\n radio: {\n getValue: function(inputs) {\n var selectedInput;\n inputs.forEach(function(input) {\n if (input.checked) {\n selectedInput = input;\n }\n });\n return selectedInput.value;\n }\n }\n};\n\nvar defaultQueryById = {};\n\nmodule.exports = function(params) {\n\n var options = params.options;\n var formContainer = params.formContainer;\n\n if (!formContainer) {\n console.warn('No formContainer in form-builder options', params);\n return;\n }\n\n if (!options) {\n formContainer.innerHTML = '';\n return;\n }\n\n var elements = getFormElements(options, params.translator);\n var id = params.id;\n var renderer = params.renderer;\n\n var defaultQuery = defaultQueryById[id] = defaultQueryById[id] || {};\n // Exclude default values.\n Object.keys(options).forEach(function(key) {\n if (!options.query || options.query.indexOf(key) === -1) {\n // Store default value.\n defaultQuery[key] = options[key].value;\n }\n });\n\n function getQueryFromForm() {\n\n var query = {};\n\n var getOptionsFromElements = function(elements) {\n // Get options from all inputs.\n elements.forEach(function(element) {\n\n if (element.context && element.context.elements) {\n\n getOptionsFromElements(element.context.elements);\n\n } else if (element.inputs) {\n\n var elementUI = UIelements[element.type];\n var inputValue;\n if (elementUI && elementUI.getValue) {\n inputValue = elementUI.getValue(element.inputs);\n } else {\n inputValue = element.inputs[0].value;\n }\n Object.assign(query, element.getQuery(inputValue));\n }\n });\n };\n\n getOptionsFromElements(elements);\n \n return query;\n }\n\n function getAndSubmitOptions() {\n var query = getQueryFromForm();\n\n Object.keys(defaultQuery).forEach(function(key) {\n if (defaultQuery[key] === query[key] \n || query[key] === undefined) { // remove undefined so it's not included while JSON.stringify\n delete query[key];\n }\n });\n\n iframely.trigger('options-changed', id, formContainer, query);\n }\n\n // Render form.\n var renderElements = function(elements) {\n var html = '';\n elements.forEach(function(element) {\n if (element.context && element.context.elements) {\n element.context.elementsHtml = renderElements(element.context.elements);\n }\n html += renderer(element.type, element.context || {});\n });\n return html;\n };\n formContainer.innerHTML = renderElements(elements);\n\n // Bind events.\n var bindElements = function(elements) {\n \n elements.forEach(function(element) {\n\n if (element.context && element.context.elements) {\n\n bindElements(element.context.elements);\n\n } else {\n\n var elementUI = UIelements[element.type];\n if (element.context) {\n element.inputs = formContainer.querySelectorAll('[name=\"' + element.context.key + '\"]');\n if (element.inputs.length > 0) {\n if (elementUI && elementUI.customEvents) {\n elementUI.customEvents(element.inputs, getAndSubmitOptions);\n } else {\n element.inputs.forEach(function(input) {\n iframely.addEventListener(input, 'change', getAndSubmitOptions);\n });\n }\n } else {\n console.warn('No inputs found for option', element.key);\n }\n }\n }\n });\n };\n bindElements(elements);\n};\n\n//# sourceURL=webpack:///./options/form-builder.js?\n}"); - -/***/ }, - -/***/ "./options/form-generator.js" -/*!***********************************!*\ - !*** ./options/form-generator.js ***! - \***********************************/ -(module) { - -eval("{var _RE = /^_./;\n\nvar translate = function (label, translator) {\n return translator && typeof translator === 'function' \n ? translator (label) || label\n : label;\n};\n\nmodule.exports = function(options, translator) {\n\n if (!options) {\n return [];\n }\n\n // Remove query key.\n options = Object.assign({}, options);\n delete options.query;\n\n var items = [];\n var keys = Object.keys(options);\n var checkboxCount = 0;\n \n keys.forEach(function(key) {\n \n var context = {};\n\n var getQuery;\n var option = options[key];\n option.key = key;\n\n var forceCheckboxForSingleKeyValue;\n var valuesKeys = option.values && Object.keys(option.values);\n var singleKey, singleLabel;\n if (valuesKeys && valuesKeys.length === 1) {\n forceCheckboxForSingleKeyValue = true;\n singleKey = valuesKeys[0];\n singleLabel = option.values[singleKey];\n }\n\n context.label = translate(singleLabel || option.label, translator);\n context.key = option.key;\n\n if (forceCheckboxForSingleKeyValue || typeof option.value === 'boolean') {\n\n if (forceCheckboxForSingleKeyValue) {\n context.checked = (singleKey === option.value) || (!singleKey && !option.value);\n } else {\n context.checked = option.value;\n }\n\n checkboxCount++;\n\n items.push({\n type: 'checkbox',\n context: context,\n order: _RE.test(key) ? 0 : 1,\n getQuery: function(checked) {\n\n var value;\n if (forceCheckboxForSingleKeyValue) {\n value = checked ? singleKey : '';\n } else {\n value = checked;\n }\n\n var result = {};\n\n if (forceCheckboxForSingleKeyValue) {\n if (value === '') {\n // Empty.\n } else {\n result[option.key] = value;\n }\n } else {\n result[option.key] = checked;\n }\n return result;\n }\n });\n\n } else if ((typeof option.value === 'number' || typeof option.value === 'string') && !option.values) {\n\n var useSlider = option.range && typeof option.range.min === 'number' && typeof option.range.max === 'number';\n var useNumber = typeof option.value === 'number';\n\n context.value = option.value;\n\n getQuery = function(inputValue) {\n var result = {};\n if (inputValue === '') {\n // Empty.\n } else {\n result[option.key] = inputValue;\n }\n return result;\n };\n\n if (useSlider) {\n context.min = option.range.min;\n context.max = option.range.max;\n items.push({\n type: 'range',\n context: context,\n order: 9, // last one\n getQuery: getQuery\n });\n } else {\n context.placeholder = translate(option.placeholder || '', translator);\n context.inputType = useNumber ? 'number' : 'text';\n items.push({\n type: 'text',\n context: context,\n order: /start/i.test(key) ? 7 : 8, // start/end for player timing, ex.: youtube\n getQuery: getQuery\n });\n }\n\n } else if (option.values) {\n\n context.value = option.value + '';\n\n getQuery = function(inputValue) {\n var result = {};\n if (inputValue === '') {\n // Empty.\n } else {\n result[option.key] = inputValue;\n }\n return result;\n };\n\n if (Object.keys(option.values).length <= 3) {\n\n if (option.label) {\n context.label = translate(option.label, translator);\n } else {\n context.label = false;\n }\n\n var i = 0;\n var hasLongLabel = false;\n var values = Object.values(option.values);\n while (i < values.length && !hasLongLabel) {\n var label = values[i];\n hasLongLabel = label.length > 8;\n i++;\n }\n context.inline = !hasLongLabel;\n\n context.items = [];\n\n Object.keys(option.values).forEach(function(key, idx2) {\n context.items.push({\n id: context.key + '-' + idx2,\n value: key,\n label: translate(option.values[key], translator),\n checked: context.value === key\n });\n });\n\n items.push({\n type: 'radio',\n context: context,\n order: hasLongLabel ? -3 : (!/theme/.test(key) ? -2 : -1),\n getQuery: getQuery\n });\n\n } else {\n\n context.items = [];\n\n Object.keys(option.values).forEach(function(key) {\n context.items.push({\n value: key,\n label: translate(option.values[key], translator),\n checked: context.value === key\n });\n });\n\n items.push({\n type: 'select',\n context: context,\n order: 5,\n getQuery: getQuery\n });\n }\n }\n });\n\n items.sort(function(a, b) {\n return a.order - b.order;\n });\n\n items.forEach(function(item) {\n delete item.order;\n });\n\n if (checkboxCount > 0) {\n\n var groupedItems = [];\n var subItems;\n\n items.forEach(function(item, idx) {\n\n if (item.type === 'checkbox') {\n\n // Grouping for checkboxes.\n\n var newCheckboxGroup = \n checkboxCount > 2\n && idx > 0 \n && !_RE.test(item.context.key) \n && items[idx - 1].type === 'checkbox'\n && _RE.test(items[idx - 1].context.key);\n\n if (!subItems // First group.\n || newCheckboxGroup // Second group on _ prefix removed.\n ) {\n\n subItems = [];\n groupedItems.push({\n type: 'group',\n context: {\n elements: subItems\n }\n });\n }\n\n subItems.push(item);\n\n } else {\n // Other items. Just add.\n groupedItems.push(item);\n }\n });\n\n return groupedItems;\n\n } else {\n return items;\n }\n};\n\n//# sourceURL=webpack:///./options/form-generator.js?\n}"); - -/***/ }, - -/***/ "./options/index.js" -/*!**************************!*\ - !*** ./options/index.js ***! - \**************************/ -(__unused_webpack_module, exports, __webpack_require__) { - -eval("{var iframely = __webpack_require__(/*! ../iframely */ \"./iframely.js\");\nvar formBuilder = __webpack_require__(/*! ./form-builder */ \"./options/form-builder.js\");\nvar renderer = __webpack_require__(/*! ./renderer */ \"./options/renderer.js\");\n\niframely.buildOptionsForm = function(id, formContainer, options, translator) {\n formBuilder({\n id: id,\n formContainer: formContainer,\n options: options,\n renderer: renderer,\n translator: translator\n });\n};\n\nexports.iframely = iframely;\n\n//# sourceURL=webpack:///./options/index.js?\n}"); - -/***/ }, - -/***/ "./options/renderer.js" -/*!*****************************!*\ - !*** ./options/renderer.js ***! - \*****************************/ -(module, __unused_webpack_exports, __webpack_require__) { - -eval("{var checkboxTemplate = __webpack_require__(/*! ./templates/checkbox.ejs */ \"./options/templates/checkbox.ejs\");\nvar rangeTemplate = __webpack_require__(/*! ./templates/range.ejs */ \"./options/templates/range.ejs\");\nvar textTemplate = __webpack_require__(/*! ./templates/text.ejs */ \"./options/templates/text.ejs\");\nvar radioTemplate = __webpack_require__(/*! ./templates/radio.ejs */ \"./options/templates/radio.ejs\");\nvar selectTemplate = __webpack_require__(/*! ./templates/select.ejs */ \"./options/templates/select.ejs\");\nvar groupTemplate = __webpack_require__(/*! ./templates/group.ejs */ \"./options/templates/group.ejs\");\n\nvar templates = {\n checkbox: checkboxTemplate,\n range: rangeTemplate,\n text: textTemplate,\n radio: radioTemplate,\n select: selectTemplate,\n group: groupTemplate\n};\n\nmodule.exports = function(type, context) {\n var template = templates[type];\n var renderedTemplate = template(context);\n return renderedTemplate;\n};\n\n//# sourceURL=webpack:///./options/renderer.js?\n}"); - -/***/ } - -/******/ }); -/************************************************************************/ -/******/ // 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 -/******/ if (!(moduleId in __webpack_modules__)) { -/******/ delete __webpack_module_cache__[moduleId]; -/******/ var e = new Error("Cannot find module '" + moduleId + "'"); -/******/ e.code = 'MODULE_NOT_FOUND'; -/******/ throw e; -/******/ } -/******/ __webpack_modules__[moduleId](module, module.exports, __webpack_require__); -/******/ -/******/ // Return the exports of the module -/******/ return module.exports; -/******/ } -/******/ -/************************************************************************/ -/******/ -/******/ // startup -/******/ // Load entry module and return exports -/******/ // This entry module can't be inlined because the eval devtool is used. -/******/ var __webpack_exports__ = __webpack_require__("./options/index.js"); -/******/ -/******/ })() -; \ No newline at end of file +(function() { + + +//#region src/iframely.ts + function createServerStub() { + const noop = () => {}; + return { + config: {}, + on: noop, + trigger: noop, + triggerAsync: noop, + load: noop, + unload: noop, + configure: noop, + extendOptions: noop, + setTheme: noop, + cancelWidget: noop, + openHref: noop, + addEventListener: noop, + isTouch: () => false, + findIframe: () => void 0, + getElementComputedStyle: () => void 0, + buildOptionsForm: noop + }; + } + var iframely = typeof window === "undefined" ? createServerStub() : window.iframely = window.iframely || {}; + iframely.config = iframely.config || {}; + +//#endregion +//#region src/options/form-generator.ts + var _RE = /^_./; + var translate = (label, translator) => { + return translator && typeof translator === "function" && label ? translator(label) || label : label; + }; + function getFormElements(options, translator) { + if (!options) return []; + options = Object.assign({}, options); + delete options.query; + const items = []; + const keys = Object.keys(options); + let checkboxCount = 0; + keys.forEach((key) => { + const context = {}; + let getQuery; + const option = options[key]; + option.key = key; + let forceCheckboxForSingleKeyValue = false; + const valuesKeys = option.values ? Object.keys(option.values) : void 0; + let singleKey, singleLabel; + if (valuesKeys && valuesKeys.length === 1) { + forceCheckboxForSingleKeyValue = true; + singleKey = valuesKeys[0]; + singleLabel = option.values[singleKey]; + } + context.label = translate(singleLabel || option.label, translator); + context.key = option.key; + if (forceCheckboxForSingleKeyValue || typeof option.value === "boolean") { + if (forceCheckboxForSingleKeyValue) context.checked = singleKey === option.value || !singleKey && !option.value; + else context.checked = option.value; + checkboxCount++; + items.push({ + type: "checkbox", + context, + order: _RE.test(key) ? 0 : 1, + getQuery: (checked) => { + let value; + if (forceCheckboxForSingleKeyValue) value = checked ? singleKey : ""; + else value = checked; + const result = {}; + if (forceCheckboxForSingleKeyValue) if (value === "") {} else result[option.key] = value; + else result[option.key] = checked; + return result; + } + }); + } else if ((typeof option.value === "number" || typeof option.value === "string") && !option.values) { + const useSlider = option.range && typeof option.range.min === "number" && typeof option.range.max === "number"; + const useNumber = typeof option.value === "number"; + context.value = option.value; + getQuery = (inputValue) => { + const result = {}; + if (inputValue === "") {} else result[option.key] = inputValue; + return result; + }; + if (useSlider) { + context.min = option.range.min; + context.max = option.range.max; + items.push({ + type: "range", + context, + order: 9, + getQuery + }); + } else { + context.placeholder = translate(option.placeholder || "", translator); + context.inputType = useNumber ? "number" : "text"; + items.push({ + type: "text", + context, + order: /start/i.test(key) ? 7 : 8, + getQuery + }); + } + } else if (option.values) { + context.value = option.value + ""; + getQuery = (inputValue) => { + const result = {}; + if (inputValue === "") {} else result[option.key] = inputValue; + return result; + }; + if (Object.keys(option.values).length <= 3) { + if (option.label) context.label = translate(option.label, translator); + else context.label = false; + let i = 0; + let hasLongLabel = false; + const values = Object.values(option.values); + while (i < values.length && !hasLongLabel) { + hasLongLabel = values[i].length > 8; + i++; + } + context.inline = !hasLongLabel; + context.items = []; + Object.keys(option.values).forEach((key, idx2) => { + context.items.push({ + id: context.key + "-" + idx2, + value: key, + label: translate(option.values[key], translator), + checked: context.value === key + }); + }); + items.push({ + type: "radio", + context, + order: hasLongLabel ? -3 : !/theme/.test(key) ? -2 : -1, + getQuery + }); + } else { + context.items = []; + Object.keys(option.values).forEach((key) => { + context.items.push({ + value: key, + label: translate(option.values[key], translator), + checked: context.value === key + }); + }); + items.push({ + type: "select", + context, + order: 5, + getQuery + }); + } + } + }); + items.sort((a, b) => a.order - b.order); + items.forEach((item) => { + delete item.order; + }); + if (checkboxCount > 0) { + const groupedItems = []; + let subItems; + items.forEach((item, idx) => { + if (item.type === "checkbox") { + const newCheckboxGroup = checkboxCount > 2 && idx > 0 && !_RE.test(item.context.key) && items[idx - 1].type === "checkbox" && _RE.test(items[idx - 1].context.key); + if (!subItems || newCheckboxGroup) { + subItems = []; + groupedItems.push({ + type: "group", + context: { elements: subItems } + }); + } + subItems.push(item); + } else groupedItems.push(item); + }); + return groupedItems; + } else return items; + } + +//#endregion +//#region src/options/form-builder.ts + var UIelements = { + checkbox: { getValue: (inputs) => { + return inputs[0].checked; + } }, + text: { + getValue: (inputs) => { + const input = inputs[0]; + let value = input.value; + if (input.type === "number") { + value = parseInt(value); + if (isNaN(value)) value = ""; + } + return value; + }, + customEvents: (inputs, submitOptionsCb) => { + const input = inputs[0]; + iframely.addEventListener(input, "click", () => { + input.select(); + }); + iframely.addEventListener(input, "blur", submitOptionsCb); + iframely.addEventListener(input, "keyup", (e) => { + if (e.keyCode === 13) submitOptionsCb(); + }); + } + }, + radio: { getValue: (inputs) => { + let selectedInput; + Array.prototype.forEach.call(inputs, (input) => { + if (input.checked) selectedInput = input; + }); + return selectedInput.value; + } } + }; + var defaultQueryById = {}; + function formBuilder(params) { + const options = params.options; + const formContainer = params.formContainer; + if (!formContainer) { + console.warn("No formContainer in form-builder options", params); + return; + } + if (!options) { + formContainer.innerHTML = ""; + return; + } + const elements = getFormElements(options, params.translator); + const id = params.id; + const renderer = params.renderer; + const defaultQuery = defaultQueryById[id] = defaultQueryById[id] || {}; + Object.keys(options).forEach((key) => { + if (!options.query || options.query.indexOf(key) === -1) defaultQuery[key] = options[key].value; + }); + function getQueryFromForm() { + const query = {}; + const getOptionsFromElements = (elements) => { + elements.forEach((element) => { + if (element.context && element.context.elements) getOptionsFromElements(element.context.elements); + else if (element.inputs) { + const elementUI = UIelements[element.type]; + let inputValue; + if (elementUI && elementUI.getValue) inputValue = elementUI.getValue(element.inputs); + else inputValue = element.inputs[0].value; + Object.assign(query, element.getQuery(inputValue)); + } + }); + }; + getOptionsFromElements(elements); + return query; + } + function getAndSubmitOptions() { + const query = getQueryFromForm(); + Object.keys(defaultQuery).forEach((key) => { + if (defaultQuery[key] === query[key] || query[key] === void 0) delete query[key]; + }); + iframely.trigger("options-changed", id, formContainer, query); + } + const renderElements = (elements) => { + let html = ""; + elements.forEach((element) => { + if (element.context && element.context.elements) element.context.elementsHtml = renderElements(element.context.elements); + html += renderer(element.type, element.context || {}); + }); + return html; + }; + formContainer.innerHTML = renderElements(elements); + const bindElements = (elements) => { + elements.forEach((element) => { + if (element.context && element.context.elements) bindElements(element.context.elements); + else { + const elementUI = UIelements[element.type]; + if (element.context) { + const inputs = formContainer.querySelectorAll("[name=\"" + element.context.key + "\"]"); + element.inputs = inputs; + if (inputs.length > 0) if (elementUI && elementUI.customEvents) elementUI.customEvents(inputs, getAndSubmitOptions); + else inputs.forEach((input) => { + iframely.addEventListener(input, "change", getAndSubmitOptions); + }); + else console.warn("No inputs found for option", element.context.key); + } + } + }); + }; + bindElements(elements); + } + +//#endregion +//#region src/options/renderer.ts + var ESCAPE_MAP = { + "&": "&", + "<": "<", + ">": ">", + "\"": """, + "'": "'" + }; + var esc = (value) => value == null ? "" : String(value).replace(/[&<>"']/g, (c) => ESCAPE_MAP[c]); + var templates = { + checkbox: (ctx) => ` +
+ + +
`, + group: (ctx) => ` +
+
${ctx.elementsHtml ?? ""}
+
`, + radio: (ctx) => ` +
+ ${ctx.label ? `` : ""} +
+ ${(ctx.items || []).map((item) => ` +
+ + +
`).join("")} +
+
`, + range: (ctx) => ` +
+ +
+ +
+
`, + select: (ctx) => ` +
+ +
+ +
+
`, + text: (ctx) => ` +
+ +
+ +
+
` + }; + var render = (type, context) => templates[type](context); + +//#endregion +//#region src/options/index.ts + function boot() { + iframely.buildOptionsForm = (id, formContainer, options, translator) => { + if (typeof iframely.trigger !== "function" || typeof iframely.addEventListener !== "function") { + console.warn("iframely.buildOptionsForm requires embed.js (or embed-options.js) to be loaded"); + return; + } + formBuilder({ + id, + formContainer, + options, + renderer: render, + translator + }); + }; + } + +//#endregion +//#region src/options/entry.ts + boot(); + +//#endregion +})(); \ No newline at end of file diff --git a/dist/options.min.js b/dist/options.min.js index 2be8265..d60e9d4 100644 --- a/dist/options.min.js +++ b/dist/options.min.js @@ -1 +1,38 @@ -(()=>{var __webpack_modules__={530(module){module.exports=function(obj){obj||(obj={});var __t,__p="",__j=Array.prototype.join;function print(){__p+=__j.call(arguments,"")}with(obj)__p+='
\n \n '+(null==(__t=label)?"":__t)+"\n \n
\n";return __p}},30(module){module.exports=function(obj){obj||(obj={});var __t,__p="",__e=_.escape;with(obj)__p+='
\n
\n '+__e(elementsHtml)+"\n
\n
";return __p}},510(module){module.exports=function(obj){obj||(obj={});var __t,__p="",__j=Array.prototype.join;function print(){__p+=__j.call(arguments,"")}with(obj)__p+='
\n ',label&&(__p+='\n \n "),__p+='\n
\n '+(null==(__t=e.label)?"":__t)+"\n \n
\n "}),__p+="\n
\n";return __p}},300(module){module.exports=function(obj){obj||(obj={});var __t,__p="";with(obj)__p+='
\n \n
\n \n
\n
';return __p}},37(module){module.exports=function(obj){obj||(obj={});var __t,__p="",__j=Array.prototype.join;function print(){__p+=__j.call(arguments,"")}with(obj)__p+='
\n \n
\n \n
\n
";return __p}},712(module){module.exports=function(obj){obj||(obj={});var __t,__p="";with(obj)__p+='
\n \n
\n \n
\n
';return __p}},774(e){var t=window.iframely=window.iframely||{};t.config=t.config||{},e.exports=t},410(e,t,n){var _=n(960),l=n(774),o={checkbox:{getValue:function(e){return e[0].checked}},text:{getValue:function(e){var t=e[0],n=t.value;return"number"===t.type&&(n=parseInt(n),isNaN(n)&&(n="")),n},customEvents:function(e,t){var n=e[0];l.addEventListener(n,"click",function(){n.select()}),l.addEventListener(n,"blur",t),l.addEventListener(n,"keyup",function(e){13===e.keyCode&&t()})}},radio:{getValue:function(e){var t;return e.forEach(function(e){e.checked&&(t=e)}),t.value}}},r={};e.exports=function(e){var t=e.options,n=e.formContainer;if(n)if(t){var a=_(t,e.translator),i=e.id,u=e.renderer,c=r[i]=r[i]||{};Object.keys(t).forEach(function(e){t.query&&-1!==t.query.indexOf(e)||(c[e]=t[e].value)});var p=function(e){var t="";return e.forEach(function(e){e.context&&e.context.elements&&(e.context.elementsHtml=p(e.context.elements)),t+=u(e.type,e.context||{})}),t};n.innerHTML=p(a);var s=function(e){e.forEach(function(e){if(e.context&&e.context.elements)s(e.context.elements);else{var t=o[e.type];e.context&&(e.inputs=n.querySelectorAll('[name="'+e.context.key+'"]'),e.inputs.length>0?t&&t.customEvents?t.customEvents(e.inputs,f):e.inputs.forEach(function(e){l.addEventListener(e,"change",f)}):console.warn("No inputs found for option",e.key))}})};s(a)}else n.innerHTML="";else console.warn("No formContainer in form-builder options",e);function f(){var e=function(){var e={},t=function(n){n.forEach(function(n){if(n.context&&n.context.elements)t(n.context.elements);else if(n.inputs){var _,l=o[n.type];_=l&&l.getValue?l.getValue(n.inputs):n.inputs[0].value,Object.assign(e,n.getQuery(_))}})};return t(a),e}();Object.keys(c).forEach(function(t){c[t]!==e[t]&&void 0!==e[t]||delete e[t]}),l.trigger("options-changed",i,n,e)}}},960(e){var t=/^_./,n=function(e,t){return t&&"function"==typeof t&&t(e)||e};e.exports=function(e,_){if(!e)return[];delete(e=Object.assign({},e)).query;var l=[],o=Object.keys(e),r=0;if(o.forEach(function(o){var a,i,u={},c=e[o];c.key=o;var p,s,f=c.values&&Object.keys(c.values);if(f&&1===f.length&&(i=!0,p=f[0],s=c.values[p]),u.label=n(s||c.label,_),u.key=c.key,i||"boolean"==typeof c.value)u.checked=i?p===c.value||!p&&!c.value:c.value,r++,l.push({type:"checkbox",context:u,order:t.test(o)?0:1,getQuery:function(e){var t;t=i?e?p:"":e;var n={};return i?""===t||(n[c.key]=t):n[c.key]=e,n}});else if("number"!=typeof c.value&&"string"!=typeof c.value||c.values){if(c.values)if(u.value=c.value+"",a=function(e){var t={};return""===e||(t[c.key]=e),t},Object.keys(c.values).length<=3){c.label?u.label=n(c.label,_):u.label=!1;for(var v=0,d=!1,y=Object.values(c.values);v8,v++;u.inline=!d,u.items=[],Object.keys(c.values).forEach(function(e,t){u.items.push({id:u.key+"-"+t,value:e,label:n(c.values[e],_),checked:u.value===e})}),l.push({type:"radio",context:u,order:d?-3:/theme/.test(o)?-1:-2,getQuery:a})}else u.items=[],Object.keys(c.values).forEach(function(e){u.items.push({value:e,label:n(c.values[e],_),checked:u.value===e})}),l.push({type:"select",context:u,order:5,getQuery:a})}else{var m=c.range&&"number"==typeof c.range.min&&"number"==typeof c.range.max,b="number"==typeof c.value;u.value=c.value,a=function(e){var t={};return""===e||(t[c.key]=e),t},m?(u.min=c.range.min,u.max=c.range.max,l.push({type:"range",context:u,order:9,getQuery:a})):(u.placeholder=n(c.placeholder||"",_),u.inputType=b?"number":"text",l.push({type:"text",context:u,order:/start/i.test(o)?7:8,getQuery:a}))}}),l.sort(function(e,t){return e.order-t.order}),l.forEach(function(e){delete e.order}),r>0){var a,i=[];return l.forEach(function(e,n){if("checkbox"===e.type){var _=r>2&&n>0&&!t.test(e.context.key)&&"checkbox"===l[n-1].type&&t.test(l[n-1].context.key);a&&!_||(a=[],i.push({type:"group",context:{elements:a}})),a.push(e)}else i.push(e)}),i}return l}},505(e,t,n){var _={checkbox:n(530),range:n(300),text:n(712),radio:n(510),select:n(37),group:n(30)};e.exports=function(e,t){return(0,_[e])(t)}}},__webpack_module_cache__={};function __webpack_require__(e){var t=__webpack_module_cache__[e];if(void 0!==t)return t.exports;var n=__webpack_module_cache__[e]={exports:{}};return __webpack_modules__[e](n,n.exports,__webpack_require__),n.exports}var __webpack_exports__={},iframely,formBuilder,renderer;iframely=__webpack_require__(774),formBuilder=__webpack_require__(410),renderer=__webpack_require__(505),iframely.buildOptionsForm=function(e,t,n,_){formBuilder({id:e,formContainer:t,options:n,renderer,translator:_})}})(); \ No newline at end of file +(function(){function e(){let e=()=>{};return{config:{},on:e,trigger:e,triggerAsync:e,load:e,unload:e,configure:e,extendOptions:e,setTheme:e,cancelWidget:e,openHref:e,addEventListener:e,isTouch:()=>!1,findIframe:()=>void 0,getElementComputedStyle:()=>void 0,buildOptionsForm:e}}var t=typeof window>`u`?e():window.iframely=window.iframely||{};t.config=t.config||{};var n=/^_./,r=(e,t)=>t&&typeof t==`function`&&e&&t(e)||e;function i(e,t){if(!e)return[];e=Object.assign({},e),delete e.query;let i=[],a=Object.keys(e),o=0;if(a.forEach(a=>{let s={},c,l=e[a];l.key=a;let u=!1,d=l.values?Object.keys(l.values):void 0,f,p;if(d&&d.length===1&&(u=!0,f=d[0],p=l.values[f]),s.label=r(p||l.label,t),s.key=l.key,u||typeof l.value==`boolean`)u?s.checked=f===l.value||!f&&!l.value:s.checked=l.value,o++,i.push({type:`checkbox`,context:s,order:+!n.test(a),getQuery:e=>{let t;t=u?e?f:``:e;let n={};return u?t===``||(n[l.key]=t):n[l.key]=e,n}});else if((typeof l.value==`number`||typeof l.value==`string`)&&!l.values){let e=l.range&&typeof l.range.min==`number`&&typeof l.range.max==`number`,n=typeof l.value==`number`;s.value=l.value,c=e=>{let t={};return e===``||(t[l.key]=e),t},e?(s.min=l.range.min,s.max=l.range.max,i.push({type:`range`,context:s,order:9,getQuery:c})):(s.placeholder=r(l.placeholder||``,t),s.inputType=n?`number`:`text`,i.push({type:`text`,context:s,order:/start/i.test(a)?7:8,getQuery:c}))}else if(l.values)if(s.value=l.value+``,c=e=>{let t={};return e===``||(t[l.key]=e),t},Object.keys(l.values).length<=3){l.label?s.label=r(l.label,t):s.label=!1;let e=0,n=!1,o=Object.values(l.values);for(;e8,e++;s.inline=!n,s.items=[],Object.keys(l.values).forEach((e,n)=>{s.items.push({id:s.key+`-`+n,value:e,label:r(l.values[e],t),checked:s.value===e})}),i.push({type:`radio`,context:s,order:n?-3:/theme/.test(a)?-1:-2,getQuery:c})}else s.items=[],Object.keys(l.values).forEach(e=>{s.items.push({value:e,label:r(l.values[e],t),checked:s.value===e})}),i.push({type:`select`,context:s,order:5,getQuery:c})}),i.sort((e,t)=>e.order-t.order),i.forEach(e=>{delete e.order}),o>0){let e=[],t;return i.forEach((r,a)=>{if(r.type===`checkbox`){let s=o>2&&a>0&&!n.test(r.context.key)&&i[a-1].type===`checkbox`&&n.test(i[a-1].context.key);(!t||s)&&(t=[],e.push({type:`group`,context:{elements:t}})),t.push(r)}else e.push(r)}),e}else return i}var a={checkbox:{getValue:e=>e[0].checked},text:{getValue:e=>{let t=e[0],n=t.value;return t.type===`number`&&(n=parseInt(n),isNaN(n)&&(n=``)),n},customEvents:(e,n)=>{let r=e[0];t.addEventListener(r,`click`,()=>{r.select()}),t.addEventListener(r,`blur`,n),t.addEventListener(r,`keyup`,e=>{e.keyCode===13&&n()})}},radio:{getValue:e=>{let t;return Array.prototype.forEach.call(e,e=>{e.checked&&(t=e)}),t.value}}},o={};function s(e){let n=e.options,r=e.formContainer;if(!r){console.warn(`No formContainer in form-builder options`,e);return}if(!n){r.innerHTML=``;return}let s=i(n,e.translator),c=e.id,l=e.renderer,u=o[c]=o[c]||{};Object.keys(n).forEach(e=>{(!n.query||n.query.indexOf(e)===-1)&&(u[e]=n[e].value)});function d(){let e={},t=n=>{n.forEach(n=>{if(n.context&&n.context.elements)t(n.context.elements);else if(n.inputs){let t=a[n.type],r;r=t&&t.getValue?t.getValue(n.inputs):n.inputs[0].value,Object.assign(e,n.getQuery(r))}})};return t(s),e}function f(){let e=d();Object.keys(u).forEach(t=>{(u[t]===e[t]||e[t]===void 0)&&delete e[t]}),t.trigger(`options-changed`,c,r,e)}let p=e=>{let t=``;return e.forEach(e=>{e.context&&e.context.elements&&(e.context.elementsHtml=p(e.context.elements)),t+=l(e.type,e.context||{})}),t};r.innerHTML=p(s);let m=e=>{e.forEach(e=>{if(e.context&&e.context.elements)m(e.context.elements);else{let n=a[e.type];if(e.context){let i=r.querySelectorAll(`[name="`+e.context.key+`"]`);e.inputs=i,i.length>0?n&&n.customEvents?n.customEvents(i,f):i.forEach(e=>{t.addEventListener(e,`change`,f)}):console.warn(`No inputs found for option`,e.context.key)}}})};m(s)}var c={"&":`&`,"<":`<`,">":`>`,'"':`"`,"'":`'`},l=e=>e==null?``:String(e).replace(/[&<>"']/g,e=>c[e]),u={checkbox:e=>` +
+ + +
`,group:e=>` +
+
${e.elementsHtml??``}
+
`,radio:e=>` +
+ ${e.label?``:``} +
+ ${(e.items||[]).map(t=>` +
+ + +
`).join(``)} +
+
`,range:e=>` +
+ +
+ +
+
`,select:e=>` +
+ +
+ +
+
`,text:e=>` +
+ +
+ +
+
`},d=(e,t)=>u[e](t);function f(){t.buildOptionsForm=(e,n,r,i)=>{if(typeof t.trigger!=`function`||typeof t.addEventListener!=`function`){console.warn(`iframely.buildOptionsForm requires embed.js (or embed-options.js) to be loaded`);return}s({id:e,formContainer:n,options:r,renderer:d,translator:i})}}f()})(); \ No newline at end of file diff --git a/dist/types/ahref.d.ts b/dist/types/ahref.d.ts new file mode 100644 index 0000000..46db090 --- /dev/null +++ b/dist/types/ahref.d.ts @@ -0,0 +1 @@ +export declare function boot(): void; diff --git a/dist/types/const.d.ts b/dist/types/const.d.ts new file mode 100644 index 0000000..46db090 --- /dev/null +++ b/dist/types/const.d.ts @@ -0,0 +1 @@ +export declare function boot(): void; diff --git a/dist/types/deprecated.d.ts b/dist/types/deprecated.d.ts new file mode 100644 index 0000000..46db090 --- /dev/null +++ b/dist/types/deprecated.d.ts @@ -0,0 +1 @@ +export declare function boot(): void; diff --git a/dist/types/dom-ready.d.ts b/dist/types/dom-ready.d.ts new file mode 100644 index 0000000..cb0ff5c --- /dev/null +++ b/dist/types/dom-ready.d.ts @@ -0,0 +1 @@ +export {}; diff --git a/dist/types/events.d.ts b/dist/types/events.d.ts new file mode 100644 index 0000000..46db090 --- /dev/null +++ b/dist/types/events.d.ts @@ -0,0 +1 @@ +export declare function boot(): void; diff --git a/dist/types/iframely.d.ts b/dist/types/iframely.d.ts new file mode 100644 index 0000000..eae984e --- /dev/null +++ b/dist/types/iframely.d.ts @@ -0,0 +1,3 @@ +import type { Iframely } from './types'; +declare const iframely: Iframely; +export default iframely; diff --git a/dist/types/import.d.ts b/dist/types/import.d.ts new file mode 100644 index 0000000..46db090 --- /dev/null +++ b/dist/types/import.d.ts @@ -0,0 +1 @@ +export declare function boot(): void; diff --git a/dist/types/index-options.d.ts b/dist/types/index-options.d.ts new file mode 100644 index 0000000..efc471c --- /dev/null +++ b/dist/types/index-options.d.ts @@ -0,0 +1 @@ +import './dom-ready'; diff --git a/dist/types/index.d.ts b/dist/types/index.d.ts new file mode 100644 index 0000000..efc471c --- /dev/null +++ b/dist/types/index.d.ts @@ -0,0 +1 @@ +import './dom-ready'; diff --git a/dist/types/intersection.d.ts b/dist/types/intersection.d.ts new file mode 100644 index 0000000..46db090 --- /dev/null +++ b/dist/types/intersection.d.ts @@ -0,0 +1 @@ +export declare function boot(): void; diff --git a/dist/types/lazy-iframe.d.ts b/dist/types/lazy-iframe.d.ts new file mode 100644 index 0000000..46db090 --- /dev/null +++ b/dist/types/lazy-iframe.d.ts @@ -0,0 +1 @@ +export declare function boot(): void; diff --git a/dist/types/lazy-img-placeholder.d.ts b/dist/types/lazy-img-placeholder.d.ts new file mode 100644 index 0000000..46db090 --- /dev/null +++ b/dist/types/lazy-img-placeholder.d.ts @@ -0,0 +1 @@ +export declare function boot(): void; diff --git a/dist/types/main-options.d.ts b/dist/types/main-options.d.ts new file mode 100644 index 0000000..1f7b990 --- /dev/null +++ b/dist/types/main-options.d.ts @@ -0,0 +1,4 @@ +import './index-options'; +import iframely from './iframely'; +export { iframely }; +export type * from './types'; diff --git a/dist/types/main.d.ts b/dist/types/main.d.ts new file mode 100644 index 0000000..a0a47c2 --- /dev/null +++ b/dist/types/main.d.ts @@ -0,0 +1,4 @@ +import './index'; +import iframely from './iframely'; +export { iframely }; +export type * from './types'; diff --git a/dist/types/messaging.d.ts b/dist/types/messaging.d.ts new file mode 100644 index 0000000..776572e --- /dev/null +++ b/dist/types/messaging.d.ts @@ -0,0 +1,3 @@ +import type { IframelyMessage } from './types'; +export declare function boot(): void; +export declare function postMessage(message: IframelyMessage | string, target_url?: string, target?: Window | null): void; diff --git a/dist/types/options/entry.d.ts b/dist/types/options/entry.d.ts new file mode 100644 index 0000000..cb0ff5c --- /dev/null +++ b/dist/types/options/entry.d.ts @@ -0,0 +1 @@ +export {}; diff --git a/dist/types/options/form-builder.d.ts b/dist/types/options/form-builder.d.ts new file mode 100644 index 0000000..de0157c --- /dev/null +++ b/dist/types/options/form-builder.d.ts @@ -0,0 +1,10 @@ +import type { Renderer } from './renderer'; +import type { TranslatorFn, WidgetOptions } from '../types'; +export interface FormBuilderParams { + id: string; + formContainer: HTMLElement; + options?: WidgetOptions; + renderer: Renderer; + translator?: TranslatorFn | null; +} +export default function formBuilder(params: FormBuilderParams): void; diff --git a/dist/types/options/form-generator.d.ts b/dist/types/options/form-generator.d.ts new file mode 100644 index 0000000..23e9d9d --- /dev/null +++ b/dist/types/options/form-generator.d.ts @@ -0,0 +1,2 @@ +import type { FormElement, TranslatorFn, WidgetOptions } from '../types'; +export default function getFormElements(options: WidgetOptions | undefined, translator?: TranslatorFn | null): FormElement[]; diff --git a/dist/types/options/index.d.ts b/dist/types/options/index.d.ts new file mode 100644 index 0000000..46db090 --- /dev/null +++ b/dist/types/options/index.d.ts @@ -0,0 +1 @@ +export declare function boot(): void; diff --git a/dist/types/options/lang/labels.de.d.ts b/dist/types/options/lang/labels.de.d.ts new file mode 100644 index 0000000..cb0ff5c --- /dev/null +++ b/dist/types/options/lang/labels.de.d.ts @@ -0,0 +1 @@ +export {}; diff --git a/dist/types/options/lang/labels.fr.d.ts b/dist/types/options/lang/labels.fr.d.ts new file mode 100644 index 0000000..cb0ff5c --- /dev/null +++ b/dist/types/options/lang/labels.fr.d.ts @@ -0,0 +1 @@ +export {}; diff --git a/dist/types/options/renderer.d.ts b/dist/types/options/renderer.d.ts new file mode 100644 index 0000000..0b880d3 --- /dev/null +++ b/dist/types/options/renderer.d.ts @@ -0,0 +1,4 @@ +import type { ElementContext, FormElementType } from '../types'; +export type Renderer = (type: FormElementType, context: ElementContext) => string; +declare const render: Renderer; +export default render; diff --git a/dist/types/options/translator.d.ts b/dist/types/options/translator.d.ts new file mode 100644 index 0000000..143770b --- /dev/null +++ b/dist/types/options/translator.d.ts @@ -0,0 +1 @@ +export declare function registerLabels(lang: string, labels: Record): void; diff --git a/dist/types/theme.d.ts b/dist/types/theme.d.ts new file mode 100644 index 0000000..46db090 --- /dev/null +++ b/dist/types/theme.d.ts @@ -0,0 +1 @@ +export declare function boot(): void; diff --git a/dist/types/types.d.ts b/dist/types/types.d.ts new file mode 100644 index 0000000..8c4d7ed --- /dev/null +++ b/dist/types/types.d.ts @@ -0,0 +1,131 @@ +export type ConfigValue = string | number | boolean; +export interface IframelyConfig { + autorun?: boolean; + theme?: string; + nonce?: string; + cdn?: string; + shadow?: string; + lazy?: ConfigValue; + key?: string; + api_key?: string; + [key: string]: ConfigValue | undefined; +} +export interface IframelyWidget { + iframe: Element; + aspectWrapper: HTMLElement; + maxWidthWrapper: HTMLElement; + url?: string; +} +export interface IframelyMessage { + method?: string; + type?: string; + context?: string; + src?: string; + url?: string; + height?: number; + domains?: string | string[]; + [key: string]: any; +} +export interface FindIframeOptions { + contentWindow: MessageEventSource | Window | null; + src?: string; + domains?: string[] | false; +} +export type TranslatorFn = (label: string) => string; +export type FormElementType = 'checkbox' | 'range' | 'text' | 'radio' | 'select' | 'group'; +export interface RadioItem { + id?: string; + value: string | number | boolean; + label: string; + checked?: boolean; +} +export interface ElementContext { + key?: string; + label?: string | false; + checked?: boolean; + value?: string | number | boolean; + min?: number; + max?: number; + placeholder?: string; + inputType?: string; + inline?: boolean; + items?: RadioItem[]; + elements?: FormElement[]; + elementsHtml?: string; + [key: string]: any; +} +export interface FormElement { + type: FormElementType; + context: ElementContext; + order?: number; + getQuery?: (inputValue: any) => Record; + inputs?: ArrayLike; + [key: string]: any; +} +export interface WidgetOption { + label?: string; + value?: ConfigValue; + values?: Record; + placeholder?: string; + range?: { + min: number; + max: number; + }; + [key: string]: any; +} +export type WidgetOptions = Record; +export interface Iframely { + config: IframelyConfig; + _loaded?: boolean; + on(event: string, cb: (...args: any[]) => void): void; + trigger(event: string, ...args: any[]): void; + triggerAsync(event: string, ...args: any[]): void; + load(...args: any[]): void; + /** + * Inverse of load(): removes built widgets from the document (or a + * container), releases their intersection observers and pending timers. + * Import/shadow widgets are not covered; consumed anchors are not restored. + */ + unload(el?: Element): void; + configure(options: Record | undefined): void; + /** @deprecated Pre-2.0 name of {@link Iframely.configure}. */ + extendOptions(options: Record | undefined): void; + getElementComputedStyle(el: Element, style: string): string | undefined; + findIframe(options: FindIframeOptions): HTMLIFrameElement | undefined; + setTheme(theme?: string, container?: Element): void; + addEventListener(elem: EventTarget, type: string, handler: (e: any) => void): void; + isTouch(): boolean; + buildOptionsForm?(id: string, formContainer: HTMLElement, options: WidgetOptions, translator?: TranslatorFn | null): void; + optionsTranslator?(lang: string): TranslatorFn | undefined; + VERSION: number; + ASPECT_WRAPPER_CLASS: string; + MAXWIDTH_WRAPPER_CLASS: string; + LOADER_CLASS: string; + DOMAINS: string[]; + CDN: string; + BASE_RE: RegExp; + ID_RE: RegExp; + SCRIPT_RE: RegExp; + CDN_RE: RegExp; + SUPPORTED_QUERY_STRING: (string | RegExp)[]; + SUPPORTED_THEMES: string[]; + LAZY_IFRAME_SHOW_TIMEOUT: number; + LAZY_IFRAME_FADE_TIMEOUT: number; + CLEAR_WRAPPER_STYLES_TIMEOUT: number; + RECOVER_HREFS_ON_CANCEL: boolean; + SHADOW: string; + SUPPORT_IFRAME_LOADING_ATTR: boolean; + widgets: { + load?: Iframely['load']; + }; + events: { + on?: Iframely['on']; + trigger?: Iframely['trigger']; + }; + [key: string]: any; +} +declare global { + interface Window { + iframely?: Iframely; + } +} diff --git a/dist/types/utils.d.ts b/dist/types/utils.d.ts new file mode 100644 index 0000000..aa54937 --- /dev/null +++ b/dist/types/utils.d.ts @@ -0,0 +1,17 @@ +import type { IframelyWidget } from './types'; +export declare function boot(): void; +export declare function getIframeWrapper(iframe: Element, checkClass?: boolean): { + aspectWrapper: HTMLElement; + maxWidthWrapper: HTMLElement; +} | undefined; +export declare function addDefaultWrappers(el: Element): { + aspectWrapper: HTMLElement; + maxWidthWrapper: HTMLElement; +}; +export declare function getWidget(iframe: Element): IframelyWidget | undefined; +export declare function setStyles(el: HTMLElement | undefined | null, styles: Record): void; +export declare function applyNonce(element: HTMLElement): void; +export declare function addQueryString(href: string, options: Record): string; +export declare function getEndpoint(src: string, options?: Record, config_params?: (string | RegExp)[]): string; +export declare function parseQueryString(url: string, allowed_query_string?: (string | RegExp)[]): Record; +export declare function createScript(): HTMLScriptElement; diff --git a/dist/types/widget-cancel.d.ts b/dist/types/widget-cancel.d.ts new file mode 100644 index 0000000..46db090 --- /dev/null +++ b/dist/types/widget-cancel.d.ts @@ -0,0 +1 @@ +export declare function boot(): void; diff --git a/dist/types/widget-click.d.ts b/dist/types/widget-click.d.ts new file mode 100644 index 0000000..46db090 --- /dev/null +++ b/dist/types/widget-click.d.ts @@ -0,0 +1 @@ +export declare function boot(): void; diff --git a/dist/types/widget-options.d.ts b/dist/types/widget-options.d.ts new file mode 100644 index 0000000..46db090 --- /dev/null +++ b/dist/types/widget-options.d.ts @@ -0,0 +1 @@ +export declare function boot(): void; diff --git a/dist/types/widget-resize.d.ts b/dist/types/widget-resize.d.ts new file mode 100644 index 0000000..46db090 --- /dev/null +++ b/dist/types/widget-resize.d.ts @@ -0,0 +1 @@ +export declare function boot(): void; diff --git a/eslint.config.js b/eslint.config.js deleted file mode 100644 index 99a278c..0000000 --- a/eslint.config.js +++ /dev/null @@ -1,64 +0,0 @@ -module.exports = [ - { - languageOptions: { - ecmaVersion: 2018, - sourceType: 'module', - globals: { - ActiveXObject: 'readonly', - console: 'readonly', - window: 'readonly', - document: 'readonly', - navigator: 'readonly', - setTimeout: 'readonly', - clearTimeout: 'readonly', - setInterval: 'readonly', - clearInterval: 'readonly', - requestAnimationFrame: 'readonly', - cancelAnimationFrame: 'readonly', - IntersectionObserver: 'readonly', - MutationObserver: 'readonly', - XMLHttpRequest: 'readonly', - location: 'readonly', - module: 'readonly', - require: 'readonly', - exports: 'readonly' - } - }, - rules: { - 'indent': [ - 'error', - 4, - { - 'ignoreComments': true - } - ], - 'linebreak-style': [ - 'error', - 'unix' - ], - 'quotes': [ - 'error', - 'single', - { - 'avoidEscape': true - } - ], - 'semi': [ - 'error', - 'always' - ], - 'no-console': [ - 'warn', - { - 'allow': ['warn', 'error'] - } - ], - 'no-empty': [ - 'error', - { - 'allowEmptyCatch': true - } - ] - } - } -]; diff --git a/oxfmt.config.ts b/oxfmt.config.ts new file mode 100644 index 0000000..ea7dff0 --- /dev/null +++ b/oxfmt.config.ts @@ -0,0 +1,10 @@ +import { defineConfig } from 'oxfmt'; + +export default defineConfig({ + useTabs: true, + tabWidth: 4, + singleQuote: true, + trailingComma: 'none', + sortPackageJson: false, + ignorePatterns: ['dist/**', 'demo/**', '**/*.md'] +}); diff --git a/oxlint.config.ts b/oxlint.config.ts new file mode 100644 index 0000000..876b97e --- /dev/null +++ b/oxlint.config.ts @@ -0,0 +1,22 @@ +import { defineConfig } from 'oxlint'; + +export default defineConfig({ + env: { + browser: true + }, + categories: { + correctness: 'error' + }, + rules: { + 'no-console': ['warn', { allow: ['warn', 'error'] }], + 'no-empty': ['error', { allowEmptyCatch: true }], + 'typescript/no-explicit-any': 'off' + }, + ignorePatterns: ['dist', 'demo', 'test-results', 'playwright-report'], + overrides: [ + { + files: ['scripts/**'], + env: { node: true, browser: false } + } + ] +}); diff --git a/package.json b/package.json index d44de9f..94e9987 100644 --- a/package.json +++ b/package.json @@ -1,40 +1,69 @@ { - "name": "@iframely/embed.js", - "version": "1.11.0", - "description": "Iframely embeds cloud JavaScript library, helps with rich media embed codes rendering for Iframely hosted iFrames. Library functions include unfurling URLs, lazy-loading, and rich-media events handling.", - "keywords": [ - "iframely", - "embed", - "embedjs", - "embed.js", - "iframe", - "oembed" - ], - "homepage": "http://iframely.com", - "repository": { - "type": "git", - "url": "https://github.com/itteco/embedjs.git" - }, - "bugs": { - "url": "https://github.com/itteco/embedjs/issues" - }, - "main": "src/index.js", - "scripts": { - "start": "webpack --env development --progress --watch", - "prebuild": "eslint ./src/**.js", - "build": "webpack --env production --progress", - "all": "webpack --env production && webpack --env development", - "lint": "eslint ./src/**.js" - }, - "devDependencies": { - "ejs-loader": "^0.5.0", - "eslint": "^10.0.0", - "eslint-webpack-plugin": "^5.0.1", - "webpack": "^5.90.0", - "webpack-cli": "^5.1.4", - "webpack-merge": "^6.0.1", - "ejs": "^5.0.1" - }, - "license": "MIT", - "dependencies": {} + "name": "@iframely/embed.js", + "version": "2.0.0", + "description": "Iframely embeds cloud JavaScript library, helps with rich media embed codes rendering for Iframely hosted iFrames. Library functions include unfurling URLs, lazy-loading, and rich-media events handling.", + "keywords": [ + "iframely", + "embed", + "embedjs", + "embed.js", + "iframe", + "oembed" + ], + "homepage": "http://iframely.com", + "repository": { + "type": "git", + "url": "https://github.com/itteco/embedjs.git" + }, + "bugs": { + "url": "https://github.com/itteco/embedjs/issues" + }, + "type": "module", + "main": "./dist/esm/main.js", + "types": "./dist/types/main.d.ts", + "exports": { + ".": { + "types": "./dist/types/main.d.ts", + "import": "./dist/esm/main.js" + }, + "./options": { + "types": "./dist/types/main-options.d.ts", + "import": "./dist/esm/main-options.js" + }, + "./i18n/de": { + "types": "./dist/types/options/lang/labels.de.d.ts", + "import": "./dist/esm/i18n.de.js" + }, + "./i18n/fr": { + "types": "./dist/types/options/lang/labels.fr.d.ts", + "import": "./dist/esm/i18n.fr.js" + } + }, + "files": [ + "dist", + "src" + ], + "scripts": { + "dev": "vite", + "serve": "node scripts/serve.mjs", + "typecheck": "tsc -p tsconfig.json", + "lint": "oxlint", + "format": "oxfmt", + "format:check": "oxfmt --check", + "test": "vitest run", + "test:watch": "vitest", + "test:e2e": "node scripts/build.js && playwright test", + "prebuild": "pnpm typecheck && pnpm lint && pnpm format:check", + "build": "node scripts/build.js && tsc -p tsconfig.build.json" + }, + "devDependencies": { + "@playwright/test": "^1.61.1", + "jsdom": "^29.1.1", + "oxfmt": "^0.58.0", + "oxlint": "^1.73.0", + "typescript": "~7.0.2", + "vite": "^8.1.4", + "vitest": "^4.1.10" + }, + "license": "MIT" } diff --git a/playwright.config.ts b/playwright.config.ts new file mode 100644 index 0000000..c5f5602 --- /dev/null +++ b/playwright.config.ts @@ -0,0 +1,29 @@ +import { defineConfig, devices } from '@playwright/test'; + +// Fixture pages in demo/ reference http://localhost:8917 with absolute URLs +// because the library's SCRIPT_RE self-configuration only matches absolute +// script src values. Keep the port in sync with scripts/serve.mjs. +const BASE_URL = 'http://localhost:8917'; + +export default defineConfig({ + testDir: 'tests/e2e', + fullyParallel: true, + reporter: [['list']], + use: { + baseURL: BASE_URL + }, + projects: [ + { + name: 'chromium', + use: { ...devices['Desktop Chrome'] } + } + ], + webServer: { + command: 'node scripts/serve.mjs', + url: BASE_URL + '/demo/index.html', + // Tests assert against the TEST placeholder key, so never reuse a + // dev server that may be running with a real key from .env. + reuseExistingServer: false, + env: { IFRAMELY_API_KEY: 'TEST' } + } +}); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 62d73f6..65875b1 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -8,87 +8,102 @@ importers: .: devDependencies: - ejs: - specifier: ^5.0.1 - version: 5.0.1 - ejs-loader: - specifier: ^0.5.0 - version: 0.5.0 - eslint: - specifier: ^10.0.0 - version: 10.0.3 - eslint-webpack-plugin: - specifier: ^5.0.1 - version: 5.0.3(eslint@10.0.3)(webpack@5.105.4) - webpack: - specifier: ^5.90.0 - version: 5.105.4(webpack-cli@5.1.4) - webpack-cli: - specifier: ^5.1.4 - version: 5.1.4(webpack@5.105.4) - webpack-merge: - specifier: ^6.0.1 - version: 6.0.1 + '@playwright/test': + specifier: ^1.61.1 + version: 1.61.1 + jsdom: + specifier: ^29.1.1 + version: 29.1.1 + oxfmt: + specifier: ^0.58.0 + version: 0.58.0 + oxlint: + specifier: ^1.73.0 + version: 1.73.0 + typescript: + specifier: ~7.0.2 + version: 7.0.2 + vite: + specifier: ^8.1.4 + version: 8.1.4(@types/node@25.5.0)(terser@5.46.0) + vitest: + specifier: ^4.1.10 + version: 4.1.10(@types/node@25.5.0)(jsdom@29.1.1)(vite@8.1.4(@types/node@25.5.0)(terser@5.46.0)) packages: - '@discoveryjs/json-ext@0.5.7': - resolution: {integrity: sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==} - engines: {node: '>=10.0.0'} + '@asamuzakjp/css-color@5.1.11': + resolution: {integrity: sha512-KVw6qIiCTUQhByfTd78h2yD1/00waTmm9uy/R7Ck/ctUyAPj+AEDLkQIdJW0T8+qGgj3j5bpNKK7Q3G+LedJWg==} + engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} - '@eslint-community/eslint-utils@4.9.1': - resolution: {integrity: sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - peerDependencies: - eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 + '@asamuzakjp/dom-selector@7.1.1': + resolution: {integrity: sha512-67RZDnYRc8H/8MLDgQCDE//zoqVFwajkepHZgmXrbwybzXOEwOWGPYGmALYl9J2DOLfFPPs6kKCqmbzV895hTQ==} + engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} - '@eslint-community/regexpp@4.12.2': - resolution: {integrity: sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==} - engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} + '@asamuzakjp/generational-cache@1.0.1': + resolution: {integrity: sha512-wajfB8KqzMCN2KGNFdLkReeHncd0AslUSrvHVvvYWuU8ghncRJoA50kT3zP9MVL0+9g4/67H+cdvBskj9THPzg==} + engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} - '@eslint/config-array@0.23.3': - resolution: {integrity: sha512-j+eEWmB6YYLwcNOdlwQ6L2OsptI/LO6lNBuLIqe5R7RetD658HLoF+Mn7LzYmAWWNNzdC6cqP+L6r8ujeYXWLw==} - engines: {node: ^20.19.0 || ^22.13.0 || >=24} + '@asamuzakjp/nwsapi@2.3.9': + resolution: {integrity: sha512-n8GuYSrI9bF7FFZ/SjhwevlHc8xaVlb/7HmHelnc/PZXBD2ZR49NnN9sMMuDdEGPeeRQ5d0hqlSlEpgCX3Wl0Q==} - '@eslint/config-helpers@0.5.3': - resolution: {integrity: sha512-lzGN0onllOZCGroKJmRwY6QcEHxbjBw1gwB8SgRSqK8YbbtEXMvKynsXc3553ckIEBxsbMBU7oOZXKIPGZNeZw==} - engines: {node: ^20.19.0 || ^22.13.0 || >=24} + '@bramus/specificity@2.4.2': + resolution: {integrity: sha512-ctxtJ/eA+t+6q2++vj5j7FYX3nRu311q1wfYH3xjlLOsczhlhxAg2FWNUXhpGvAw3BWo1xBcvOV6/YLc2r5FJw==} + hasBin: true - '@eslint/core@1.1.1': - resolution: {integrity: sha512-QUPblTtE51/7/Zhfv8BDwO0qkkzQL7P/aWWbqcf4xWLEYn1oKjdO0gglQBB4GAsu7u6wjijbCmzsUTy6mnk6oQ==} - engines: {node: ^20.19.0 || ^22.13.0 || >=24} + '@csstools/color-helpers@6.1.0': + resolution: {integrity: sha512-064IFJdjTfUqnjpCVpMOdbr8FLQBhinbZj6yRv2An2E41O/pLEXqfFRWqGq/SxlE5PEUYTlvWsG2r8MswAVvkg==} + engines: {node: '>=20.19.0'} - '@eslint/object-schema@3.0.3': - resolution: {integrity: sha512-iM869Pugn9Nsxbh/YHRqYiqd23AmIbxJOcpUMOuWCVNdoQJ5ZtwL6h3t0bcZzJUlC3Dq9jCFCESBZnX0GTv7iQ==} - engines: {node: ^20.19.0 || ^22.13.0 || >=24} + '@csstools/css-calc@3.2.1': + resolution: {integrity: sha512-DtdHlgXh5ZkA43cwBcAm+huzgJiwx3ZTWVjBs94kwz2xKqSimDA3lBgCjphYgwgVUMWatSM0pDd8TILB1yrVVg==} + engines: {node: '>=20.19.0'} + peerDependencies: + '@csstools/css-parser-algorithms': ^4.0.0 + '@csstools/css-tokenizer': ^4.0.0 - '@eslint/plugin-kit@0.6.1': - resolution: {integrity: sha512-iH1B076HoAshH1mLpHMgwdGeTs0CYwL0SPMkGuSebZrwBp16v415e9NZXg2jtrqPVQjf6IANe2Vtlr5KswtcZQ==} - engines: {node: ^20.19.0 || ^22.13.0 || >=24} + '@csstools/css-color-parser@4.1.9': + resolution: {integrity: sha512-paQcIaOO53Rk5+YrBaBjm/SgrV4INImjo2BT1DtQRYr+XeTRbeAYlS+jxXp9drqvKmtFnWRJKIalDLhZZDu42A==} + engines: {node: '>=20.19.0'} + peerDependencies: + '@csstools/css-parser-algorithms': ^4.0.0 + '@csstools/css-tokenizer': ^4.0.0 - '@humanfs/core@0.19.1': - resolution: {integrity: sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==} - engines: {node: '>=18.18.0'} + '@csstools/css-parser-algorithms@4.0.0': + resolution: {integrity: sha512-+B87qS7fIG3L5h3qwJ/IFbjoVoOe/bpOdh9hAjXbvx0o8ImEmUsGXN0inFOnk2ChCFgqkkGFQ+TpM5rbhkKe4w==} + engines: {node: '>=20.19.0'} + peerDependencies: + '@csstools/css-tokenizer': ^4.0.0 + + '@csstools/css-syntax-patches-for-csstree@1.1.6': + resolution: {integrity: sha512-TcJCWFbXLPpJYq6z7bfOyjWYJDiDg2/I4gyUC9pqPNqHFRIey0EB0q0L5cSnQDfWJg8Jd6VadakxdIez/3zkqQ==} + peerDependencies: + css-tree: ^3.2.1 + peerDependenciesMeta: + css-tree: + optional: true - '@humanfs/node@0.16.7': - resolution: {integrity: sha512-/zUx+yOsIrG4Y43Eh2peDeKCxlRt/gET6aHfaKpuq267qXdYDFViVHfMaLyygZOnl0kGWxFIgsBy8QFuTLUXEQ==} - engines: {node: '>=18.18.0'} + '@csstools/css-tokenizer@4.0.0': + resolution: {integrity: sha512-QxULHAm7cNu72w97JUNCBFODFaXpbDg+dP8b/oWFAZ2MTRppA3U00Y2L1HqaS4J6yBqxwa/Y3nMBaxVKbB/NsA==} + engines: {node: '>=20.19.0'} - '@humanwhocodes/module-importer@1.0.1': - resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} - engines: {node: '>=12.22'} + '@emnapi/core@1.11.1': + resolution: {integrity: sha512-RSvbQmHzdKzNsLYa/wHrbc3KN4sYLKAdPZxqiM2HATqv/SBk2/ENSHpvXGaLOMcsAyz0poEGqkmmKYG3OWiJEQ==} - '@humanwhocodes/retry@0.4.3': - resolution: {integrity: sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==} - engines: {node: '>=18.18'} + '@emnapi/runtime@1.11.1': + resolution: {integrity: sha512-vgj7R3y3Wgx24IQaGPA/R6YFXLHVMOZ0uVEyIQPaWs+rd1AzfEMXlAC22FYwO1XkKR6NPsq7mUandH8oIRdZFw==} - '@jest/schemas@29.6.3': - resolution: {integrity: sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + '@emnapi/wasi-threads@1.2.2': + resolution: {integrity: sha512-c95qOXkHdydNKhscBTebqEC1CVAZpyqOfVfBzQ1qgzyl3gfeldUjIggDbIZgDKsHLgnsM+igH7TJ/eAasaVuMA==} - '@jest/types@29.6.3': - resolution: {integrity: sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + '@exodus/bytes@1.15.1': + resolution: {integrity: sha512-S6mL0yNB/Abt9Ei4tq8gDhcczc4S3+vQ4ra7vxnAf+YHC02srtqxKKZghx2Dq6p0e66THKwR6r8N6P95wEty7Q==} + engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} + peerDependencies: + '@noble/hashes': ^1.8.0 || ^2.0.0 + peerDependenciesMeta: + '@noble/hashes': + optional: true '@jridgewell/gen-mapping@0.3.13': resolution: {integrity: sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==} @@ -106,628 +121,787 @@ packages: '@jridgewell/trace-mapping@0.3.31': resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==} - '@sinclair/typebox@0.27.10': - resolution: {integrity: sha512-MTBk/3jGLNB2tVxv6uLlFh1iu64iYOQ2PbdOSK3NW8JZsmlaOh2q6sdtKowBhfw8QFLmYNzTW4/oK4uATIi6ZA==} - - '@types/eslint-scope@3.7.7': - resolution: {integrity: sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==} - - '@types/eslint@9.6.1': - resolution: {integrity: sha512-FXx2pKgId/WyYo2jXw63kk7/+TY7u7AziEJxJAnSFzHlqTAS3Ync6SvgYAN/k4/PQpnnVuzoMuVnByKK2qp0ag==} + '@napi-rs/wasm-runtime@1.1.6': + resolution: {integrity: sha512-ZLv/JdUfkvOy9eCnnBaGfiO+XimbjebAeO+MRQqD/B+FR1tnRN0tpKSJHRbE8sFfS6aqsXZ67TQjfwfsxULVbg==} + peerDependencies: + '@emnapi/core': ^1.7.1 + '@emnapi/runtime': ^1.7.1 + + '@oxc-project/types@0.139.0': + resolution: {integrity: sha512-r9gHphtCs+1M7J0pw6Sn/hh/Wpa/iQrOOkrNAlVLF/gHq+/CJmHIWKKUUhdWjcD6CIa8idarspCsASiXCXvFUw==} + + '@oxfmt/binding-android-arm-eabi@0.58.0': + resolution: {integrity: sha512-Uz62sHduGGPftXtILGyxdSW4PX82rUg+rfdNqhsgxe881g4rIoXlIqmZQ6HVKcF4f+F8qMhdD03Bx5u7gmeTdg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm] + os: [android] + + '@oxfmt/binding-android-arm64@0.58.0': + resolution: {integrity: sha512-rD0lRaJp1b+9vw6X4A2dJWKukd6X8yxiicN4JxXcXayolmUypRZxk+lKR+fVOu5q/iYc0fh5fR4bgmfOfVlbaA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [android] + + '@oxfmt/binding-darwin-arm64@0.58.0': + resolution: {integrity: sha512-uzbPPk7O6M+w2K65vcQ1woga3wgP8zghjL1KOG5b6qJ8dvYHZJ1VShaslg2KOK6yQIwCQtcMCXqLBM6sqXUNTg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [darwin] + + '@oxfmt/binding-darwin-x64@0.58.0': + resolution: {integrity: sha512-L0nKYDxU32oxeQqJj21W9SlIMnf81VZEhyah6iDvFhf5q0oynq498Fopth7blErUJVBpVtxQ98RMCfMPqpJX6w==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [darwin] + + '@oxfmt/binding-freebsd-x64@0.58.0': + resolution: {integrity: sha512-woNwfD58dC5PGS9LSLSD5JYfo/EFK5iG9vhDWkcCg3q78ag7KC8bpDqgvPHrMoXpx83OLXxoSOhu6z8FsVTHlg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [freebsd] + + '@oxfmt/binding-linux-arm-gnueabihf@0.58.0': + resolution: {integrity: sha512-Sqs8nMLxuQpY21NKJ1u4stPDmO5hskBCNNh2E3AdCfI1QqWtf4m+Qn4mGEIUO4KGmuq3SWc/SZ80uy5IiwTCDw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm] + os: [linux] + + '@oxfmt/binding-linux-arm-musleabihf@0.58.0': + resolution: {integrity: sha512-Vd4exzBI5B5hB9m22JiTQzIL23WvHo/Pe+sNXPNeBLXSP9swCBPKCEBRwKpmpQzYhlgYaCgfPcGXPKAJBRIiZQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm] + os: [linux] + + '@oxfmt/binding-linux-arm64-gnu@0.58.0': + resolution: {integrity: sha512-bUWi5mHV+4Vi56RLHE1h6q/HHfwAIT3XoB9vJAVeRzfu5NriXM8y6eeJu0vlKa0C9kq2rq1sOWRClhdLHPocrg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [linux] + libc: [glibc] + + '@oxfmt/binding-linux-arm64-musl@0.58.0': + resolution: {integrity: sha512-2ZHxemzgHcjtktAuVUwSoyXmGo/t+aF5tS1ciPpPei4rhSyrz3JOqDosXXrmhN/yLUSzJjtuW7ToTWqfQpCj2w==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [linux] + libc: [musl] + + '@oxfmt/binding-linux-ppc64-gnu@0.58.0': + resolution: {integrity: sha512-AwKkVwjVmFQ3bcO7j0McGYAqCKH2a326fswfofng/E8VewCT/raeeGQr4huVhY704deK8AWASSTlxzMj0eZc6Q==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [ppc64] + os: [linux] + libc: [glibc] + + '@oxfmt/binding-linux-riscv64-gnu@0.58.0': + resolution: {integrity: sha512-xsRpTxfUnJF8D3AUKko/qyWdjw4GZVHlCVFuGlzSCTeewLmykKINW8em1+wx+axsDVtJJcMtvsiaXggXxrlHgw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [riscv64] + os: [linux] + libc: [glibc] + + '@oxfmt/binding-linux-riscv64-musl@0.58.0': + resolution: {integrity: sha512-Z4AYOTcy7nYEIiXwD62PlerimyYRcfJOgUbQAEBjXz098kxKuERBlRntofGy69HHhe9E0TLVNMl1yspVNu+efw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [riscv64] + os: [linux] + libc: [musl] + + '@oxfmt/binding-linux-s390x-gnu@0.58.0': + resolution: {integrity: sha512-A3nhhtZPC/TKVWOPj9q/H3p2znJDCcHWYlJBhWL8hGq/bFmBaNBHC8Np6E581yVq1w9Mi3rMDNzDalWvtUfJtQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [s390x] + os: [linux] + libc: [glibc] + + '@oxfmt/binding-linux-x64-gnu@0.58.0': + resolution: {integrity: sha512-2g+tVkgwqphw8R4hgo+kF4oz8+P5RwVOtr9+irsC7uwEp0e9j7Crw8kDGKL20uYlLPD7g02DqA61mC/UNYx98A==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [linux] + libc: [glibc] + + '@oxfmt/binding-linux-x64-musl@0.58.0': + resolution: {integrity: sha512-rc15P6AbyyB7426aN8AakLd02Trb3a6ML/mmfAQeVHJEfVofWLcWIrBdy6zDEY+DIaL/s8E4GGPboVw+oP3+EA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [linux] + libc: [musl] + + '@oxfmt/binding-openharmony-arm64@0.58.0': + resolution: {integrity: sha512-ZWoTM27/HYPOh9iq86DAbhPu9nXb8qKvvGU/h8OfliyVUFAMMNTLDkGsWDKKnDqIkqvZ9+dXlgUOsH1LYO3O7g==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [openharmony] + + '@oxfmt/binding-win32-arm64-msvc@0.58.0': + resolution: {integrity: sha512-LHZnqFXe2dEfkRI4XdZS/57nEOT/I4UCRX5IyM9v4GYW9XwQCjGe1IUK59SuKw3POwvcgWQ4pme2cYXmNqTNPg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [win32] + + '@oxfmt/binding-win32-ia32-msvc@0.58.0': + resolution: {integrity: sha512-mZKpg20TpheCJym1rarcZCUJeW1sSruw8zAAaCYWvuVfwIUDN1CXdrPU/JgCWReXTCTrEfCB8Wyo3hh9jSZ2EA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [ia32] + os: [win32] + + '@oxfmt/binding-win32-x64-msvc@0.58.0': + resolution: {integrity: sha512-N/wUU4N5PZ2orBtI+Ko7MnMfYLfE7K91UrGMY/c/pYyHR3lA9kwst1XugkZx+92YcRh/Eo+iv2eTESSWXfiZPA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [win32] + + '@oxlint/binding-android-arm-eabi@1.73.0': + resolution: {integrity: sha512-HZQRN/UMBu+Ut+/9MiAChkbP4qZqrNOWBcNI45vOT40GVhbGR0JgHB87L48D4iAqFQIdVmeQYtV9RF89AjTKkg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm] + os: [android] + + '@oxlint/binding-android-arm64@1.73.0': + resolution: {integrity: sha512-Gp+KJRylv2aW7thRpG5p1KTxZq4ZJFbWowrKzufNq9d3ssl3r3JviYV45/+p+7CN1Nv0zDd1e8Ex0b/HUDq4TQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [android] + + '@oxlint/binding-darwin-arm64@1.73.0': + resolution: {integrity: sha512-3de96NdtXhxERMjIz7wsp2HYMY6pMQycGxFWac2mFecAx6VeARF/IqFb1QIaqiCRIdfzBwzTed+pCTCoiS+CYA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [darwin] + + '@oxlint/binding-darwin-x64@1.73.0': + resolution: {integrity: sha512-5zx/uPW32TiaOeVY1dQ/H5iOf0K1HOdFKOJhLqGl4o63+i1fpzoqqu/mKtd7OFgFjNCdhlyTGgjVkQTZm1ELcg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [darwin] + + '@oxlint/binding-freebsd-x64@1.73.0': + resolution: {integrity: sha512-qNe4gKHaGnLuZJ8toUg90JAa0S2vTVvDw+0bRi3q1avXZXDT4u5mMeECf3nD4HYrbdn1O7dXqWut4onY/yx/Xg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [freebsd] + + '@oxlint/binding-linux-arm-gnueabihf@1.73.0': + resolution: {integrity: sha512-cCehYh5hTbfShm/fxTD6wwrGUWIpvX+N5OxmAMhFhDeTGXvw+BeNj889tpxsFQ9ZLatQ6wImuY8tsKLZ+FMz7w==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm] + os: [linux] + + '@oxlint/binding-linux-arm-musleabihf@1.73.0': + resolution: {integrity: sha512-d5j5GDU/2dMgjVhw7TQT9ITrsIr1Y02KEXKyVGIXUkD+KiaxE9TP65FS2ZdgTBemQvoRL+gSBdbrIm3cQIeacg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm] + os: [linux] + + '@oxlint/binding-linux-arm64-gnu@1.73.0': + resolution: {integrity: sha512-Eyf1SrP3+yR1DI3OJgOY2Pvrr9dWP9TK37xPaDYycwTtlGlI45erJAVIfH5/m/xosDt6BupJYEFi47bvbTuuyw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [linux] + libc: [glibc] + + '@oxlint/binding-linux-arm64-musl@1.73.0': + resolution: {integrity: sha512-IlT/OJApEDKaMmCooHuncgJZbbCe7T5QIWmTZBEtYscWvzPQuuEinVcid6kwQRVQOUdb7PUCz4jQHnaYXdfJXw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [linux] + libc: [musl] + + '@oxlint/binding-linux-ppc64-gnu@1.73.0': + resolution: {integrity: sha512-L+JYcb/vdg5fmcH08V6o0YYLU28cTH1SPNulwJdvK9NK49aXSkYy6oNpKBmddArVOXYqNepriDGiZ04G54kh1Q==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [ppc64] + os: [linux] + libc: [glibc] + + '@oxlint/binding-linux-riscv64-gnu@1.73.0': + resolution: {integrity: sha512-Qtk0g3bKV6OwWjIm7R8kQN1uOZRKQt/MODK2a8QfkwhTpXBD53ozx5XLVWLGDQAVyp2otLW4D2wB98XfAfMPGA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [riscv64] + os: [linux] + libc: [glibc] + + '@oxlint/binding-linux-riscv64-musl@1.73.0': + resolution: {integrity: sha512-wX0NQKZVxltkAOVmzFcpOaMpdaUvsq1Eqpx9tkAfl71UdkTlSo1R4AdAnGccR1Fm2+TzFgZ22CyyGuZ41RDr/A==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [riscv64] + os: [linux] + libc: [musl] + + '@oxlint/binding-linux-s390x-gnu@1.73.0': + resolution: {integrity: sha512-vPe7UGBMWyiLTtnqS4xxgMQFSFGmtQwhwCxuiw6lXygaO6bVt0D8dFVg8Xv05eaiN3ybC0HXXHUAohFMFvqoCQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [s390x] + os: [linux] + libc: [glibc] + + '@oxlint/binding-linux-x64-gnu@1.73.0': + resolution: {integrity: sha512-2CwIWr9cemFC/CbRBWZvuk5mffz6ObmfFkfcC/9rTQ7f+icNhYr2kOjf9Rt8lLvugvkdGDOmkoVoFFHh6ClCTw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [linux] + libc: [glibc] + + '@oxlint/binding-linux-x64-musl@1.73.0': + resolution: {integrity: sha512-nDadfJgg7NBBxG0N560wOe7LLX5QiYp6qBaI7viuk5EUORFBktU/NfV0MbTqU3gTqQDCh4VyxKdo5VADxk9w8Q==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [linux] + libc: [musl] + + '@oxlint/binding-openharmony-arm64@1.73.0': + resolution: {integrity: sha512-wGjJC+NLH9xP+IKGn9RDW94ojJR/wPbg5WCnQjj/oReaOtCQthr8ws1zICe77JFmo4ouUdeTHHZL/ESGiF6Pmw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [openharmony] + + '@oxlint/binding-win32-arm64-msvc@1.73.0': + resolution: {integrity: sha512-I7X47GPGljw225YUQ5SbC/rb1Kkdrd0yQf0x+hYxeKS6DpfjMbo9ccQPQ6LNY6BoJQ1sHhgDUGuMn5Vg5gHT6w==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [win32] + + '@oxlint/binding-win32-ia32-msvc@1.73.0': + resolution: {integrity: sha512-5lWj+3h+74Fm1jYOO9qkJA4xkAlZA099DkXppuXsk7UpnpZLttsefrZU469vChGaG6hcSqrkKXQOvMTZtbjeNg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [ia32] + os: [win32] + + '@oxlint/binding-win32-x64-msvc@1.73.0': + resolution: {integrity: sha512-WaNRvh4f6zY9CvUQk2YoA1O90ieWrIklI84+HXFr9Isjz9CSESrdqo/RtIYt4Dll/cAchqGDMehfaZd0vqEFZw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [win32] + + '@playwright/test@1.61.1': + resolution: {integrity: sha512-8nKv6+0RJSL9FE4jYOEGXnPeM/Hg12qZpmqzZjRh3qM0Y7c3z1mrOTfFLids72RDQYVh9WpLEfR5WdpNX4fkig==} + engines: {node: '>=18'} + hasBin: true - '@types/esrecurse@4.3.1': - resolution: {integrity: sha512-xJBAbDifo5hpffDBuHl0Y8ywswbiAp/Wi7Y/GtAgSlZyIABppyurxVueOPE8LUQOxdlgi6Zqce7uoEpqNTeiUw==} + '@rolldown/binding-android-arm64@1.1.5': + resolution: {integrity: sha512-lZg8fqIv2v7FF237bwMgzGZEJvGL79/s5knJ/i6FmsGF4XXlzccZ4jb+TrFIxtSSxFtIpdsgrPZeMk1I9AFcyQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [android] + + '@rolldown/binding-darwin-arm64@1.1.5': + resolution: {integrity: sha512-51Bnx9pNiMRKSUNtBfySkNJ9vMU9Hh3I1ozDd6gyPPYzaXCfnptUcEZxXGYFn+ul2dtcMUiqGR1Yai2K10uoTw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [darwin] + + '@rolldown/binding-darwin-x64@1.1.5': + resolution: {integrity: sha512-Tm+gbfC0aHu1tBA/JvKQh32S0K6YgCHkiAF4/W6xX0K0RmNuc94VeK419dJoE65R5aRxmo+noZQSWrAMF6yb6g==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [darwin] + + '@rolldown/binding-freebsd-x64@1.1.5': + resolution: {integrity: sha512-JMzDKCCXq93YccG5gz3hvOs1oXRKAf0XYpfOS88e+wZrC8Iugj6j68867vrYZkvpDDpKn/KoKORThmchMpF6TA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [freebsd] + + '@rolldown/binding-linux-arm-gnueabihf@1.1.5': + resolution: {integrity: sha512-uML21j2K5TfPGutKxub+M+nLjZIrWjXQ5Grx4lCe/nimTj9B4L63zHpjXLl4y0L3mcm2htEQIb06oCG/szerNw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm] + os: [linux] + + '@rolldown/binding-linux-arm64-gnu@1.1.5': + resolution: {integrity: sha512-navSiuTMogvnQoZoM/v+l3ZWo50/NTwSHSzheABx/RCnmUPaKwq9qSo4Br2OYRs21+Fz8uFqITZM3H4opOB0/Q==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [linux] + libc: [glibc] + + '@rolldown/binding-linux-arm64-musl@1.1.5': + resolution: {integrity: sha512-lAryqH7IteztmCXQXk0etKj4wBQ7Gx5S6LjKhsgp9zb8I5bsuvU/2llH1hDQcjsFeqIsovMVN339/8pUDDBXxA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [linux] + libc: [musl] + + '@rolldown/binding-linux-ppc64-gnu@1.1.5': + resolution: {integrity: sha512-fsK/sNBnxzBlL4O1JNrZakVQxPspqpED5dLtNsZS9oOKmtSpdNIzxH2kkol5HYTWJN47sE20ztMJPxfZ89qGOg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [ppc64] + os: [linux] + libc: [glibc] + + '@rolldown/binding-linux-s390x-gnu@1.1.5': + resolution: {integrity: sha512-gLYb4BIadlfTOYT5gO503n8zQjXflgzpD0FcyKh0Mzx3rqCZKnHoJWV9xe1KXUJ5lx2JfcSHr/mhzS0PC/McAA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [s390x] + os: [linux] + libc: [glibc] + + '@rolldown/binding-linux-x64-gnu@1.1.5': + resolution: {integrity: sha512-FjcpEKUyJygHgs1o50VYNvkt5+7Le/VEdYt0AkRpkL33MnyQfwr8l5mXwMmfmTbyMPr5vJLC+8/Gd9gXnwU1QQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [linux] + libc: [glibc] + + '@rolldown/binding-linux-x64-musl@1.1.5': + resolution: {integrity: sha512-Me+PfPI2TMeOQk0gYWfLQZtTktrmzbr8cDboqX83XKc7UrgAi55gF+2dUkWdxd19n55Essp2yeca+O9N5rBxHg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [linux] + libc: [musl] + + '@rolldown/binding-openharmony-arm64@1.1.5': + resolution: {integrity: sha512-yc5WrLzXks6zCQfn9Oxr8pORKyl/pF+QjHmW/Qx3qu0oyrrNC+y2JLTU1E2rcWYAmzlnqngWXHQjy51VzW70Vw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [openharmony] + + '@rolldown/binding-wasm32-wasi@1.1.5': + resolution: {integrity: sha512-VbQGPX2b4r48TAMIM2cjgluIM1HYutm4pcTEJsle7iEP7sB1dFqtPLBVbdLAZCxy1txCcPxf4QFf4v8uvltPqA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [wasm32] + + '@rolldown/binding-win32-arm64-msvc@1.1.5': + resolution: {integrity: sha512-gHv82k63z4qpV5+Q1y/12KrK0ltWBukVDI8nZcbT7Tt/ZlOIVwppazneq0F93oDxTo3IgAMEDIoQh3E2n6mVsw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [win32] + + '@rolldown/binding-win32-x64-msvc@1.1.5': + resolution: {integrity: sha512-tTZuDBPw85tEN5PQi1pnEBzDy0Z49HtScLAbD5t6hyeU92A95pRWaSMw1GZZi/RwgSgUIl0xrSlXIT/9QzvYSA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [win32] + + '@rolldown/pluginutils@1.0.1': + resolution: {integrity: sha512-2j9bGt5Jh8hj+vPtgzPtl72j0yRxHAyumoo6TNfAjsLB04UtpSvPbPcDcBMxz7n+9CYB0c1GxQFxYRg2jimqGw==} + + '@standard-schema/spec@1.1.0': + resolution: {integrity: sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==} + + '@tybys/wasm-util@0.10.3': + resolution: {integrity: sha512-F3fo1MYrRJYL3zER0OUOmkutjr1Vp23m7OsSgp7nq4SP6OqX6C/56XFIPAl5bt3zaBRjmW7SGz3u/6LwFpYcOg==} + + '@types/chai@5.2.3': + resolution: {integrity: sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==} + + '@types/deep-eql@4.0.2': + resolution: {integrity: sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==} '@types/estree@1.0.8': resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==} - '@types/istanbul-lib-coverage@2.0.6': - resolution: {integrity: sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==} - - '@types/istanbul-lib-report@3.0.3': - resolution: {integrity: sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==} - - '@types/istanbul-reports@3.0.4': - resolution: {integrity: sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==} - - '@types/json-schema@7.0.15': - resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} - '@types/node@25.5.0': resolution: {integrity: sha512-jp2P3tQMSxWugkCUKLRPVUpGaL5MVFwF8RDuSRztfwgN1wmqJeMSbKlnEtQqU8UrhTmzEmZdu2I6v2dpp7XIxw==} - '@types/yargs-parser@21.0.3': - resolution: {integrity: sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==} - - '@types/yargs@17.0.35': - resolution: {integrity: sha512-qUHkeCyQFxMXg79wQfTtfndEC+N9ZZg76HJftDJp+qH2tV7Gj4OJi7l+PiWwJ+pWtW8GwSmqsDj/oymhrTWXjg==} - - '@webassemblyjs/ast@1.14.1': - resolution: {integrity: sha512-nuBEDgQfm1ccRp/8bCQrx1frohyufl4JlbMMZ4P1wpeOfDhF6FQkxZJ1b/e+PLwr6X1Nhw6OLme5usuBWYBvuQ==} - - '@webassemblyjs/floating-point-hex-parser@1.13.2': - resolution: {integrity: sha512-6oXyTOzbKxGH4steLbLNOu71Oj+C8Lg34n6CqRvqfS2O71BxY6ByfMDRhBytzknj9yGUPVJ1qIKhRlAwO1AovA==} - - '@webassemblyjs/helper-api-error@1.13.2': - resolution: {integrity: sha512-U56GMYxy4ZQCbDZd6JuvvNV/WFildOjsaWD3Tzzvmw/mas3cXzRJPMjP83JqEsgSbyrmaGjBfDtV7KDXV9UzFQ==} - - '@webassemblyjs/helper-buffer@1.14.1': - resolution: {integrity: sha512-jyH7wtcHiKssDtFPRB+iQdxlDf96m0E39yb0k5uJVhFGleZFoNw1c4aeIcVUPPbXUVJ94wwnMOAqUHyzoEPVMA==} - - '@webassemblyjs/helper-numbers@1.13.2': - resolution: {integrity: sha512-FE8aCmS5Q6eQYcV3gI35O4J789wlQA+7JrqTTpJqn5emA4U2hvwJmvFRC0HODS+3Ye6WioDklgd6scJ3+PLnEA==} - - '@webassemblyjs/helper-wasm-bytecode@1.13.2': - resolution: {integrity: sha512-3QbLKy93F0EAIXLh0ogEVR6rOubA9AoZ+WRYhNbFyuB70j3dRdwH9g+qXhLAO0kiYGlg3TxDV+I4rQTr/YNXkA==} - - '@webassemblyjs/helper-wasm-section@1.14.1': - resolution: {integrity: sha512-ds5mXEqTJ6oxRoqjhWDU83OgzAYjwsCV8Lo/N+oRsNDmx/ZDpqalmrtgOMkHwxsG0iI//3BwWAErYRHtgn0dZw==} - - '@webassemblyjs/ieee754@1.13.2': - resolution: {integrity: sha512-4LtOzh58S/5lX4ITKxnAK2USuNEvpdVV9AlgGQb8rJDHaLeHciwG4zlGr0j/SNWlr7x3vO1lDEsuePvtcDNCkw==} - - '@webassemblyjs/leb128@1.13.2': - resolution: {integrity: sha512-Lde1oNoIdzVzdkNEAWZ1dZ5orIbff80YPdHx20mrHwHrVNNTjNr8E3xz9BdpcGqRQbAEa+fkrCb+fRFTl/6sQw==} - - '@webassemblyjs/utf8@1.13.2': - resolution: {integrity: sha512-3NQWGjKTASY1xV5m7Hr0iPeXD9+RDobLll3T9d2AO+g3my8xy5peVyjSag4I50mR1bBSN/Ct12lo+R9tJk0NZQ==} - - '@webassemblyjs/wasm-edit@1.14.1': - resolution: {integrity: sha512-RNJUIQH/J8iA/1NzlE4N7KtyZNHi3w7at7hDjvRNm5rcUXa00z1vRz3glZoULfJ5mpvYhLybmVcwcjGrC1pRrQ==} - - '@webassemblyjs/wasm-gen@1.14.1': - resolution: {integrity: sha512-AmomSIjP8ZbfGQhumkNvgC33AY7qtMCXnN6bL2u2Js4gVCg8fp735aEiMSBbDR7UQIj90n4wKAFUSEd0QN2Ukg==} - - '@webassemblyjs/wasm-opt@1.14.1': - resolution: {integrity: sha512-PTcKLUNvBqnY2U6E5bdOQcSM+oVP/PmrDY9NzowJjislEjwP/C4an2303MCVS2Mg9d3AJpIGdUFIQQWbPds0Sw==} - - '@webassemblyjs/wasm-parser@1.14.1': - resolution: {integrity: sha512-JLBl+KZ0R5qB7mCnud/yyX08jWFw5MsoalJ1pQ4EdFlgj9VdXKGuENGsiCIjegI1W7p91rUlcB/LB5yRJKNTcQ==} - - '@webassemblyjs/wast-printer@1.14.1': - resolution: {integrity: sha512-kPSSXE6De1XOR820C90RIo2ogvZG+c3KiHzqUoO/F34Y2shGzesfqv7o57xrxovZJH/MetF5UjroJ/R/3isoiw==} - - '@webpack-cli/configtest@2.1.1': - resolution: {integrity: sha512-wy0mglZpDSiSS0XHrVR+BAdId2+yxPSoJW8fsna3ZpYSlufjvxnP4YbKTCBZnNIcGN4r6ZPXV55X4mYExOfLmw==} - engines: {node: '>=14.15.0'} - peerDependencies: - webpack: 5.x.x - webpack-cli: 5.x.x - - '@webpack-cli/info@2.0.2': - resolution: {integrity: sha512-zLHQdI/Qs1UyT5UBdWNqsARasIA+AaF8t+4u2aS2nEpBQh2mWIVb8qAklq0eUENnC5mOItrIB4LiS9xMtph18A==} - engines: {node: '>=14.15.0'} - peerDependencies: - webpack: 5.x.x - webpack-cli: 5.x.x - - '@webpack-cli/serve@2.0.5': - resolution: {integrity: sha512-lqaoKnRYBdo1UgDX8uF24AfGMifWK19TxPmM5FHc2vAGxrJ/qtyUyFBWoY1tISZdelsQ5fBcOusifo5o5wSJxQ==} - engines: {node: '>=14.15.0'} + '@typescript/typescript-aix-ppc64@7.0.2': + resolution: {integrity: sha512-MTKKkWB7p/0E9xi1d1tHtZ5PiLkGEMIq88pK2CubZjOsLtYTLqhgIgi6zepFa+9GHZ6h05NMCkQxGKiPXMxXtQ==} + engines: {node: '>=16.20.0'} + cpu: [ppc64] + os: [aix] + + '@typescript/typescript-darwin-arm64@7.0.2': + resolution: {integrity: sha512-gowzar9MwS/aRWp6f3a4KUqzRjAZjOsmGNCM6LcTgXum+dBfgsBVMN+AgvOCCbguXyick6LJhpBszxMebJ8syA==} + engines: {node: '>=16.20.0'} + cpu: [arm64] + os: [darwin] + + '@typescript/typescript-darwin-x64@7.0.2': + resolution: {integrity: sha512-SZ9xZInqApNlNGc9s0W1VSsktYSOe9cFqNOIqmN1Gs8SmkjKZYFt017G4VwPxASInODuAdbTW7sXiFUf893RgA==} + engines: {node: '>=16.20.0'} + cpu: [x64] + os: [darwin] + + '@typescript/typescript-freebsd-arm64@7.0.2': + resolution: {integrity: sha512-W5NH4y/J0plIIS5b2xvTEkU7JFxyqdMAOgf+Ilhl0vHQXKO5dZoxd+C/jEtq56c4F3wk71RB4BMRQ2XdI+bwYQ==} + engines: {node: '>=16.20.0'} + cpu: [arm64] + os: [freebsd] + + '@typescript/typescript-freebsd-x64@7.0.2': + resolution: {integrity: sha512-UMGDx5sTpzNw3WiPebH7l90IWfJggEd+egHt/q6p7/Cm3zqoV7VxkGXt+3DxPIw8CcmvAB0j3sVVfbhX+M4Tpw==} + engines: {node: '>=16.20.0'} + cpu: [x64] + os: [freebsd] + + '@typescript/typescript-linux-arm64@7.0.2': + resolution: {integrity: sha512-Qh4eU4/y3yDjnfjjyPYihMj5/ODIlmt+Bzu17OI+fiSRDW57QmU5SiN63exPRNJPKUzcc1INa1NXdrJ+MqHjUQ==} + engines: {node: '>=16.20.0'} + cpu: [arm64] + os: [linux] + + '@typescript/typescript-linux-arm@7.0.2': + resolution: {integrity: sha512-gffT3xPz9sR7j/YJExkyPntrI0P2EP9XbOyWzth2/Gs0RstK+90RBcO0ncXoXy/beYll1SXw846Nf2zdnEz0QQ==} + engines: {node: '>=16.20.0'} + cpu: [arm] + os: [linux] + + '@typescript/typescript-linux-loong64@7.0.2': + resolution: {integrity: sha512-uEHck9i8hoAzXPiYRib1O7miOnz23SxIeVl6F4LXox+qov1K35jHcEW6VHKvZI+pyvl7fZEP4MCU5LYvIq1GuQ==} + engines: {node: '>=16.20.0'} + cpu: [loong64] + os: [linux] + + '@typescript/typescript-linux-mips64el@7.0.2': + resolution: {integrity: sha512-R4KvAMnE43W5Qeqb0Ly56O3mWMWIAgsMyz36DCaycd5nbg/9kzm0liw3JocfRqyJY0KPmzFjbswozXyW0DnIYA==} + engines: {node: '>=16.20.0'} + cpu: [mips64el] + os: [linux] + + '@typescript/typescript-linux-ppc64@7.0.2': + resolution: {integrity: sha512-DORx5b3sd/4S7eayxm4FQv+A7CrkUIGRaHiwI8oiHTAI1fAPWhF4J0vAlkC8biAlHSVVwxMQ3tjZ2/DVbnQiiA==} + engines: {node: '>=16.20.0'} + cpu: [ppc64] + os: [linux] + + '@typescript/typescript-linux-riscv64@7.0.2': + resolution: {integrity: sha512-wf0jqEDOjrPRnKwYRyyJDRo11KMbvMFrU+q4zqKyChODBzvlkbhNQfKvLxQCcwTpdDaXSHZTVuh0JoCrKCUMHQ==} + engines: {node: '>=16.20.0'} + cpu: [riscv64] + os: [linux] + + '@typescript/typescript-linux-s390x@7.0.2': + resolution: {integrity: sha512-IkwJc3L7yhytWd/ewjyxNDfOmswCm9GWMJT/ue/dU4aZNbwZeYAetq42VyLmsmSjvoX7z74X6ZaYCtzAr0EuGw==} + engines: {node: '>=16.20.0'} + cpu: [s390x] + os: [linux] + + '@typescript/typescript-linux-x64@7.0.2': + resolution: {integrity: sha512-EYdf2cNg7rgCWJnxCdJ+F3V39O8ihb37eHAu1LK8oAFizgTQbPOK7zHHXbPt8rX24COqODXeI3sIf0fCXG7H/A==} + engines: {node: '>=16.20.0'} + cpu: [x64] + os: [linux] + + '@typescript/typescript-netbsd-arm64@7.0.2': + resolution: {integrity: sha512-+polYF4MF04aPpO5FTkHran9yUQDSXqy5GiSDKpsll5jy3l3+g9QLhpf39T+ePtefhXLOGrLl0QIjkQP6VnelA==} + engines: {node: '>=16.20.0'} + cpu: [arm64] + os: [netbsd] + + '@typescript/typescript-netbsd-x64@7.0.2': + resolution: {integrity: sha512-8YIT0EHM/3dq10ZOVF/A7pc/YSMtbcecct4rWtexrnSCHOPcpC2KTLXfTCR6vDpnSiY12heNb1GiN/wu+T/FyA==} + engines: {node: '>=16.20.0'} + cpu: [x64] + os: [netbsd] + + '@typescript/typescript-openbsd-arm64@7.0.2': + resolution: {integrity: sha512-APT8+ClYnuYm1u9+kgGXoMj2VzWzcymwh2gNSQVySHfkRDGOTVkoWLjCmOQSaO+PoqQ57B0flRp9SA+7GnnkzQ==} + engines: {node: '>=16.20.0'} + cpu: [arm64] + os: [openbsd] + + '@typescript/typescript-openbsd-x64@7.0.2': + resolution: {integrity: sha512-yX7s+Q0Dln0Dt9tEzZsAjXXR/+ytBM7AlglaqyeMPxQszJ1JhlJdZ6jLA+IzldHtflX81em7lDao1xXu+aRRkg==} + engines: {node: '>=16.20.0'} + cpu: [x64] + os: [openbsd] + + '@typescript/typescript-sunos-x64@7.0.2': + resolution: {integrity: sha512-dLJDGaLZ1D4HPQn62u1n8mBDkJREwMsAkCdkwd4Ieqw+x3TUyTsqY0YiBCtE6H6OzzgGk3iuZ3vFWRS+E8/d1g==} + engines: {node: '>=16.20.0'} + cpu: [x64] + os: [sunos] + + '@typescript/typescript-win32-arm64@7.0.2': + resolution: {integrity: sha512-Gyl1Vy6OsWesLzmq+EP0Fb7b4Nid5232AvcA2SFcdYreldpNtYFFofPjnt62y9hQy7VTaZp65ICJjuAQRaVcIQ==} + engines: {node: '>=16.20.0'} + cpu: [arm64] + os: [win32] + + '@typescript/typescript-win32-x64@7.0.2': + resolution: {integrity: sha512-0BQ3HkAHHlKLSp1qRvf3SUhGpGsDuhB/jgFw75guyqbxJqEaS0Cw/VFO8i2nHglJUzQCRtMMR/IBAKE3ETMC4g==} + engines: {node: '>=16.20.0'} + cpu: [x64] + os: [win32] + + '@vitest/expect@4.1.10': + resolution: {integrity: sha512-YsCn+qAk1GWjQOWFEsEcL2gNQ0zmVmQu3T03qP6UyjhtmdtwtbuI+DASn/7iQB3HGTXkdBwGddzxPlmiql5vlA==} + + '@vitest/mocker@4.1.10': + resolution: {integrity: sha512-v0xaezt+DKEmKfaxg133ldzADrwLGd7Ze1MfQQTYfvs8OqZIwbxyxaYURivwV7sWy5fqn3rH5uOrSp07bp44Ow==} peerDependencies: - webpack: 5.x.x - webpack-cli: 5.x.x - webpack-dev-server: '*' + msw: ^2.4.9 + vite: ^6.0.0 || ^7.0.0 || ^8.0.0 peerDependenciesMeta: - webpack-dev-server: + msw: + optional: true + vite: optional: true - '@xtuc/ieee754@1.2.0': - resolution: {integrity: sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==} + '@vitest/pretty-format@4.1.10': + resolution: {integrity: sha512-W1HsjSH4MXQ9YfmmhLAoIYf1HRfekQCGngeIgcei6MP5QQGWUe0gkopdZQaVCFO+JDJMrAJGwa5pRpNpvy4P8Q==} - '@xtuc/long@4.2.2': - resolution: {integrity: sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==} + '@vitest/runner@4.1.10': + resolution: {integrity: sha512-IKI6kpIH+LmpROplyLwBBaCfMgOZOMsygVa6BARD6ahA04VRuJSa6OaVG7kRvSEMD870Vd91rSSw0eegtWyLGg==} - acorn-import-phases@1.0.4: - resolution: {integrity: sha512-wKmbr/DDiIXzEOiWrTTUcDm24kQ2vGfZQvM2fwg2vXqR5uW6aapr7ObPtj1th32b9u90/Pf4AItvdTh42fBmVQ==} - engines: {node: '>=10.13.0'} - peerDependencies: - acorn: ^8.14.0 + '@vitest/snapshot@4.1.10': + resolution: {integrity: sha512-xRkfOT1qpTAi/Ti4Y1LtfRc3kEuqxGw59eN2jN9pRWMtS/XDevekhcFSqvQqjUNGksfjMJu3Y+oJ+4Ypn2OaJw==} - acorn-jsx@5.3.2: - resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} - peerDependencies: - acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 + '@vitest/spy@4.1.10': + resolution: {integrity: sha512-PLf/Ugvoq5wO/b4rwYCR1h2PSIdXz7wnkQFMiUpLdtM7l6pqVFcQIBEHyT1+l+cj7mNwAfZHzqXqDyjvOuwbDw==} + + '@vitest/utils@4.1.10': + resolution: {integrity: sha512-fy9am/HWxbaGt/Sawrp90vt6Y6jQwf1RX77cz3uwoJwJVMli/e1IEwRPnMNJ7vKfPTwo0diXifkpPvwH9v7nGA==} acorn@8.16.0: resolution: {integrity: sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==} engines: {node: '>=0.4.0'} hasBin: true - ajv-formats@2.1.1: - resolution: {integrity: sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==} - peerDependencies: - ajv: ^8.0.0 - peerDependenciesMeta: - ajv: - optional: true - - ajv-keywords@5.1.0: - resolution: {integrity: sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==} - peerDependencies: - ajv: ^8.8.2 - - ajv@6.14.0: - resolution: {integrity: sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw==} - - ajv@8.18.0: - resolution: {integrity: sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==} - - ansi-styles@4.3.0: - resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} - engines: {node: '>=8'} - - balanced-match@4.0.4: - resolution: {integrity: sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==} - engines: {node: 18 || 20 || >=22} - - baseline-browser-mapping@2.10.7: - resolution: {integrity: sha512-1ghYO3HnxGec0TCGBXiDLVns4eCSx4zJpxnHrlqFQajmhfKMQBzUGDdkMK7fUW7PTHTeLf+j87aTuKuuwWzMGw==} - engines: {node: '>=6.0.0'} - hasBin: true - - big.js@5.2.2: - resolution: {integrity: sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==} - - brace-expansion@5.0.4: - resolution: {integrity: sha512-h+DEnpVvxmfVefa4jFbCf5HdH5YMDXRsmKflpf1pILZWRFlTbJpxeU55nJl4Smt5HQaGzg1o6RHFPJaOqnmBDg==} - engines: {node: 18 || 20 || >=22} + assertion-error@2.0.1: + resolution: {integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==} + engines: {node: '>=12'} - braces@3.0.3: - resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} - engines: {node: '>=8'} - - browserslist@4.28.1: - resolution: {integrity: sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==} - engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} - hasBin: true + bidi-js@1.0.3: + resolution: {integrity: sha512-RKshQI1R3YQ+n9YJz2QQ147P66ELpa1FQEg20Dk8oW9t2KgLbpDLLp9aGZ7y8WHSshDknG0bknqGw5/tyCs5tw==} buffer-from@1.1.2: resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} - caniuse-lite@1.0.30001778: - resolution: {integrity: sha512-PN7uxFL+ExFJO61aVmP1aIEG4i9whQd4eoSCebav62UwDyp5OHh06zN4jqKSMePVgxHifCw1QJxdRkA1Pisekg==} + chai@6.2.2: + resolution: {integrity: sha512-NUPRluOfOiTKBKvWPtSD4PhFvWCqOi0BGStNWs57X9js7XGTprSmFoz5F0tWhR4WPjNeR9jXqdC7/UpSJTnlRg==} + engines: {node: '>=18'} - chalk@4.1.2: - resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} - engines: {node: '>=10'} + commander@2.20.3: + resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==} - chrome-trace-event@1.0.4: - resolution: {integrity: sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ==} - engines: {node: '>=6.0'} + convert-source-map@2.0.0: + resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} - ci-info@3.9.0: - resolution: {integrity: sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==} - engines: {node: '>=8'} + css-tree@3.2.1: + resolution: {integrity: sha512-X7sjQzceUhu1u7Y/ylrRZFU2FS6LRiFVp6rKLPg23y3x3c3DOKAwuXGDp+PAGjh6CSnCjYeAul8pcT8bAl+lSA==} + engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0} - clone-deep@4.0.1: - resolution: {integrity: sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==} - engines: {node: '>=6'} + data-urls@7.0.0: + resolution: {integrity: sha512-23XHcCF+coGYevirZceTVD7NdJOqVn+49IHyxgszm+JIiHLoB2TkmPtsYkNWT1pvRSGkc35L6NHs0yHkN2SumA==} + engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} - color-convert@2.0.1: - resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} - engines: {node: '>=7.0.0'} + decimal.js@10.6.0: + resolution: {integrity: sha512-YpgQiITW3JXGntzdUmyUR1V812Hn8T1YVXhCu+wO3OpS4eU9l4YdD3qjyiKdV6mvV29zapkMeD390UVEf2lkUg==} - color-name@1.1.4: - resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + detect-libc@2.1.2: + resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==} + engines: {node: '>=8'} - colorette@2.0.20: - resolution: {integrity: sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==} + entities@8.0.0: + resolution: {integrity: sha512-zwfzJecQ/Uej6tusMqwAqU/6KL2XaB2VZ2Jg54Je6ahNBGNH6Ek6g3jjNCF0fG9EWQKGZNddNjU5F1ZQn/sBnA==} + engines: {node: '>=20.19.0'} - commander@10.0.1: - resolution: {integrity: sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==} - engines: {node: '>=14'} + es-module-lexer@2.3.0: + resolution: {integrity: sha512-KLdwQm2NvGLDkQDCGvmiQrhkd0JbMzXthwQAUgWjQuQdBLFa3eiBP5arXZyA+f8x+x7OXgud6bq2rxjGtHV2tw==} - commander@2.20.3: - resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==} + estree-walker@3.0.3: + resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==} - cross-spawn@7.0.6: - resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} - engines: {node: '>= 8'} + expect-type@1.4.0: + resolution: {integrity: sha512-KfYbmpRm0VbLjEvVa9yGwCi9GI34xvi7A/HXYWQO65CSD2u3MczUJSuwXKFIxlGsgBQizV9q5J9NHj4VG0n+pA==} + engines: {node: '>=12.0.0'} - debug@4.4.3: - resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==} - engines: {node: '>=6.0'} + fdir@6.5.0: + resolution: {integrity: sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==} + engines: {node: '>=12.0.0'} peerDependencies: - supports-color: '*' + picomatch: ^3 || ^4 peerDependenciesMeta: - supports-color: + picomatch: optional: true - deep-is@0.1.4: - resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} + fsevents@2.3.2: + resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] - ejs-loader@0.5.0: - resolution: {integrity: sha512-iirFqlP3tiFoedNZ7dQcjvechunl054VbW6Ki38T/pabgXMAncduSE0ZXLeVGn1NbmcUJF9Z5TC0EvQ4RIpP9Q==} + fsevents@2.3.3: + resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] - ejs@5.0.1: - resolution: {integrity: sha512-COqBPFMxuPTPspXl2DkVYaDS3HtrD1GpzOGkNTJ1IYkifq/r9h8SVEFrjA3D9/VJGOEoMQcrlhpntcSUrM8k6A==} - engines: {node: '>=0.12.18'} - hasBin: true - - electron-to-chromium@1.5.313: - resolution: {integrity: sha512-QBMrTWEf00GXZmJyx2lbYD45jpI3TUFnNIzJ5BBc8piGUDwMPa1GV6HJWTZVvY/eiN3fSopl7NRbgGp9sZ9LTA==} + html-encoding-sniffer@6.0.0: + resolution: {integrity: sha512-CV9TW3Y3f8/wT0BRFc1/KAVQ3TUHiXmaAb6VW9vtiMFf7SLoMd1PdAc4W3KFOFETBJUb90KatHqlsZMWV+R9Gg==} + engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} - emojis-list@3.0.0: - resolution: {integrity: sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==} - engines: {node: '>= 4'} + is-potential-custom-element-name@1.0.1: + resolution: {integrity: sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==} - enhanced-resolve@5.20.0: - resolution: {integrity: sha512-/ce7+jQ1PQ6rVXwe+jKEg5hW5ciicHwIQUagZkp6IufBoY3YDgdTTY1azVs0qoRgVmvsNB+rbjLJxDAeHHtwsQ==} - engines: {node: '>=10.13.0'} + jsdom@29.1.1: + resolution: {integrity: sha512-ECi4Fi2f7BdJtUKTflYRTiaMxIB0O6zfR1fX0GXpUrf6flp8QIYn1UT20YQqdSOfk2dfkCwS8LAFoJDEppNK5Q==} + engines: {node: ^20.19.0 || ^22.13.0 || >=24.0.0} + peerDependencies: + canvas: ^3.0.0 + peerDependenciesMeta: + canvas: + optional: true - envinfo@7.21.0: - resolution: {integrity: sha512-Lw7I8Zp5YKHFCXL7+Dz95g4CcbMEpgvqZNNq3AmlT5XAV6CgAAk6gyAMqn2zjw08K9BHfcNuKrMiCPLByGafow==} - engines: {node: '>=4'} + lightningcss-android-arm64@1.32.0: + resolution: {integrity: sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [android] + + lightningcss-darwin-arm64@1.32.0: + resolution: {integrity: sha512-RzeG9Ju5bag2Bv1/lwlVJvBE3q6TtXskdZLLCyfg5pt+HLz9BqlICO7LZM7VHNTTn/5PRhHFBSjk5lc4cmscPQ==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [darwin] + + lightningcss-darwin-x64@1.32.0: + resolution: {integrity: sha512-U+QsBp2m/s2wqpUYT/6wnlagdZbtZdndSmut/NJqlCcMLTWp5muCrID+K5UJ6jqD2BFshejCYXniPDbNh73V8w==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [darwin] + + lightningcss-freebsd-x64@1.32.0: + resolution: {integrity: sha512-JCTigedEksZk3tHTTthnMdVfGf61Fky8Ji2E4YjUTEQX14xiy/lTzXnu1vwiZe3bYe0q+SpsSH/CTeDXK6WHig==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [freebsd] + + lightningcss-linux-arm-gnueabihf@1.32.0: + resolution: {integrity: sha512-x6rnnpRa2GL0zQOkt6rts3YDPzduLpWvwAF6EMhXFVZXD4tPrBkEFqzGowzCsIWsPjqSK+tyNEODUBXeeVHSkw==} + engines: {node: '>= 12.0.0'} + cpu: [arm] + os: [linux] + + lightningcss-linux-arm64-gnu@1.32.0: + resolution: {integrity: sha512-0nnMyoyOLRJXfbMOilaSRcLH3Jw5z9HDNGfT/gwCPgaDjnx0i8w7vBzFLFR1f6CMLKF8gVbebmkUN3fa/kQJpQ==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [linux] + libc: [glibc] + + lightningcss-linux-arm64-musl@1.32.0: + resolution: {integrity: sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [linux] + libc: [musl] + + lightningcss-linux-x64-gnu@1.32.0: + resolution: {integrity: sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [linux] + libc: [glibc] + + lightningcss-linux-x64-musl@1.32.0: + resolution: {integrity: sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [linux] + libc: [musl] + + lightningcss-win32-arm64-msvc@1.32.0: + resolution: {integrity: sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [win32] + + lightningcss-win32-x64-msvc@1.32.0: + resolution: {integrity: sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [win32] + + lightningcss@1.32.0: + resolution: {integrity: sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ==} + engines: {node: '>= 12.0.0'} + + lru-cache@11.5.2: + resolution: {integrity: sha512-4pfM1Ff0x50o0tQwb5ucw/RzNyD0/YJME6IVcStalZuMWxdt3sR3huStTtxz4PUmvZfRguvDejasvQ2kifR11g==} + engines: {node: 20 || >=22} + + magic-string@0.30.21: + resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==} + + mdn-data@2.27.1: + resolution: {integrity: sha512-9Yubnt3e8A0OKwxYSXyhLymGW4sCufcLG6VdiDdUGVkPhpqLxlvP5vl1983gQjJl3tqbrM731mjaZaP68AgosQ==} + + nanoid@3.3.15: + resolution: {integrity: sha512-y7Wygv/7mEOvxTuEQDB8StXdMRBWf1kR/tlhAzBRUFkB2jfcLOAxO/SHmOO2zgz1pVgK29/kyupn059/bCHdjA==} + engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} hasBin: true - es-module-lexer@2.0.0: - resolution: {integrity: sha512-5POEcUuZybH7IdmGsD8wlf0AI55wMecM9rVBTI/qEAy2c1kTOm3DjFYjrBdI2K3BaJjJYfYFeRtM0t9ssnRuxw==} - - escalade@3.2.0: - resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} - engines: {node: '>=6'} - - escape-string-regexp@4.0.0: - resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} - engines: {node: '>=10'} + obug@2.1.3: + resolution: {integrity: sha512-9miFgM2OFba7hB+pRgvtV84pYTBaoTHohvmIgiRt6dRIzbwEOIaNaP+dIlGs2fNFoB0SeISs0Jz5WFVRid6Xyg==} + engines: {node: '>=12.20.0'} - eslint-scope@5.1.1: - resolution: {integrity: sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==} - engines: {node: '>=8.0.0'} - - eslint-scope@9.1.2: - resolution: {integrity: sha512-xS90H51cKw0jltxmvmHy2Iai1LIqrfbw57b79w/J7MfvDfkIkFZ+kj6zC3BjtUwh150HsSSdxXZcsuv72miDFQ==} - engines: {node: ^20.19.0 || ^22.13.0 || >=24} - - eslint-visitor-keys@3.4.3: - resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - - eslint-visitor-keys@5.0.1: - resolution: {integrity: sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==} - engines: {node: ^20.19.0 || ^22.13.0 || >=24} - - eslint-webpack-plugin@5.0.3: - resolution: {integrity: sha512-P2Id4RMSMQMwMEuw3W9x3n2qDbKPeD+tehWMY3ENFsoSPKNZ9i3WTZEsFE7NeQIpNebhNEGw8qorvpLVq1rK1g==} - engines: {node: '>= 18.12.0'} - peerDependencies: - eslint: ^8.0.0 || ^9.0.0 - webpack: ^5.0.0 - - eslint@10.0.3: - resolution: {integrity: sha512-COV33RzXZkqhG9P2rZCFl9ZmJ7WL+gQSCRzE7RhkbclbQPtLAWReL7ysA0Sh4c8Im2U9ynybdR56PV0XcKvqaQ==} - engines: {node: ^20.19.0 || ^22.13.0 || >=24} + oxfmt@0.58.0: + resolution: {integrity: sha512-8feG/7NVEHDVwc1OUpP6Pks+TnaDFUw2jLLFIMi5bcmmwxAX2wBQvjSzj62RRTYBf2Op1Wt8xbkmagmPTR5ETg==} + engines: {node: ^20.19.0 || >=22.12.0} hasBin: true peerDependencies: - jiti: '*' + svelte: ^5.0.0 + vite-plus: '*' peerDependenciesMeta: - jiti: + svelte: + optional: true + vite-plus: optional: true - espree@11.2.0: - resolution: {integrity: sha512-7p3DrVEIopW1B1avAGLuCSh1jubc01H2JHc8B4qqGblmg5gI9yumBgACjWo4JlIc04ufug4xJ3SQI8HkS/Rgzw==} - engines: {node: ^20.19.0 || ^22.13.0 || >=24} - - esquery@1.7.0: - resolution: {integrity: sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==} - engines: {node: '>=0.10'} - - esrecurse@4.3.0: - resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} - engines: {node: '>=4.0'} - - estraverse@4.3.0: - resolution: {integrity: sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==} - engines: {node: '>=4.0'} - - estraverse@5.3.0: - resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} - engines: {node: '>=4.0'} - - esutils@2.0.3: - resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} - engines: {node: '>=0.10.0'} - - events@3.3.0: - resolution: {integrity: sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==} - engines: {node: '>=0.8.x'} - - fast-deep-equal@3.1.3: - resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} - - fast-json-stable-stringify@2.1.0: - resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} - - fast-levenshtein@2.0.6: - resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} - - fast-uri@3.1.0: - resolution: {integrity: sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==} - - fastest-levenshtein@1.0.16: - resolution: {integrity: sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==} - engines: {node: '>= 4.9.1'} - - file-entry-cache@8.0.0: - resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==} - engines: {node: '>=16.0.0'} - - fill-range@7.1.1: - resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} - engines: {node: '>=8'} - - find-up@4.1.0: - resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==} - engines: {node: '>=8'} - - find-up@5.0.0: - resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} - engines: {node: '>=10'} - - flat-cache@4.0.1: - resolution: {integrity: sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==} - engines: {node: '>=16'} - - flat@5.0.2: - resolution: {integrity: sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==} + oxlint@1.73.0: + resolution: {integrity: sha512-u91G9TJzU6yqKWNZUYprQB07W7YvntZXaRxQ6CkoytepYhLWUXWsr1M8zUJ34VatNPuUAr3Z8GH+O2A331CluQ==} + engines: {node: ^20.19.0 || >=22.12.0} hasBin: true + peerDependencies: + oxlint-tsgolint: '>=0.24.0' + vite-plus: '*' + peerDependenciesMeta: + oxlint-tsgolint: + optional: true + vite-plus: + optional: true - flatted@3.4.1: - resolution: {integrity: sha512-IxfVbRFVlV8V/yRaGzk0UVIcsKKHMSfYw66T/u4nTwlWteQePsxe//LjudR1AMX4tZW3WFCh3Zqa/sjlqpbURQ==} - - function-bind@1.1.2: - resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} - - glob-parent@6.0.2: - resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} - engines: {node: '>=10.13.0'} - - glob-to-regexp@0.4.1: - resolution: {integrity: sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==} - - graceful-fs@4.2.11: - resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} + parse5@8.0.1: + resolution: {integrity: sha512-z1e/HMG90obSGeidlli3hj7cbocou0/wa5HacvI3ASx34PecNjNQeaHNo5WIZpWofN9kgkqV1q5YvXe3F0FoPw==} - has-flag@4.0.0: - resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} - engines: {node: '>=8'} + pathe@2.0.3: + resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==} - hasown@2.0.2: - resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} - engines: {node: '>= 0.4'} + picocolors@1.1.1: + resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} - ignore@5.3.2: - resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==} - engines: {node: '>= 4'} + picomatch@4.0.5: + resolution: {integrity: sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A==} + engines: {node: '>=12'} - import-local@3.2.0: - resolution: {integrity: sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA==} - engines: {node: '>=8'} + playwright-core@1.61.1: + resolution: {integrity: sha512-h7Qlt6m4REp25qvIdvbDtVmD4LqVXfpRxhORv9L0jzETM05p4fuPJ3dKyuSXQxDSbXnmS79HAgi9589lGSpLkg==} + engines: {node: '>=18'} hasBin: true - imurmurhash@0.1.4: - resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} - engines: {node: '>=0.8.19'} - - interpret@3.1.1: - resolution: {integrity: sha512-6xwYfHbajpoF0xLW+iwLkhwgvLoZDfjYfoFNu8ftMoXINzwuymNLd9u/KmwtdT2GbR+/Cz66otEGEVVUHX9QLQ==} - engines: {node: '>=10.13.0'} - - is-core-module@2.16.1: - resolution: {integrity: sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==} - engines: {node: '>= 0.4'} - - is-extglob@2.1.1: - resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} - engines: {node: '>=0.10.0'} - - is-glob@4.0.3: - resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} - engines: {node: '>=0.10.0'} - - is-number@7.0.0: - resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} - engines: {node: '>=0.12.0'} - - is-plain-object@2.0.4: - resolution: {integrity: sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==} - engines: {node: '>=0.10.0'} - - isexe@2.0.0: - resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} - - isobject@3.0.1: - resolution: {integrity: sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==} - engines: {node: '>=0.10.0'} - - jest-util@29.7.0: - resolution: {integrity: sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - jest-worker@27.5.1: - resolution: {integrity: sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==} - engines: {node: '>= 10.13.0'} - - jest-worker@29.7.0: - resolution: {integrity: sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - json-buffer@3.0.1: - resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} - - json-parse-even-better-errors@2.3.1: - resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} - - json-schema-traverse@0.4.1: - resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} - - json-schema-traverse@1.0.0: - resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==} - - json-stable-stringify-without-jsonify@1.0.1: - resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} - - json5@2.2.3: - resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} - engines: {node: '>=6'} + playwright@1.61.1: + resolution: {integrity: sha512-DWnY5o3YbLWK4GovuAVwpqL+1VwGNdUGrRr++8j8PtQQzvAVZUIMjKQ90fY689sEJZJBbZVw1rXaOKSTitkzPQ==} + engines: {node: '>=18'} hasBin: true - keyv@4.5.4: - resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} - - kind-of@6.0.3: - resolution: {integrity: sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==} - engines: {node: '>=0.10.0'} - - levn@0.4.1: - resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} - engines: {node: '>= 0.8.0'} - - loader-runner@4.3.1: - resolution: {integrity: sha512-IWqP2SCPhyVFTBtRcgMHdzlf9ul25NwaFx4wCEH/KjAXuuHY4yNjvPXsBokp8jCB936PyWRaPKUNh8NvylLp2Q==} - engines: {node: '>=6.11.5'} - - loader-utils@2.0.4: - resolution: {integrity: sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==} - engines: {node: '>=8.9.0'} - - locate-path@5.0.0: - resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==} - engines: {node: '>=8'} - - locate-path@6.0.0: - resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} - engines: {node: '>=10'} - - lodash@4.17.23: - resolution: {integrity: sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w==} - - merge-stream@2.0.0: - resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} - - micromatch@4.0.8: - resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} - engines: {node: '>=8.6'} - - mime-db@1.52.0: - resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} - engines: {node: '>= 0.6'} - - mime-types@2.1.35: - resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} - engines: {node: '>= 0.6'} - - minimatch@10.2.4: - resolution: {integrity: sha512-oRjTw/97aTBN0RHbYCdtF1MQfvusSIBQM0IZEgzl6426+8jSC0nF1a/GmnVLpfB9yyr6g6FTqWqiZVbxrtaCIg==} - engines: {node: 18 || 20 || >=22} - - ms@2.1.3: - resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} - - natural-compare@1.4.0: - resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} - - neo-async@2.6.2: - resolution: {integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==} - - node-releases@2.0.36: - resolution: {integrity: sha512-TdC8FSgHz8Mwtw9g5L4gR/Sh9XhSP/0DEkQxfEFXOpiul5IiHgHan2VhYYb6agDSfp4KuvltmGApc8HMgUrIkA==} - - normalize-path@3.0.0: - resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} - engines: {node: '>=0.10.0'} - - optionator@0.9.4: - resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==} - engines: {node: '>= 0.8.0'} - - p-limit@2.3.0: - resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==} - engines: {node: '>=6'} - - p-limit@3.1.0: - resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} - engines: {node: '>=10'} - - p-locate@4.1.0: - resolution: {integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==} - engines: {node: '>=8'} - - p-locate@5.0.0: - resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} - engines: {node: '>=10'} - - p-try@2.2.0: - resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==} - engines: {node: '>=6'} - - path-exists@4.0.0: - resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} - engines: {node: '>=8'} - - path-key@3.1.1: - resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} - engines: {node: '>=8'} - - path-parse@1.0.7: - resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} - - picocolors@1.1.1: - resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} - - picomatch@2.3.1: - resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} - engines: {node: '>=8.6'} - - pkg-dir@4.2.0: - resolution: {integrity: sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==} - engines: {node: '>=8'} - - prelude-ls@1.2.1: - resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} - engines: {node: '>= 0.8.0'} + postcss@8.5.16: + resolution: {integrity: sha512-vuwillviilfKZsg0VGj5R/YwwcHx4SLsIOI/7K6mQkWx+l5cUHTjj5g0AasTBcyXsbfTgrwsUNmVUb5xVwyPwg==} + engines: {node: ^10 || ^12 || >=14} punycode@2.3.1: resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} engines: {node: '>=6'} - rechoir@0.8.0: - resolution: {integrity: sha512-/vxpCXddiX8NGfGO/mTafwjq4aFa/71pvamip0++IQk3zG8cbCj0fifNPrjjF1XMXUne91jL9OoxmdykoEtifQ==} - engines: {node: '>= 10.13.0'} - require-from-string@2.0.2: resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} engines: {node: '>=0.10.0'} - resolve-cwd@3.0.0: - resolution: {integrity: sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==} - engines: {node: '>=8'} - - resolve-from@5.0.0: - resolution: {integrity: sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==} - engines: {node: '>=8'} - - resolve@1.22.11: - resolution: {integrity: sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ==} - engines: {node: '>= 0.4'} + rolldown@1.1.5: + resolution: {integrity: sha512-t9z29cJjXf/vxQ8dyhCSpt6H6aSwHTk8cT5I3iy6SMXuFpk5mB6PL6XfC8PCwrPTx93udwKUm9HRteAlTGBLiA==} + engines: {node: ^20.19.0 || >=22.12.0} hasBin: true - schema-utils@4.3.3: - resolution: {integrity: sha512-eflK8wEtyOE6+hsaRVPxvUKYCpRgzLqDTb8krvAsRIwOGlHoSgYLgBXoubGgLd2fT41/OUYdb48v4k4WWHQurA==} - engines: {node: '>= 10.13.0'} - - shallow-clone@3.0.1: - resolution: {integrity: sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==} - engines: {node: '>=8'} + saxes@6.0.0: + resolution: {integrity: sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==} + engines: {node: '>=v12.22.7'} - shebang-command@2.0.0: - resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} - engines: {node: '>=8'} + siginfo@2.0.0: + resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==} - shebang-regex@3.0.0: - resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} - engines: {node: '>=8'} + source-map-js@1.2.1: + resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} + engines: {node: '>=0.10.0'} source-map-support@0.5.21: resolution: {integrity: sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==} @@ -736,191 +910,263 @@ packages: resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} engines: {node: '>=0.10.0'} - supports-color@7.2.0: - resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} - engines: {node: '>=8'} - - supports-color@8.1.1: - resolution: {integrity: sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==} - engines: {node: '>=10'} + stackback@0.0.2: + resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==} - supports-preserve-symlinks-flag@1.0.0: - resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} - engines: {node: '>= 0.4'} + std-env@4.2.0: + resolution: {integrity: sha512-oCUKSupKTHX53EyjDtuZQ64pjLJ6yYCtpmEw0goYxtjG9KpbRe8KAsl2tBUGU9DyMcJ0RwJ8GqJAFzMXcXW1Rw==} - tapable@2.3.0: - resolution: {integrity: sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg==} - engines: {node: '>=6'} - - terser-webpack-plugin@5.4.0: - resolution: {integrity: sha512-Bn5vxm48flOIfkdl5CaD2+1CiUVbonWQ3KQPyP7/EuIl9Gbzq/gQFOzaMFUEgVjB1396tcK0SG8XcNJ/2kDH8g==} - engines: {node: '>= 10.13.0'} - peerDependencies: - '@swc/core': '*' - esbuild: '*' - uglify-js: '*' - webpack: ^5.1.0 - peerDependenciesMeta: - '@swc/core': - optional: true - esbuild: - optional: true - uglify-js: - optional: true + symbol-tree@3.2.4: + resolution: {integrity: sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==} terser@5.46.0: resolution: {integrity: sha512-jTwoImyr/QbOWFFso3YoU3ik0jBBDJ6JTOQiy/J2YxVJdZCc+5u7skhNwiOR3FQIygFqVUPHl7qbbxtjW2K3Qg==} engines: {node: '>=10'} hasBin: true - to-regex-range@5.0.1: - resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} - engines: {node: '>=8.0'} + tinybench@2.9.0: + resolution: {integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==} - type-check@0.4.0: - resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} - engines: {node: '>= 0.8.0'} + tinyexec@1.2.4: + resolution: {integrity: sha512-SHf/r48b7vOrjve9PxJo3MN5v5yuyjHvdUcrQffT3WXMUfnGmHDVbC4k3sHJaJTgZCwpUplIaAo5ANtMyp3YHg==} + engines: {node: '>=18'} - undici-types@7.18.2: - resolution: {integrity: sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w==} + tinyglobby@0.2.17: + resolution: {integrity: sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==} + engines: {node: '>=12.0.0'} - update-browserslist-db@1.2.3: - resolution: {integrity: sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==} + tinypool@2.1.0: + resolution: {integrity: sha512-Pugqs6M0m7Lv1I7FtxN4aoyToKg1C4tu+/381vH35y8oENM/Ai7f7C4StcoK4/+BSw9ebcS8jRiVrORFKCALLw==} + engines: {node: ^20.0.0 || >=22.0.0} + + tinyrainbow@3.1.0: + resolution: {integrity: sha512-Bf+ILmBgretUrdJxzXM0SgXLZ3XfiaUuOj/IKQHuTXip+05Xn+uyEYdVg0kYDipTBcLrCVyUzAPz7QmArb0mmw==} + engines: {node: '>=14.0.0'} + + tldts-core@7.4.7: + resolution: {integrity: sha512-rNlAI8fKn/JckBMUSbNL/ES2kmDiurWaE49l+ikwEc9A6lFR7gMx9AhgQMQKBK4H5w4pKLH64JzZfB99uRsGNQ==} + + tldts@7.4.7: + resolution: {integrity: sha512-56L0/9HELHSsG1bFCzay8UoLxzRL7kpFf7Wl5q/kSYwiSJGACvro61xnKzPNM+SadxllzdtXsKDSXE7HPeqIAw==} hasBin: true - peerDependencies: - browserslist: '>= 4.21.0' - uri-js@4.4.1: - resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} + tough-cookie@6.0.2: + resolution: {integrity: sha512-exgYmnmL/sJpR3upZfXG5PoatXQii55xAiXGXzY+sROLZ/Y+SLcp9PgJNI9Vz37HpQ74WvDcLT8eqm+kV3FzrA==} + engines: {node: '>=16'} + + tr46@6.0.0: + resolution: {integrity: sha512-bLVMLPtstlZ4iMQHpFHTR7GAGj2jxi8Dg0s2h2MafAE4uSWF98FC/3MomU51iQAMf8/qDUbKWf5GxuvvVcXEhw==} + engines: {node: '>=20'} + + tslib@2.8.1: + resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} - watchpack@2.5.1: - resolution: {integrity: sha512-Zn5uXdcFNIA1+1Ei5McRd+iRzfhENPCe7LeABkJtNulSxjma+l7ltNx55BWZkRlwRnpOgHqxnjyaDgJnNXnqzg==} - engines: {node: '>=10.13.0'} + typescript@7.0.2: + resolution: {integrity: sha512-8FYau96o3NKOhbjKi/qNvG/W5jhzxkbdm5sj9AbZ/5T5sWqn3hJgLfGx27sRKZWTvyzCP8dLRBTf5tBTSRVUNA==} + engines: {node: '>=16.20.0'} + hasBin: true + + undici-types@7.18.2: + resolution: {integrity: sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w==} - webpack-cli@5.1.4: - resolution: {integrity: sha512-pIDJHIEI9LR0yxHXQ+Qh95k2EvXpWzZ5l+d+jIo+RdSm9MiHfzazIxwwni/p7+x4eJZuvG1AJwgC4TNQ7NRgsg==} - engines: {node: '>=14.15.0'} + undici@7.28.0: + resolution: {integrity: sha512-cRZYrTDwWznlnRiPjggAGxZXanty6M8RV1ff8Wm4LWXBp7/IG8v5DnOm74DtUBp9OONpK75YlPnIjQqX0dBDtA==} + engines: {node: '>=20.18.1'} + + vite@8.1.4: + resolution: {integrity: sha512-bTT9PsdWO+MQMNG9ZXIP/qM9wGh37DFxTV/sPq9cFpHr3w4jkgef032PkAL9jAqhk3Nz8NQw3O8n6/xFkqO4QQ==} + engines: {node: ^20.19.0 || >=22.12.0} hasBin: true peerDependencies: - '@webpack-cli/generators': '*' - webpack: 5.x.x - webpack-bundle-analyzer: '*' - webpack-dev-server: '*' + '@types/node': ^20.19.0 || >=22.12.0 + '@vitejs/devtools': ^0.3.0 + esbuild: ^0.27.0 || ^0.28.0 + jiti: '>=1.21.0' + less: ^4.0.0 + sass: ^1.70.0 + sass-embedded: ^1.70.0 + stylus: '>=0.54.8' + sugarss: ^5.0.0 + terser: ^5.16.0 + tsx: ^4.8.1 + yaml: ^2.4.2 peerDependenciesMeta: - '@webpack-cli/generators': + '@types/node': optional: true - webpack-bundle-analyzer: + '@vitejs/devtools': optional: true - webpack-dev-server: + esbuild: + optional: true + jiti: + optional: true + less: + optional: true + sass: + optional: true + sass-embedded: + optional: true + stylus: + optional: true + sugarss: + optional: true + terser: + optional: true + tsx: + optional: true + yaml: optional: true - webpack-merge@5.10.0: - resolution: {integrity: sha512-+4zXKdx7UnO+1jaN4l2lHVD+mFvnlZQP/6ljaJVb4SZiwIKeUnrT5l0gkT8z+n4hKpC+jpOv6O9R+gLtag7pSA==} - engines: {node: '>=10.0.0'} - - webpack-merge@6.0.1: - resolution: {integrity: sha512-hXXvrjtx2PLYx4qruKl+kyRSLc52V+cCvMxRjmKwoA+CBbbF5GfIBtR6kCvl0fYGqTUPKB+1ktVmTHqMOzgCBg==} - engines: {node: '>=18.0.0'} - - webpack-sources@3.3.4: - resolution: {integrity: sha512-7tP1PdV4vF+lYPnkMR0jMY5/la2ub5Fc/8VQrrU+lXkiM6C4TjVfGw7iKfyhnTQOsD+6Q/iKw0eFciziRgD58Q==} - engines: {node: '>=10.13.0'} - - webpack@5.105.4: - resolution: {integrity: sha512-jTywjboN9aHxFlToqb0K0Zs9SbBoW4zRUlGzI2tYNxVYcEi/IPpn+Xi4ye5jTLvX2YeLuic/IvxNot+Q1jMoOw==} - engines: {node: '>=10.13.0'} + vitest@4.1.10: + resolution: {integrity: sha512-R9jUTe5S4Qb0HCd4TNqpC7oGcrMssMRGXLW80ubjWsW9VH5GF8y1Y0SFLY9AbqSk6nt0PnOx4H4WNJYZ13GUPw==} + engines: {node: ^20.0.0 || ^22.0.0 || >=24.0.0} hasBin: true peerDependencies: - webpack-cli: '*' + '@edge-runtime/vm': '*' + '@opentelemetry/api': ^1.9.0 + '@types/node': ^20.0.0 || ^22.0.0 || >=24.0.0 + '@vitest/browser-playwright': 4.1.10 + '@vitest/browser-preview': 4.1.10 + '@vitest/browser-webdriverio': 4.1.10 + '@vitest/coverage-istanbul': 4.1.10 + '@vitest/coverage-v8': 4.1.10 + '@vitest/ui': 4.1.10 + happy-dom: '*' + jsdom: '*' + vite: ^6.0.0 || ^7.0.0 || ^8.0.0 peerDependenciesMeta: - webpack-cli: + '@edge-runtime/vm': + optional: true + '@opentelemetry/api': + optional: true + '@types/node': + optional: true + '@vitest/browser-playwright': + optional: true + '@vitest/browser-preview': + optional: true + '@vitest/browser-webdriverio': + optional: true + '@vitest/coverage-istanbul': + optional: true + '@vitest/coverage-v8': + optional: true + '@vitest/ui': + optional: true + happy-dom: + optional: true + jsdom: optional: true - which@2.0.2: - resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} - engines: {node: '>= 8'} - hasBin: true + w3c-xmlserializer@5.0.0: + resolution: {integrity: sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==} + engines: {node: '>=18'} - wildcard@2.0.1: - resolution: {integrity: sha512-CC1bOL87PIWSBhDcTrdeLo6eGT7mCFtrg0uIJtqJUFyK+eJnzl8A1niH56uu7KMa5XFrtiV+AQuHO3n7DsHnLQ==} + webidl-conversions@8.0.1: + resolution: {integrity: sha512-BMhLD/Sw+GbJC21C/UgyaZX41nPt8bUTg+jWyDeg7e7YN4xOM05YPSIXceACnXVtqyEw/LMClUQMtMZ+PGGpqQ==} + engines: {node: '>=20'} - word-wrap@1.2.5: - resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==} - engines: {node: '>=0.10.0'} + whatwg-mimetype@5.0.0: + resolution: {integrity: sha512-sXcNcHOC51uPGF0P/D4NVtrkjSU2fNsm9iog4ZvZJsL3rjoDAzXZhkm2MWt1y+PUdggKAYVoMAIYcs78wJ51Cw==} + engines: {node: '>=20'} - yocto-queue@0.1.0: - resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} - engines: {node: '>=10'} + whatwg-url@16.0.1: + resolution: {integrity: sha512-1to4zXBxmXHV3IiSSEInrreIlu02vUOvrhxJJH5vcxYTBDAx51cqZiKdyTxlecdKNSjj8EcxGBxNf6Vg+945gw==} + engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} -snapshots: + why-is-node-running@2.3.0: + resolution: {integrity: sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==} + engines: {node: '>=8'} + hasBin: true - '@discoveryjs/json-ext@0.5.7': {} + xml-name-validator@5.0.0: + resolution: {integrity: sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==} + engines: {node: '>=18'} - '@eslint-community/eslint-utils@4.9.1(eslint@10.0.3)': - dependencies: - eslint: 10.0.3 - eslint-visitor-keys: 3.4.3 + xmlchars@2.2.0: + resolution: {integrity: sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==} - '@eslint-community/regexpp@4.12.2': {} +snapshots: - '@eslint/config-array@0.23.3': + '@asamuzakjp/css-color@5.1.11': dependencies: - '@eslint/object-schema': 3.0.3 - debug: 4.4.3 - minimatch: 10.2.4 - transitivePeerDependencies: - - supports-color + '@asamuzakjp/generational-cache': 1.0.1 + '@csstools/css-calc': 3.2.1(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0) + '@csstools/css-color-parser': 4.1.9(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0) + '@csstools/css-parser-algorithms': 4.0.0(@csstools/css-tokenizer@4.0.0) + '@csstools/css-tokenizer': 4.0.0 - '@eslint/config-helpers@0.5.3': + '@asamuzakjp/dom-selector@7.1.1': dependencies: - '@eslint/core': 1.1.1 + '@asamuzakjp/generational-cache': 1.0.1 + '@asamuzakjp/nwsapi': 2.3.9 + bidi-js: 1.0.3 + css-tree: 3.2.1 + is-potential-custom-element-name: 1.0.1 + + '@asamuzakjp/generational-cache@1.0.1': {} + + '@asamuzakjp/nwsapi@2.3.9': {} - '@eslint/core@1.1.1': + '@bramus/specificity@2.4.2': dependencies: - '@types/json-schema': 7.0.15 + css-tree: 3.2.1 - '@eslint/object-schema@3.0.3': {} + '@csstools/color-helpers@6.1.0': {} - '@eslint/plugin-kit@0.6.1': + '@csstools/css-calc@3.2.1(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0)': dependencies: - '@eslint/core': 1.1.1 - levn: 0.4.1 + '@csstools/css-parser-algorithms': 4.0.0(@csstools/css-tokenizer@4.0.0) + '@csstools/css-tokenizer': 4.0.0 - '@humanfs/core@0.19.1': {} + '@csstools/css-color-parser@4.1.9(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0)': + dependencies: + '@csstools/color-helpers': 6.1.0 + '@csstools/css-calc': 3.2.1(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0) + '@csstools/css-parser-algorithms': 4.0.0(@csstools/css-tokenizer@4.0.0) + '@csstools/css-tokenizer': 4.0.0 - '@humanfs/node@0.16.7': + '@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0)': dependencies: - '@humanfs/core': 0.19.1 - '@humanwhocodes/retry': 0.4.3 + '@csstools/css-tokenizer': 4.0.0 - '@humanwhocodes/module-importer@1.0.1': {} + '@csstools/css-syntax-patches-for-csstree@1.1.6(css-tree@3.2.1)': + optionalDependencies: + css-tree: 3.2.1 - '@humanwhocodes/retry@0.4.3': {} + '@csstools/css-tokenizer@4.0.0': {} - '@jest/schemas@29.6.3': + '@emnapi/core@1.11.1': dependencies: - '@sinclair/typebox': 0.27.10 + '@emnapi/wasi-threads': 1.2.2 + tslib: 2.8.1 + optional: true - '@jest/types@29.6.3': + '@emnapi/runtime@1.11.1': dependencies: - '@jest/schemas': 29.6.3 - '@types/istanbul-lib-coverage': 2.0.6 - '@types/istanbul-reports': 3.0.4 - '@types/node': 25.5.0 - '@types/yargs': 17.0.35 - chalk: 4.1.2 + tslib: 2.8.1 + optional: true + + '@emnapi/wasi-threads@1.2.2': + dependencies: + tslib: 2.8.1 + optional: true + + '@exodus/bytes@1.15.1': {} '@jridgewell/gen-mapping@0.3.13': dependencies: '@jridgewell/sourcemap-codec': 1.5.5 '@jridgewell/trace-mapping': 0.3.31 + optional: true - '@jridgewell/resolve-uri@3.1.2': {} + '@jridgewell/resolve-uri@3.1.2': + optional: true '@jridgewell/source-map@0.3.11': dependencies: '@jridgewell/gen-mapping': 0.3.13 '@jridgewell/trace-mapping': 0.3.31 + optional: true '@jridgewell/sourcemap-codec@1.5.5': {} @@ -928,630 +1174,575 @@ snapshots: dependencies: '@jridgewell/resolve-uri': 3.1.2 '@jridgewell/sourcemap-codec': 1.5.5 + optional: true - '@sinclair/typebox@0.27.10': {} - - '@types/eslint-scope@3.7.7': + '@napi-rs/wasm-runtime@1.1.6(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1)': dependencies: - '@types/eslint': 9.6.1 - '@types/estree': 1.0.8 + '@emnapi/core': 1.11.1 + '@emnapi/runtime': 1.11.1 + '@tybys/wasm-util': 0.10.3 + optional: true - '@types/eslint@9.6.1': - dependencies: - '@types/estree': 1.0.8 - '@types/json-schema': 7.0.15 + '@oxc-project/types@0.139.0': {} - '@types/esrecurse@4.3.1': {} + '@oxfmt/binding-android-arm-eabi@0.58.0': + optional: true - '@types/estree@1.0.8': {} + '@oxfmt/binding-android-arm64@0.58.0': + optional: true - '@types/istanbul-lib-coverage@2.0.6': {} + '@oxfmt/binding-darwin-arm64@0.58.0': + optional: true - '@types/istanbul-lib-report@3.0.3': - dependencies: - '@types/istanbul-lib-coverage': 2.0.6 + '@oxfmt/binding-darwin-x64@0.58.0': + optional: true - '@types/istanbul-reports@3.0.4': - dependencies: - '@types/istanbul-lib-report': 3.0.3 + '@oxfmt/binding-freebsd-x64@0.58.0': + optional: true - '@types/json-schema@7.0.15': {} + '@oxfmt/binding-linux-arm-gnueabihf@0.58.0': + optional: true - '@types/node@25.5.0': - dependencies: - undici-types: 7.18.2 + '@oxfmt/binding-linux-arm-musleabihf@0.58.0': + optional: true - '@types/yargs-parser@21.0.3': {} + '@oxfmt/binding-linux-arm64-gnu@0.58.0': + optional: true - '@types/yargs@17.0.35': - dependencies: - '@types/yargs-parser': 21.0.3 + '@oxfmt/binding-linux-arm64-musl@0.58.0': + optional: true - '@webassemblyjs/ast@1.14.1': - dependencies: - '@webassemblyjs/helper-numbers': 1.13.2 - '@webassemblyjs/helper-wasm-bytecode': 1.13.2 + '@oxfmt/binding-linux-ppc64-gnu@0.58.0': + optional: true - '@webassemblyjs/floating-point-hex-parser@1.13.2': {} + '@oxfmt/binding-linux-riscv64-gnu@0.58.0': + optional: true - '@webassemblyjs/helper-api-error@1.13.2': {} + '@oxfmt/binding-linux-riscv64-musl@0.58.0': + optional: true - '@webassemblyjs/helper-buffer@1.14.1': {} + '@oxfmt/binding-linux-s390x-gnu@0.58.0': + optional: true - '@webassemblyjs/helper-numbers@1.13.2': - dependencies: - '@webassemblyjs/floating-point-hex-parser': 1.13.2 - '@webassemblyjs/helper-api-error': 1.13.2 - '@xtuc/long': 4.2.2 + '@oxfmt/binding-linux-x64-gnu@0.58.0': + optional: true - '@webassemblyjs/helper-wasm-bytecode@1.13.2': {} + '@oxfmt/binding-linux-x64-musl@0.58.0': + optional: true - '@webassemblyjs/helper-wasm-section@1.14.1': - dependencies: - '@webassemblyjs/ast': 1.14.1 - '@webassemblyjs/helper-buffer': 1.14.1 - '@webassemblyjs/helper-wasm-bytecode': 1.13.2 - '@webassemblyjs/wasm-gen': 1.14.1 + '@oxfmt/binding-openharmony-arm64@0.58.0': + optional: true - '@webassemblyjs/ieee754@1.13.2': - dependencies: - '@xtuc/ieee754': 1.2.0 + '@oxfmt/binding-win32-arm64-msvc@0.58.0': + optional: true - '@webassemblyjs/leb128@1.13.2': - dependencies: - '@xtuc/long': 4.2.2 + '@oxfmt/binding-win32-ia32-msvc@0.58.0': + optional: true - '@webassemblyjs/utf8@1.13.2': {} + '@oxfmt/binding-win32-x64-msvc@0.58.0': + optional: true - '@webassemblyjs/wasm-edit@1.14.1': - dependencies: - '@webassemblyjs/ast': 1.14.1 - '@webassemblyjs/helper-buffer': 1.14.1 - '@webassemblyjs/helper-wasm-bytecode': 1.13.2 - '@webassemblyjs/helper-wasm-section': 1.14.1 - '@webassemblyjs/wasm-gen': 1.14.1 - '@webassemblyjs/wasm-opt': 1.14.1 - '@webassemblyjs/wasm-parser': 1.14.1 - '@webassemblyjs/wast-printer': 1.14.1 - - '@webassemblyjs/wasm-gen@1.14.1': - dependencies: - '@webassemblyjs/ast': 1.14.1 - '@webassemblyjs/helper-wasm-bytecode': 1.13.2 - '@webassemblyjs/ieee754': 1.13.2 - '@webassemblyjs/leb128': 1.13.2 - '@webassemblyjs/utf8': 1.13.2 + '@oxlint/binding-android-arm-eabi@1.73.0': + optional: true - '@webassemblyjs/wasm-opt@1.14.1': - dependencies: - '@webassemblyjs/ast': 1.14.1 - '@webassemblyjs/helper-buffer': 1.14.1 - '@webassemblyjs/wasm-gen': 1.14.1 - '@webassemblyjs/wasm-parser': 1.14.1 + '@oxlint/binding-android-arm64@1.73.0': + optional: true - '@webassemblyjs/wasm-parser@1.14.1': - dependencies: - '@webassemblyjs/ast': 1.14.1 - '@webassemblyjs/helper-api-error': 1.13.2 - '@webassemblyjs/helper-wasm-bytecode': 1.13.2 - '@webassemblyjs/ieee754': 1.13.2 - '@webassemblyjs/leb128': 1.13.2 - '@webassemblyjs/utf8': 1.13.2 - - '@webassemblyjs/wast-printer@1.14.1': - dependencies: - '@webassemblyjs/ast': 1.14.1 - '@xtuc/long': 4.2.2 + '@oxlint/binding-darwin-arm64@1.73.0': + optional: true - '@webpack-cli/configtest@2.1.1(webpack-cli@5.1.4)(webpack@5.105.4)': - dependencies: - webpack: 5.105.4(webpack-cli@5.1.4) - webpack-cli: 5.1.4(webpack@5.105.4) + '@oxlint/binding-darwin-x64@1.73.0': + optional: true - '@webpack-cli/info@2.0.2(webpack-cli@5.1.4)(webpack@5.105.4)': - dependencies: - webpack: 5.105.4(webpack-cli@5.1.4) - webpack-cli: 5.1.4(webpack@5.105.4) + '@oxlint/binding-freebsd-x64@1.73.0': + optional: true - '@webpack-cli/serve@2.0.5(webpack-cli@5.1.4)(webpack@5.105.4)': - dependencies: - webpack: 5.105.4(webpack-cli@5.1.4) - webpack-cli: 5.1.4(webpack@5.105.4) + '@oxlint/binding-linux-arm-gnueabihf@1.73.0': + optional: true - '@xtuc/ieee754@1.2.0': {} + '@oxlint/binding-linux-arm-musleabihf@1.73.0': + optional: true - '@xtuc/long@4.2.2': {} + '@oxlint/binding-linux-arm64-gnu@1.73.0': + optional: true - acorn-import-phases@1.0.4(acorn@8.16.0): - dependencies: - acorn: 8.16.0 + '@oxlint/binding-linux-arm64-musl@1.73.0': + optional: true - acorn-jsx@5.3.2(acorn@8.16.0): - dependencies: - acorn: 8.16.0 + '@oxlint/binding-linux-ppc64-gnu@1.73.0': + optional: true - acorn@8.16.0: {} + '@oxlint/binding-linux-riscv64-gnu@1.73.0': + optional: true - ajv-formats@2.1.1(ajv@8.18.0): - optionalDependencies: - ajv: 8.18.0 + '@oxlint/binding-linux-riscv64-musl@1.73.0': + optional: true - ajv-keywords@5.1.0(ajv@8.18.0): - dependencies: - ajv: 8.18.0 - fast-deep-equal: 3.1.3 + '@oxlint/binding-linux-s390x-gnu@1.73.0': + optional: true - ajv@6.14.0: - dependencies: - fast-deep-equal: 3.1.3 - fast-json-stable-stringify: 2.1.0 - json-schema-traverse: 0.4.1 - uri-js: 4.4.1 + '@oxlint/binding-linux-x64-gnu@1.73.0': + optional: true - ajv@8.18.0: - dependencies: - fast-deep-equal: 3.1.3 - fast-uri: 3.1.0 - json-schema-traverse: 1.0.0 - require-from-string: 2.0.2 + '@oxlint/binding-linux-x64-musl@1.73.0': + optional: true - ansi-styles@4.3.0: - dependencies: - color-convert: 2.0.1 - - balanced-match@4.0.4: {} - - baseline-browser-mapping@2.10.7: {} + '@oxlint/binding-openharmony-arm64@1.73.0': + optional: true - big.js@5.2.2: {} + '@oxlint/binding-win32-arm64-msvc@1.73.0': + optional: true - brace-expansion@5.0.4: - dependencies: - balanced-match: 4.0.4 + '@oxlint/binding-win32-ia32-msvc@1.73.0': + optional: true - braces@3.0.3: - dependencies: - fill-range: 7.1.1 + '@oxlint/binding-win32-x64-msvc@1.73.0': + optional: true - browserslist@4.28.1: + '@playwright/test@1.61.1': dependencies: - baseline-browser-mapping: 2.10.7 - caniuse-lite: 1.0.30001778 - electron-to-chromium: 1.5.313 - node-releases: 2.0.36 - update-browserslist-db: 1.2.3(browserslist@4.28.1) + playwright: 1.61.1 - buffer-from@1.1.2: {} + '@rolldown/binding-android-arm64@1.1.5': + optional: true - caniuse-lite@1.0.30001778: {} + '@rolldown/binding-darwin-arm64@1.1.5': + optional: true - chalk@4.1.2: - dependencies: - ansi-styles: 4.3.0 - supports-color: 7.2.0 + '@rolldown/binding-darwin-x64@1.1.5': + optional: true - chrome-trace-event@1.0.4: {} + '@rolldown/binding-freebsd-x64@1.1.5': + optional: true - ci-info@3.9.0: {} + '@rolldown/binding-linux-arm-gnueabihf@1.1.5': + optional: true - clone-deep@4.0.1: - dependencies: - is-plain-object: 2.0.4 - kind-of: 6.0.3 - shallow-clone: 3.0.1 + '@rolldown/binding-linux-arm64-gnu@1.1.5': + optional: true - color-convert@2.0.1: - dependencies: - color-name: 1.1.4 + '@rolldown/binding-linux-arm64-musl@1.1.5': + optional: true - color-name@1.1.4: {} + '@rolldown/binding-linux-ppc64-gnu@1.1.5': + optional: true - colorette@2.0.20: {} + '@rolldown/binding-linux-s390x-gnu@1.1.5': + optional: true - commander@10.0.1: {} + '@rolldown/binding-linux-x64-gnu@1.1.5': + optional: true - commander@2.20.3: {} + '@rolldown/binding-linux-x64-musl@1.1.5': + optional: true - cross-spawn@7.0.6: - dependencies: - path-key: 3.1.1 - shebang-command: 2.0.0 - which: 2.0.2 + '@rolldown/binding-openharmony-arm64@1.1.5': + optional: true - debug@4.4.3: + '@rolldown/binding-wasm32-wasi@1.1.5': dependencies: - ms: 2.1.3 + '@emnapi/core': 1.11.1 + '@emnapi/runtime': 1.11.1 + '@napi-rs/wasm-runtime': 1.1.6(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1) + optional: true - deep-is@0.1.4: {} + '@rolldown/binding-win32-arm64-msvc@1.1.5': + optional: true - ejs-loader@0.5.0: - dependencies: - loader-utils: 2.0.4 - lodash: 4.17.23 + '@rolldown/binding-win32-x64-msvc@1.1.5': + optional: true - ejs@5.0.1: {} + '@rolldown/pluginutils@1.0.1': {} - electron-to-chromium@1.5.313: {} + '@standard-schema/spec@1.1.0': {} - emojis-list@3.0.0: {} + '@tybys/wasm-util@0.10.3': + dependencies: + tslib: 2.8.1 + optional: true - enhanced-resolve@5.20.0: + '@types/chai@5.2.3': dependencies: - graceful-fs: 4.2.11 - tapable: 2.3.0 + '@types/deep-eql': 4.0.2 + assertion-error: 2.0.1 - envinfo@7.21.0: {} + '@types/deep-eql@4.0.2': {} - es-module-lexer@2.0.0: {} + '@types/estree@1.0.8': {} - escalade@3.2.0: {} + '@types/node@25.5.0': + dependencies: + undici-types: 7.18.2 + optional: true - escape-string-regexp@4.0.0: {} + '@typescript/typescript-aix-ppc64@7.0.2': + optional: true - eslint-scope@5.1.1: - dependencies: - esrecurse: 4.3.0 - estraverse: 4.3.0 + '@typescript/typescript-darwin-arm64@7.0.2': + optional: true - eslint-scope@9.1.2: - dependencies: - '@types/esrecurse': 4.3.1 - '@types/estree': 1.0.8 - esrecurse: 4.3.0 - estraverse: 5.3.0 + '@typescript/typescript-darwin-x64@7.0.2': + optional: true - eslint-visitor-keys@3.4.3: {} + '@typescript/typescript-freebsd-arm64@7.0.2': + optional: true - eslint-visitor-keys@5.0.1: {} + '@typescript/typescript-freebsd-x64@7.0.2': + optional: true - eslint-webpack-plugin@5.0.3(eslint@10.0.3)(webpack@5.105.4): - dependencies: - '@types/eslint': 9.6.1 - eslint: 10.0.3 - flatted: 3.4.1 - jest-worker: 29.7.0 - micromatch: 4.0.8 - normalize-path: 3.0.0 - schema-utils: 4.3.3 - webpack: 5.105.4(webpack-cli@5.1.4) - - eslint@10.0.3: - dependencies: - '@eslint-community/eslint-utils': 4.9.1(eslint@10.0.3) - '@eslint-community/regexpp': 4.12.2 - '@eslint/config-array': 0.23.3 - '@eslint/config-helpers': 0.5.3 - '@eslint/core': 1.1.1 - '@eslint/plugin-kit': 0.6.1 - '@humanfs/node': 0.16.7 - '@humanwhocodes/module-importer': 1.0.1 - '@humanwhocodes/retry': 0.4.3 - '@types/estree': 1.0.8 - ajv: 6.14.0 - cross-spawn: 7.0.6 - debug: 4.4.3 - escape-string-regexp: 4.0.0 - eslint-scope: 9.1.2 - eslint-visitor-keys: 5.0.1 - espree: 11.2.0 - esquery: 1.7.0 - esutils: 2.0.3 - fast-deep-equal: 3.1.3 - file-entry-cache: 8.0.0 - find-up: 5.0.0 - glob-parent: 6.0.2 - ignore: 5.3.2 - imurmurhash: 0.1.4 - is-glob: 4.0.3 - json-stable-stringify-without-jsonify: 1.0.1 - minimatch: 10.2.4 - natural-compare: 1.4.0 - optionator: 0.9.4 - transitivePeerDependencies: - - supports-color + '@typescript/typescript-linux-arm64@7.0.2': + optional: true - espree@11.2.0: - dependencies: - acorn: 8.16.0 - acorn-jsx: 5.3.2(acorn@8.16.0) - eslint-visitor-keys: 5.0.1 + '@typescript/typescript-linux-arm@7.0.2': + optional: true - esquery@1.7.0: - dependencies: - estraverse: 5.3.0 + '@typescript/typescript-linux-loong64@7.0.2': + optional: true - esrecurse@4.3.0: - dependencies: - estraverse: 5.3.0 + '@typescript/typescript-linux-mips64el@7.0.2': + optional: true - estraverse@4.3.0: {} + '@typescript/typescript-linux-ppc64@7.0.2': + optional: true - estraverse@5.3.0: {} + '@typescript/typescript-linux-riscv64@7.0.2': + optional: true - esutils@2.0.3: {} + '@typescript/typescript-linux-s390x@7.0.2': + optional: true - events@3.3.0: {} + '@typescript/typescript-linux-x64@7.0.2': + optional: true - fast-deep-equal@3.1.3: {} + '@typescript/typescript-netbsd-arm64@7.0.2': + optional: true - fast-json-stable-stringify@2.1.0: {} + '@typescript/typescript-netbsd-x64@7.0.2': + optional: true - fast-levenshtein@2.0.6: {} + '@typescript/typescript-openbsd-arm64@7.0.2': + optional: true - fast-uri@3.1.0: {} + '@typescript/typescript-openbsd-x64@7.0.2': + optional: true - fastest-levenshtein@1.0.16: {} + '@typescript/typescript-sunos-x64@7.0.2': + optional: true - file-entry-cache@8.0.0: - dependencies: - flat-cache: 4.0.1 + '@typescript/typescript-win32-arm64@7.0.2': + optional: true - fill-range@7.1.1: - dependencies: - to-regex-range: 5.0.1 + '@typescript/typescript-win32-x64@7.0.2': + optional: true - find-up@4.1.0: + '@vitest/expect@4.1.10': dependencies: - locate-path: 5.0.0 - path-exists: 4.0.0 + '@standard-schema/spec': 1.1.0 + '@types/chai': 5.2.3 + '@vitest/spy': 4.1.10 + '@vitest/utils': 4.1.10 + chai: 6.2.2 + tinyrainbow: 3.1.0 - find-up@5.0.0: + '@vitest/mocker@4.1.10(vite@8.1.4(@types/node@25.5.0)(terser@5.46.0))': dependencies: - locate-path: 6.0.0 - path-exists: 4.0.0 + '@vitest/spy': 4.1.10 + estree-walker: 3.0.3 + magic-string: 0.30.21 + optionalDependencies: + vite: 8.1.4(@types/node@25.5.0)(terser@5.46.0) - flat-cache@4.0.1: + '@vitest/pretty-format@4.1.10': dependencies: - flatted: 3.4.1 - keyv: 4.5.4 - - flat@5.0.2: {} + tinyrainbow: 3.1.0 - flatted@3.4.1: {} - - function-bind@1.1.2: {} - - glob-parent@6.0.2: + '@vitest/runner@4.1.10': dependencies: - is-glob: 4.0.3 - - glob-to-regexp@0.4.1: {} + '@vitest/utils': 4.1.10 + pathe: 2.0.3 - graceful-fs@4.2.11: {} - - has-flag@4.0.0: {} - - hasown@2.0.2: + '@vitest/snapshot@4.1.10': dependencies: - function-bind: 1.1.2 + '@vitest/pretty-format': 4.1.10 + '@vitest/utils': 4.1.10 + magic-string: 0.30.21 + pathe: 2.0.3 - ignore@5.3.2: {} + '@vitest/spy@4.1.10': {} - import-local@3.2.0: + '@vitest/utils@4.1.10': dependencies: - pkg-dir: 4.2.0 - resolve-cwd: 3.0.0 - - imurmurhash@0.1.4: {} - - interpret@3.1.1: {} + '@vitest/pretty-format': 4.1.10 + convert-source-map: 2.0.0 + tinyrainbow: 3.1.0 - is-core-module@2.16.1: - dependencies: - hasown: 2.0.2 + acorn@8.16.0: + optional: true - is-extglob@2.1.1: {} + assertion-error@2.0.1: {} - is-glob@4.0.3: + bidi-js@1.0.3: dependencies: - is-extglob: 2.1.1 + require-from-string: 2.0.2 - is-number@7.0.0: {} + buffer-from@1.1.2: + optional: true - is-plain-object@2.0.4: - dependencies: - isobject: 3.0.1 + chai@6.2.2: {} - isexe@2.0.0: {} + commander@2.20.3: + optional: true - isobject@3.0.1: {} + convert-source-map@2.0.0: {} - jest-util@29.7.0: + css-tree@3.2.1: dependencies: - '@jest/types': 29.6.3 - '@types/node': 25.5.0 - chalk: 4.1.2 - ci-info: 3.9.0 - graceful-fs: 4.2.11 - picomatch: 2.3.1 + mdn-data: 2.27.1 + source-map-js: 1.2.1 - jest-worker@27.5.1: + data-urls@7.0.0: dependencies: - '@types/node': 25.5.0 - merge-stream: 2.0.0 - supports-color: 8.1.1 - - jest-worker@29.7.0: - dependencies: - '@types/node': 25.5.0 - jest-util: 29.7.0 - merge-stream: 2.0.0 - supports-color: 8.1.1 - - json-buffer@3.0.1: {} - - json-parse-even-better-errors@2.3.1: {} + whatwg-mimetype: 5.0.0 + whatwg-url: 16.0.1 + transitivePeerDependencies: + - '@noble/hashes' - json-schema-traverse@0.4.1: {} + decimal.js@10.6.0: {} - json-schema-traverse@1.0.0: {} + detect-libc@2.1.2: {} - json-stable-stringify-without-jsonify@1.0.1: {} + entities@8.0.0: {} - json5@2.2.3: {} + es-module-lexer@2.3.0: {} - keyv@4.5.4: + estree-walker@3.0.3: dependencies: - json-buffer: 3.0.1 + '@types/estree': 1.0.8 - kind-of@6.0.3: {} + expect-type@1.4.0: {} - levn@0.4.1: - dependencies: - prelude-ls: 1.2.1 - type-check: 0.4.0 - - loader-runner@4.3.1: {} + fdir@6.5.0(picomatch@4.0.5): + optionalDependencies: + picomatch: 4.0.5 - loader-utils@2.0.4: - dependencies: - big.js: 5.2.2 - emojis-list: 3.0.0 - json5: 2.2.3 + fsevents@2.3.2: + optional: true - locate-path@5.0.0: - dependencies: - p-locate: 4.1.0 + fsevents@2.3.3: + optional: true - locate-path@6.0.0: + html-encoding-sniffer@6.0.0: dependencies: - p-locate: 5.0.0 - - lodash@4.17.23: {} - - merge-stream@2.0.0: {} + '@exodus/bytes': 1.15.1 + transitivePeerDependencies: + - '@noble/hashes' + + is-potential-custom-element-name@1.0.1: {} + + jsdom@29.1.1: + dependencies: + '@asamuzakjp/css-color': 5.1.11 + '@asamuzakjp/dom-selector': 7.1.1 + '@bramus/specificity': 2.4.2 + '@csstools/css-syntax-patches-for-csstree': 1.1.6(css-tree@3.2.1) + '@exodus/bytes': 1.15.1 + css-tree: 3.2.1 + data-urls: 7.0.0 + decimal.js: 10.6.0 + html-encoding-sniffer: 6.0.0 + is-potential-custom-element-name: 1.0.1 + lru-cache: 11.5.2 + parse5: 8.0.1 + saxes: 6.0.0 + symbol-tree: 3.2.4 + tough-cookie: 6.0.2 + undici: 7.28.0 + w3c-xmlserializer: 5.0.0 + webidl-conversions: 8.0.1 + whatwg-mimetype: 5.0.0 + whatwg-url: 16.0.1 + xml-name-validator: 5.0.0 + transitivePeerDependencies: + - '@noble/hashes' - micromatch@4.0.8: - dependencies: - braces: 3.0.3 - picomatch: 2.3.1 + lightningcss-android-arm64@1.32.0: + optional: true - mime-db@1.52.0: {} + lightningcss-darwin-arm64@1.32.0: + optional: true - mime-types@2.1.35: - dependencies: - mime-db: 1.52.0 + lightningcss-darwin-x64@1.32.0: + optional: true - minimatch@10.2.4: - dependencies: - brace-expansion: 5.0.4 + lightningcss-freebsd-x64@1.32.0: + optional: true - ms@2.1.3: {} + lightningcss-linux-arm-gnueabihf@1.32.0: + optional: true - natural-compare@1.4.0: {} + lightningcss-linux-arm64-gnu@1.32.0: + optional: true - neo-async@2.6.2: {} + lightningcss-linux-arm64-musl@1.32.0: + optional: true - node-releases@2.0.36: {} + lightningcss-linux-x64-gnu@1.32.0: + optional: true - normalize-path@3.0.0: {} + lightningcss-linux-x64-musl@1.32.0: + optional: true - optionator@0.9.4: - dependencies: - deep-is: 0.1.4 - fast-levenshtein: 2.0.6 - levn: 0.4.1 - prelude-ls: 1.2.1 - type-check: 0.4.0 - word-wrap: 1.2.5 - - p-limit@2.3.0: - dependencies: - p-try: 2.2.0 + lightningcss-win32-arm64-msvc@1.32.0: + optional: true - p-limit@3.1.0: - dependencies: - yocto-queue: 0.1.0 + lightningcss-win32-x64-msvc@1.32.0: + optional: true - p-locate@4.1.0: + lightningcss@1.32.0: dependencies: - p-limit: 2.3.0 - - p-locate@5.0.0: + detect-libc: 2.1.2 + optionalDependencies: + lightningcss-android-arm64: 1.32.0 + lightningcss-darwin-arm64: 1.32.0 + lightningcss-darwin-x64: 1.32.0 + lightningcss-freebsd-x64: 1.32.0 + lightningcss-linux-arm-gnueabihf: 1.32.0 + lightningcss-linux-arm64-gnu: 1.32.0 + lightningcss-linux-arm64-musl: 1.32.0 + lightningcss-linux-x64-gnu: 1.32.0 + lightningcss-linux-x64-musl: 1.32.0 + lightningcss-win32-arm64-msvc: 1.32.0 + lightningcss-win32-x64-msvc: 1.32.0 + + lru-cache@11.5.2: {} + + magic-string@0.30.21: dependencies: - p-limit: 3.1.0 - - p-try@2.2.0: {} - - path-exists@4.0.0: {} - - path-key@3.1.1: {} + '@jridgewell/sourcemap-codec': 1.5.5 - path-parse@1.0.7: {} + mdn-data@2.27.1: {} - picocolors@1.1.1: {} + nanoid@3.3.15: {} - picomatch@2.3.1: {} + obug@2.1.3: {} - pkg-dir@4.2.0: + oxfmt@0.58.0: dependencies: - find-up: 4.1.0 + tinypool: 2.1.0 + optionalDependencies: + '@oxfmt/binding-android-arm-eabi': 0.58.0 + '@oxfmt/binding-android-arm64': 0.58.0 + '@oxfmt/binding-darwin-arm64': 0.58.0 + '@oxfmt/binding-darwin-x64': 0.58.0 + '@oxfmt/binding-freebsd-x64': 0.58.0 + '@oxfmt/binding-linux-arm-gnueabihf': 0.58.0 + '@oxfmt/binding-linux-arm-musleabihf': 0.58.0 + '@oxfmt/binding-linux-arm64-gnu': 0.58.0 + '@oxfmt/binding-linux-arm64-musl': 0.58.0 + '@oxfmt/binding-linux-ppc64-gnu': 0.58.0 + '@oxfmt/binding-linux-riscv64-gnu': 0.58.0 + '@oxfmt/binding-linux-riscv64-musl': 0.58.0 + '@oxfmt/binding-linux-s390x-gnu': 0.58.0 + '@oxfmt/binding-linux-x64-gnu': 0.58.0 + '@oxfmt/binding-linux-x64-musl': 0.58.0 + '@oxfmt/binding-openharmony-arm64': 0.58.0 + '@oxfmt/binding-win32-arm64-msvc': 0.58.0 + '@oxfmt/binding-win32-ia32-msvc': 0.58.0 + '@oxfmt/binding-win32-x64-msvc': 0.58.0 + + oxlint@1.73.0: + optionalDependencies: + '@oxlint/binding-android-arm-eabi': 1.73.0 + '@oxlint/binding-android-arm64': 1.73.0 + '@oxlint/binding-darwin-arm64': 1.73.0 + '@oxlint/binding-darwin-x64': 1.73.0 + '@oxlint/binding-freebsd-x64': 1.73.0 + '@oxlint/binding-linux-arm-gnueabihf': 1.73.0 + '@oxlint/binding-linux-arm-musleabihf': 1.73.0 + '@oxlint/binding-linux-arm64-gnu': 1.73.0 + '@oxlint/binding-linux-arm64-musl': 1.73.0 + '@oxlint/binding-linux-ppc64-gnu': 1.73.0 + '@oxlint/binding-linux-riscv64-gnu': 1.73.0 + '@oxlint/binding-linux-riscv64-musl': 1.73.0 + '@oxlint/binding-linux-s390x-gnu': 1.73.0 + '@oxlint/binding-linux-x64-gnu': 1.73.0 + '@oxlint/binding-linux-x64-musl': 1.73.0 + '@oxlint/binding-openharmony-arm64': 1.73.0 + '@oxlint/binding-win32-arm64-msvc': 1.73.0 + '@oxlint/binding-win32-ia32-msvc': 1.73.0 + '@oxlint/binding-win32-x64-msvc': 1.73.0 + + parse5@8.0.1: + dependencies: + entities: 8.0.0 + + pathe@2.0.3: {} - prelude-ls@1.2.1: {} + picocolors@1.1.1: {} - punycode@2.3.1: {} + picomatch@4.0.5: {} - rechoir@0.8.0: - dependencies: - resolve: 1.22.11 + playwright-core@1.61.1: {} - require-from-string@2.0.2: {} - - resolve-cwd@3.0.0: + playwright@1.61.1: dependencies: - resolve-from: 5.0.0 - - resolve-from@5.0.0: {} + playwright-core: 1.61.1 + optionalDependencies: + fsevents: 2.3.2 - resolve@1.22.11: + postcss@8.5.16: dependencies: - is-core-module: 2.16.1 - path-parse: 1.0.7 - supports-preserve-symlinks-flag: 1.0.0 + nanoid: 3.3.15 + picocolors: 1.1.1 + source-map-js: 1.2.1 - schema-utils@4.3.3: - dependencies: - '@types/json-schema': 7.0.15 - ajv: 8.18.0 - ajv-formats: 2.1.1(ajv@8.18.0) - ajv-keywords: 5.1.0(ajv@8.18.0) + punycode@2.3.1: {} - shallow-clone@3.0.1: - dependencies: - kind-of: 6.0.3 + require-from-string@2.0.2: {} - shebang-command@2.0.0: + rolldown@1.1.5: dependencies: - shebang-regex: 3.0.0 - - shebang-regex@3.0.0: {} + '@oxc-project/types': 0.139.0 + '@rolldown/pluginutils': 1.0.1 + optionalDependencies: + '@rolldown/binding-android-arm64': 1.1.5 + '@rolldown/binding-darwin-arm64': 1.1.5 + '@rolldown/binding-darwin-x64': 1.1.5 + '@rolldown/binding-freebsd-x64': 1.1.5 + '@rolldown/binding-linux-arm-gnueabihf': 1.1.5 + '@rolldown/binding-linux-arm64-gnu': 1.1.5 + '@rolldown/binding-linux-arm64-musl': 1.1.5 + '@rolldown/binding-linux-ppc64-gnu': 1.1.5 + '@rolldown/binding-linux-s390x-gnu': 1.1.5 + '@rolldown/binding-linux-x64-gnu': 1.1.5 + '@rolldown/binding-linux-x64-musl': 1.1.5 + '@rolldown/binding-openharmony-arm64': 1.1.5 + '@rolldown/binding-wasm32-wasi': 1.1.5 + '@rolldown/binding-win32-arm64-msvc': 1.1.5 + '@rolldown/binding-win32-x64-msvc': 1.1.5 + + saxes@6.0.0: + dependencies: + xmlchars: 2.2.0 + + siginfo@2.0.0: {} + + source-map-js@1.2.1: {} source-map-support@0.5.21: dependencies: buffer-from: 1.1.2 source-map: 0.6.1 + optional: true - source-map@0.6.1: {} - - supports-color@7.2.0: - dependencies: - has-flag: 4.0.0 - - supports-color@8.1.1: - dependencies: - has-flag: 4.0.0 + source-map@0.6.1: + optional: true - supports-preserve-symlinks-flag@1.0.0: {} + stackback@0.0.2: {} - tapable@2.3.0: {} + std-env@4.2.0: {} - terser-webpack-plugin@5.4.0(webpack@5.105.4): - dependencies: - '@jridgewell/trace-mapping': 0.3.31 - jest-worker: 27.5.1 - schema-utils: 4.3.3 - terser: 5.46.0 - webpack: 5.105.4(webpack-cli@5.1.4) + symbol-tree@3.2.4: {} terser@5.46.0: dependencies: @@ -1559,103 +1750,127 @@ snapshots: acorn: 8.16.0 commander: 2.20.3 source-map-support: 0.5.21 + optional: true - to-regex-range@5.0.1: - dependencies: - is-number: 7.0.0 + tinybench@2.9.0: {} + + tinyexec@1.2.4: {} - type-check@0.4.0: + tinyglobby@0.2.17: dependencies: - prelude-ls: 1.2.1 + fdir: 6.5.0(picomatch@4.0.5) + picomatch: 4.0.5 - undici-types@7.18.2: {} + tinypool@2.1.0: {} - update-browserslist-db@1.2.3(browserslist@4.28.1): - dependencies: - browserslist: 4.28.1 - escalade: 3.2.0 - picocolors: 1.1.1 + tinyrainbow@3.1.0: {} - uri-js@4.4.1: - dependencies: - punycode: 2.3.1 + tldts-core@7.4.7: {} - watchpack@2.5.1: + tldts@7.4.7: dependencies: - glob-to-regexp: 0.4.1 - graceful-fs: 4.2.11 + tldts-core: 7.4.7 - webpack-cli@5.1.4(webpack@5.105.4): - dependencies: - '@discoveryjs/json-ext': 0.5.7 - '@webpack-cli/configtest': 2.1.1(webpack-cli@5.1.4)(webpack@5.105.4) - '@webpack-cli/info': 2.0.2(webpack-cli@5.1.4)(webpack@5.105.4) - '@webpack-cli/serve': 2.0.5(webpack-cli@5.1.4)(webpack@5.105.4) - colorette: 2.0.20 - commander: 10.0.1 - cross-spawn: 7.0.6 - envinfo: 7.21.0 - fastest-levenshtein: 1.0.16 - import-local: 3.2.0 - interpret: 3.1.1 - rechoir: 0.8.0 - webpack: 5.105.4(webpack-cli@5.1.4) - webpack-merge: 5.10.0 - - webpack-merge@5.10.0: + tough-cookie@6.0.2: dependencies: - clone-deep: 4.0.1 - flat: 5.0.2 - wildcard: 2.0.1 + tldts: 7.4.7 - webpack-merge@6.0.1: + tr46@6.0.0: dependencies: - clone-deep: 4.0.1 - flat: 5.0.2 - wildcard: 2.0.1 + punycode: 2.3.1 + + tslib@2.8.1: + optional: true + + typescript@7.0.2: + optionalDependencies: + '@typescript/typescript-aix-ppc64': 7.0.2 + '@typescript/typescript-darwin-arm64': 7.0.2 + '@typescript/typescript-darwin-x64': 7.0.2 + '@typescript/typescript-freebsd-arm64': 7.0.2 + '@typescript/typescript-freebsd-x64': 7.0.2 + '@typescript/typescript-linux-arm': 7.0.2 + '@typescript/typescript-linux-arm64': 7.0.2 + '@typescript/typescript-linux-loong64': 7.0.2 + '@typescript/typescript-linux-mips64el': 7.0.2 + '@typescript/typescript-linux-ppc64': 7.0.2 + '@typescript/typescript-linux-riscv64': 7.0.2 + '@typescript/typescript-linux-s390x': 7.0.2 + '@typescript/typescript-linux-x64': 7.0.2 + '@typescript/typescript-netbsd-arm64': 7.0.2 + '@typescript/typescript-netbsd-x64': 7.0.2 + '@typescript/typescript-openbsd-arm64': 7.0.2 + '@typescript/typescript-openbsd-x64': 7.0.2 + '@typescript/typescript-sunos-x64': 7.0.2 + '@typescript/typescript-win32-arm64': 7.0.2 + '@typescript/typescript-win32-x64': 7.0.2 + + undici-types@7.18.2: + optional: true - webpack-sources@3.3.4: {} + undici@7.28.0: {} - webpack@5.105.4(webpack-cli@5.1.4): + vite@8.1.4(@types/node@25.5.0)(terser@5.46.0): dependencies: - '@types/eslint-scope': 3.7.7 - '@types/estree': 1.0.8 - '@types/json-schema': 7.0.15 - '@webassemblyjs/ast': 1.14.1 - '@webassemblyjs/wasm-edit': 1.14.1 - '@webassemblyjs/wasm-parser': 1.14.1 - acorn: 8.16.0 - acorn-import-phases: 1.0.4(acorn@8.16.0) - browserslist: 4.28.1 - chrome-trace-event: 1.0.4 - enhanced-resolve: 5.20.0 - es-module-lexer: 2.0.0 - eslint-scope: 5.1.1 - events: 3.3.0 - glob-to-regexp: 0.4.1 - graceful-fs: 4.2.11 - json-parse-even-better-errors: 2.3.1 - loader-runner: 4.3.1 - mime-types: 2.1.35 - neo-async: 2.6.2 - schema-utils: 4.3.3 - tapable: 2.3.0 - terser-webpack-plugin: 5.4.0(webpack@5.105.4) - watchpack: 2.5.1 - webpack-sources: 3.3.4 + lightningcss: 1.32.0 + picomatch: 4.0.5 + postcss: 8.5.16 + rolldown: 1.1.5 + tinyglobby: 0.2.17 optionalDependencies: - webpack-cli: 5.1.4(webpack@5.105.4) + '@types/node': 25.5.0 + fsevents: 2.3.3 + terser: 5.46.0 + + vitest@4.1.10(@types/node@25.5.0)(jsdom@29.1.1)(vite@8.1.4(@types/node@25.5.0)(terser@5.46.0)): + dependencies: + '@vitest/expect': 4.1.10 + '@vitest/mocker': 4.1.10(vite@8.1.4(@types/node@25.5.0)(terser@5.46.0)) + '@vitest/pretty-format': 4.1.10 + '@vitest/runner': 4.1.10 + '@vitest/snapshot': 4.1.10 + '@vitest/spy': 4.1.10 + '@vitest/utils': 4.1.10 + es-module-lexer: 2.3.0 + expect-type: 1.4.0 + magic-string: 0.30.21 + obug: 2.1.3 + pathe: 2.0.3 + picomatch: 4.0.5 + std-env: 4.2.0 + tinybench: 2.9.0 + tinyexec: 1.2.4 + tinyglobby: 0.2.17 + tinyrainbow: 3.1.0 + vite: 8.1.4(@types/node@25.5.0)(terser@5.46.0) + why-is-node-running: 2.3.0 + optionalDependencies: + '@types/node': 25.5.0 + jsdom: 29.1.1 transitivePeerDependencies: - - '@swc/core' - - esbuild - - uglify-js + - msw - which@2.0.2: + w3c-xmlserializer@5.0.0: dependencies: - isexe: 2.0.0 + xml-name-validator: 5.0.0 - wildcard@2.0.1: {} + webidl-conversions@8.0.1: {} + + whatwg-mimetype@5.0.0: {} + + whatwg-url@16.0.1: + dependencies: + '@exodus/bytes': 1.15.1 + tr46: 6.0.0 + webidl-conversions: 8.0.1 + transitivePeerDependencies: + - '@noble/hashes' + + why-is-node-running@2.3.0: + dependencies: + siginfo: 2.0.0 + stackback: 0.0.2 - word-wrap@1.2.5: {} + xml-name-validator@5.0.0: {} - yocto-queue@0.1.0: {} + xmlchars@2.2.0: {} diff --git a/scripts/build.js b/scripts/build.js new file mode 100644 index 0000000..fe1bfdb --- /dev/null +++ b/scripts/build.js @@ -0,0 +1,65 @@ +import { rm } from 'node:fs/promises'; +import { build } from 'vite'; + +// Each IIFE bundle must be a single self-contained file with a fixed name: +// the library locates its own ` + }) + ); +} + +test('parses config from its own script src query string', async ({ page }) => { + await stubWidget(page); + await page.goto('/demo/index.html'); + + await page.waitForFunction(() => (window as any).iframely && (window as any).iframely._loaded); + + const state = await page.evaluate(() => { + const iframely = (window as any).iframely; + return { + api_key: iframely.config.api_key, + theme: iframely.config.theme, + intersection: iframely.config.intersection, + cdn: iframely.CDN, + stylesInjected: !!document.getElementById('iframely-styles') + }; + }); + + expect(state).toEqual({ + api_key: 'TEST', + theme: 'dark', + intersection: true, + cdn: 'cdn.iframe.ly', + stylesInjected: true + }); +}); + +test('unfurls an anchor into an iframe pointing at the API endpoint', async ({ page }) => { + await stubWidget(page); + await page.goto('/demo/index.html'); + + const iframe = page.locator('.iframely-responsive iframe'); + await expect(iframe).toHaveCount(1); + await expect(page.locator('a[data-iframely-url]')).toHaveCount(0); + + const src = await iframe.getAttribute('src'); + expect(src).toContain('cdn.iframe.ly/api/iframe'); + expect(src).toContain( + 'url=' + encodeURIComponent('https://www.youtube.com/watch?v=dQw4w9WgXcQ') + ); + expect(src).toContain('v=1'); + expect(src).toContain('app=1'); + expect(src).toContain('theme=dark'); + expect(src).toContain('api_key=TEST'); +}); + +test('handles a resize message from the widget iframe', async ({ page }) => { + await stubWidget( + page, + "parent.postMessage(JSON.stringify({ method: 'resize', height: 400 }), '*');" + ); + await page.goto('/demo/index.html'); + + const aspectWrapper = page.locator('.iframely-responsive'); + await expect(aspectWrapper).toHaveCSS('height', '400px'); + await expect(aspectWrapper).toHaveCSS('padding-bottom', '0px'); +}); + +test('handles a cancelWidget message by removing the widget', async ({ page }) => { + await stubWidget(page, "parent.postMessage(JSON.stringify({ method: 'cancelWidget' }), '*');"); + await page.goto('/demo/index.html'); + + await expect(page.locator('.iframely-embed')).toHaveCount(0); + await expect(page.locator('iframe')).toHaveCount(0); +}); + +test('recreates a link on cancel when the anchor had text', async ({ page }) => { + await stubWidget(page, "parent.postMessage(JSON.stringify({ method: 'cancelWidget' }), '*');"); + await page.goto('/demo/cancel-recover.html'); + + const link = page.locator('a[href="https://www.youtube.com/watch?v=dQw4w9WgXcQ"]'); + await expect(link).toHaveText('Watch the video'); + await expect(link).toHaveAttribute('target', '_blank'); + await expect(link).toHaveAttribute('rel', 'noopener'); + await expect(page.locator('.iframely-embed')).toHaveCount(0); +}); diff --git a/tests/e2e/esm.spec.ts b/tests/e2e/esm.spec.ts new file mode 100644 index 0000000..53e887f --- /dev/null +++ b/tests/e2e/esm.spec.ts @@ -0,0 +1,46 @@ +import { test, expect } from '@playwright/test'; + +test.beforeEach(async ({ page }) => { + await page.route('**/api/iframe*', (route) => + route.fulfill({ + contentType: 'text/html', + body: 'widget' + }) + ); + await page.goto('/demo/esm.html'); + await page.waitForFunction(() => !!(window as any).__esm); +}); + +test('the ESM build exports the same singleton that is attached to window', async ({ page }) => { + const state = await page.evaluate(() => (window as any).__esm); + expect(state).toEqual({ + sameSingleton: true, + version: 1, + hasOn: true, + autorun: false + }); +}); + +test('does not auto-run on import; iframely.load() activates it', async ({ page }) => { + // Give the dom-ready autorun path time to fire if it (wrongly) were active. + await page.waitForTimeout(250); + await expect(page.locator('a[data-iframely-url]')).toHaveCount(1); + await expect(page.locator('iframe')).toHaveCount(0); + + await page.evaluate(() => (window as any).__load()); + + const iframe = page.locator('.iframely-responsive iframe'); + await expect(iframe).toHaveCount(1); + await expect(page.locator('a[data-iframely-url]')).toHaveCount(0); + expect(await iframe.getAttribute('src')).toContain('cdn.iframe.ly/api/iframe'); +}); + +test('iframely.unload() removes the widgets load() built', async ({ page }) => { + await page.evaluate(() => (window as any).__load()); + await expect(page.locator('.iframely-responsive iframe')).toHaveCount(1); + + await page.evaluate(() => (window as any).iframely.unload()); + + await expect(page.locator('iframe')).toHaveCount(0); + await expect(page.locator('.iframely-embed')).toHaveCount(0); +}); diff --git a/tests/e2e/options-standalone.spec.ts b/tests/e2e/options-standalone.spec.ts new file mode 100644 index 0000000..d78b4c7 --- /dev/null +++ b/tests/e2e/options-standalone.spec.ts @@ -0,0 +1,22 @@ +import { test, expect } from '@playwright/test'; + +test('options.js without embed.js fails silently on buildOptionsForm', async ({ page }) => { + const pageErrors: string[] = []; + const warnings: string[] = []; + page.on('pageerror', (error) => pageErrors.push(error.message)); + page.on('console', (message) => { + if (message.type() === 'warning') { + warnings.push(message.text()); + } + }); + + await page.goto('/demo/options-standalone.html'); + await page.waitForFunction(() => (window as any).__done); + + // The inline script ran to completion: nothing threw. + expect(pageErrors).toEqual([]); + expect(await page.evaluate(() => (window as any).__errors)).toEqual([]); + // The form was not rendered, and a warning points at the missing embed.js. + await expect(page.locator('#form *')).toHaveCount(0); + expect(warnings.join('|')).toContain('requires embed.js'); +}); diff --git a/tests/e2e/options.spec.ts b/tests/e2e/options.spec.ts new file mode 100644 index 0000000..fae0ba5 --- /dev/null +++ b/tests/e2e/options.spec.ts @@ -0,0 +1,43 @@ +import { test, expect } from '@playwright/test'; + +test.beforeEach(async ({ page }) => { + await page.goto('/demo/options.html'); + await page.waitForFunction(() => !!document.querySelector('#form input')); +}); + +test('renders all option element types, grouped', async ({ page }) => { + const form = page.locator('#form'); + await expect(form.locator('input[type="checkbox"]')).toHaveCount(2); + await expect(form.locator('input[type="radio"]')).toHaveCount(3); + await expect(form.locator('select')).toHaveCount(1); + await expect(form.locator('input[type="range"]')).toHaveCount(1); + // Checkboxes are wrapped in a group container. + await expect(form.locator('.iframely-option__group .iframely-option-checkbox')).toHaveCount(2); +}); + +test('applies German labels from the separately loaded i18n bundle', async ({ page }) => { + const labels = await page.locator('#form label').allTextContents(); + const text = labels.join('|'); + expect(text).toContain('Theme Farbe'); + expect(text).toContain('Artwork ausblenden'); + expect(text).toContain('Wiedergabeliste anzeigen'); + expect(text).toContain('Höhe einstellen'); + // Select options are translated too. + const optionTexts = await page.locator('#form select option').allTextContents(); + expect(optionTexts).toContain('Klassisch'); + expect(optionTexts).toContain('Bild'); +}); + +test('fires options-changed with the non-default query on user input', async ({ page }) => { + await page.locator('#form input[name="_hide"]').check(); + + const changes = await page.evaluate(() => (window as any).__optionsChanged); + expect(changes).toHaveLength(1); + expect(changes[0].id).toBe('test-form'); + expect(changes[0].query._hide).toBe(true); + + await page.locator('#form select[name="style"]').selectOption('mini'); + const changes2 = await page.evaluate(() => (window as any).__optionsChanged); + expect(changes2).toHaveLength(2); + expect(changes2[1].query.style).toBe('mini'); +}); diff --git a/tests/e2e/surface.spec.ts b/tests/e2e/surface.spec.ts new file mode 100644 index 0000000..9f904af --- /dev/null +++ b/tests/e2e/surface.spec.ts @@ -0,0 +1,80 @@ +import { test, expect } from '@playwright/test'; + +// The public window.iframely surface as shipped by the last webpack build +// (v1.11), plus `configure` (new in 2.0; `extendOptions` remains as its +// deprecated alias). Nothing else may be added or removed. +const EXPECTED_KEYS = [ + 'ASPECT_WRAPPER_CLASS', + 'BASE_RE', + 'CDN', + 'CDN_RE', + 'CLEAR_WRAPPER_STYLES_TIMEOUT', + 'DOMAINS', + 'ID_RE', + 'LAZY_IFRAME_FADE_TIMEOUT', + 'LAZY_IFRAME_SHOW_TIMEOUT', + 'LOADER_CLASS', + 'MAXWIDTH_WRAPPER_CLASS', + 'RECOVER_HREFS_ON_CANCEL', + 'SCRIPT_RE', + 'SHADOW', + 'SUPPORTED_QUERY_STRING', + 'SUPPORTED_THEMES', + 'SUPPORT_IFRAME_LOADING_ATTR', + 'VERSION', + '_loaded', + 'addEventListener', + 'buildImportWidgets', + 'cancelWidget', + 'config', + 'configure', + 'events', + 'extendOptions', + 'findIframe', + 'getElementComputedStyle', + 'isTouch', + 'load', + 'on', + 'openHref', + 'setTheme', + 'trigger', + 'triggerAsync', + // unload is new in 2.0. + 'unload', + 'widgets' +]; + +test('embed.js exposes the exact pre-migration API surface', async ({ page }) => { + await page.goto('/demo/new.html'); + await page.waitForFunction(() => (window as any).iframely && (window as any).iframely._loaded); + + const keys = await page.evaluate(() => Object.keys((window as any).iframely).sort()); + expect(keys).toEqual(EXPECTED_KEYS); + + const constants = await page.evaluate(() => { + const iframely = (window as any).iframely; + return { + version: iframely.VERSION, + supportsLoadingAttr: iframely.SUPPORT_IFRAME_LOADING_ATTR, + domains: iframely.DOMAINS + }; + }); + // VERSION is sent to the API as the v= param; it must stay 1. + expect(constants.version).toBe(1); + expect(constants.supportsLoadingAttr).toBe(true); + expect(constants.domains).toEqual(['cdn.iframe.ly', 'iframe.ly', 'if-cdn.com', 'iframely.net']); +}); + +test('embed-options.js additionally exposes buildOptionsForm', async ({ page }) => { + await page.goto('/demo/options.html'); + await page.waitForFunction(() => (window as any).iframely && (window as any).iframely._loaded); + + const extras = await page.evaluate(() => { + const iframely = (window as any).iframely; + return { + buildOptionsForm: typeof iframely.buildOptionsForm, + optionsTranslator: typeof iframely.optionsTranslator + }; + }); + expect(extras).toEqual({ buildOptionsForm: 'function', optionsTranslator: 'function' }); +}); diff --git a/tests/unit/events.test.ts b/tests/unit/events.test.ts new file mode 100644 index 0000000..21f4813 --- /dev/null +++ b/tests/unit/events.test.ts @@ -0,0 +1,53 @@ +import { beforeAll, describe, expect, it, vi } from 'vitest'; +import iframely from '../../src/iframely'; +import { boot as bootEvents } from '../../src/events'; + +beforeAll(() => { + bootEvents(); +}); + +describe('events', () => { + it('calls handlers synchronously with trigger, in registration order', () => { + const calls: string[] = []; + iframely.on('sync-test', () => calls.push('first')); + iframely.on('sync-test', () => calls.push('second')); + + iframely.trigger('sync-test'); + expect(calls).toEqual(['first', 'second']); + }); + + it('passes trigger arguments and binds this to the singleton', () => { + const cb = vi.fn(); + iframely.on('args-test', cb); + + iframely.trigger('args-test', 1, 'two', { three: 3 }); + expect(cb).toHaveBeenCalledWith(1, 'two', { three: 3 }); + expect(cb.mock.contexts[0]).toBe(iframely); + }); + + it('does not call handlers of other events', () => { + const cb = vi.fn(); + iframely.on('event-a', cb); + iframely.trigger('event-b'); + expect(cb).not.toHaveBeenCalled(); + }); + + it('triggerAsync defers handlers to the next animation frame', async () => { + const cb = vi.fn(); + iframely.on('async-test', cb); + + iframely.triggerAsync('async-test', 42); + expect(cb).not.toHaveBeenCalled(); + + await vi.waitFor(() => expect(cb).toHaveBeenCalledWith(42)); + }); + + it('clears init handlers after the first init', () => { + const cb = vi.fn(); + iframely.on('init', cb); + + iframely.trigger('init'); + iframely.trigger('init'); + expect(cb).toHaveBeenCalledTimes(1); + }); +}); diff --git a/tests/unit/form-builder.test.ts b/tests/unit/form-builder.test.ts new file mode 100644 index 0000000..470781c --- /dev/null +++ b/tests/unit/form-builder.test.ts @@ -0,0 +1,122 @@ +import { beforeAll, beforeEach, describe, expect, it, vi } from 'vitest'; +import iframely from '../../src/iframely'; +import { boot as bootConst } from '../../src/const'; +import { boot as bootEvents } from '../../src/events'; +import formBuilder from '../../src/options/form-builder'; +import renderer from '../../src/options/renderer'; + +beforeAll(() => { + bootConst(); + bootEvents(); + // Provided by import.ts in the embed bundle; stubbed here to unit-test + // the options subsystem in isolation. + iframely.addEventListener = (elem, type, handler) => elem.addEventListener(type, handler); +}); + +let container: HTMLElement; +let changes: { id: string; query: Record }[]; + +beforeEach(() => { + document.body.innerHTML = '
'; + container = document.getElementById('form')!; + changes = []; +}); + +function buildForm(id = 'test-' + Math.random()): string { + formBuilder({ + id: id, + formContainer: container, + renderer: renderer, + options: { + theme: { + label: 'Theme color', + value: 'light', + values: { light: 'Light', dark: 'Dark', auto: 'Auto' } + }, + _hide: { label: 'Hide artwork', value: false }, + _playlist: { label: 'Include playlist', value: true }, + maxheight: { label: 'Adjust height', value: '' } + } + }); + return id; +} + +describe('form-builder', () => { + beforeAll(() => { + iframely.on( + 'options-changed', + (id: string, formContainer: HTMLElement, query: Record) => { + changes.push({ id, query }); + } + ); + }); + + it('renders all element types into the container', () => { + buildForm(); + expect(container.querySelectorAll('input[type="radio"]')).toHaveLength(3); + expect(container.querySelectorAll('input[type="checkbox"]')).toHaveLength(2); + expect(container.querySelectorAll('input[type="text"]')).toHaveLength(1); + expect(container.querySelectorAll('.iframely-option__group').length).toBeGreaterThan(0); + }); + + it('fires options-changed with only non-default values', () => { + const id = buildForm(); + + const hide = container.querySelector('input[name="_hide"]')!; + hide.checked = true; + hide.dispatchEvent(new Event('change', { bubbles: true })); + + expect(changes).toHaveLength(1); + expect(changes[0].id).toBe(id); + expect(changes[0].query).toEqual({ _hide: true }); + }); + + it('omits values that return to their defaults', () => { + buildForm(); + + const dark = container.querySelector( + 'input[name="theme"][value="dark"]' + )!; + dark.checked = true; + dark.dispatchEvent(new Event('change', { bubbles: true })); + expect(changes[0].query).toEqual({ theme: 'dark' }); + + const light = container.querySelector( + 'input[name="theme"][value="light"]' + )!; + light.checked = true; + dark.checked = false; + light.dispatchEvent(new Event('change', { bubbles: true })); + expect(changes[1].query).toEqual({}); + }); + + it('submits text inputs on Enter', () => { + buildForm(); + + const text = container.querySelector('input[name="maxheight"]')!; + text.value = '300'; + const enter = new KeyboardEvent('keyup'); + Object.defineProperty(enter, 'keyCode', { value: 13 }); + text.dispatchEvent(enter); + + expect(changes).toHaveLength(1); + expect(changes[0].query).toEqual({ maxheight: '300' }); + + text.value = '400'; + text.dispatchEvent(new FocusEvent('blur')); + expect(changes[1].query).toEqual({ maxheight: '400' }); + }); + + it('clears the container when options are missing', () => { + container.innerHTML = 'old'; + formBuilder({ id: 'x', formContainer: container, renderer: renderer }); + expect(container.innerHTML).toBe(''); + }); + + it('warns without a form container', () => { + const warn = vi.spyOn(console, 'warn').mockImplementation(() => {}); + formBuilder({ id: 'x', formContainer: null as unknown as HTMLElement, renderer: renderer }); + expect(warn).toHaveBeenCalled(); + warn.mockRestore(); + }); +}); diff --git a/tests/unit/form-generator.test.ts b/tests/unit/form-generator.test.ts new file mode 100644 index 0000000..24767e2 --- /dev/null +++ b/tests/unit/form-generator.test.ts @@ -0,0 +1,138 @@ +import { describe, expect, it } from 'vitest'; +import getFormElements from '../../src/options/form-generator'; +import type { FormElement } from '../../src/types'; + +function flatten(elements: FormElement[]): FormElement[] { + return elements.flatMap((el) => (el.type === 'group' ? flatten(el.context.elements!) : [el])); +} + +describe('form-generator', () => { + it('returns an empty list without options', () => { + expect(getFormElements(undefined)).toEqual([]); + }); + + it('drops the reserved query key', () => { + const elements = getFormElements({ query: ['a'] }); + expect(elements).toEqual([]); + }); + + it('maps a boolean option to a checkbox with a boolean query', () => { + const [group] = getFormElements({ _hide: { label: 'Hide artwork', value: true } }); + expect(group.type).toBe('group'); + const [checkbox] = group.context.elements!; + expect(checkbox.type).toBe('checkbox'); + expect(checkbox.context.checked).toBe(true); + expect(checkbox.getQuery!(false)).toEqual({ _hide: false }); + }); + + it('forces a checkbox for a single key-value option and maps checked to the key', () => { + const [group] = getFormElements({ + card: { label: 'ignored', value: '', values: { small: 'Make it a small card' } } + }); + const [checkbox] = group.context.elements!; + expect(checkbox.type).toBe('checkbox'); + expect(checkbox.context.label).toBe('Make it a small card'); + expect(checkbox.context.checked).toBe(false); // value '' does not match the single key + expect(checkbox.getQuery!(true)).toEqual({ card: 'small' }); + expect(checkbox.getQuery!(false)).toEqual({}); + + const [checkedGroup] = getFormElements({ + card: { value: 'small', values: { small: 'Make it a small card' } } + }); + expect(checkedGroup.context.elements![0].context.checked).toBe(true); + }); + + it('maps a string option to a text input and a number option to a number input', () => { + const elements = getFormElements({ + start: { label: 'Start from', value: '11', placeholder: 'ex.: 11' }, + maxheight: { label: 'Adjust height', value: 200 } + }); + const text = elements.find((el) => el.context.key === 'start')!; + const number = elements.find((el) => el.context.key === 'maxheight')!; + expect(text.type).toBe('text'); + expect(text.context.inputType).toBe('text'); + expect(text.context.placeholder).toBe('ex.: 11'); + expect(number.context.inputType).toBe('number'); + expect(number.getQuery!('')).toEqual({}); + expect(number.getQuery!(300)).toEqual({ maxheight: 300 }); + }); + + it('maps a ranged numeric option to a range slider ordered last', () => { + const elements = getFormElements({ + height: { label: 'Height', value: 200, range: { min: 100, max: 600 } }, + name: { label: 'Name', value: 'x' } + }); + expect(elements[elements.length - 1].type).toBe('range'); + expect(elements[elements.length - 1].context).toMatchObject({ + min: 100, + max: 600, + value: 200 + }); + }); + + it('maps up to 3 values to radios and more than 3 to a select', () => { + const [radio] = getFormElements({ + theme: { + label: 'Theme color', + value: 'dark', + values: { light: 'Light', dark: 'Dark', auto: 'Auto' } + } + }); + expect(radio.type).toBe('radio'); + expect(radio.context.inline).toBe(true); // all labels are short + expect(radio.context.items).toHaveLength(3); + expect(radio.context.items![1]).toMatchObject({ + id: 'theme-1', + value: 'dark', + checked: true + }); + + const [select] = getFormElements({ + style: { + label: 'Style', + value: 'mini', + values: { mini: 'Mini', classic: 'Classic', picture: 'Picture', big: 'Big' } + } + }); + expect(select.type).toBe('select'); + expect(select.context.items).toHaveLength(4); + }); + + it('disables inline radios and label for long or missing labels', () => { + const [radio] = getFormElements({ + layout: { value: 'a', values: { a: 'A very long label indeed', b: 'B' } } + }); + expect(radio.type).toBe('radio'); + expect(radio.context.inline).toBe(false); + expect(radio.context.label).toBe(false); + }); + + it('groups checkboxes and starts a new group at the _-prefix boundary', () => { + const elements = getFormElements({ + _a: { label: 'A', value: true }, + _b: { label: 'B', value: false }, + c: { label: 'C', value: true } + }); + const groups = elements.filter((el) => el.type === 'group'); + expect(groups).toHaveLength(2); + expect(groups[0].context.elements!.map((el) => el.context.key)).toEqual(['_a', '_b']); + expect(groups[1].context.elements!.map((el) => el.context.key)).toEqual(['c']); + expect(flatten(elements)).toHaveLength(3); + }); + + it('applies the translator, falling back to the original label', () => { + const translator = (label: string) => (label === 'Light' ? 'Hell' : ''); + const [radio] = getFormElements( + { + theme: { + label: 'Theme color', + value: 'light', + values: { light: 'Light', dark: 'Dark' } + } + }, + translator + ); + expect(radio.context.items![0].label).toBe('Hell'); + expect(radio.context.items![1].label).toBe('Dark'); // empty translation falls back + }); +}); diff --git a/tests/unit/messaging.test.ts b/tests/unit/messaging.test.ts new file mode 100644 index 0000000..c7b1bb6 --- /dev/null +++ b/tests/unit/messaging.test.ts @@ -0,0 +1,148 @@ +import { beforeAll, beforeEach, describe, expect, it, vi } from 'vitest'; +import iframely from '../../src/iframely'; +import { boot as bootConst } from '../../src/const'; +import { boot as bootEvents } from '../../src/events'; +import { boot as bootUtils } from '../../src/utils'; +import { boot as bootMessaging } from '../../src/messaging'; +import * as messaging from '../../src/messaging'; + +beforeAll(() => { + bootConst(); + bootEvents(); + bootUtils(); + bootMessaging(); +}); + +beforeEach(() => { + iframely.config = {}; + document.body.innerHTML = ''; +}); + +function buildWidgetIframe( + src = 'https://cdn.iframe.ly/api/iframe?url=https%3A%2F%2Fx.com' +): HTMLIFrameElement { + document.body.innerHTML = + '
' + + '' + + '
'; + return document.querySelector('iframe')!; +} + +describe('postMessage', () => { + it('stringifies the message, adds the page context and trims the target origin', () => { + const iframe = buildWidgetIframe(); + const target = iframe.contentWindow!; + const spy = vi.spyOn(target, 'postMessage'); + + messaging.postMessage( + { method: 'getSize' }, + 'https://cdn.iframe.ly/some/deep/path?x=1', + target + ); + + expect(spy).toHaveBeenCalledTimes(1); + const [data, origin] = spy.mock.calls[0]; + expect(JSON.parse(data as string)).toEqual({ + method: 'getSize', + context: document.location.href + }); + expect(origin).toBe('https://cdn.iframe.ly'); + }); + + it('defaults the target origin to *', () => { + const iframe = buildWidgetIframe(); + const target = iframe.contentWindow!; + const spy = vi.spyOn(target, 'postMessage'); + + messaging.postMessage({ method: 'getSize' }, undefined, target); + expect(spy.mock.calls[0][1]).toBe('*'); + }); +}); + +describe('findIframe', () => { + it('finds an iframe by contentWindow among domain-matched iframes', () => { + const iframe = buildWidgetIframe(); + const found = iframely.findIframe({ + contentWindow: iframe.contentWindow, + domains: iframely.DOMAINS + }); + expect(found).toBe(iframe); + }); + + it('finds an iframe by src match', () => { + const iframe = buildWidgetIframe(); + const found = iframely.findIframe({ + contentWindow: iframe.contentWindow, + src: 'https://cdn.iframe.ly/api/iframe', + domains: false + }); + expect(found).toBe(iframe); + }); + + it('returns undefined for an unknown contentWindow', () => { + buildWidgetIframe(); + expect( + iframely.findIframe({ contentWindow: window, domains: iframely.DOMAINS }) + ).toBeUndefined(); + }); + + it('finds iframes inside shadow roots', () => { + document.body.innerHTML = '
'; + const host = document.querySelector('.iframely-shadow')!; + const shadowRoot = host.attachShadow({ mode: 'open' }); + shadowRoot.innerHTML = ''; + const iframe = shadowRoot.querySelector('iframe')!; + + const found = iframely.findIframe({ + contentWindow: iframe.contentWindow, + domains: iframely.DOMAINS + }); + expect(found).toBe(iframe); + }); +}); + +describe('message listener', () => { + function dispatchMessage(data: unknown, source: MessageEventSource | null): void { + window.dispatchEvent(new MessageEvent('message', { data, source })); + } + + it('resolves the widget and triggers the iframely message event for JSON messages', () => { + const iframe = buildWidgetIframe(); + const seen: any[] = []; + iframely.on('message', (widget: any, message: any) => seen.push({ widget, message })); + + dispatchMessage( + JSON.stringify({ method: 'test-method', domains: 'all' }), + iframe.contentWindow + ); + + expect(seen).toHaveLength(1); + expect(seen[0].message.method).toBe('test-method'); + expect(seen[0].widget.iframe).toBe(iframe); + expect(seen[0].widget.url).toBe('https://x.com'); + }); + + it('supports the pym height fallback format', () => { + const iframe = buildWidgetIframe(); + const seen: any[] = []; + iframely.on('message', (widget: any, message: any) => seen.push(message)); + + dispatchMessage('heightxPYMx120', iframe.contentWindow); + + expect(seen).toHaveLength(1); + expect(seen[0]).toEqual({ method: 'resize', height: 121, domains: 'all' }); + }); + + it('ignores unrelated messages', () => { + buildWidgetIframe(); + const cb = vi.fn(); + iframely.on('message', cb); + + dispatchMessage('unparseable garbage', null); + dispatchMessage(JSON.stringify({ noMethod: true }), null); + + expect(cb).not.toHaveBeenCalled(); + }); +}); diff --git a/tests/unit/options-standalone.test.ts b/tests/unit/options-standalone.test.ts new file mode 100644 index 0000000..231b9c2 --- /dev/null +++ b/tests/unit/options-standalone.test.ts @@ -0,0 +1,27 @@ +import { beforeEach, describe, expect, it, vi } from 'vitest'; +import iframely from '../../src/iframely'; +import { boot as bootOptions } from '../../src/options/index'; + +// Deliberately boots ONLY the options module — no events, no import — +// mirroring a page that loads the standalone options.js without embed.js. +describe('standalone options bundle without embed', () => { + beforeEach(() => { + document.body.innerHTML = '
'; + bootOptions(); + }); + + it('buildOptionsForm fails silently with a warning instead of throwing', () => { + const warn = vi.spyOn(console, 'warn').mockImplementation(() => {}); + const container = document.getElementById('form')!; + + expect(() => { + iframely.buildOptionsForm!('id', container, { + _hide: { label: 'Hide artwork', value: false } + }); + }).not.toThrow(); + + expect(container.innerHTML).toBe(''); + expect(warn).toHaveBeenCalledWith(expect.stringContaining('requires embed.js')); + warn.mockRestore(); + }); +}); diff --git a/tests/unit/renderer.test.ts b/tests/unit/renderer.test.ts new file mode 100644 index 0000000..bb3ba6c --- /dev/null +++ b/tests/unit/renderer.test.ts @@ -0,0 +1,108 @@ +import { describe, expect, it } from 'vitest'; +import render from '../../src/options/renderer'; + +describe('renderer', () => { + it('renders a checkbox with id/name/label and the checked attribute', () => { + const html = render('checkbox', { key: '_hide', label: 'Hide artwork', checked: true }); + expect(html).toContain('type="checkbox"'); + expect(html).toContain('id="_hide"'); + expect(html).toContain('name="_hide"'); + expect(html).toContain('checked="checked"'); + expect(html).toContain('Hide artwork'); + + const unchecked = render('checkbox', { + key: '_hide', + label: 'Hide artwork', + checked: false + }); + expect(unchecked).not.toContain('checked'); + }); + + it('HTML-escapes scalar interpolations', () => { + const html = render('checkbox', { key: 'k', label: '"quoted" & \'raw\'' }); + expect(html).not.toContain(''); + expect(html).toContain('<b>"quoted" & 'raw'</b>'); + }); + + it('renders nullish values as empty strings', () => { + const html = render('text', { key: 'k', label: 'L' }); + expect(html).toContain('placeholder=""'); + expect(html).toContain('value=""'); + expect(html).not.toContain('undefined'); + }); + + it('injects group elementsHtml raw', () => { + const child = render('checkbox', { key: 'c', label: 'C' }); + const html = render('group', { elementsHtml: child }); + expect(html).toContain('iframely-option__group'); + expect(html).toContain('type="checkbox"'); // not escaped + expect(html).not.toContain('<input'); + }); + + it('renders radio items with per-item ids, values and checked state', () => { + const html = render('radio', { + key: 'theme', + label: 'Theme color', + inline: true, + items: [ + { id: 'theme-0', value: 'light', label: 'Light', checked: true }, + { id: 'theme-1', value: 'dark', label: 'Dark', checked: false } + ] + }); + expect(html).toContain('iframely-option__group-inline'); + expect(html).toContain('Theme color:'); + expect(html).toContain('id="theme-0"'); + expect(html).toContain('value="light" checked="checked"'); + expect(html).toContain('value="dark"'); + expect(html).not.toContain('value="dark" checked'); + expect((html.match(/name="theme"/g) || []).length).toBe(2); + }); + + it('omits the radio group label when label is false', () => { + const html = render('radio', { + key: 'k', + label: false, + items: [{ id: 'k-0', value: 'a', label: 'A', checked: false }] + }); + expect(html).not.toContain('iframely-option__label'); + expect(html).not.toContain('iframely-option__group-inline'); + }); + + it('renders select options with the selected attribute', () => { + const html = render('select', { + key: 'style', + label: 'Widget style', + items: [ + { value: 'mini', label: 'Mini', checked: false }, + { value: 'classic', label: 'Classic', checked: true } + ] + }); + expect(html).toContain('Classic'); + expect(html).toContain(''); + }); + + it('renders a range input with min/max/step and CSS custom properties', () => { + const html = render('range', { key: 'h', label: 'Height', min: 100, max: 600, value: 200 }); + expect(html).toContain('type="range"'); + expect(html).toContain('min="100"'); + expect(html).toContain('max="600"'); + expect(html).toContain('step="1"'); + expect(html).toContain('value="200"'); + expect(html).toContain('style="--min: 100; --max: 600; --val: 200;"'); + }); + + it('renders a text input with the requested inputType and placeholder', () => { + const html = render('text', { + key: 'start', + label: 'Start from', + inputType: 'number', + placeholder: 'ex.: 11', + value: 5 + }); + expect(html).toContain('type="number"'); + expect(html).toContain('placeholder="ex.: 11"'); + expect(html).toContain('value="5"'); + }); +}); diff --git a/tests/unit/ssr.test.ts b/tests/unit/ssr.test.ts new file mode 100644 index 0000000..435c57c --- /dev/null +++ b/tests/unit/ssr.test.ts @@ -0,0 +1,42 @@ +// @vitest-environment node +// +// Simulates an isomorphic (e.g. SvelteKit) server pass: no window, no +// document. Importing any public entry must neither throw nor run browser +// side effects, and the exported singleton must be an inert no-op stub. +import { describe, expect, it } from 'vitest'; + +describe('SSR import (node environment)', () => { + it('runs without browser globals', () => { + expect(typeof window).toBe('undefined'); + expect(typeof document).toBe('undefined'); + }); + + it('imports the main entry without errors or side effects', async () => { + const { iframely } = await import('../../src/main'); + expect(iframely).toBeDefined(); + // Nothing booted: the browser-only bootstrap was skipped. + expect(iframely._loaded).toBeUndefined(); + }); + + it('tolerates API calls on the server as no-ops', async () => { + const { iframely } = await import('../../src/main'); + expect(() => { + iframely.on('load', () => {}); + iframely.trigger('anything'); + iframely.load(); + iframely.unload(); + iframely.configure({ api_key: 'x' }); + iframely.setTheme('dark'); + iframely.cancelWidget(); + }).not.toThrow(); + // The stub must stay stateless: one server module instance is shared + // across requests. + expect(iframely.config).toEqual({}); + }); + + it('imports the options and i18n entries without errors', async () => { + await expect(import('../../src/main-options')).resolves.toBeDefined(); + await expect(import('../../src/options/lang/labels.de')).resolves.toBeDefined(); + await expect(import('../../src/options/lang/labels.fr')).resolves.toBeDefined(); + }); +}); diff --git a/tests/unit/theme.test.ts b/tests/unit/theme.test.ts new file mode 100644 index 0000000..e695b37 --- /dev/null +++ b/tests/unit/theme.test.ts @@ -0,0 +1,63 @@ +import { beforeAll, beforeEach, describe, expect, it, vi } from 'vitest'; +import iframely from '../../src/iframely'; +import { boot as bootConst } from '../../src/const'; +import { boot as bootEvents } from '../../src/events'; +import { boot as bootUtils } from '../../src/utils'; +import { boot as bootTheme } from '../../src/theme'; + +beforeAll(() => { + bootConst(); + bootEvents(); + bootUtils(); + bootTheme(); +}); + +beforeEach(() => { + iframely.config = {}; + document.body.innerHTML = ''; +}); + +describe('setTheme', () => { + it('stores a supported theme, notifies iframes and triggers set-theme', () => { + document.body.innerHTML = ''; + const iframe = document.querySelector('iframe')!; + const spy = vi.spyOn(iframe.contentWindow!, 'postMessage'); + const setThemeCb = vi.fn(); + iframely.on('set-theme', setThemeCb); + + iframely.setTheme('dark'); + + expect(iframely.config.theme).toBe('dark'); + expect(setThemeCb).toHaveBeenCalledWith('dark'); + expect(JSON.parse(spy.mock.calls[0][0] as string)).toMatchObject({ + method: 'setTheme', + data: 'dark' + }); + }); + + it('scopes to a container element when provided, without touching config', () => { + document.body.innerHTML = + '
' + + ''; + const inside = document.querySelector('#scope iframe')!; + const outside = document.querySelector('#outside')!; + const insideSpy = vi.spyOn(inside.contentWindow!, 'postMessage'); + const outsideSpy = vi.spyOn(outside.contentWindow!, 'postMessage'); + + iframely.setTheme('light', document.getElementById('scope')!); + + expect(insideSpy).toHaveBeenCalled(); + expect(outsideSpy).not.toHaveBeenCalled(); + expect(iframely.config.theme).toBeUndefined(); + }); + + it('warns and does nothing for an unsupported theme', () => { + const warn = vi.spyOn(console, 'warn').mockImplementation(() => {}); + + iframely.setTheme('neon'); + + expect(warn).toHaveBeenCalled(); + expect(iframely.config.theme).toBeUndefined(); + warn.mockRestore(); + }); +}); diff --git a/tests/unit/translator.test.ts b/tests/unit/translator.test.ts new file mode 100644 index 0000000..7f380aa --- /dev/null +++ b/tests/unit/translator.test.ts @@ -0,0 +1,36 @@ +import { describe, expect, it } from 'vitest'; +import iframely from '../../src/iframely'; +import * as translator from '../../src/options/translator'; + +describe('translator', () => { + it('assigns iframely.optionsTranslator at import time', () => { + expect(typeof iframely.optionsTranslator).toBe('function'); + }); + + it('translates registered labels', () => { + translator.registerLabels('de', { Light: 'Hell', Dark: 'Dunkel' }); + const t = iframely.optionsTranslator!('de')!; + expect(t('Light')).toBe('Hell'); + expect(t('Dark')).toBe('Dunkel'); + }); + + it('falls back to the original label for unknown or empty translations', () => { + translator.registerLabels('de', { Auto: '' }); + const t = iframely.optionsTranslator!('de')!; + expect(t('Auto')).toBe('Auto'); + expect(t('Unknown label')).toBe('Unknown label'); + }); + + it('returns identity for an unregistered language', () => { + const t = iframely.optionsTranslator!('xx')!; + expect(t('Light')).toBe('Light'); + }); + + it('merges labels registered in multiple calls', () => { + translator.registerLabels('fr', { Light: 'Lumière' }); + translator.registerLabels('fr', { Dark: 'Sombre' }); + const t = iframely.optionsTranslator!('fr')!; + expect(t('Light')).toBe('Lumière'); + expect(t('Dark')).toBe('Sombre'); + }); +}); diff --git a/tests/unit/unload.test.ts b/tests/unit/unload.test.ts new file mode 100644 index 0000000..fdbd4d2 --- /dev/null +++ b/tests/unit/unload.test.ts @@ -0,0 +1,99 @@ +import { beforeAll, beforeEach, describe, expect, it, vi } from 'vitest'; +import iframely from '../../src/iframely'; +import { boot as bootConst } from '../../src/const'; +import { boot as bootEvents } from '../../src/events'; +import { boot as bootUtils } from '../../src/utils'; +import { boot as bootImport } from '../../src/import'; + +beforeAll(() => { + bootConst(); + bootEvents(); + bootUtils(); + bootImport(); +}); + +beforeEach(() => { + iframely.config = {}; + document.body.innerHTML = ''; +}); + +function widgetHtml(src: string): string { + return ( + '
' + + '' + + '
' + ); +} + +describe('unload', () => { + it('removes all built widgets from the document', () => { + document.body.innerHTML = + widgetHtml('https://cdn.iframe.ly/api/iframe?url=https%3A%2F%2Fx.com') + + widgetHtml('https://iframely.net/abc123') + + ''; + + iframely.unload(); + + expect(document.querySelectorAll('.iframely-embed')).toHaveLength(0); + // Non-Iframely iframes are left alone. + expect(document.getElementById('foreign')).not.toBeNull(); + }); + + it('removes lazy widgets that have not loaded yet (data-iframely-url)', () => { + document.body.innerHTML = + '
' + + '' + + '
'; + + iframely.unload(); + + expect(document.querySelectorAll('.iframely-embed')).toHaveLength(0); + }); + + it('scopes removal to a container when one is given', () => { + document.body.innerHTML = + '
' + + widgetHtml('https://cdn.iframe.ly/one') + + '
' + + '
' + + widgetHtml('https://cdn.iframe.ly/two') + + '
'; + + iframely.unload(document.getElementById('a')!); + + expect(document.querySelectorAll('#a .iframely-embed')).toHaveLength(0); + expect(document.querySelectorAll('#b .iframely-embed')).toHaveLength(1); + }); + + it('leaves widgets without the library wrapper structure alone', () => { + document.body.innerHTML = '
'; + + iframely.unload(); + + expect(document.querySelectorAll('iframe')).toHaveLength(1); + }); + + it('triggers unload-widget per widget and a final unload event', () => { + document.body.innerHTML = widgetHtml('https://cdn.iframe.ly/one'); + const perWidget = vi.fn(); + const done = vi.fn(); + iframely.on('unload-widget', perWidget); + iframely.on('unload', done); + + iframely.unload(); + + expect(perWidget).toHaveBeenCalledTimes(1); + expect(perWidget.mock.calls[0][0].iframe).toBeInstanceOf(HTMLIFrameElement); + expect(done).toHaveBeenCalledWith(undefined); + }); + + it('resets transient import state on a full unload', () => { + iframely.import = document.createElement('script'); + + iframely.unload(); + + expect(iframely.import).toBeUndefined(); + }); +}); diff --git a/tests/unit/utils.test.ts b/tests/unit/utils.test.ts new file mode 100644 index 0000000..430a9c9 --- /dev/null +++ b/tests/unit/utils.test.ts @@ -0,0 +1,217 @@ +import { beforeAll, beforeEach, describe, expect, it } from 'vitest'; +import iframely from '../../src/iframely'; +import { boot as bootConst } from '../../src/const'; +import { boot as bootEvents } from '../../src/events'; +import { boot as bootUtils } from '../../src/utils'; +import { boot as bootDeprecated } from '../../src/deprecated'; +import * as utils from '../../src/utils'; + +beforeAll(() => { + bootConst(); + bootEvents(); + bootUtils(); +}); + +beforeEach(() => { + iframely.config = {}; + document.body.innerHTML = ''; +}); + +describe('addQueryString', () => { + it('appends params with ? for a bare href and & for an existing query', () => { + expect(utils.addQueryString('//host/path', { a: 'b' })).toBe('//host/path?a=b'); + expect(utils.addQueryString('//host/path?x=1', { a: 'b' })).toBe('//host/path?x=1&a=b'); + }); + + it('url-encodes values', () => { + expect(utils.addQueryString('//host/p', { url: 'https://a.com/?x=1&y=2' })).toBe( + '//host/p?url=' + encodeURIComponent('https://a.com/?x=1&y=2') + ); + }); + + it('converts booleans to 1/0 except for _-prefixed keys', () => { + expect(utils.addQueryString('//host/p', { lazy: true, autoplay: false })).toBe( + '//host/p?lazy=1&autoplay=0' + ); + expect(utils.addQueryString('//host/p', { _opt: true })).toBe('//host/p?_opt=true'); + }); + + it('expands arrays into repeated params', () => { + expect(utils.addQueryString('//host/p', { uri: ['a', 'b'] })).toBe('//host/p?uri=a&uri=b'); + }); + + it('skips undefined values and keys already present in the href', () => { + expect(utils.addQueryString('//host/p?a=1', { a: '2', b: undefined, c: '3' })).toBe( + '//host/p?a=1&c=3' + ); + }); +}); + +describe('parseQueryString', () => { + it('parses all params without an allowlist', () => { + expect(utils.parseQueryString('//host/p?a=1&b=x%20y')).toEqual({ a: '1', b: 'x y' }); + }); + + it('returns an empty object without a query string', () => { + expect(utils.parseQueryString('//host/p')).toEqual({}); + }); + + it('filters by allowlist of strings and regexps', () => { + const parsed = utils.parseQueryString('//h/p?api_key=k&_opt=1&evil=x', ['api_key', /^_.+/]); + expect(parsed).toEqual({ api_key: 'k', _opt: '1' }); + }); +}); + +describe('getEndpoint', () => { + it('prefixes relative paths with the CDN and protocol slashes', () => { + expect(utils.getEndpoint('/api/iframe', { url: 'https://x.com' })).toBe( + '//cdn.iframe.ly/api/iframe?url=' + encodeURIComponent('https://x.com') + ); + }); + + it('prefers an explicit CDN option and removes it from the query', () => { + const endpoint = utils.getEndpoint('/api/iframe', { CDN: '//other.cdn', url: 'u' }); + expect(endpoint).toBe('//other.cdn/api/iframe?url=u'); + }); + + it('keeps absolute urls untouched apart from the query string', () => { + expect(utils.getEndpoint('https://cdn.iframe.ly/abc', { v: 1 })).toBe( + 'https://cdn.iframe.ly/abc?v=1' + ); + }); + + it('adds matching iframely.config values for config_params, including regex matches', () => { + iframely.configure({ api_key: 'KEY', _theme_opt: 'x', unrelated: 'nope' }); + const endpoint = utils.getEndpoint( + '/api/iframe', + { url: 'u' }, + iframely.SUPPORTED_QUERY_STRING + ); + expect(endpoint).toContain('api_key=KEY'); + expect(endpoint).toContain('_theme_opt=x'); + expect(endpoint).not.toContain('unrelated'); + }); +}); + +describe('configure', () => { + it('normalizes falsy/truthy string and number values to booleans', () => { + iframely.configure({ + a: '0', + b: 'false', + c: 0, + d: false, + e: '1', + f: 'true', + g: 1, + h: true, + i: 'text' + }); + expect(iframely.config).toEqual({ + a: false, + b: false, + c: false, + d: false, + e: true, + f: true, + g: true, + h: true, + i: 'text' + }); + }); + + it('does not override values previously disabled with false', () => { + iframely.configure({ lazy: false }); + iframely.configure({ lazy: true }); + expect(iframely.config.lazy).toBe(false); + }); + + it('ignores undefined options', () => { + expect(() => iframely.configure(undefined)).not.toThrow(); + }); + + it('keeps extendOptions as a deprecated alias', () => { + bootDeprecated(); + expect(iframely.extendOptions).toBe(iframely.configure); + }); +}); + +describe('widget wrappers', () => { + function buildWidgetDom( + inner = '' + ) { + document.body.innerHTML = + '
' + + inner + + '
'; + return document.querySelector('.iframely-responsive')!.firstElementChild!; + } + + it('getIframeWrapper finds both wrappers for a well-formed widget', () => { + const iframe = buildWidgetDom(); + const wrapper = utils.getIframeWrapper(iframe, true)!; + expect(wrapper.aspectWrapper.className).toBe('iframely-responsive'); + expect(wrapper.maxWidthWrapper.className).toBe('iframely-embed'); + }); + + it('getIframeWrapper returns undefined without the wrapper structure', () => { + document.body.innerHTML = '
'; + expect(utils.getIframeWrapper(document.querySelector('iframe')!, true)).toBeUndefined(); + }); + + it('getWidget extracts the url from an iframe src url= param', () => { + const iframe = buildWidgetDom(); + const widget = utils.getWidget(iframe)!; + expect(widget.iframe).toBe(iframe); + expect(widget.url).toBe('https://x.com'); + }); + + it('getWidget extracts the url from an anchor href', () => { + const a = buildWidgetDom(''); + const widget = utils.getWidget(a)!; + expect(widget.url).toBe('https://y.com/page'); + }); + + it('addDefaultWrappers inserts the two-wrapper structure before the element', () => { + document.body.innerHTML = '

x

'; + const a = document.getElementById('link')!; + const wrapper = utils.addDefaultWrappers(a); + expect(wrapper.maxWidthWrapper.className).toBe('iframely-embed'); + expect(wrapper.aspectWrapper.parentNode).toBe(wrapper.maxWidthWrapper); + expect(wrapper.maxWidthWrapper.nextSibling).toBe(a); + }); +}); + +describe('setStyles', () => { + it('converts numeric values to px', () => { + const el = document.createElement('div'); + utils.setStyles(el, { height: 400, width: '250' }); + expect(el.style.height).toBe('400px'); + expect(el.style.width).toBe('250px'); + }); + + it('keeps non-numeric string values as-is and skips max-width "keep"', () => { + const el = document.createElement('div'); + el.style.maxWidth = '100px'; + utils.setStyles(el, { position: 'absolute', 'max-width': 'keep' }); + expect(el.style.position).toBe('absolute'); + expect(el.style.maxWidth).toBe('100px'); + }); + + it('tolerates a missing element', () => { + expect(() => utils.setStyles(null, { height: 1 })).not.toThrow(); + }); +}); + +describe('createScript / applyNonce', () => { + it('creates a script and applies the configured nonce', () => { + iframely.config.nonce = 'abc123'; + const script = utils.createScript(); + expect(script.tagName).toBe('SCRIPT'); + expect(script.nonce).toBe('abc123'); + }); + + it('leaves nonce empty when not configured', () => { + const script = utils.createScript(); + expect(script.nonce).toBeFalsy(); + }); +}); diff --git a/tsconfig.build.json b/tsconfig.build.json new file mode 100644 index 0000000..678fb95 --- /dev/null +++ b/tsconfig.build.json @@ -0,0 +1,13 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "noEmit": false, + "emitDeclarationOnly": true, + "declaration": true, + "declarationMap": false, + "rootDir": "src", + "outDir": "dist/types" + }, + "include": ["src"], + "exclude": ["src/options/lang/labels.LAN.example.ts"] +} diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..9039213 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,27 @@ +{ + "compilerOptions": { + "target": "ES2022", + "lib": ["ES2022", "DOM", "DOM.Iterable"], + "module": "ESNext", + "moduleResolution": "bundler", + "types": [], + + "strict": true, + "noImplicitOverride": true, + "noFallthroughCasesInSwitch": true, + + "isolatedModules": true, + "verbatimModuleSyntax": true, + "forceConsistentCasingInFileNames": true, + "skipLibCheck": true, + "noEmit": true + }, + "include": [ + "src", + "tests", + "vitest.config.ts", + "playwright.config.ts", + "oxlint.config.ts", + "oxfmt.config.ts" + ] +} diff --git a/vitest.config.ts b/vitest.config.ts new file mode 100644 index 0000000..fea63e2 --- /dev/null +++ b/vitest.config.ts @@ -0,0 +1,8 @@ +import { defineConfig } from 'vitest/config'; + +export default defineConfig({ + test: { + environment: 'jsdom', + include: ['tests/unit/**/*.test.ts'] + } +}); diff --git a/webpack.config.js b/webpack.config.js deleted file mode 100644 index 8f08f95..0000000 --- a/webpack.config.js +++ /dev/null @@ -1,4 +0,0 @@ -module.exports = function(env) { - const environment = env.production ? 'production' : 'development'; - return require(`./conf/webpack.${environment}.js`); -};