From 3e246c37f5f1e72af2b5af703bb6a605a6b89a89 Mon Sep 17 00:00:00 2001 From: Xinyi Feng Date: Mon, 10 Jun 2024 14:54:05 -0700 Subject: [PATCH 01/10] remove v1 engine --- plugins/experimentation/.eslintignore | 1 - plugins/experimentation/.eslintrc.js | 21 - plugins/experimentation/.stylelintrc.json | 8 - plugins/experimentation/CODE_OF_CONDUCT.md | 74 - plugins/experimentation/LICENSE.md | 201 - plugins/experimentation/README.md | 187 - plugins/experimentation/package-lock.json | 4348 -------------------- plugins/experimentation/package.json | 37 - plugins/experimentation/src/index.js | 712 ---- plugins/experimentation/src/preview.css | 276 -- plugins/experimentation/src/preview.js | 518 --- plugins/experimentation/src/ued.js | 192 - 12 files changed, 6575 deletions(-) delete mode 100644 plugins/experimentation/.eslintignore delete mode 100644 plugins/experimentation/.eslintrc.js delete mode 100644 plugins/experimentation/.stylelintrc.json delete mode 100644 plugins/experimentation/CODE_OF_CONDUCT.md delete mode 100644 plugins/experimentation/LICENSE.md delete mode 100644 plugins/experimentation/README.md delete mode 100644 plugins/experimentation/package-lock.json delete mode 100644 plugins/experimentation/package.json delete mode 100644 plugins/experimentation/src/index.js delete mode 100644 plugins/experimentation/src/preview.css delete mode 100644 plugins/experimentation/src/preview.js delete mode 100644 plugins/experimentation/src/ued.js diff --git a/plugins/experimentation/.eslintignore b/plugins/experimentation/.eslintignore deleted file mode 100644 index 0a87cad0..00000000 --- a/plugins/experimentation/.eslintignore +++ /dev/null @@ -1 +0,0 @@ -src/ued.js \ No newline at end of file diff --git a/plugins/experimentation/.eslintrc.js b/plugins/experimentation/.eslintrc.js deleted file mode 100644 index 76f220db..00000000 --- a/plugins/experimentation/.eslintrc.js +++ /dev/null @@ -1,21 +0,0 @@ -module.exports = { - root: true, - extends: 'airbnb-base', - env: { - browser: true, - }, - parser: '@babel/eslint-parser', - parserOptions: { - allowImportExportEverywhere: true, - sourceType: 'module', - requireConfigFile: false, - }, - rules: { - // allow reassigning param - 'no-param-reassign': [2, { props: false }], - 'linebreak-style': ['error', 'unix'], - 'import/extensions': ['error', { - js: 'always', - }], - }, -}; diff --git a/plugins/experimentation/.stylelintrc.json b/plugins/experimentation/.stylelintrc.json deleted file mode 100644 index 153d9d99..00000000 --- a/plugins/experimentation/.stylelintrc.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "extends": [ - "stylelint-config-standard" - ], - "rules": { - "declaration-block-no-redundant-longhand-properties": null - } -} diff --git a/plugins/experimentation/CODE_OF_CONDUCT.md b/plugins/experimentation/CODE_OF_CONDUCT.md deleted file mode 100644 index 75f92707..00000000 --- a/plugins/experimentation/CODE_OF_CONDUCT.md +++ /dev/null @@ -1,74 +0,0 @@ -# Adobe Code of Conduct - -## Our Pledge - -In the interest of fostering an open and welcoming environment, we as -contributors and maintainers pledge to making participation in our project and -our community a harassment-free experience for everyone, regardless of age, body -size, disability, ethnicity, gender identity and expression, level of experience, -nationality, personal appearance, race, religion, or sexual identity and -orientation. - -## Our Standards - -Examples of behavior that contributes to creating a positive environment -include: - -* Using welcoming and inclusive language -* Being respectful of differing viewpoints and experiences -* Gracefully accepting constructive criticism -* Focusing on what is best for the community -* Showing empathy towards other community members - -Examples of unacceptable behavior by participants include: - -* The use of sexualized language or imagery and unwelcome sexual attention or -advances -* Trolling, insulting/derogatory comments, and personal or political attacks -* Public or private harassment -* Publishing others' private information, such as a physical or electronic - address, without explicit permission -* Other conduct which could reasonably be considered inappropriate in a - professional setting - -## Our Responsibilities - -Project maintainers are responsible for clarifying the standards of acceptable -behavior and are expected to take appropriate and fair corrective action in -response to any instances of unacceptable behavior. - -Project maintainers have the right and responsibility to remove, edit, or -reject comments, commits, code, wiki edits, issues, and other contributions -that are not aligned to this Code of Conduct, or to ban temporarily or -permanently any contributor for other behaviors that they deem inappropriate, -threatening, offensive, or harmful. - -## Scope - -This Code of Conduct applies both within project spaces and in public spaces -when an individual is representing the project or its community. Examples of -representing a project or community include using an official project e-mail -address, posting via an official social media account, or acting as an appointed -representative at an online or offline event. Representation of a project may be -further defined and clarified by project maintainers. - -## Enforcement - -Instances of abusive, harassing, or otherwise unacceptable behavior may be -reported by contacting the project team at Grp-opensourceoffice@adobe.com. All -complaints will be reviewed and investigated and will result in a response that -is deemed necessary and appropriate to the circumstances. The project team is -obligated to maintain confidentiality with regard to the reporter of an incident. -Further details of specific enforcement policies may be posted separately. - -Project maintainers who do not follow or enforce the Code of Conduct in good -faith may face temporary or permanent repercussions as determined by other -members of the project's leadership. - -## Attribution - -This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, -available at [http://contributor-covenant.org/version/1/4][version] - -[homepage]: http://contributor-covenant.org -[version]: http://contributor-covenant.org/version/1/4/ \ No newline at end of file diff --git a/plugins/experimentation/LICENSE.md b/plugins/experimentation/LICENSE.md deleted file mode 100644 index f49a4e16..00000000 --- a/plugins/experimentation/LICENSE.md +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. \ No newline at end of file diff --git a/plugins/experimentation/README.md b/plugins/experimentation/README.md deleted file mode 100644 index 1a9efb14..00000000 --- a/plugins/experimentation/README.md +++ /dev/null @@ -1,187 +0,0 @@ -# AEM Edge Delivery Services Experimentation - -The AEM Experimentation plugin helps you quickly set up experimentation and segmentation on your AEM project. -It is currently available to customers in collaboration with AEM Engineering via co-innovation VIP Projects. -To implement experimentation or personalization use-cases, please reach out to the AEM Engineering team in the Slack channel dedicated to your project. - -## Features - -The AEM Experimentation plugin supports: -- :busts_in_silhouette: serving different content variations to different audiences, including custom audience definitions for your project that can be either resolved directly in-browser or against a trusted backend API. -- :money_with_wings: serving different content variations based on marketing campaigns you are running, so that you can easily track email and/or social campaigns -- :chart_with_upwards_trend: running A/B test experiments on a set of variants to measure and improve the conversion on your site. This works particularly with our :chart: [RUM conversion tracking plugin](https://github.com/adobe/franklin-rum-conversion). -- :rocket: easy simulation of each experience and basic reporting leveraging in-page overlays - -## Installation - -Add the plugin to your AEM project by running: -```sh -git subtree add --squash --prefix plugins/experimentation git@github.com:adobe/aem-experimentation.git main -``` - -If you later want to pull the latest changes and update your local copy of the plugin -```sh -git subtree pull --squash --prefix plugins/experimentation git@github.com:adobe/aem-experimentation.git main -``` - -If you prefer using `https` links you'd replace `git@github.com:adobe/aem-experimentation.git` in the above commands by `https://github.com/adobe/aem-experimentation.git`. - -If the `subtree pull` command is failing with an error like: -``` -fatal: can't squash-merge: 'plugins/experimentation' was never added -``` -you can just delete the folder and re-add the plugin via the `git subtree add` command above. - -## Project instrumentation - -:warning: The plugin requires that you have a recent RUM instrumentation from the AEM boilerplate that supports `sampleRUM.always`. If you are getting errors that `.on` cannot be called on an `undefined` object, please apply the changes from https://github.com/adobe/aem-boilerplate/pull/247/files to your `lib-franklin.js`. - -### On top of the plugin system - -The easiest way to add the plugin is if your project is set up with the plugin system extension in the boilerplate. -You'll know you have it if `window.hlx.plugins` is defined on your page. - -If you don't have it, you can follow the proposal in https://github.com/adobe/aem-lib/pull/23 and https://github.com/adobe/aem-boilerplate/pull/275 and apply the changes to your `aem.js`/`lib-franklin.js` and `scripts.js`. - -Once you have confirmed this, you'll need to edit your `scripts.js` in your AEM project and add the following at the start of the file: -```js -const AUDIENCES = { - mobile: () => window.innerWidth < 600, - desktop: () => window.innerWidth >= 600, - // define your custom audiences here as needed -}; - -window.hlx.plugins.add('experimentation', { - condition: () => getMetadata('experiment') - || Object.keys(getAllMetadata('campaign')).length - || Object.keys(getAllMetadata('audience')).length, - options: { audiences: AUDIENCES }, - url: '/plugins/experimentation/src/index.js', -}); -``` - -### On top of a regular boilerplate project - -Typically, you'd know you don't have the plugin system if you don't see a reference to `window.hlx.plugins` in your `scripts.js`. In that case, you can still manually instrument this plugin in your project by falling back to a more manual instrumentation. To properly connect and configure the plugin for your project, you'll need to edit your `scripts.js` in your AEM project and add the following: - -1. at the start of the file: - ```js - const AUDIENCES = { - mobile: () => window.innerWidth < 600, - desktop: () => window.innerWidth >= 600, - // define your custom audiences here as needed - }; - - /** - * Gets all the metadata elements that are in the given scope. - * @param {String} scope The scope/prefix for the metadata - * @returns an array of HTMLElement nodes that match the given scope - */ - export function getAllMetadata(scope) { - return [...document.head.querySelectorAll(`meta[property^="${scope}:"],meta[name^="${scope}-"]`)] - .reduce((res, meta) => { - const id = toClassName(meta.name - ? meta.name.substring(scope.length + 1) - : meta.getAttribute('property').split(':')[1]); - res[id] = meta.getAttribute('content'); - return res; - }, {}); - } - ``` -2. if this is the first plugin you add to your project, you'll also need to add: - ```js - // Define an execution context - const pluginContext = { - getAllMetadata, - getMetadata, - loadCSS, - loadScript, - sampleRUM, - toCamelCase, - toClassName, - }; - ``` -3. Early in the `loadEager` method you'll need to add: - ```js - async function loadEager(doc) { - … - // Add below snippet early in the eager phase - if (getMetadata('experiment') - || Object.keys(getAllMetadata('campaign')).length - || Object.keys(getAllMetadata('audience')).length) { - // eslint-disable-next-line import/no-relative-packages - const { loadEager: runEager } = await import('../plugins/experimentation/src/index.js'); - await runEager(document, { audiences: AUDIENCES }, pluginContext); - } - … - } - ``` - This needs to be done as early as possible since this will be blocking the eager phase and impacting your LCP, so we want this to execute as soon as possible. -4. Finally at the end of the `loadLazy` method you'll have to add: - ```js - async function loadLazy(doc) { - … - // Add below snippet at the end of the lazy phase - if ((getMetadata('experiment') - || Object.keys(getAllMetadata('campaign')).length - || Object.keys(getAllMetadata('audience')).length)) { - // eslint-disable-next-line import/no-relative-packages - const { loadLazy: runLazy } = await import('../plugins/experimentation/src/index.js'); - await runLazy(document, { audiences: AUDIENCES }, pluginContext); - } - } - ``` - This is mostly used for the authoring overlay, and as such isn't essential to the page rendering, so having it at the end of the lazy phase is good enough. - -### Custom options - -There are various aspects of the plugin that you can configure via options you are passing to the 2 main methods above (`runEager`/`runLazy`). -You have already seen the `audiences` option in the examples above, but here is the full list we support: - -```js -runEager.call(document, { - // Overrides the base path if the plugin was installed in a sub-directory - basePath: '', - - // Lets you configure the prod environment. - // (prod environments do not get the pill overlay) - prodHost: 'www.my-website.com', - // if you have several, or need more complex logic to toggle pill overlay, you can use - isProd: () => window.location.hostname.endsWith('hlx.page') - || window.location.hostname === ('localhost'), - - /* Generic properties */ - // RUM sampling rate on regular AEM pages is 1 out of 100 page views - // but we increase this by default for audiences, campaigns and experiments - // to 1 out of 10 page views so we can collect metrics faster of the relative - // short durations of those campaigns/experiments - rumSamplingRate: 10, - - // the storage type used to persist data between page views - // (for instance to remember what variant in an experiment the user was served) - storage: window.SessionStorage, - - /* Audiences related properties */ - // See more details on the dedicated Audiences page linked below - audiences: {}, - audiencesMetaTagPrefix: 'audience', - audiencesQueryParameter: 'audience', - - /* Campaigns related properties */ - // See more details on the dedicated Campaigns page linked below - campaignsMetaTagPrefix: 'campaign', - campaignsQueryParameter: 'campaign', - - /* Experimentation related properties */ - // See more details on the dedicated Experiments page linked below - experimentsRoot: '/experiments', - experimentsConfigFile: 'manifest.json', - experimentsMetaTag: 'experiment', - experimentsQueryParameter: 'experiment', -}, pluginContext); -``` - -For detailed implementation instructions on the different features, please read the dedicated pages we have on those topics: -- [Audiences](https://github.com/adobe/aem-experimentation/wiki/Audiences) -- [Campaigns](https://github.com/adobe/aem-experimentation/wiki/Campaigns) -- [Experiments](https://github.com/adobe/aem-experimentation/wiki/Experiments) diff --git a/plugins/experimentation/package-lock.json b/plugins/experimentation/package-lock.json deleted file mode 100644 index 30b8d3e7..00000000 --- a/plugins/experimentation/package-lock.json +++ /dev/null @@ -1,4348 +0,0 @@ -{ - "name": "@adobe/aem-experimentation", - "version": "1.0.0", - "lockfileVersion": 3, - "requires": true, - "packages": { - "": { - "name": "@adobe/aem-experimentation", - "version": "1.0.0", - "license": "Apache-2.0", - "devDependencies": { - "@babel/eslint-parser": "7.22.15", - "eslint": "8.48.0", - "eslint-config-airbnb-base": "15.0.0", - "eslint-plugin-import": "2.28.1", - "stylelint": "15.10.3", - "stylelint-config-standard": "34.0.0" - } - }, - "node_modules/@aashutoshrathi/word-wrap": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz", - "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/@ampproject/remapping": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.1.tgz", - "integrity": "sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==", - "dev": true, - "peer": true, - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.0", - "@jridgewell/trace-mapping": "^0.3.9" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@babel/code-frame": { - "version": "7.22.13", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.13.tgz", - "integrity": "sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==", - "dev": true, - "dependencies": { - "@babel/highlight": "^7.22.13", - "chalk": "^2.4.2" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/code-frame/node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/code-frame/node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/code-frame/node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/@babel/code-frame/node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true - }, - "node_modules/@babel/code-frame/node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "dev": true, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/@babel/code-frame/node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/code-frame/node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/compat-data": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.22.20.tgz", - "integrity": "sha512-BQYjKbpXjoXwFW5jGqiizJQQT/aC7pFm9Ok1OWssonuguICi264lbgMzRp2ZMmRSlfkX6DsWDDcsrctK8Rwfiw==", - "dev": true, - "peer": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/core": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.23.0.tgz", - "integrity": "sha512-97z/ju/Jy1rZmDxybphrBuI+jtJjFVoz7Mr9yUQVVVi+DNZE333uFQeMOqcCIy1x3WYBIbWftUSLmbNXNT7qFQ==", - "dev": true, - "peer": true, - "dependencies": { - "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.22.13", - "@babel/generator": "^7.23.0", - "@babel/helper-compilation-targets": "^7.22.15", - "@babel/helper-module-transforms": "^7.23.0", - "@babel/helpers": "^7.23.0", - "@babel/parser": "^7.23.0", - "@babel/template": "^7.22.15", - "@babel/traverse": "^7.23.0", - "@babel/types": "^7.23.0", - "convert-source-map": "^2.0.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.2", - "json5": "^2.2.3", - "semver": "^6.3.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/babel" - } - }, - "node_modules/@babel/core/node_modules/json5": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", - "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", - "dev": true, - "peer": true, - "bin": { - "json5": "lib/cli.js" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/@babel/eslint-parser": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/eslint-parser/-/eslint-parser-7.22.15.tgz", - "integrity": "sha512-yc8OOBIQk1EcRrpizuARSQS0TWAcOMpEJ1aafhNznaeYkeL+OhqnDObGFylB8ka8VFF/sZc+S4RzHyO+3LjQxg==", - "dev": true, - "dependencies": { - "@nicolo-ribaudo/eslint-scope-5-internals": "5.1.1-v1", - "eslint-visitor-keys": "^2.1.0", - "semver": "^6.3.1" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || >=14.0.0" - }, - "peerDependencies": { - "@babel/core": "^7.11.0", - "eslint": "^7.5.0 || ^8.0.0" - } - }, - "node_modules/@babel/eslint-parser/node_modules/eslint-visitor-keys": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", - "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/@babel/generator": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.0.tgz", - "integrity": "sha512-lN85QRR+5IbYrMWM6Y4pE/noaQtg4pNiqeNGX60eqOfo6gtEj6uw/JagelB8vVztSd7R6M5n1+PQkDbHbBRU4g==", - "dev": true, - "peer": true, - "dependencies": { - "@babel/types": "^7.23.0", - "@jridgewell/gen-mapping": "^0.3.2", - "@jridgewell/trace-mapping": "^0.3.17", - "jsesc": "^2.5.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-compilation-targets": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.15.tgz", - "integrity": "sha512-y6EEzULok0Qvz8yyLkCvVX+02ic+By2UdOhylwUOvOn9dvYc9mKICJuuU1n1XBI02YWsNsnrY1kc6DVbjcXbtw==", - "dev": true, - "peer": true, - "dependencies": { - "@babel/compat-data": "^7.22.9", - "@babel/helper-validator-option": "^7.22.15", - "browserslist": "^4.21.9", - "lru-cache": "^5.1.1", - "semver": "^6.3.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-compilation-targets/node_modules/lru-cache": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", - "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", - "dev": true, - "peer": true, - "dependencies": { - "yallist": "^3.0.2" - } - }, - "node_modules/@babel/helper-compilation-targets/node_modules/yallist": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", - "dev": true, - "peer": true - }, - "node_modules/@babel/helper-environment-visitor": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz", - "integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==", - "dev": true, - "peer": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-function-name": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz", - "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==", - "dev": true, - "peer": true, - "dependencies": { - "@babel/template": "^7.22.15", - "@babel/types": "^7.23.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-hoist-variables": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz", - "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==", - "dev": true, - "peer": true, - "dependencies": { - "@babel/types": "^7.22.5" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-module-imports": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.22.15.tgz", - "integrity": "sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w==", - "dev": true, - "peer": true, - "dependencies": { - "@babel/types": "^7.22.15" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-module-transforms": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.23.0.tgz", - "integrity": "sha512-WhDWw1tdrlT0gMgUJSlX0IQvoO1eN279zrAUbVB+KpV2c3Tylz8+GnKOLllCS6Z/iZQEyVYxhZVUdPTqs2YYPw==", - "dev": true, - "peer": true, - "dependencies": { - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-module-imports": "^7.22.15", - "@babel/helper-simple-access": "^7.22.5", - "@babel/helper-split-export-declaration": "^7.22.6", - "@babel/helper-validator-identifier": "^7.22.20" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/helper-simple-access": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz", - "integrity": "sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==", - "dev": true, - "peer": true, - "dependencies": { - "@babel/types": "^7.22.5" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-split-export-declaration": { - "version": "7.22.6", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", - "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", - "dev": true, - "peer": true, - "dependencies": { - "@babel/types": "^7.22.5" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-string-parser": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz", - "integrity": "sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==", - "dev": true, - "peer": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-validator-identifier": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", - "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-validator-option": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.22.15.tgz", - "integrity": "sha512-bMn7RmyFjY/mdECUbgn9eoSY4vqvacUnS9i9vGAGttgFWesO6B4CYWA7XlpbWgBt71iv/hfbPlynohStqnu5hA==", - "dev": true, - "peer": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helpers": { - "version": "7.23.1", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.23.1.tgz", - "integrity": "sha512-chNpneuK18yW5Oxsr+t553UZzzAs3aZnFm4bxhebsNTeshrC95yA7l5yl7GBAG+JG1rF0F7zzD2EixK9mWSDoA==", - "dev": true, - "peer": true, - "dependencies": { - "@babel/template": "^7.22.15", - "@babel/traverse": "^7.23.0", - "@babel/types": "^7.23.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/highlight": { - "version": "7.22.13", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.13.tgz", - "integrity": "sha512-C/BaXcnnvBCmHTpz/VGZ8jgtE2aYlW4hxDhseJAWZb7gqGM/qtCK6iZUb0TyKFf7BOUsBH7Q7fkRsDRhg1XklQ==", - "dev": true, - "dependencies": { - "@babel/helper-validator-identifier": "^7.22.5", - "chalk": "^2.4.2", - "js-tokens": "^4.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/highlight/node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/highlight/node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/highlight/node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/@babel/highlight/node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true - }, - "node_modules/@babel/highlight/node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "dev": true, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/@babel/highlight/node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/highlight/node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/parser": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.0.tgz", - "integrity": "sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw==", - "dev": true, - "peer": true, - "bin": { - "parser": "bin/babel-parser.js" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@babel/template": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz", - "integrity": "sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==", - "dev": true, - "peer": true, - "dependencies": { - "@babel/code-frame": "^7.22.13", - "@babel/parser": "^7.22.15", - "@babel/types": "^7.22.15" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/traverse": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.0.tgz", - "integrity": "sha512-t/QaEvyIoIkwzpiZ7aoSKK8kObQYeF7T2v+dazAYCb8SXtp58zEVkWW7zAnju8FNKNdr4ScAOEDmMItbyOmEYw==", - "dev": true, - "peer": true, - "dependencies": { - "@babel/code-frame": "^7.22.13", - "@babel/generator": "^7.23.0", - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-function-name": "^7.23.0", - "@babel/helper-hoist-variables": "^7.22.5", - "@babel/helper-split-export-declaration": "^7.22.6", - "@babel/parser": "^7.23.0", - "@babel/types": "^7.23.0", - "debug": "^4.1.0", - "globals": "^11.1.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/traverse/node_modules/globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", - "dev": true, - "peer": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/types": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.0.tgz", - "integrity": "sha512-0oIyUfKoI3mSqMvsxBdclDwxXKXAUA8v/apZbc+iSyARYou1o8ZGDxbUYyLFoW2arqS2jDGqJuZvv1d/io1axg==", - "dev": true, - "peer": true, - "dependencies": { - "@babel/helper-string-parser": "^7.22.5", - "@babel/helper-validator-identifier": "^7.22.20", - "to-fast-properties": "^2.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@csstools/css-parser-algorithms": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/@csstools/css-parser-algorithms/-/css-parser-algorithms-2.3.1.tgz", - "integrity": "sha512-xrvsmVUtefWMWQsGgFffqWSK03pZ1vfDki4IVIIUxxDKnGBzqNgv0A7SB1oXtVNEkcVO8xi1ZrTL29HhSu5kGA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/csstools" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - } - ], - "engines": { - "node": "^14 || ^16 || >=18" - }, - "peerDependencies": { - "@csstools/css-tokenizer": "^2.2.0" - } - }, - "node_modules/@csstools/css-tokenizer": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@csstools/css-tokenizer/-/css-tokenizer-2.2.0.tgz", - "integrity": "sha512-wErmsWCbsmig8sQKkM6pFhr/oPha1bHfvxsUY5CYSQxwyhA9Ulrs8EqCgClhg4Tgg2XapVstGqSVcz0xOYizZA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/csstools" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - } - ], - "engines": { - "node": "^14 || ^16 || >=18" - } - }, - "node_modules/@csstools/media-query-list-parser": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@csstools/media-query-list-parser/-/media-query-list-parser-2.1.4.tgz", - "integrity": "sha512-V/OUXYX91tAC1CDsiY+HotIcJR+vPtzrX8pCplCpT++i8ThZZsq5F5dzZh/bDM3WUOjrvC1ljed1oSJxMfjqhw==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/csstools" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - } - ], - "engines": { - "node": "^14 || ^16 || >=18" - }, - "peerDependencies": { - "@csstools/css-parser-algorithms": "^2.3.1", - "@csstools/css-tokenizer": "^2.2.0" - } - }, - "node_modules/@csstools/selector-specificity": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@csstools/selector-specificity/-/selector-specificity-3.0.0.tgz", - "integrity": "sha512-hBI9tfBtuPIi885ZsZ32IMEU/5nlZH/KOVYJCOh7gyMxaVLGmLedYqFN6Ui1LXkI8JlC8IsuC0rF0btcRZKd5g==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/csstools" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - } - ], - "engines": { - "node": "^14 || ^16 || >=18" - }, - "peerDependencies": { - "postcss-selector-parser": "^6.0.13" - } - }, - "node_modules/@eslint-community/eslint-utils": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", - "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", - "dev": true, - "dependencies": { - "eslint-visitor-keys": "^3.3.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" - } - }, - "node_modules/@eslint-community/regexpp": { - "version": "4.8.0", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.8.0.tgz", - "integrity": "sha512-JylOEEzDiOryeUnFbQz+oViCXS0KsvR1mvHkoMiu5+UiBvy+RYX7tzlIIIEstF/gVa2tj9AQXk3dgnxv6KxhFg==", - "dev": true, - "engines": { - "node": "^12.0.0 || ^14.0.0 || >=16.0.0" - } - }, - "node_modules/@eslint/eslintrc": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.2.tgz", - "integrity": "sha512-+wvgpDsrB1YqAMdEUCcnTlpfVBH7Vqn6A/NT3D8WVXFIaKMlErPIZT3oCIAVCOtarRpMtelZLqJeU3t7WY6X6g==", - "dev": true, - "dependencies": { - "ajv": "^6.12.4", - "debug": "^4.3.2", - "espree": "^9.6.0", - "globals": "^13.19.0", - "ignore": "^5.2.0", - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", - "minimatch": "^3.1.2", - "strip-json-comments": "^3.1.1" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/@eslint/js": { - "version": "8.48.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.48.0.tgz", - "integrity": "sha512-ZSjtmelB7IJfWD2Fvb7+Z+ChTIKWq6kjda95fLcQKNS5aheVHn4IkfgRQE3sIIzTcSLwLcLZUD9UBt+V7+h+Pw==", - "dev": true, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, - "node_modules/@humanwhocodes/config-array": { - "version": "0.11.11", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.11.tgz", - "integrity": "sha512-N2brEuAadi0CcdeMXUkhbZB84eskAc8MEX1By6qEchoVywSgXPIjou4rYsl0V3Hj0ZnuGycGCjdNgockbzeWNA==", - "dev": true, - "dependencies": { - "@humanwhocodes/object-schema": "^1.2.1", - "debug": "^4.1.1", - "minimatch": "^3.0.5" - }, - "engines": { - "node": ">=10.10.0" - } - }, - "node_modules/@humanwhocodes/module-importer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", - "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", - "dev": true, - "engines": { - "node": ">=12.22" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/nzakas" - } - }, - "node_modules/@humanwhocodes/object-schema": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", - "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", - "dev": true - }, - "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", - "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", - "dev": true, - "peer": true, - "dependencies": { - "@jridgewell/set-array": "^1.0.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz", - "integrity": "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==", - "dev": true, - "peer": true, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/set-array": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", - "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", - "dev": true, - "peer": true, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.4.15", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", - "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", - "dev": true, - "peer": true - }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.19", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.19.tgz", - "integrity": "sha512-kf37QtfW+Hwx/buWGMPcR60iF9ziHa6r/CZJIHbmcm4+0qrXiVdxegAH0F6yddEVQ7zdkjcGCgCzUu+BcbhQxw==", - "dev": true, - "peer": true, - "dependencies": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" - } - }, - "node_modules/@nicolo-ribaudo/eslint-scope-5-internals": { - "version": "5.1.1-v1", - "resolved": "https://registry.npmjs.org/@nicolo-ribaudo/eslint-scope-5-internals/-/eslint-scope-5-internals-5.1.1-v1.tgz", - "integrity": "sha512-54/JRvkLIzzDWshCWfuhadfrfZVPiElY8Fcgmg1HroEly/EDSszzhBAsarCux+D/kOslTRquNzuyGSmUSTTHGg==", - "dev": true, - "dependencies": { - "eslint-scope": "5.1.1" - } - }, - "node_modules/@nicolo-ribaudo/eslint-scope-5-internals/node_modules/eslint-scope": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", - "dev": true, - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/@nicolo-ribaudo/eslint-scope-5-internals/node_modules/estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", - "dev": true, - "dependencies": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", - "dev": true, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", - "dev": true, - "dependencies": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@types/json5": { - "version": "0.0.29", - "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", - "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", - "dev": true - }, - "node_modules/@types/minimist": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.2.tgz", - "integrity": "sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ==", - "dev": true - }, - "node_modules/@types/normalize-package-data": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.1.tgz", - "integrity": "sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==", - "dev": true - }, - "node_modules/acorn": { - "version": "8.10.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz", - "integrity": "sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==", - "dev": true, - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/acorn-jsx": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", - "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", - "dev": true, - "peerDependencies": { - "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" - } - }, - "node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true - }, - "node_modules/array-buffer-byte-length": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz", - "integrity": "sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "is-array-buffer": "^3.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/array-includes": { - "version": "3.1.6", - "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.6.tgz", - "integrity": "sha512-sgTbLvL6cNnw24FnbaDyjmvddQ2ML8arZsgaJhoABMoplz/4QRhtrYS+alr1BUM1Bwp6dhx8vVCBSLG+StwOFw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4", - "get-intrinsic": "^1.1.3", - "is-string": "^1.0.7" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/array-union": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/array.prototype.findlastindex": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.2.tgz", - "integrity": "sha512-tb5thFFlUcp7NdNF6/MpDk/1r/4awWG1FIz3YqDf+/zJSTezBb+/5WViH41obXULHVpDzoiCLpJ/ZO9YbJMsdw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4", - "es-shim-unscopables": "^1.0.0", - "get-intrinsic": "^1.1.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/array.prototype.flat": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.1.tgz", - "integrity": "sha512-roTU0KWIOmJ4DRLmwKd19Otg0/mT3qPNt0Qb3GWW8iObuZXxrjB/pzn0R3hqpRSWg4HCwqx+0vwOnWnvlOyeIA==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4", - "es-shim-unscopables": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/array.prototype.flatmap": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.1.tgz", - "integrity": "sha512-8UGn9O1FDVvMNB0UlLv4voxRMze7+FpHyF5mSMRjWHUMlpoDViniy05870VlxhfgTnLbpuwTzvD76MTtWxB/mQ==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4", - "es-shim-unscopables": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/arraybuffer.prototype.slice": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.1.tgz", - "integrity": "sha512-09x0ZWFEjj4WD8PDbykUwo3t9arLn8NIzmmYEJFpYekOAQjpkGSyrQhNoRTcwwcFRu+ycWF78QZ63oWTqSjBcw==", - "dev": true, - "dependencies": { - "array-buffer-byte-length": "^1.0.0", - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "get-intrinsic": "^1.2.1", - "is-array-buffer": "^3.0.2", - "is-shared-array-buffer": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/arrify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", - "integrity": "sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/astral-regex": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", - "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/available-typed-arrays": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", - "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true - }, - "node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dev": true, - "dependencies": { - "fill-range": "^7.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/browserslist": { - "version": "4.22.1", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.22.1.tgz", - "integrity": "sha512-FEVc202+2iuClEhZhrWy6ZiAcRLvNMyYcxZ8raemul1DYVOVdFsbqckWLdsixQZCpJlwe77Z3UTalE7jsjnKfQ==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "peer": true, - "dependencies": { - "caniuse-lite": "^1.0.30001541", - "electron-to-chromium": "^1.4.535", - "node-releases": "^2.0.13", - "update-browserslist-db": "^1.0.13" - }, - "bin": { - "browserslist": "cli.js" - }, - "engines": { - "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" - } - }, - "node_modules/call-bind": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", - "dev": true, - "dependencies": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/camelcase": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", - "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/camelcase-keys": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-7.0.2.tgz", - "integrity": "sha512-Rjs1H+A9R+Ig+4E/9oyB66UC5Mj9Xq3N//vcLf2WzgdTi/3gUu3Z9KoqmlrEG4VuuLK8wJHofxzdQXz/knhiYg==", - "dev": true, - "dependencies": { - "camelcase": "^6.3.0", - "map-obj": "^4.1.0", - "quick-lru": "^5.1.1", - "type-fest": "^1.2.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/camelcase-keys/node_modules/type-fest": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-1.4.0.tgz", - "integrity": "sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/caniuse-lite": { - "version": "1.0.30001543", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001543.tgz", - "integrity": "sha512-qxdO8KPWPQ+Zk6bvNpPeQIOH47qZSYdFZd6dXQzb2KzhnSXju4Kd7H1PkSJx6NICSMgo/IhRZRhhfPTHYpJUCA==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/caniuse-lite" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "peer": true - }, - "node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/colord": { - "version": "2.9.3", - "resolved": "https://registry.npmjs.org/colord/-/colord-2.9.3.tgz", - "integrity": "sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw==", - "dev": true - }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "dev": true - }, - "node_modules/confusing-browser-globals": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/confusing-browser-globals/-/confusing-browser-globals-1.0.11.tgz", - "integrity": "sha512-JsPKdmh8ZkmnHxDk55FZ1TqVLvEQTvoByJZRN9jzI0UjxK/QgAmsphz7PGtqgPieQZ/CQcHWXCR7ATDNhGe+YA==", - "dev": true - }, - "node_modules/convert-source-map": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", - "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", - "dev": true, - "peer": true - }, - "node_modules/cosmiconfig": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.2.0.tgz", - "integrity": "sha512-3rTMnFJA1tCOPwRxtgF4wd7Ab2qvDbL8jX+3smjIbS4HlZBagTlpERbdN7iAbWlrfxE3M8c27kTwTawQ7st+OQ==", - "dev": true, - "dependencies": { - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", - "parse-json": "^5.0.0", - "path-type": "^4.0.0" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/d-fischer" - } - }, - "node_modules/cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, - "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/css-functions-list": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/css-functions-list/-/css-functions-list-3.2.0.tgz", - "integrity": "sha512-d/jBMPyYybkkLVypgtGv12R+pIFw4/f/IHtCTxWpZc8ofTYOPigIgmA6vu5rMHartZC+WuXhBUHfnyNUIQSYrg==", - "dev": true, - "engines": { - "node": ">=12.22" - } - }, - "node_modules/css-tree": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.3.1.tgz", - "integrity": "sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw==", - "dev": true, - "dependencies": { - "mdn-data": "2.0.30", - "source-map-js": "^1.0.1" - }, - "engines": { - "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0" - } - }, - "node_modules/cssesc": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", - "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", - "dev": true, - "bin": { - "cssesc": "bin/cssesc" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/decamelize": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-5.0.1.tgz", - "integrity": "sha512-VfxadyCECXgQlkoEAjeghAr5gY3Hf+IKjKb+X8tGVDtveCjN+USwprd2q3QXBR9T1+x2DG0XZF5/w+7HAtSaXA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/decamelize-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/decamelize-keys/-/decamelize-keys-1.1.1.tgz", - "integrity": "sha512-WiPxgEirIV0/eIOMcnFBA3/IJZAZqKnwAwWyvvdi4lsr1WCN22nhdf/3db3DoZcUjTV2SqfzIwNyp6y2xs3nmg==", - "dev": true, - "dependencies": { - "decamelize": "^1.1.0", - "map-obj": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/decamelize-keys/node_modules/decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/decamelize-keys/node_modules/map-obj": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", - "integrity": "sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/deep-is": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", - "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", - "dev": true - }, - "node_modules/define-properties": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.0.tgz", - "integrity": "sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA==", - "dev": true, - "dependencies": { - "has-property-descriptors": "^1.0.0", - "object-keys": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/dir-glob": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", - "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", - "dev": true, - "dependencies": { - "path-type": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", - "dev": true, - "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/electron-to-chromium": { - "version": "1.4.539", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.539.tgz", - "integrity": "sha512-wRmWJ8F7rgmINuI32S6r2SLrw/h/bJQsDSvBiq9GBfvc2Lh73qTOwn73r3Cf67mjVgFGJYcYtmERzySa5jIWlg==", - "dev": true, - "peer": true - }, - "node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "node_modules/error-ex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", - "dev": true, - "dependencies": { - "is-arrayish": "^0.2.1" - } - }, - "node_modules/es-abstract": { - "version": "1.22.1", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.22.1.tgz", - "integrity": "sha512-ioRRcXMO6OFyRpyzV3kE1IIBd4WG5/kltnzdxSCqoP8CMGs/Li+M1uF5o7lOkZVFjDs+NLesthnF66Pg/0q0Lw==", - "dev": true, - "dependencies": { - "array-buffer-byte-length": "^1.0.0", - "arraybuffer.prototype.slice": "^1.0.1", - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", - "es-set-tostringtag": "^2.0.1", - "es-to-primitive": "^1.2.1", - "function.prototype.name": "^1.1.5", - "get-intrinsic": "^1.2.1", - "get-symbol-description": "^1.0.0", - "globalthis": "^1.0.3", - "gopd": "^1.0.1", - "has": "^1.0.3", - "has-property-descriptors": "^1.0.0", - "has-proto": "^1.0.1", - "has-symbols": "^1.0.3", - "internal-slot": "^1.0.5", - "is-array-buffer": "^3.0.2", - "is-callable": "^1.2.7", - "is-negative-zero": "^2.0.2", - "is-regex": "^1.1.4", - "is-shared-array-buffer": "^1.0.2", - "is-string": "^1.0.7", - "is-typed-array": "^1.1.10", - "is-weakref": "^1.0.2", - "object-inspect": "^1.12.3", - "object-keys": "^1.1.1", - "object.assign": "^4.1.4", - "regexp.prototype.flags": "^1.5.0", - "safe-array-concat": "^1.0.0", - "safe-regex-test": "^1.0.0", - "string.prototype.trim": "^1.2.7", - "string.prototype.trimend": "^1.0.6", - "string.prototype.trimstart": "^1.0.6", - "typed-array-buffer": "^1.0.0", - "typed-array-byte-length": "^1.0.0", - "typed-array-byte-offset": "^1.0.0", - "typed-array-length": "^1.0.4", - "unbox-primitive": "^1.0.2", - "which-typed-array": "^1.1.10" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/es-set-tostringtag": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.1.tgz", - "integrity": "sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg==", - "dev": true, - "dependencies": { - "get-intrinsic": "^1.1.3", - "has": "^1.0.3", - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-shim-unscopables": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.0.tgz", - "integrity": "sha512-Jm6GPcCdC30eMLbZ2x8z2WuRwAws3zTBBKuusffYVUrNj/GVSUAZ+xKMaUpfNDR5IbyNA5LJbaecoUVbmUcB1w==", - "dev": true, - "dependencies": { - "has": "^1.0.3" - } - }, - "node_modules/es-to-primitive": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", - "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", - "dev": true, - "dependencies": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", - "dev": true, - "peer": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint": { - "version": "8.48.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.48.0.tgz", - "integrity": "sha512-sb6DLeIuRXxeM1YljSe1KEx9/YYeZFQWcV8Rq9HfigmdDEugjLEVEa1ozDjL6YDjBpQHPJxJzze+alxi4T3OLg==", - "dev": true, - "dependencies": { - "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.6.1", - "@eslint/eslintrc": "^2.1.2", - "@eslint/js": "8.48.0", - "@humanwhocodes/config-array": "^0.11.10", - "@humanwhocodes/module-importer": "^1.0.1", - "@nodelib/fs.walk": "^1.2.8", - "ajv": "^6.12.4", - "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", - "debug": "^4.3.2", - "doctrine": "^3.0.0", - "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.2.2", - "eslint-visitor-keys": "^3.4.3", - "espree": "^9.6.1", - "esquery": "^1.4.2", - "esutils": "^2.0.2", - "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^6.0.1", - "find-up": "^5.0.0", - "glob-parent": "^6.0.2", - "globals": "^13.19.0", - "graphemer": "^1.4.0", - "ignore": "^5.2.0", - "imurmurhash": "^0.1.4", - "is-glob": "^4.0.0", - "is-path-inside": "^3.0.3", - "js-yaml": "^4.1.0", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", - "lodash.merge": "^4.6.2", - "minimatch": "^3.1.2", - "natural-compare": "^1.4.0", - "optionator": "^0.9.3", - "strip-ansi": "^6.0.1", - "text-table": "^0.2.0" - }, - "bin": { - "eslint": "bin/eslint.js" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint-config-airbnb-base": { - "version": "15.0.0", - "resolved": "https://registry.npmjs.org/eslint-config-airbnb-base/-/eslint-config-airbnb-base-15.0.0.tgz", - "integrity": "sha512-xaX3z4ZZIcFLvh2oUNvcX5oEofXda7giYmuplVxoOg5A7EXJMrUyqRgR+mhDhPK8LZ4PttFOBvCYDbX3sUoUig==", - "dev": true, - "dependencies": { - "confusing-browser-globals": "^1.0.10", - "object.assign": "^4.1.2", - "object.entries": "^1.1.5", - "semver": "^6.3.0" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - }, - "peerDependencies": { - "eslint": "^7.32.0 || ^8.2.0", - "eslint-plugin-import": "^2.25.2" - } - }, - "node_modules/eslint-import-resolver-node": { - "version": "0.3.9", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz", - "integrity": "sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==", - "dev": true, - "dependencies": { - "debug": "^3.2.7", - "is-core-module": "^2.13.0", - "resolve": "^1.22.4" - } - }, - "node_modules/eslint-import-resolver-node/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/eslint-module-utils": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.8.0.tgz", - "integrity": "sha512-aWajIYfsqCKRDgUfjEXNN/JlrzauMuSEy5sbd7WXbtW3EH6A6MpwEh42c7qD+MqQo9QMJ6fWLAeIJynx0g6OAw==", - "dev": true, - "dependencies": { - "debug": "^3.2.7" - }, - "engines": { - "node": ">=4" - }, - "peerDependenciesMeta": { - "eslint": { - "optional": true - } - } - }, - "node_modules/eslint-module-utils/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/eslint-plugin-import": { - "version": "2.28.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.28.1.tgz", - "integrity": "sha512-9I9hFlITvOV55alzoKBI+K9q74kv0iKMeY6av5+umsNwayt59fz692daGyjR+oStBQgx6nwR9rXldDev3Clw+A==", - "dev": true, - "dependencies": { - "array-includes": "^3.1.6", - "array.prototype.findlastindex": "^1.2.2", - "array.prototype.flat": "^1.3.1", - "array.prototype.flatmap": "^1.3.1", - "debug": "^3.2.7", - "doctrine": "^2.1.0", - "eslint-import-resolver-node": "^0.3.7", - "eslint-module-utils": "^2.8.0", - "has": "^1.0.3", - "is-core-module": "^2.13.0", - "is-glob": "^4.0.3", - "minimatch": "^3.1.2", - "object.fromentries": "^2.0.6", - "object.groupby": "^1.0.0", - "object.values": "^1.1.6", - "semver": "^6.3.1", - "tsconfig-paths": "^3.14.2" - }, - "engines": { - "node": ">=4" - }, - "peerDependencies": { - "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8" - } - }, - "node_modules/eslint-plugin-import/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/eslint-plugin-import/node_modules/doctrine": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", - "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", - "dev": true, - "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/eslint-scope": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", - "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", - "dev": true, - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint-visitor-keys": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", - "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", - "dev": true, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/espree": { - "version": "9.6.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", - "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", - "dev": true, - "dependencies": { - "acorn": "^8.9.0", - "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.4.1" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/esquery": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", - "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", - "dev": true, - "dependencies": { - "estraverse": "^5.1.0" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/esrecurse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", - "dev": true, - "dependencies": { - "estraverse": "^5.2.0" - }, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true - }, - "node_modules/fast-glob": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.1.tgz", - "integrity": "sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==", - "dev": true, - "dependencies": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.4" - }, - "engines": { - "node": ">=8.6.0" - } - }, - "node_modules/fast-glob/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true - }, - "node_modules/fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", - "dev": true - }, - "node_modules/fastest-levenshtein": { - "version": "1.0.16", - "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz", - "integrity": "sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==", - "dev": true, - "engines": { - "node": ">= 4.9.1" - } - }, - "node_modules/fastq": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", - "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==", - "dev": true, - "dependencies": { - "reusify": "^1.0.4" - } - }, - "node_modules/file-entry-cache": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", - "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", - "dev": true, - "dependencies": { - "flat-cache": "^3.0.4" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - } - }, - "node_modules/fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "dev": true, - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dev": true, - "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/flat-cache": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.1.0.tgz", - "integrity": "sha512-OHx4Qwrrt0E4jEIcI5/Xb+f+QmJYNj2rrK8wiIdQOIrB9WrrJL8cjZvXdXuBTkkEwEqLycb5BeZDV1o2i9bTew==", - "dev": true, - "dependencies": { - "flatted": "^3.2.7", - "keyv": "^4.5.3", - "rimraf": "^3.0.2" - }, - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/flatted": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz", - "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==", - "dev": true - }, - "node_modules/for-each": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", - "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", - "dev": true, - "dependencies": { - "is-callable": "^1.1.3" - } - }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", - "dev": true - }, - "node_modules/function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true - }, - "node_modules/function.prototype.name": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.6.tgz", - "integrity": "sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "functions-have-names": "^1.2.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/functions-have-names": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", - "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/gensync": { - "version": "1.0.0-beta.2", - "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", - "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", - "dev": true, - "peer": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/get-intrinsic": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.1.tgz", - "integrity": "sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==", - "dev": true, - "dependencies": { - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-proto": "^1.0.1", - "has-symbols": "^1.0.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/get-symbol-description": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", - "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/glob-parent": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", - "dev": true, - "dependencies": { - "is-glob": "^4.0.3" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/global-modules": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-2.0.0.tgz", - "integrity": "sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A==", - "dev": true, - "dependencies": { - "global-prefix": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/global-prefix": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-3.0.0.tgz", - "integrity": "sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg==", - "dev": true, - "dependencies": { - "ini": "^1.3.5", - "kind-of": "^6.0.2", - "which": "^1.3.1" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/global-prefix/node_modules/which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "dev": true, - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "which": "bin/which" - } - }, - "node_modules/globals": { - "version": "13.21.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.21.0.tgz", - "integrity": "sha512-ybyme3s4yy/t/3s35bewwXKOf7cvzfreG2lH0lZl0JB7I4GxRP2ghxOK/Nb9EkRXdbBXZLfq/p/0W2JUONB/Gg==", - "dev": true, - "dependencies": { - "type-fest": "^0.20.2" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/globalthis": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz", - "integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==", - "dev": true, - "dependencies": { - "define-properties": "^1.1.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/globby": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", - "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", - "dev": true, - "dependencies": { - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.2.9", - "ignore": "^5.2.0", - "merge2": "^1.4.1", - "slash": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/globjoin": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/globjoin/-/globjoin-0.1.4.tgz", - "integrity": "sha512-xYfnw62CKG8nLkZBfWbhWwDw02CHty86jfPcc2cr3ZfeuK9ysoVPPEUxf21bAD/rWAgk52SuBrLJlefNy8mvFg==", - "dev": true - }, - "node_modules/gopd": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", - "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", - "dev": true, - "dependencies": { - "get-intrinsic": "^1.1.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/graphemer": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", - "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", - "dev": true - }, - "node_modules/hard-rejection": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/hard-rejection/-/hard-rejection-2.1.0.tgz", - "integrity": "sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dev": true, - "dependencies": { - "function-bind": "^1.1.1" - }, - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/has-bigints": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", - "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/has-property-descriptors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz", - "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==", - "dev": true, - "dependencies": { - "get-intrinsic": "^1.1.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-proto": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", - "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-symbols": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", - "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-tostringtag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", - "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", - "dev": true, - "dependencies": { - "has-symbols": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/hosted-git-info": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz", - "integrity": "sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==", - "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/html-tags": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/html-tags/-/html-tags-3.3.1.tgz", - "integrity": "sha512-ztqyC3kLto0e9WbNp0aeP+M3kTt+nbaIveGmUxAtZa+8iFgKLUOD4YKM5j+f3QD89bra7UeumolZHKuOXnTmeQ==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/ignore": { - "version": "5.2.4", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", - "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", - "dev": true, - "engines": { - "node": ">= 4" - } - }, - "node_modules/import-fresh": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", - "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", - "dev": true, - "dependencies": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/import-lazy": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-4.0.0.tgz", - "integrity": "sha512-rKtvo6a868b5Hu3heneU+L4yEQ4jYKLtjpnPeUdK7h0yzXGmyBTypknlkCvHFBqfX9YlorEiMM6Dnq/5atfHkw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", - "dev": true, - "engines": { - "node": ">=0.8.19" - } - }, - "node_modules/indent-string": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-5.0.0.tgz", - "integrity": "sha512-m6FAo/spmsW2Ab2fU35JTYwtOKa2yAwXSwgjSv1TJzh4Mh7mC3lzAOVLBprb72XsTrgkEIsl7YrFNAiDiRhIGg==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "dev": true, - "dependencies": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true - }, - "node_modules/ini": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", - "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", - "dev": true - }, - "node_modules/internal-slot": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.5.tgz", - "integrity": "sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ==", - "dev": true, - "dependencies": { - "get-intrinsic": "^1.2.0", - "has": "^1.0.3", - "side-channel": "^1.0.4" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/is-array-buffer": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.2.tgz", - "integrity": "sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.2.0", - "is-typed-array": "^1.1.10" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", - "dev": true - }, - "node_modules/is-bigint": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", - "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", - "dev": true, - "dependencies": { - "has-bigints": "^1.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-boolean-object": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", - "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-callable": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", - "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-core-module": { - "version": "2.13.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.0.tgz", - "integrity": "sha512-Z7dk6Qo8pOCp3l4tsX2C5ZVas4V+UxwQodwZhLopL91TX8UyyHEXafPcyoeeWuLrwzHcr3igO78wNLwHJHsMCQ==", - "dev": true, - "dependencies": { - "has": "^1.0.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-date-object": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", - "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", - "dev": true, - "dependencies": { - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dev": true, - "dependencies": { - "is-extglob": "^2.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-negative-zero": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", - "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true, - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/is-number-object": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", - "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", - "dev": true, - "dependencies": { - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-path-inside": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", - "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-plain-obj": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", - "integrity": "sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-plain-object": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", - "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-regex": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", - "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-shared-array-buffer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz", - "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-string": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", - "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", - "dev": true, - "dependencies": { - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-symbol": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", - "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", - "dev": true, - "dependencies": { - "has-symbols": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-typed-array": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.12.tgz", - "integrity": "sha512-Z14TF2JNG8Lss5/HMqt0//T9JeHXttXy5pH/DBU4vi98ozO2btxzq9MwYDZYnKwU8nRsz/+GVFVRDq3DkVuSPg==", - "dev": true, - "dependencies": { - "which-typed-array": "^1.1.11" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-weakref": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", - "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/isarray": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", - "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", - "dev": true - }, - "node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true - }, - "node_modules/js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true - }, - "node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/jsesc": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", - "dev": true, - "peer": true, - "bin": { - "jsesc": "bin/jsesc" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/json-buffer": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", - "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", - "dev": true - }, - "node_modules/json-parse-even-better-errors": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", - "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", - "dev": true - }, - "node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, - "node_modules/json-stable-stringify-without-jsonify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", - "dev": true - }, - "node_modules/json5": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", - "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", - "dev": true, - "dependencies": { - "minimist": "^1.2.0" - }, - "bin": { - "json5": "lib/cli.js" - } - }, - "node_modules/keyv": { - "version": "4.5.3", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.3.tgz", - "integrity": "sha512-QCiSav9WaX1PgETJ+SpNnx2PRRapJ/oRSXM4VO5OGYGSjrxbKPVFVhB3l2OCbLCk329N8qyAtsJjSjvVBWzEug==", - "dev": true, - "dependencies": { - "json-buffer": "3.0.1" - } - }, - "node_modules/kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/known-css-properties": { - "version": "0.28.0", - "resolved": "https://registry.npmjs.org/known-css-properties/-/known-css-properties-0.28.0.tgz", - "integrity": "sha512-9pSL5XB4J+ifHP0e0jmmC98OGC1nL8/JjS+fi6mnTlIf//yt/MfVLtKg7S6nCtj/8KTcWX7nRlY0XywoYY1ISQ==", - "dev": true - }, - "node_modules/levn": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", - "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", - "dev": true, - "dependencies": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/lines-and-columns": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", - "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", - "dev": true - }, - "node_modules/locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dev": true, - "dependencies": { - "p-locate": "^5.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/lodash.merge": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", - "dev": true - }, - "node_modules/lodash.truncate": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz", - "integrity": "sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw==", - "dev": true - }, - "node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/map-obj": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-4.3.0.tgz", - "integrity": "sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/mathml-tag-names": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/mathml-tag-names/-/mathml-tag-names-2.1.3.tgz", - "integrity": "sha512-APMBEanjybaPzUrfqU0IMU5I0AswKMH7k8OTLs0vvV4KZpExkTkY87nR/zpbuTPj+gARop7aGUbl11pnDfW6xg==", - "dev": true, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/mdn-data": { - "version": "2.0.30", - "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.30.tgz", - "integrity": "sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==", - "dev": true - }, - "node_modules/meow": { - "version": "10.1.5", - "resolved": "https://registry.npmjs.org/meow/-/meow-10.1.5.tgz", - "integrity": "sha512-/d+PQ4GKmGvM9Bee/DPa8z3mXs/pkvJE2KEThngVNOqtmljC6K7NMPxtc2JeZYTmpWb9k/TmxjeL18ez3h7vCw==", - "dev": true, - "dependencies": { - "@types/minimist": "^1.2.2", - "camelcase-keys": "^7.0.0", - "decamelize": "^5.0.0", - "decamelize-keys": "^1.1.0", - "hard-rejection": "^2.1.0", - "minimist-options": "4.1.0", - "normalize-package-data": "^3.0.2", - "read-pkg-up": "^8.0.0", - "redent": "^4.0.0", - "trim-newlines": "^4.0.2", - "type-fest": "^1.2.2", - "yargs-parser": "^20.2.9" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/meow/node_modules/type-fest": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-1.4.0.tgz", - "integrity": "sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "dev": true, - "engines": { - "node": ">= 8" - } - }, - "node_modules/micromatch": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", - "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", - "dev": true, - "dependencies": { - "braces": "^3.0.2", - "picomatch": "^2.3.1" - }, - "engines": { - "node": ">=8.6" - } - }, - "node_modules/min-indent": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", - "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/minimist": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", - "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/minimist-options": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/minimist-options/-/minimist-options-4.1.0.tgz", - "integrity": "sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==", - "dev": true, - "dependencies": { - "arrify": "^1.0.1", - "is-plain-obj": "^1.1.0", - "kind-of": "^6.0.3" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "node_modules/nanoid": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz", - "integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "bin": { - "nanoid": "bin/nanoid.cjs" - }, - "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" - } - }, - "node_modules/natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", - "dev": true - }, - "node_modules/node-releases": { - "version": "2.0.13", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.13.tgz", - "integrity": "sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ==", - "dev": true, - "peer": true - }, - "node_modules/normalize-package-data": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-3.0.3.tgz", - "integrity": "sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA==", - "dev": true, - "dependencies": { - "hosted-git-info": "^4.0.1", - "is-core-module": "^2.5.0", - "semver": "^7.3.4", - "validate-npm-package-license": "^3.0.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/normalize-package-data/node_modules/semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", - "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-inspect": { - "version": "1.12.3", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz", - "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "dev": true, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/object.assign": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz", - "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "has-symbols": "^1.0.3", - "object-keys": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object.entries": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.7.tgz", - "integrity": "sha512-jCBs/0plmPsOnrKAfFQXRG2NFjlhZgjjcBLSmTnEhU8U6vVTsVe8ANeQJCHTl3gSsI4J+0emOoCgoKlmQPMgmA==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/object.fromentries": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.7.tgz", - "integrity": "sha512-UPbPHML6sL8PI/mOqPwsH4G6iyXcCGzLin8KvEPenOZN5lpCNBZZQ+V62vdjB1mQHrmqGQt5/OJzemUA+KJmEA==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object.groupby": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.1.tgz", - "integrity": "sha512-HqaQtqLnp/8Bn4GL16cj+CUYbnpe1bh0TtEaWvybszDG4tgxCJuRpV8VGuvNaI1fAnI4lUJzDG55MXcOH4JZcQ==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "get-intrinsic": "^1.2.1" - } - }, - "node_modules/object.values": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.7.tgz", - "integrity": "sha512-aU6xnDFYT3x17e/f0IiiwlGPTy2jzMySGfUB4fq6z7CV8l85CWHDk5ErhyhpfDHhrOMwGFhSQkhMGHaIotA6Ng==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "dev": true, - "dependencies": { - "wrappy": "1" - } - }, - "node_modules/optionator": { - "version": "0.9.3", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", - "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==", - "dev": true, - "dependencies": { - "@aashutoshrathi/word-wrap": "^1.2.3", - "deep-is": "^0.1.3", - "fast-levenshtein": "^2.0.6", - "levn": "^0.4.1", - "prelude-ls": "^1.2.1", - "type-check": "^0.4.0" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "dependencies": { - "yocto-queue": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dev": true, - "dependencies": { - "p-limit": "^3.0.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/parent-module": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", - "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", - "dev": true, - "dependencies": { - "callsites": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/parse-json": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", - "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.0.0", - "error-ex": "^1.3.1", - "json-parse-even-better-errors": "^2.3.0", - "lines-and-columns": "^1.1.6" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true - }, - "node_modules/path-type": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/picocolors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", - "dev": true - }, - "node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true, - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/postcss": { - "version": "8.4.29", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.29.tgz", - "integrity": "sha512-cbI+jaqIeu/VGqXEarWkRCCffhjgXc0qjBtXpqJhTBohMUjUQnbBr0xqX3vEKudc4iviTewcJo5ajcec5+wdJw==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/postcss" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "dependencies": { - "nanoid": "^3.3.6", - "picocolors": "^1.0.0", - "source-map-js": "^1.0.2" - }, - "engines": { - "node": "^10 || ^12 || >=14" - } - }, - "node_modules/postcss-resolve-nested-selector": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/postcss-resolve-nested-selector/-/postcss-resolve-nested-selector-0.1.1.tgz", - "integrity": "sha512-HvExULSwLqHLgUy1rl3ANIqCsvMS0WHss2UOsXhXnQaZ9VCc2oBvIpXrl00IUFT5ZDITME0o6oiXeiHr2SAIfw==", - "dev": true - }, - "node_modules/postcss-safe-parser": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/postcss-safe-parser/-/postcss-safe-parser-6.0.0.tgz", - "integrity": "sha512-FARHN8pwH+WiS2OPCxJI8FuRJpTVnn6ZNFiqAM2aeW2LwTHWWmWgIyKC6cUo0L8aeKiF/14MNvnpls6R2PBeMQ==", - "dev": true, - "engines": { - "node": ">=12.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - "peerDependencies": { - "postcss": "^8.3.3" - } - }, - "node_modules/postcss-selector-parser": { - "version": "6.0.13", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.13.tgz", - "integrity": "sha512-EaV1Gl4mUEV4ddhDnv/xtj7sxwrwxdetHdWUGnT4VJQf+4d05v6lHYZr8N573k5Z0BViss7BDhfWtKS3+sfAqQ==", - "dev": true, - "dependencies": { - "cssesc": "^3.0.0", - "util-deprecate": "^1.0.2" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/postcss-value-parser": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", - "dev": true - }, - "node_modules/prelude-ls": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", - "dev": true, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/punycode": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", - "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/queue-microtask": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/quick-lru": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", - "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/read-pkg": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-6.0.0.tgz", - "integrity": "sha512-X1Fu3dPuk/8ZLsMhEj5f4wFAF0DWoK7qhGJvgaijocXxBmSToKfbFtqbxMO7bVjNA1dmE5huAzjXj/ey86iw9Q==", - "dev": true, - "dependencies": { - "@types/normalize-package-data": "^2.4.0", - "normalize-package-data": "^3.0.2", - "parse-json": "^5.2.0", - "type-fest": "^1.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/read-pkg-up": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-8.0.0.tgz", - "integrity": "sha512-snVCqPczksT0HS2EC+SxUndvSzn6LRCwpfSvLrIfR5BKDQQZMaI6jPRC9dYvYFDRAuFEAnkwww8kBBNE/3VvzQ==", - "dev": true, - "dependencies": { - "find-up": "^5.0.0", - "read-pkg": "^6.0.0", - "type-fest": "^1.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/read-pkg-up/node_modules/type-fest": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-1.4.0.tgz", - "integrity": "sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/read-pkg/node_modules/type-fest": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-1.4.0.tgz", - "integrity": "sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/redent": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/redent/-/redent-4.0.0.tgz", - "integrity": "sha512-tYkDkVVtYkSVhuQ4zBgfvciymHaeuel+zFKXShfDnFP5SyVEP7qo70Rf1jTOTCx3vGNAbnEi/xFkcfQVMIBWag==", - "dev": true, - "dependencies": { - "indent-string": "^5.0.0", - "strip-indent": "^4.0.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/regexp.prototype.flags": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.0.tgz", - "integrity": "sha512-0SutC3pNudRKgquxGoRGIz946MZVHqbNfPjBdxeOhBrdgDKlRoXmYLQN9xRbrR09ZXWeGAdPuif7egofn6v5LA==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "functions-have-names": "^1.2.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/require-from-string": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", - "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/resolve": { - "version": "1.22.4", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.4.tgz", - "integrity": "sha512-PXNdCiPqDqeUou+w1C2eTQbNfxKSuMxqTCuvlmmMsk1NWHL5fRrhY6Pl0qEYYc6+QqGClco1Qj8XnjPego4wfg==", - "dev": true, - "dependencies": { - "is-core-module": "^2.13.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - }, - "bin": { - "resolve": "bin/resolve" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/reusify": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", - "dev": true, - "engines": { - "iojs": ">=1.0.0", - "node": ">=0.10.0" - } - }, - "node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/run-parallel": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", - "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "dependencies": { - "queue-microtask": "^1.2.2" - } - }, - "node_modules/safe-array-concat": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.0.0.tgz", - "integrity": "sha512-9dVEFruWIsnie89yym+xWTAYASdpw3CJV7Li/6zBewGf9z2i1j31rP6jnY0pHEO4QZh6N0K11bFjWmdR8UGdPQ==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.2.0", - "has-symbols": "^1.0.3", - "isarray": "^2.0.5" - }, - "engines": { - "node": ">=0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/safe-regex-test": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.0.tgz", - "integrity": "sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.3", - "is-regex": "^1.1.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, - "dependencies": { - "shebang-regex": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/side-channel": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", - "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.0", - "get-intrinsic": "^1.0.2", - "object-inspect": "^1.9.0" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/signal-exit": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", - "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", - "dev": true, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/slice-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", - "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.0.0", - "astral-regex": "^2.0.0", - "is-fullwidth-code-point": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/slice-ansi?sponsor=1" - } - }, - "node_modules/source-map-js": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", - "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/spdx-correct": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz", - "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==", - "dev": true, - "dependencies": { - "spdx-expression-parse": "^3.0.0", - "spdx-license-ids": "^3.0.0" - } - }, - "node_modules/spdx-exceptions": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", - "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", - "dev": true - }, - "node_modules/spdx-expression-parse": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", - "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", - "dev": true, - "dependencies": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" - } - }, - "node_modules/spdx-license-ids": { - "version": "3.0.13", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.13.tgz", - "integrity": "sha512-XkD+zwiqXHikFZm4AX/7JSCXA98U5Db4AFd5XUg/+9UNtnH75+Z9KxtpYiJZx36mUDVOwH83pl7yvCer6ewM3w==", - "dev": true - }, - "node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/string.prototype.trim": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.7.tgz", - "integrity": "sha512-p6TmeT1T3411M8Cgg9wBTMRtY2q9+PNy9EV1i2lIXUN/btt763oIfxwN3RR8VU6wHX8j/1CFy0L+YuThm6bgOg==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/string.prototype.trimend": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.6.tgz", - "integrity": "sha512-JySq+4mrPf9EsDBEDYMOb/lM7XQLulwg5R/m1r0PXEFqrV0qHvl58sdTilSXtKOflCsK2E8jxf+GKC0T07RWwQ==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/string.prototype.trimstart": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.6.tgz", - "integrity": "sha512-omqjMDaY92pbn5HOX7f9IccLA+U1tA9GvtU4JrodiXFfYB7jPzzHpRzpglLAjtUV6bB557zwClJezTqnAiYnQA==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/strip-indent": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-4.0.0.tgz", - "integrity": "sha512-mnVSV2l+Zv6BLpSD/8V87CW/y9EmmbYzGCIavsnsI6/nwn26DwffM/yztm30Z/I2DY9wdS3vXVCMnHDgZaVNoA==", - "dev": true, - "dependencies": { - "min-indent": "^1.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/style-search": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/style-search/-/style-search-0.1.0.tgz", - "integrity": "sha512-Dj1Okke1C3uKKwQcetra4jSuk0DqbzbYtXipzFlFMZtowbF1x7BKJwB9AayVMyFARvU8EDrZdcax4At/452cAg==", - "dev": true - }, - "node_modules/stylelint": { - "version": "15.10.3", - "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-15.10.3.tgz", - "integrity": "sha512-aBQMMxYvFzJJwkmg+BUUg3YfPyeuCuKo2f+LOw7yYbU8AZMblibwzp9OV4srHVeQldxvSFdz0/Xu8blq2AesiA==", - "dev": true, - "dependencies": { - "@csstools/css-parser-algorithms": "^2.3.1", - "@csstools/css-tokenizer": "^2.2.0", - "@csstools/media-query-list-parser": "^2.1.4", - "@csstools/selector-specificity": "^3.0.0", - "balanced-match": "^2.0.0", - "colord": "^2.9.3", - "cosmiconfig": "^8.2.0", - "css-functions-list": "^3.2.0", - "css-tree": "^2.3.1", - "debug": "^4.3.4", - "fast-glob": "^3.3.1", - "fastest-levenshtein": "^1.0.16", - "file-entry-cache": "^6.0.1", - "global-modules": "^2.0.0", - "globby": "^11.1.0", - "globjoin": "^0.1.4", - "html-tags": "^3.3.1", - "ignore": "^5.2.4", - "import-lazy": "^4.0.0", - "imurmurhash": "^0.1.4", - "is-plain-object": "^5.0.0", - "known-css-properties": "^0.28.0", - "mathml-tag-names": "^2.1.3", - "meow": "^10.1.5", - "micromatch": "^4.0.5", - "normalize-path": "^3.0.0", - "picocolors": "^1.0.0", - "postcss": "^8.4.27", - "postcss-resolve-nested-selector": "^0.1.1", - "postcss-safe-parser": "^6.0.0", - "postcss-selector-parser": "^6.0.13", - "postcss-value-parser": "^4.2.0", - "resolve-from": "^5.0.0", - "string-width": "^4.2.3", - "strip-ansi": "^6.0.1", - "style-search": "^0.1.0", - "supports-hyperlinks": "^3.0.0", - "svg-tags": "^1.0.0", - "table": "^6.8.1", - "write-file-atomic": "^5.0.1" - }, - "bin": { - "stylelint": "bin/stylelint.mjs" - }, - "engines": { - "node": "^14.13.1 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/stylelint" - } - }, - "node_modules/stylelint-config-recommended": { - "version": "13.0.0", - "resolved": "https://registry.npmjs.org/stylelint-config-recommended/-/stylelint-config-recommended-13.0.0.tgz", - "integrity": "sha512-EH+yRj6h3GAe/fRiyaoO2F9l9Tgg50AOFhaszyfov9v6ayXJ1IkSHwTxd7lB48FmOeSGDPLjatjO11fJpmarkQ==", - "dev": true, - "engines": { - "node": "^14.13.1 || >=16.0.0" - }, - "peerDependencies": { - "stylelint": "^15.10.0" - } - }, - "node_modules/stylelint-config-standard": { - "version": "34.0.0", - "resolved": "https://registry.npmjs.org/stylelint-config-standard/-/stylelint-config-standard-34.0.0.tgz", - "integrity": "sha512-u0VSZnVyW9VSryBG2LSO+OQTjN7zF9XJaAJRX/4EwkmU0R2jYwmBSN10acqZisDitS0CLiEiGjX7+Hrq8TAhfQ==", - "dev": true, - "dependencies": { - "stylelint-config-recommended": "^13.0.0" - }, - "engines": { - "node": "^14.13.1 || >=16.0.0" - }, - "peerDependencies": { - "stylelint": "^15.10.0" - } - }, - "node_modules/stylelint/node_modules/balanced-match": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-2.0.0.tgz", - "integrity": "sha512-1ugUSr8BHXRnK23KfuYS+gVMC3LB8QGH9W1iGtDPsNWoQbgtXSExkBu2aDR4epiGWZOjZsj6lDl/N/AqqTC3UA==", - "dev": true - }, - "node_modules/stylelint/node_modules/resolve-from": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", - "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/supports-hyperlinks": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-3.0.0.tgz", - "integrity": "sha512-QBDPHyPQDRTy9ku4URNGY5Lah8PAaXs6tAAwp55sL5WCsSW7GIfdf6W5ixfziW+t7wh3GVvHyHHyQ1ESsoRvaA==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0", - "supports-color": "^7.0.0" - }, - "engines": { - "node": ">=14.18" - } - }, - "node_modules/supports-preserve-symlinks-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", - "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/svg-tags": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/svg-tags/-/svg-tags-1.0.0.tgz", - "integrity": "sha512-ovssysQTa+luh7A5Weu3Rta6FJlFBBbInjOh722LIt6klpU2/HtdUbszju/G4devcvk8PGt7FCLv5wftu3THUA==", - "dev": true - }, - "node_modules/table": { - "version": "6.8.1", - "resolved": "https://registry.npmjs.org/table/-/table-6.8.1.tgz", - "integrity": "sha512-Y4X9zqrCftUhMeH2EptSSERdVKt/nEdijTOacGD/97EKjhQ/Qs8RTlEGABSJNNN8lac9kheH+af7yAkEWlgneA==", - "dev": true, - "dependencies": { - "ajv": "^8.0.1", - "lodash.truncate": "^4.4.2", - "slice-ansi": "^4.0.0", - "string-width": "^4.2.3", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/table/node_modules/ajv": { - "version": "8.12.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", - "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/table/node_modules/json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true - }, - "node_modules/text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", - "dev": true - }, - "node_modules/to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", - "dev": true, - "peer": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "dependencies": { - "is-number": "^7.0.0" - }, - "engines": { - "node": ">=8.0" - } - }, - "node_modules/trim-newlines": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-4.1.1.tgz", - "integrity": "sha512-jRKj0n0jXWo6kh62nA5TEh3+4igKDXLvzBJcPpiizP7oOolUrYIxmVBG9TOtHYFHoddUk6YvAkGeGoSVTXfQXQ==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/tsconfig-paths": { - "version": "3.14.2", - "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.14.2.tgz", - "integrity": "sha512-o/9iXgCYc5L/JxCHPe3Hvh8Q/2xm5Z+p18PESBU6Ff33695QnCHBEjcytY2q19ua7Mbl/DavtBOLq+oG0RCL+g==", - "dev": true, - "dependencies": { - "@types/json5": "^0.0.29", - "json5": "^1.0.2", - "minimist": "^1.2.6", - "strip-bom": "^3.0.0" - } - }, - "node_modules/type-check": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", - "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", - "dev": true, - "dependencies": { - "prelude-ls": "^1.2.1" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/typed-array-buffer": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.0.tgz", - "integrity": "sha512-Y8KTSIglk9OZEr8zywiIHG/kmQ7KWyjseXs1CbSo8vC42w7hg2HgYTxSWwP0+is7bWDc1H+Fo026CpHFwm8tkw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.2.1", - "is-typed-array": "^1.1.10" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/typed-array-byte-length": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.0.tgz", - "integrity": "sha512-Or/+kvLxNpeQ9DtSydonMxCx+9ZXOswtwJn17SNLvhptaXYDJvkFFP5zbfU/uLmvnBJlI4yrnXRxpdWH/M5tNA==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "for-each": "^0.3.3", - "has-proto": "^1.0.1", - "is-typed-array": "^1.1.10" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/typed-array-byte-offset": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.0.tgz", - "integrity": "sha512-RD97prjEt9EL8YgAgpOkf3O4IF9lhJFr9g0htQkm0rchFp/Vx7LW5Q8fSXXub7BXAODyUQohRMyOc3faCPd0hg==", - "dev": true, - "dependencies": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", - "for-each": "^0.3.3", - "has-proto": "^1.0.1", - "is-typed-array": "^1.1.10" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/typed-array-length": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.4.tgz", - "integrity": "sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "for-each": "^0.3.3", - "is-typed-array": "^1.1.9" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/unbox-primitive": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", - "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "has-bigints": "^1.0.2", - "has-symbols": "^1.0.3", - "which-boxed-primitive": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/update-browserslist-db": { - "version": "1.0.13", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz", - "integrity": "sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "peer": true, - "dependencies": { - "escalade": "^3.1.1", - "picocolors": "^1.0.0" - }, - "bin": { - "update-browserslist-db": "cli.js" - }, - "peerDependencies": { - "browserslist": ">= 4.21.0" - } - }, - "node_modules/uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dev": true, - "dependencies": { - "punycode": "^2.1.0" - } - }, - "node_modules/util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", - "dev": true - }, - "node_modules/validate-npm-package-license": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", - "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", - "dev": true, - "dependencies": { - "spdx-correct": "^3.0.0", - "spdx-expression-parse": "^3.0.0" - } - }, - "node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/which-boxed-primitive": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", - "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", - "dev": true, - "dependencies": { - "is-bigint": "^1.0.1", - "is-boolean-object": "^1.1.0", - "is-number-object": "^1.0.4", - "is-string": "^1.0.5", - "is-symbol": "^1.0.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/which-typed-array": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.11.tgz", - "integrity": "sha512-qe9UWWpkeG5yzZ0tNYxDmd7vo58HDBc39mZ0xWWpolAGADdFOzkfamWLDxkOWcvHQKVmdTyQdLD4NOfjLWTKew==", - "dev": true, - "dependencies": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", - "dev": true - }, - "node_modules/write-file-atomic": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-5.0.1.tgz", - "integrity": "sha512-+QU2zd6OTD8XWIJCbffaiQeH9U73qIqafo1x6V1snCWYGJf6cVE0cDR4D8xRzcEnfI21IFrUPzPGtcPf8AC+Rw==", - "dev": true, - "dependencies": { - "imurmurhash": "^0.1.4", - "signal-exit": "^4.0.1" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, - "node_modules/yargs-parser": { - "version": "20.2.9", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", - "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/yocto-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", - "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - } - } -} diff --git a/plugins/experimentation/package.json b/plugins/experimentation/package.json deleted file mode 100644 index 97fb757c..00000000 --- a/plugins/experimentation/package.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "name": "@adobe/aem-experimentation", - "version": "1.0.0", - "main": "src/index.js", - "scripts": { - "lint:js": "eslint src", - "lint:css": "stylelint src/**/*.css", - "lint": "npm run lint:js && npm run lint:css" - }, - "repository": { - "type": "git", - "url": "git+ssh://git@github.com/adobe/aem-experimentation.git" - }, - "author": "Adobe Inc.", - "license": "Apache-2.0", - "keywords": [ - "aem", - "experimentation", - "experience", - "decisioning", - "plugin", - "campaigns", - "audiences" - ], - "bugs": { - "url": "https://github.com/adobe/aem-experimentation/issues" - }, - "homepage": "https://github.com/adobe/aem-experimentation#readme", - "devDependencies": { - "@babel/eslint-parser": "7.22.15", - "eslint": "8.48.0", - "eslint-config-airbnb-base": "15.0.0", - "eslint-plugin-import": "2.28.1", - "stylelint": "15.10.3", - "stylelint-config-standard": "34.0.0" - } -} diff --git a/plugins/experimentation/src/index.js b/plugins/experimentation/src/index.js deleted file mode 100644 index 5ee2136a..00000000 --- a/plugins/experimentation/src/index.js +++ /dev/null @@ -1,712 +0,0 @@ -/* - * Copyright 2022 Adobe. All rights reserved. - * This file is licensed to you under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. You may obtain a copy - * of the License at http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under - * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS - * OF ANY KIND, either express or implied. See the License for the specific language - * governing permissions and limitations under the License. - */ -const MAX_SAMPLING_RATE = 10; // At a maximum we sample 1 in 10 requests - -export const DEFAULT_OPTIONS = { - // Generic properties - rumSamplingRate: MAX_SAMPLING_RATE, // 1 in 10 requests - - // Audiences related properties - audiences: {}, - audiencesMetaTagPrefix: 'audience', - audiencesQueryParameter: 'audience', - - // Campaigns related properties - campaignsMetaTagPrefix: 'campaign', - campaignsQueryParameter: 'campaign', - - // Experimentation related properties - experimentsRoot: '/experiments', - experimentsConfigFile: 'manifest.json', - experimentsMetaTag: 'experiment', - experimentsQueryParameter: 'experiment', -}; - -/** - * Checks if the current engine is detected as being a bot. - * @returns `true` if the current engine is detected as being, `false` otherwise - */ -function isBot() { - return navigator.userAgent.match(/bot|crawl|spider/i); -} - -/** - * Checks if any of the configured audiences on the page can be resolved. - * @param {string[]} applicableAudiences a list of configured audiences for the page - * @param {object} options the plugin options - * @returns Returns the names of the resolved audiences, or `null` if no audience is configured - */ -export async function getResolvedAudiences(applicableAudiences, options, context) { - if (!applicableAudiences.length || !Object.keys(options.audiences).length) { - return null; - } - // If we have a forced audience set in the query parameters (typically for simulation purposes) - // we check if it is applicable - const usp = new URLSearchParams(window.location.search); - const forcedAudience = usp.has(options.audiencesQueryParameter) - ? context.toClassName(usp.get(options.audiencesQueryParameter)) - : null; - if (forcedAudience) { - return applicableAudiences.includes(forcedAudience) ? [forcedAudience] : []; - } - - // Otherwise, return the list of audiences that are resolved on the page - const results = await Promise.all( - applicableAudiences - .map((key) => { - if (options.audiences[key] && typeof options.audiences[key] === 'function') { - return options.audiences[key](); - } - return false; - }), - ); - return applicableAudiences.filter((_, i) => results[i]); -} - -/** - * Replaces element with content from path - * @param {string} path - * @param {HTMLElement} main - * @return Returns the path that was loaded or null if the loading failed - */ -async function replaceInner(path, main) { - try { - const resp = await fetch(path); - if (!resp.ok) { - // eslint-disable-next-line no-console - console.log('error loading content:', resp); - return null; - } - const html = await resp.text(); - // parse with DOMParser to guarantee valid HTML, and no script execution(s) - const dom = new DOMParser().parseFromString(html, 'text/html'); - // do not use replaceWith API here since this would replace the main reference - // in scripts.js as well and prevent proper decoration of the sections/blocks - main.innerHTML = dom.querySelector('main').innerHTML; - return path; - } catch (e) { - // eslint-disable-next-line no-console - console.log(`error loading content: ${path}`, e); - } - return null; -} - -/** - * Parses the experimentation configuration sheet and creates an internal model. - * - * Output model is expected to have the following structure: - * { - * id: , - * label: , - * blocks: , - * audiences: [], - * status: Active | Inactive, - * variantNames: [], - * variants: { - * [variantName]: { - * label: - * percentageSplit: , - * pages: , - * blocks: , - * } - * } - * }; - */ -function parseExperimentConfig(json, context) { - const config = {}; - try { - json.settings.data.forEach((line) => { - const key = context.toCamelCase(line.Name); - if (key === 'audience' || key === 'audiences') { - config.audiences = line.Value ? line.Value.split(',').map((str) => str.trim()) : []; - } else if (key === 'experimentName') { - config.label = line.Value; - } else { - config[key] = line.Value; - } - }); - const variants = {}; - let variantNames = Object.keys(json.experiences.data[0]); - variantNames.shift(); - variantNames = variantNames.map((vn) => context.toCamelCase(vn)); - variantNames.forEach((variantName) => { - variants[variantName] = {}; - }); - let lastKey = 'default'; - json.experiences.data.forEach((line) => { - let key = context.toCamelCase(line.Name); - if (!key) key = lastKey; - lastKey = key; - const vns = Object.keys(line); - vns.shift(); - vns.forEach((vn) => { - const camelVN = context.toCamelCase(vn); - if (key === 'pages' || key === 'blocks') { - variants[camelVN][key] = variants[camelVN][key] || []; - if (key === 'pages') variants[camelVN][key].push(new URL(line[vn]).pathname); - else variants[camelVN][key].push(line[vn]); - } else { - variants[camelVN][key] = line[vn]; - } - }); - }); - config.variants = variants; - config.variantNames = variantNames; - return config; - } catch (e) { - // eslint-disable-next-line no-console - console.log('error parsing experiment config:', e, json); - } - return null; -} - -/** - * Checks if the given config is a valid experimentation configuration. - * @param {object} config the config to check - * @returns `true` if it is valid, `false` otherwise - */ -export function isValidExperimentationConfig(config) { - if (!config.variantNames - || !config.variantNames.length - || !config.variants - || !Object.values(config.variants).length - || !Object.values(config.variants).every((v) => ( - typeof v === 'object' - && !!v.blocks - && !!v.pages - && (v.percentageSplit === '' || !!v.percentageSplit) - ))) { - return false; - } - return true; -} - -/** - * Calculates percentage split for variants where the percentage split is not - * explicitly configured. - * Substracts from 100 the explicitly configured percentage splits, - * and divides the remaining percentage, among the variants without explicit - * percentage split configured - * @param {Array} variant objects - */ -function inferEmptyPercentageSplits(variants) { - const variantsWithoutPercentage = []; - - const remainingPercentage = variants.reduce((result, variant) => { - if (!variant.percentageSplit) { - variantsWithoutPercentage.push(variant); - } - const newResult = result - parseFloat(variant.percentageSplit || 0); - return newResult; - }, 1); - if (variantsWithoutPercentage.length) { - const missingPercentage = remainingPercentage / variantsWithoutPercentage.length; - variantsWithoutPercentage.forEach((v) => { - v.percentageSplit = missingPercentage.toFixed(2); - }); - } -} - -/** - * Gets experiment config from the metadata. - * - * @param {string} experimentId The experiment identifier - * @param {string} instantExperiment The list of varaints - * @returns {object} the experiment manifest - */ -function getConfigForInstantExperiment( - experimentId, - instantExperiment, - pluginOptions, - context, -) { - const audience = context.getMetadata(`${pluginOptions.experimentsMetaTag}-audience`); - const config = { - label: `Instant Experiment: ${experimentId}`, - audiences: audience ? audience.split(',').map(context.toClassName) : [], - status: context.getMetadata(`${pluginOptions.experimentsMetaTag}-status`) || 'Active', - startDate: context.getMetadata(`${pluginOptions.experimentsMetaTag}-start-date`), - endDate: context.getMetadata(`${pluginOptions.experimentsMetaTag}-end-date`), - id: experimentId, - variants: {}, - variantNames: [], - }; - - const nbOfVariants = Number(instantExperiment); - const pages = Number.isNaN(nbOfVariants) - ? instantExperiment.split(',').map((p) => new URL(p.trim(), window.location).pathname) - : new Array(nbOfVariants).fill(window.location.pathname); - - const splitString = context.getMetadata(`${pluginOptions.experimentsMetaTag}-split`); - const splits = splitString - // custom split - ? splitString.split(',').map((i) => parseInt(i, 10) / 100) - // even split fallback - : [...new Array(pages.length)].map(() => 1 / (pages.length + 1)); - - config.variantNames.push('control'); - config.variants.control = { - percentageSplit: '', - pages: [window.location.pathname], - blocks: [], - label: 'Control', - }; - - pages.forEach((page, i) => { - const vname = `challenger-${i + 1}`; - config.variantNames.push(vname); - config.variants[vname] = { - percentageSplit: `${splits[i].toFixed(2)}`, - pages: [page], - blocks: [], - label: `Challenger ${i + 1}`, - }; - }); - inferEmptyPercentageSplits(Object.values(config.variants)); - return (config); -} - -/** - * Gets experiment config from the manifest and transforms it to more easily - * consumable structure. - * - * the manifest consists of two sheets "settings" and "experiences", by default - * - * "settings" is applicable to the entire test and contains information - * like "Audience", "Status" or "Blocks". - * - * "experience" hosts the experiences in rows, consisting of: - * a "Percentage Split", "Label" and a set of "Links". - * - * - * @param {string} experimentId The experiment identifier - * @param {object} pluginOptions The plugin options - * @returns {object} containing the experiment manifest - */ -async function getConfigForFullExperiment(experimentId, pluginOptions, context) { - let path; - if (experimentId.includes(`/${pluginOptions.experimentsConfigFile}`)) { - path = new URL(experimentId, window.location.origin).href; - // eslint-disable-next-line no-param-reassign - [experimentId] = path.split('/').splice(-2, 1); - } else { - path = `${pluginOptions.experimentsRoot}/${experimentId}/${pluginOptions.experimentsConfigFile}`; - } - try { - const resp = await fetch(path); - if (!resp.ok) { - // eslint-disable-next-line no-console - console.log('error loading experiment config:', resp); - return null; - } - const json = await resp.json(); - const config = pluginOptions.parser - ? pluginOptions.parser(json, context) - : parseExperimentConfig(json, context); - if (!config) { - return null; - } - config.id = experimentId; - config.manifest = path; - config.basePath = `${pluginOptions.experimentsRoot}/${experimentId}`; - inferEmptyPercentageSplits(Object.values(config.variants)); - config.status = context.getMetadata(`${pluginOptions.experimentsMetaTag}-status`) || config.status; - return config; - } catch (e) { - // eslint-disable-next-line no-console - console.log(`error loading experiment manifest: ${path}`, e); - } - return null; -} - -function getDecisionPolicy(config) { - const decisionPolicy = { - id: 'content-experimentation-policy', - rootDecisionNodeId: 'n1', - decisionNodes: [{ - id: 'n1', - type: 'EXPERIMENTATION', - experiment: { - id: config.id, - identityNamespace: 'ECID', - randomizationUnit: 'DEVICE', - treatments: Object.entries(config.variants).map(([key, props]) => ({ - id: key, - allocationPercentage: Number(props.percentageSplit) * 100, - })), - }, - }], - }; - return decisionPolicy; -} - -async function getConfig(experiment, instantExperiment, pluginOptions, context) { - const usp = new URLSearchParams(window.location.search); - const [forcedExperiment, forcedVariant] = usp.has(pluginOptions.experimentsQueryParameter) - ? usp.get(pluginOptions.experimentsQueryParameter).split('/') - : []; - - const experimentConfig = instantExperiment - ? await getConfigForInstantExperiment(experiment, instantExperiment, pluginOptions, context) - : await getConfigForFullExperiment(experiment, pluginOptions, context); - - // eslint-disable-next-line no-console - console.debug(experimentConfig); - if (!experimentConfig) { - return null; - } - - const forcedAudience = usp.has(pluginOptions.audiencesQueryParameter) - ? context.toClassName(usp.get(pluginOptions.audiencesQueryParameter)) - : null; - - experimentConfig.resolvedAudiences = await getResolvedAudiences( - experimentConfig.audiences.map(context.toClassName), - pluginOptions, - context, - ); - experimentConfig.run = ( - // experiment is active or forced - (['active', 'on', 'true'].includes(context.toClassName(experimentConfig.status)) || forcedExperiment) - // experiment has resolved audiences if configured - && (!experimentConfig.resolvedAudiences || experimentConfig.resolvedAudiences.length) - // forced audience resolves if defined - && (!forcedAudience || experimentConfig.audiences.includes(forcedAudience)) - && (!experimentConfig.startDate || new Date(experimentConfig.startDate) <= Date.now()) - && (!experimentConfig.endDate || new Date(experimentConfig.endDate) > Date.now()) - ); - - window.hlx = window.hlx || {}; - window.hlx.experiment = experimentConfig; - - // eslint-disable-next-line no-console - console.debug('run', experimentConfig.run, experimentConfig.audiences); - if (forcedVariant && experimentConfig.variantNames.includes(forcedVariant)) { - experimentConfig.selectedVariant = forcedVariant; - } else { - // eslint-disable-next-line import/extensions - const { ued } = await import('./ued.js'); - const decision = ued.evaluateDecisionPolicy(getDecisionPolicy(experimentConfig), {}); - experimentConfig.selectedVariant = decision.items[0].id; - } - return experimentConfig; -} - -export async function runExperiment(document, options, context) { - if (isBot()) { - return false; - } - - const pluginOptions = { ...DEFAULT_OPTIONS, ...(options || {}) }; - const experiment = context.getMetadata(pluginOptions.experimentsMetaTag); - if (!experiment) { - return false; - } - const variants = context.getMetadata('instant-experiment') - || context.getMetadata(`${pluginOptions.experimentsMetaTag}-variants`); - let experimentConfig; - try { - experimentConfig = await getConfig(experiment, variants, pluginOptions, context); - } catch (err) { - // eslint-disable-next-line no-console - console.error('Invalid experiment config.', err); - } - if (!experimentConfig || !isValidExperimentationConfig(experimentConfig)) { - // eslint-disable-next-line no-console - console.warn('Invalid experiment config. Please review your metadata, sheet and parser.'); - return false; - } - - const usp = new URLSearchParams(window.location.search); - const forcedVariant = usp.has(pluginOptions.experimentsQueryParameter) - ? usp.get(pluginOptions.experimentsQueryParameter).split('/')[1] - : null; - if (!experimentConfig.run && !forcedVariant) { - // eslint-disable-next-line no-console - console.warn('Experiment will not run. It is either not active or its configured audiences are not resolved.'); - return false; - } - // eslint-disable-next-line no-console - console.debug(`running experiment (${window.hlx.experiment.id}) -> ${window.hlx.experiment.selectedVariant}`); - - if (experimentConfig.selectedVariant === experimentConfig.variantNames[0]) { - document.body.classList.add(`experiment-${context.toClassName(experimentConfig.id)}`); - document.body.classList.add(`variant-${context.toClassName(experimentConfig.selectedVariant)}`); - context.sampleRUM('experiment', { - source: experimentConfig.id, - target: experimentConfig.selectedVariant, - }); - return false; - } - - const { pages } = experimentConfig.variants[experimentConfig.selectedVariant]; - if (!pages.length) { - return false; - } - - const currentPath = window.location.pathname; - const control = experimentConfig.variants[experimentConfig.variantNames[0]]; - const index = control.pages.indexOf(currentPath); - if (index < 0) { - return false; - } - - // Fullpage content experiment - document.body.classList.add(`experiment-${context.toClassName(experimentConfig.id)}`); - let result; - if (pages[index] !== currentPath) { - result = await replaceInner(pages[index], document.querySelector('main')); - } else { - result = currentPath; - } - experimentConfig.servedExperience = result || currentPath; - if (!result) { - // eslint-disable-next-line no-console - console.debug(`failed to serve variant ${window.hlx.experiment.selectedVariant}. Falling back to ${experimentConfig.variantNames[0]}.`); - } - document.body.classList.add(`variant-${context.toClassName(result ? experimentConfig.selectedVariant : experimentConfig.variantNames[0])}`); - context.sampleRUM('experiment', { - source: experimentConfig.id, - target: result ? experimentConfig.selectedVariant : experimentConfig.variantNames[0], - }); - return result; -} - -export async function runCampaign(document, options, context) { - if (isBot()) { - return false; - } - - const pluginOptions = { ...DEFAULT_OPTIONS, ...options }; - const usp = new URLSearchParams(window.location.search); - const campaign = (usp.has(pluginOptions.campaignsQueryParameter) - ? context.toClassName(usp.get(pluginOptions.campaignsQueryParameter)) - : null) - || (usp.has('utm_campaign') ? context.toClassName(usp.get('utm_campaign')) : null); - if (!campaign) { - return false; - } - - let audiences = context.getMetadata(`${pluginOptions.campaignsMetaTagPrefix}-audience`); - let resolvedAudiences = null; - if (audiences) { - audiences = audiences.split(',').map(context.toClassName); - resolvedAudiences = await getResolvedAudiences(audiences, pluginOptions, context); - if (!!resolvedAudiences && !resolvedAudiences.length) { - return false; - } - } - - const allowedCampaigns = context.getAllMetadata(pluginOptions.campaignsMetaTagPrefix); - if (!Object.keys(allowedCampaigns).includes(campaign)) { - return false; - } - - const urlString = allowedCampaigns[campaign]; - if (!urlString) { - return false; - } - - window.hlx.campaign = { selectedCampaign: campaign }; - if (resolvedAudiences) { - window.hlx.campaign.resolvedAudiences = window.hlx.campaign; - } - - try { - const url = new URL(urlString); - const result = await replaceInner(url.pathname, document.querySelector('main')); - window.hlx.campaign.servedExperience = result || window.location.pathname; - if (!result) { - // eslint-disable-next-line no-console - console.debug(`failed to serve campaign ${campaign}. Falling back to default content.`); - } - document.body.classList.add(`campaign-${campaign}`); - context.sampleRUM('campaign', { - source: window.location.href, - target: result ? campaign : 'default', - }); - return result; - } catch (err) { - // eslint-disable-next-line no-console - console.error(err); - return false; - } -} - -export async function serveAudience(document, options, context) { - if (isBot()) { - return false; - } - - const pluginOptions = { ...DEFAULT_OPTIONS, ...(options || {}) }; - const configuredAudiences = context.getAllMetadata(pluginOptions.audiencesMetaTagPrefix); - if (!Object.keys(configuredAudiences).length) { - return false; - } - - const audiences = await getResolvedAudiences( - Object.keys(configuredAudiences).map(context.toClassName), - pluginOptions, - context, - ); - if (!audiences || !audiences.length) { - return false; - } - - const usp = new URLSearchParams(window.location.search); - const forcedAudience = usp.has(pluginOptions.audiencesQueryParameter) - ? context.toClassName(usp.get(pluginOptions.audiencesQueryParameter)) - : null; - - const selectedAudience = forcedAudience || audiences[0]; - const urlString = configuredAudiences[selectedAudience]; - if (!urlString) { - return false; - } - - window.hlx.audience = { selectedAudience }; - - try { - const url = new URL(urlString); - const result = await replaceInner(url.pathname, document.querySelector('main')); - window.hlx.audience.servedExperience = result || window.location.pathname; - if (!result) { - // eslint-disable-next-line no-console - console.debug(`failed to serve audience ${selectedAudience}. Falling back to default content.`); - } - document.body.classList.add(audiences.map((audience) => `audience-${audience}`)); - context.sampleRUM('audiences', { - source: window.location.href, - target: result ? forcedAudience || audiences.join(',') : 'default', - }); - return result; - } catch (err) { - // eslint-disable-next-line no-console - console.error(err); - return false; - } -} - -window.hlx.patchBlockConfig?.push((config) => { - const { experiment } = window.hlx; - - // No experiment is running - if (!experiment || !experiment.run) { - return config; - } - - // The current experiment does not modify the block - if (experiment.selectedVariant === experiment.variantNames[0] - || !experiment.variants[experiment.variantNames[0]].blocks - || !experiment.variants[experiment.variantNames[0]].blocks.includes(config.blockName)) { - return config; - } - - // The current experiment does not modify the block code - const variant = experiment.variants[experiment.selectedVariant]; - if (!variant.blocks.length) { - return config; - } - - let index = experiment.variants[experiment.variantNames[0]].blocks.indexOf(''); - if (index < 0) { - index = experiment.variants[experiment.variantNames[0]].blocks.indexOf(config.blockName); - } - if (index < 0) { - index = experiment.variants[experiment.variantNames[0]].blocks.indexOf(`/blocks/${config.blockName}`); - } - if (index < 0) { - return config; - } - - let origin = ''; - let path; - if (/^https?:\/\//.test(variant.blocks[index])) { - const url = new URL(variant.blocks[index]); - // Experimenting from a different branch - if (url.origin !== window.location.origin) { - origin = url.origin; - } - // Experimenting from a block path - if (url.pathname !== '/') { - path = url.pathname; - } else { - path = `/blocks/${config.blockName}`; - } - } else { // Experimenting from a different branch on the same branch - path = `/blocks/${variant.blocks[index]}`; - } - if (!origin && !path) { - return config; - } - - const { codeBasePath } = window.hlx; - return { - ...config, - cssPath: `${origin}${codeBasePath}${path}/${config.blockName}.css`, - jsPath: `${origin}${codeBasePath}${path}/${config.blockName}.js`, - }; -}); - -let isAdjusted = false; -function adjustedRumSamplingRate(checkpoint, options, context) { - const pluginOptions = { ...DEFAULT_OPTIONS, ...(options || {}) }; - return (data) => { - if (!window.hlx.rum.isSelected && !isAdjusted) { - isAdjusted = true; - // adjust sampling rate based on project config … - window.hlx.rum.weight = Math.min( - window.hlx.rum.weight, - // … but limit it to the 10% sampling at max to avoid losing anonymization - // and reduce burden on the backend - Math.max(pluginOptions.rumSamplingRate, MAX_SAMPLING_RATE), - ); - window.hlx.rum.isSelected = (window.hlx.rum.random * window.hlx.rum.weight < 1); - if (window.hlx.rum.isSelected) { - context.sampleRUM(checkpoint, data); - } - } - return true; - }; -} - -export async function loadEager(document, options, context) { - context.sampleRUM.always.on('audiences', adjustedRumSamplingRate('audiences', options, context)); - context.sampleRUM.always.on('campaign', adjustedRumSamplingRate('campaign', options, context)); - context.sampleRUM.always.on('experiment', adjustedRumSamplingRate('experiment', options, context)); - let res = await runCampaign(document, options, context); - if (!res) { - res = await runExperiment(document, options, context); - } - if (!res) { - res = await serveAudience(document, options, context); - } -} - -export async function loadLazy(document, options, context) { - const pluginOptions = { - ...DEFAULT_OPTIONS, - ...(options || {}), - }; - // do not show the experimentation pill on prod domains - if (window.location.hostname.endsWith('.live') - || (typeof options.isProd === 'function' && options.isProd()) - || (options.prodHost - && (options.prodHost === window.location.host - || options.prodHost === window.location.hostname - || options.prodHost === window.location.origin))) { - return; - } - // eslint-disable-next-line import/no-cycle - const preview = await import('./preview.js'); - preview.default(document, pluginOptions, { ...context, getResolvedAudiences }); -} diff --git a/plugins/experimentation/src/preview.css b/plugins/experimentation/src/preview.css deleted file mode 100644 index 9b02fbd7..00000000 --- a/plugins/experimentation/src/preview.css +++ /dev/null @@ -1,276 +0,0 @@ -/* - * Copyright 2022 Adobe. All rights reserved. - * This file is licensed to you under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. You may obtain a copy - * of the License at http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under - * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS - * OF ANY KIND, either express or implied. See the License for the specific language - * governing permissions and limitations under the License. - */ -[hidden] { - display: none !important; -} - -.hlx-highlight { - --highlight-size: .5rem; - - outline-color: #888; - outline-offset: calc(-1 * var(--highlight-size)); - outline-style: dashed; - outline-width: var(--highlight-size); - background-color: #8882; -} - -.hlx-preview-overlay { - z-index: 99; - position: fixed; - color: #eee; - font-size: 1rem; - font-weight: 600; - display: flex; - flex-direction: column; - gap: .5rem; - inset: auto auto 1em; - align-items: center; - justify-content: flex-end; - width: 100%; -} - -.hlx-badge { - --color: #888; - - border-radius: 2em; - background-color: var(--color); - border-style: solid; - border-color: #fff; - color: #eee; - padding: 1em 1.5em; - cursor: pointer; - display: flex; - align-items: center; - position: relative; - font-size: inherit; - overflow: initial; - margin: 0; - justify-content: space-between; - text-transform: none; -} - -.hlx-badge:focus, -.hlx-badge:hover { - --color: #888; -} - -.hlx-badge:focus-visible { - outline-style: solid; - outline-width: .25em; -} - -.hlx-badge > span { - user-select: none; -} - -.hlx-badge .hlx-open { - box-sizing: border-box; - position: relative; - display: block; - width: 22px; - height: 22px; - border: 2px solid; - border-radius: 100px; - margin-left: 16px; -} - -.hlx-badge .hlx-open::after { - content: ""; - display: block; - box-sizing: border-box; - position: absolute; - width: 6px; - height: 6px; - border-top: 2px solid; - border-right: 2px solid; - transform: rotate(-45deg); - left: 6px; - bottom: 5px; -} - -.hlx-badge.hlx-testing { - background-color: #fa0f00; - color: #fff; -} - -.hlx-popup { - position: absolute; - bottom: 6.5em; - left: 50%; - transform: translateX(-50%); - max-width: calc(100vw - 2em); - min-width: calc(300px - 2em); - background-color: #444; - border-radius: 16px; - box-shadow: 0 0 10px #000; - font-size: 12px; - text-align: initial; - white-space: initial; -} - -.hlx-popup a:any-link { - color: #eee; - border: 2px solid; - padding: 5px 12px; - display: inline-block; - border-radius: 20px; - text-decoration: none; -} - -.hlx-popup-header { - display: grid; - grid-template: - "label actions" - "description actions" - / 1fr min-content; - background-color: #222; - border-radius: 16px 16px 0 0; - padding: 24px 16px; -} - -.hlx-popup-header-label { - grid-area: label; -} - -.hlx-popup-header-description { - grid-area: description; -} - -.hlx-popup-header-actions { - grid-area: actions; - display: flex; - flex-direction: column; -} - -.hlx-popup h4, .hlx-popup h5 { - margin: 0; -} - -.hlx-popup h4 { - font-size: 16px; -} - -.hlx-popup h5 { - font-size: 14px; -} - - -.hlx-popup p { - margin: 0; -} - -.hlx-popup::before { - content: ''; - width: 0; - height: 0; - position: absolute; - border-left: 15px solid transparent; - border-right: 15px solid transparent; - border-top: 15px solid #444; - bottom: -15px; - right: 50%; - transform: translateX(50%); -} - -.hlx-hidden { - display: none; -} - -.hlx-badge.is-active, -.hlx-badge[aria-pressed="true"] { - --color: #280; -} - -.hlx-badge.is-inactive, -.hlx-badge[aria-pressed="false"] { - --color: #fa0f00; -} - -.hlx-popup-item { - display: grid; - grid-template: - "label actions" - "description actions" - / 1fr min-content; - margin: 1em; - padding: 1em; - border-radius: 1em; - gap: 1em; -} - -.hlx-popup-item-label { - grid-area: label; - white-space: nowrap; -} - -.hlx-popup-item-description { - grid-area: description; -} - -.hlx-popup-item-actions { - grid-area: actions; - display: flex; - flex-direction: column; -} - -.hlx-popup-item.is-selected { - background-color: #666; -} - -.hlx-popup-item .hlx-button { - flex: 0 0 auto; -} - -@media (width >= 600px) { - .hlx-highlight { - --highlight-size: .75rem; - } - - .hlx-preview-overlay { - right: 1em; - align-items: end; - font-size: 1.25rem; - } - - .hlx-popup { - right: 0; - left: auto; - transform: none; - min-width: 300px; - bottom: 8em; - } - - .hlx-popup::before { - right: 26px; - transform: none; - } -} - -@media (width >= 900px) { - .hlx-highlight { - --highlight-size: 1rem; - } - - .hlx-preview-overlay { - flex-flow: row wrap-reverse; - justify-content: flex-end; - font-size: 1.5rem; - } - - .hlx-popup { - bottom: 9em; - } - - .hlx-popup::before { - right: 32px; - } -} diff --git a/plugins/experimentation/src/preview.js b/plugins/experimentation/src/preview.js deleted file mode 100644 index 5c871eb8..00000000 --- a/plugins/experimentation/src/preview.js +++ /dev/null @@ -1,518 +0,0 @@ -/* - * Copyright 2022 Adobe. All rights reserved. - * This file is licensed to you under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. You may obtain a copy - * of the License at http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under - * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS - * OF ANY KIND, either express or implied. See the License for the specific language - * governing permissions and limitations under the License. - */ - -const DOMAIN_KEY_NAME = 'aem-domainkey'; - -class AemExperimentationBar extends HTMLElement { - connectedCallback() { - // Create a shadow root - const shadow = this.attachShadow({ mode: 'open' }); - - const cssPath = new URL(new Error().stack.split('\n')[2].match(/[a-z]+:[^:]+/)[0]).pathname.replace('preview.js', 'preview.css'); - const link = document.createElement('link'); - link.rel = 'stylesheet'; - link.href = cssPath; - link.onload = () => { - shadow.querySelector('.hlx-preview-overlay').removeAttribute('hidden'); - }; - shadow.append(link); - - const el = document.createElement('div'); - el.className = 'hlx-preview-overlay'; - el.setAttribute('hidden', true); - shadow.append(el); - } -} -customElements.define('aem-experimentation-bar', AemExperimentationBar); - -function createPreviewOverlay() { - const overlay = document.createElement('aem-experimentation-bar'); - return overlay; -} - -function getOverlay() { - let overlay = document.querySelector('aem-experimentation-bar')?.shadowRoot.children[1]; - if (!overlay) { - const el = createPreviewOverlay(); - document.body.append(el); - [, overlay] = el.shadowRoot.children; - } - return overlay; -} - -function createButton(label) { - const button = document.createElement('button'); - button.className = 'hlx-badge'; - const text = document.createElement('span'); - text.innerHTML = label; - button.append(text); - return button; -} - -function createPopupItem(item) { - const actions = typeof item === 'object' - ? item.actions.map((action) => (action.href - ? `` - : ``)) - : []; - const div = document.createElement('div'); - div.className = `hlx-popup-item${item.isSelected ? ' is-selected' : ''}`; - div.innerHTML = ` -
${typeof item === 'object' ? item.label : item}
- ${item.description ? `
${item.description}
` : ''} - ${actions.length ? `
${actions}
` : ''}`; - const buttons = [...div.querySelectorAll('.hlx-button a')]; - item.actions?.forEach((action, index) => { - if (action.onclick) { - buttons[index].addEventListener('click', action.onclick); - } - }); - return div; -} - -function createPopupDialog(header, items = []) { - const actions = typeof header === 'object' - ? (header.actions || []).map((action) => (action.href - ? `` - : ``)) - : []; - const popup = document.createElement('div'); - popup.className = 'hlx-popup hlx-hidden'; - popup.innerHTML = ` -
-
${typeof header === 'object' ? header.label : header}
- ${header.description ? `
${header.description}
` : ''} - ${actions.length ? `
${actions}
` : ''} -
-
`; - const list = popup.querySelector('.hlx-popup-items'); - items.forEach((item) => { - list.append(createPopupItem(item)); - }); - const buttons = [...popup.querySelectorAll('.hlx-popup-header-actions .hlx-button a')]; - header.actions?.forEach((action, index) => { - if (action.onclick) { - buttons[index].addEventListener('click', action.onclick); - } - }); - return popup; -} - -function createPopupButton(label, header, items) { - const button = createButton(label); - const popup = createPopupDialog(header, items); - button.innerHTML += ''; - button.append(popup); - button.addEventListener('click', () => { - popup.classList.toggle('hlx-hidden'); - }); - return button; -} - -// eslint-disable-next-line no-unused-vars -function createToggleButton(label) { - const button = document.createElement('div'); - button.className = 'hlx-badge'; - button.role = 'button'; - button.setAttribute('aria-pressed', false); - button.setAttribute('tabindex', 0); - const text = document.createElement('span'); - text.innerHTML = label; - button.append(text); - button.addEventListener('click', () => { - button.setAttribute('aria-pressed', button.getAttribute('aria-pressed') === 'false'); - }); - return button; -} - -const percentformat = new Intl.NumberFormat('en-US', { style: 'percent', maximumSignificantDigits: 2 }); -const countformat = new Intl.NumberFormat('en-US', { maximumSignificantDigits: 2 }); -const significanceformat = { - format: (value) => { - if (value < 0.005) { - return 'highly significant'; - } - if (value < 0.05) { - return 'significant'; - } - if (value < 0.1) { - return 'marginally significant'; - } - return 'not significant'; - }, -}; -const bigcountformat = { - format: (value) => { - if (value > 1000000) { - return `${countformat.format(value / 1000000)}M`; - } - if (value > 1000) { - return `${countformat.format(value / 1000)}K`; - } - return countformat.format(value); - }, -}; - -function createVariant(experiment, variantName, config, options) { - const selectedVariant = config?.selectedVariant || config?.variantNames[0]; - const variant = config.variants[variantName]; - const split = variant.percentageSplit; - const percentage = percentformat.format(split); - - const experimentURL = new URL(window.location.href); - // this will retain other query params such as ?rum=on - experimentURL.searchParams.set(options.experimentsQueryParameter, `${experiment}/${variantName}`); - - return { - label: `${variantName}`, - description: ` -

${variant.label}

-

(${percentage} split)

-

`, - actions: [{ label: 'Simulate', href: experimentURL.href }], - isSelected: selectedVariant === variantName, - }; -} - -async function fetchRumData(experiment, options) { - if (!options.domainKey) { - // eslint-disable-next-line no-console - console.warn('Cannot show RUM data. No `domainKey` configured.'); - return null; - } - if (!options.prodHost && (typeof options.isProd !== 'function' || !options.isProd())) { - // eslint-disable-next-line no-console - console.warn('Cannot show RUM data. No `prodHost` configured or custom `isProd` method provided.'); - return null; - } - - // the query is a bit slow, so I'm only fetching the results when the popup is opened - const resultsURL = new URL('https://helix-pages.anywhere.run/helix-services/run-query@v3/rum-experiments'); - // restrict results to the production host, this also reduces query cost - if (typeof options.isProd === 'function' && options.isProd()) { - resultsURL.searchParams.set('url', window.location.host); - } else if (options.prodHost) { - resultsURL.searchParams.set('url', options.prodHost); - } - resultsURL.searchParams.set('domainkey', options.domainKey); - resultsURL.searchParams.set('experiment', experiment); - - const response = await fetch(resultsURL.href); - if (!response.ok) { - return null; - } - - const { results } = await response.json(); - const { data } = results; - if (!data.length) { - return null; - } - - const numberify = (obj) => Object.entries(obj).reduce((o, [k, v]) => { - o[k] = Number.parseFloat(v); - o[k] = Number.isNaN(o[k]) ? v : o[k]; - return o; - }, {}); - - const variantsAsNums = data.map(numberify); - const totals = Object.entries( - variantsAsNums.reduce((o, v) => { - Object.entries(v).forEach(([k, val]) => { - if (typeof val === 'number' && Number.isInteger(val) && k.startsWith('variant_')) { - o[k] = (o[k] || 0) + val; - } else if (typeof val === 'number' && Number.isInteger(val) && k.startsWith('control_')) { - o[k] = val; - } - }); - return o; - }, {}), - ).reduce((o, [k, v]) => { - o[k] = v; - const vkey = k.replace(/^(variant|control)_/, 'variant_'); - const ckey = k.replace(/^(variant|control)_/, 'control_'); - const tkey = k.replace(/^(variant|control)_/, 'total_'); - if (!Number.isNaN(o[ckey]) && !Number.isNaN(o[vkey])) { - o[tkey] = o[ckey] + o[vkey]; - } - return o; - }, {}); - const richVariants = variantsAsNums - .map((v) => ({ - ...v, - allocation_rate: v.variant_experimentations / totals.total_experimentations, - })) - .reduce((o, v) => { - const variantName = v.variant; - o[variantName] = v; - return o; - }, { - control: { - variant: 'control', - ...Object.entries(variantsAsNums[0]).reduce((k, v) => { - const [key, val] = v; - if (key.startsWith('control_')) { - k[key.replace(/^control_/, 'variant_')] = val; - } - return k; - }, {}), - }, - }); - const winner = variantsAsNums.reduce((w, v) => { - if (v.variant_conversion_rate > w.conversion_rate && v.p_value < 0.05) { - w.conversion_rate = v.variant_conversion_rate; - w.p_value = v.p_value; - w.variant = v.variant; - } - return w; - }, { variant: 'control', p_value: 1, conversion_rate: 0 }); - - return { - richVariants, - totals, - variantsAsNums, - winner, - }; -} - -function populatePerformanceMetrics(div, config, { - richVariants, totals, variantsAsNums, winner, -}) { - // add summary - const summary = div.querySelector('.hlx-info'); - summary.innerHTML = `Showing results for ${bigcountformat.format(totals.total_experimentations)} visits and ${bigcountformat.format(totals.total_conversions)} conversions: `; - if (totals.total_conversion_events < 500 && winner.p_value > 0.05) { - summary.innerHTML += ` not yet enough data to determine a winner. Keep going until you get ${bigcountformat.format((500 * totals.total_experimentations) / totals.total_conversion_events)} visits.`; - } else if (winner.p_value > 0.05) { - summary.innerHTML += ' no significant difference between variants. In doubt, stick with control.'; - } else if (winner.variant === 'control') { - summary.innerHTML += ' Stick with control. No variant is better than the control.'; - } else { - summary.innerHTML += ` ${winner.variant} is the winner.`; - } - - // add traffic allocation to control and each variant - config.variantNames.forEach((variantName, index) => { - const variantDiv = document.querySelectorAll('.hlx-popup-item')[index]; - const percentage = variantDiv.querySelector('.percentage'); - percentage.innerHTML = ` - ${bigcountformat.format(richVariants[variantName].variant_conversions)} clicks / - ${bigcountformat.format(richVariants[variantName].variant_experimentations)} visits - (${percentformat.format(richVariants[variantName].variant_experimentations / totals.total_experimentations)} split) - `; - }); - - // add click rate and significance to each variant - variantsAsNums.forEach((result) => { - const variant = document.querySelectorAll('.hlx-popup-item')[config.variantNames.indexOf(result.variant)]; - if (variant) { - const performance = variant.querySelector('.performance'); - performance.innerHTML = ` - click rate: ${percentformat.format(result.variant_conversion_rate)} - vs. ${percentformat.format(result.control_conversion_rate)} - ${significanceformat.format(result.p_value)} - `; - } - }); -} - -/** - * Create Badge if a Page is enlisted in a AEM Experiment - * @return {Object} returns a badge or empty string - */ -async function decorateExperimentPill(overlay, options, context) { - const config = window?.hlx?.experiment; - const experiment = context.toClassName(context.getMetadata(options.experimentsMetaTag)); - if (!experiment || !config) { - return; - } - // eslint-disable-next-line no-console - console.log('preview experiment', experiment); - - const domainKey = window.localStorage.getItem(DOMAIN_KEY_NAME); - const pill = createPopupButton( - `Experiment: ${config.id}`, - { - label: config.label, - description: ` -
- ${config.status} - ${config.resolvedAudiences ? ', ' : ''} - ${config.resolvedAudiences && config.resolvedAudiences.length ? config.resolvedAudiences[0] : ''} - ${config.resolvedAudiences && !config.resolvedAudiences.length ? 'No audience resolved' : ''} - ${config.variants[config.variantNames[0]].blocks.length ? ', Blocks: ' : ''} - ${config.variants[config.variantNames[0]].blocks.join(',')} -
-
How is it going?
`, - actions: [ - ...config.manifest ? [{ label: 'Manifest', href: config.manifest }] : [], - { - label: '', - onclick: async () => { - // eslint-disable-next-line no-alert - const key = window.prompt( - 'Please enter your domain key:', - window.localStorage.getItem(DOMAIN_KEY_NAME) || '', - ); - if (key && key.match(/[a-f0-9-]+/)) { - window.localStorage.setItem(DOMAIN_KEY_NAME, key); - const performanceMetrics = await fetchRumData(experiment, { - ...options, - domainKey: key, - }); - if (performanceMetrics === null) { - return; - } - populatePerformanceMetrics(pill, config, performanceMetrics); - } else if (key === '') { - window.localStorage.removeItem(DOMAIN_KEY_NAME); - } - }, - }, - ], - }, - config.variantNames.map((vname) => createVariant(experiment, vname, config, options)), - ); - if (config.run) { - pill.classList.add(`is-${context.toClassName(config.status)}`); - } - overlay.append(pill); - - const performanceMetrics = await fetchRumData(experiment, { ...options, domainKey }); - if (performanceMetrics === null) { - return; - } - populatePerformanceMetrics(pill, config, performanceMetrics); -} - -function createCampaign(campaign, isSelected, options) { - const url = new URL(window.location.href); - if (campaign !== 'default') { - url.searchParams.set(options.campaignsQueryParameter, campaign); - } else { - url.searchParams.delete(options.campaignsQueryParameter); - } - - return { - label: `${campaign}`, - actions: [{ label: 'Simulate', href: url.href }], - isSelected, - }; -} - -/** - * Create Badge if a Page is enlisted in a AEM Campaign - * @return {Object} returns a badge or empty string - */ -async function decorateCampaignPill(overlay, options, context) { - const campaigns = context.getAllMetadata(options.campaignsMetaTagPrefix); - if (!Object.keys(campaigns).length) { - return; - } - - const usp = new URLSearchParams(window.location.search); - const forcedAudience = usp.has(options.audiencesQueryParameter) - ? context.toClassName(usp.get(options.audiencesQueryParameter)) - : null; - const audiences = campaigns.audience?.split(',').map(context.toClassName) || []; - const resolvedAudiences = await context.getResolvedAudiences(audiences, options); - const isActive = forcedAudience - ? audiences.includes(forcedAudience) - : (!resolvedAudiences || !!resolvedAudiences.length); - const campaign = (usp.has(options.campaignsQueryParameter) - ? context.toClassName(usp.get(options.campaignsQueryParameter)) - : null) - || (usp.has('utm_campaign') ? context.toClassName(usp.get('utm_campaign')) : null); - const pill = createPopupButton( - `Campaign: ${campaign || 'default'}`, - { - label: 'Campaigns on this page:', - description: ` -
- ${audiences.length && resolvedAudiences?.length ? `Audience: ${resolvedAudiences[0]}` : ''} - ${audiences.length && !resolvedAudiences?.length ? 'No audience resolved' : ''} - ${!audiences.length || !resolvedAudiences ? 'No audience configured' : ''} -
`, - }, - [ - createCampaign('default', !campaign || !isActive, options), - ...Object.keys(campaigns) - .filter((c) => c !== 'audience') - .map((c) => createCampaign(c, isActive && context.toClassName(campaign) === c, options)), - ], - ); - - if (campaign && isActive) { - pill.classList.add('is-active'); - } - overlay.append(pill); -} - -function createAudience(audience, isSelected, options) { - const url = new URL(window.location.href); - url.searchParams.set(options.audiencesQueryParameter, audience); - - return { - label: `${audience}`, - actions: [{ label: 'Simulate', href: url.href }], - isSelected, - }; -} - -/** - * Create Badge if a Page is enlisted in a AEM Audiences - * @return {Object} returns a badge or empty string - */ -async function decorateAudiencesPill(overlay, options, context) { - const audiences = context.getAllMetadata(options.audiencesMetaTagPrefix); - if (!Object.keys(audiences).length || !Object.keys(options.audiences).length) { - return; - } - - const resolvedAudiences = await context.getResolvedAudiences( - Object.keys(audiences), - options, - context, - ); - const pill = createPopupButton( - 'Audiences', - { - label: 'Audiences for this page:', - }, - [ - createAudience('default', !resolvedAudiences.length || resolvedAudiences[0] === 'default', options), - ...Object.keys(audiences) - .filter((a) => a !== 'audience') - .map((a) => createAudience(a, resolvedAudiences && resolvedAudiences[0] === a, options)), - ], - ); - - if (resolvedAudiences.length) { - pill.classList.add('is-active'); - } - overlay.append(pill); -} - -/** - * Decorates Preview mode badges and overlays - * @return {Object} returns a badge or empty string - */ -export default async function decoratePreviewMode(document, options, context) { - try { - const overlay = getOverlay(options); - await decorateAudiencesPill(overlay, options, context); - await decorateCampaignPill(overlay, options, context); - await decorateExperimentPill(overlay, options, context); - } catch (e) { - // eslint-disable-next-line no-console - console.log(e); - } -} diff --git a/plugins/experimentation/src/ued.js b/plugins/experimentation/src/ued.js deleted file mode 100644 index d28e91c3..00000000 --- a/plugins/experimentation/src/ued.js +++ /dev/null @@ -1,192 +0,0 @@ -/* - * Copyright 2022 Adobe. All rights reserved. - * This file is licensed to you under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. You may obtain a copy - * of the License at http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under - * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS - * OF ANY KIND, either express or implied. See the License for the specific language - * governing permissions and limitations under the License. - */ - -var storage = window.sessionStorage; - -function murmurhash3_32_gc(key, seed) { - var remainder = key.length & 3; - var bytes = key.length - remainder; - var c1 = 0xcc9e2d51; - var c2 = 0x1b873593; - var h1 = seed; - var k1; - var h1b; - var i = 0; - while (i < bytes) { - k1 = - ((key.charCodeAt(i) & 0xff)) | - ((key.charCodeAt(++i) & 0xff) << 8) | - ((key.charCodeAt(++i) & 0xff) << 16) | - ((key.charCodeAt(++i) & 0xff) << 24); - ++i; - k1 = ((((k1 & 0xffff) * c1) + ((((k1 >>> 16) * c1) & 0xffff) << 16))) & 0xffffffff; - k1 = (k1 << 15) | (k1 >>> 17); - k1 = ((((k1 & 0xffff) * c2) + ((((k1 >>> 16) * c2) & 0xffff) << 16))) & 0xffffffff; - h1 ^= k1; - h1 = (h1 << 13) | (h1 >>> 19); - h1b = ((((h1 & 0xffff) * 5) + ((((h1 >>> 16) * 5) & 0xffff) << 16))) & 0xffffffff; - h1 = (((h1b & 0xffff) + 0x6b64) + ((((h1b >>> 16) + 0xe654) & 0xffff) << 16)); - } - k1 = 0; - switch (remainder) { - case 3: k1 ^= (key.charCodeAt(i + 2) & 0xff) << 16; - case 2: k1 ^= (key.charCodeAt(i + 1) & 0xff) << 8; - case 1: - k1 ^= (key.charCodeAt(i) & 0xff); - k1 = (((k1 & 0xffff) * c1) + ((((k1 >>> 16) * c1) & 0xffff) << 16)) & 0xffffffff; - k1 = (k1 << 15) | (k1 >>> 17); - k1 = (((k1 & 0xffff) * c2) + ((((k1 >>> 16) * c2) & 0xffff) << 16)) & 0xffffffff; - h1 ^= k1; - } - h1 ^= key.length; - h1 ^= h1 >>> 16; - h1 = (((h1 & 0xffff) * 0x85ebca6b) + ((((h1 >>> 16) * 0x85ebca6b) & 0xffff) << 16)) & 0xffffffff; - h1 ^= h1 >>> 13; - h1 = ((((h1 & 0xffff) * 0xc2b2ae35) + ((((h1 >>> 16) * 0xc2b2ae35) & 0xffff) << 16))) & 0xffffffff; - h1 ^= h1 >>> 16; - return h1 >>> 0; -} - -var TOTAL_BUCKETS = 10000; -function getBucket(saltedId) { - var hash = murmurhash3_32_gc(saltedId, 0); - var hashFixedBucket = Math.abs(hash) % TOTAL_BUCKETS; - var bucket = hashFixedBucket / TOTAL_BUCKETS; - return bucket; -} -function pickWithWeightsBucket(allocationPercentages, treatments, bucket) { - var sum = allocationPercentages.reduce(function (partialSum, a) { return partialSum + a; }, 0); - var partialSum = 0.0; - for (var i = 0; i < treatments.length; i++) { - partialSum += Number(allocationPercentages[i].toFixed(2)) / sum; - if (bucket > partialSum) { - continue; - } - return treatments[i]; - } -} -function assignTreatmentByVisitor(experimentid, identityId, allocationPercentages, treatments) { - var saltedId = experimentid + '.' + identityId; - var bucketId = getBucket(saltedId); - var treatmentId = pickWithWeightsBucket(allocationPercentages, treatments, bucketId); - return { - treatmentId: treatmentId, - bucketId: bucketId - }; -} - -var LOCAL_STORAGE_KEY = 'unified-decisioning-experiments'; -function assignTreatment(allocationPercentages, treatments) { - var random = Math.random() * 100; - var i = treatments.length; - while (random > 0 && i > 0) { - i -= 1; - random -= +allocationPercentages[i]; - } - return treatments[i]; -} -function getLastExperimentTreatment(experimentId) { - var experimentsStr = storage.getItem(LOCAL_STORAGE_KEY); - if (experimentsStr) { - var experiments = JSON.parse(experimentsStr); - if (experiments[experimentId]) { - return experiments[experimentId].treatment; - } - } - return null; -} -function setLastExperimentTreatment(experimentId, treatment) { - var experimentsStr = storage.getItem(LOCAL_STORAGE_KEY); - var experiments = experimentsStr ? JSON.parse(experimentsStr) : {}; - var now = new Date(); - var expKeys = Object.keys(experiments); - expKeys.forEach(function (key) { - var date = new Date(experiments[key].date); - if ((now.getTime() - date.getTime()) > (1000 * 86400 * 30)) { - delete experiments[key]; - } - }); - var date = now.toISOString().split('T')[0]; - experiments[experimentId] = { treatment: treatment, date: date }; - storage.setItem(LOCAL_STORAGE_KEY, JSON.stringify(experiments)); -} -function assignTreatmentByDevice(experimentId, allocationPercentages, treatments) { - var cachedTreatmentId = getLastExperimentTreatment(experimentId); - var treatmentIdResponse; - if (!cachedTreatmentId || !treatments.includes(cachedTreatmentId)) { - var assignedTreatmentId = assignTreatment(allocationPercentages, treatments); - setLastExperimentTreatment(experimentId, assignedTreatmentId); - treatmentIdResponse = assignedTreatmentId; - } - else { - treatmentIdResponse = cachedTreatmentId; - } - return { - treatmentId: treatmentIdResponse - }; -} - -var RandomizationUnit = { - VISITOR: 'VISITOR', - DEVICE: 'DEVICE' -}; -function evaluateExperiment(context, experiment) { - var experimentId = experiment.id, identityNamespace = experiment.identityNamespace, _a = experiment.randomizationUnit, randomizationUnit = _a === void 0 ? RandomizationUnit.VISITOR : _a; - var identityMap = context.identityMap; - var treatments = experiment.treatments.map(function (item) { return item.id; }); - var allocationPercentages = experiment.treatments.map(function (item) { return item.allocationPercentage; }); - var treatmentAssignment = null; - switch (randomizationUnit) { - case RandomizationUnit.VISITOR: { - var identityId = identityMap[identityNamespace][0].id; - treatmentAssignment = assignTreatmentByVisitor(experimentId, identityId, allocationPercentages, treatments); - break; - } - case RandomizationUnit.DEVICE: { - treatmentAssignment = assignTreatmentByDevice(experimentId, allocationPercentages, treatments); - break; - } - default: - throw new Error("Unknow randomization unit"); - } - var evaluationResponse = { - experimentId: experimentId, - hashedBucket: treatmentAssignment.bucketId, - treatment: { - id: treatmentAssignment.treatmentId - } - }; - return evaluationResponse; -} - -function traverseDecisionTree(decisionNodesMap, context, currentNodeId) { - var _a = decisionNodesMap[currentNodeId], experiment = _a.experiment, type = _a.type; - if (type === 'EXPERIMENTATION') { - var treatment = evaluateExperiment(context, experiment).treatment; - return [treatment]; - } -} -function evaluateDecisionPolicy(decisionPolicy, context) { - if (context.storage && context.storage instanceof Storage) { - storage = context.storage; - } - var decisionNodesMap = {}; - decisionPolicy.decisionNodes.forEach(function (item) { - decisionNodesMap[item['id']] = item; - }); - var items = traverseDecisionTree(decisionNodesMap, context, decisionPolicy.rootDecisionNodeId); - return { - items: items - }; -} - -export const ued = { evaluateDecisionPolicy }; From 5b251ff67e80d6a39dd1cb7e819ca25fb09052aa Mon Sep 17 00:00:00 2001 From: Xinyi Feng Date: Mon, 10 Jun 2024 15:31:56 -0700 Subject: [PATCH 02/10] Squashed 'plugins/experimentation/' content from commit 33c3263 git-subtree-dir: plugins/experimentation git-subtree-split: 33c326394030a65b47dcf328f9124bed1adeaff2 --- .eslintrc.js | 21 + .github/workflows/release.yaml | 36 + .github/workflows/run-tests.yaml | 28 + .gitignore | 3 + .releaserc | 13 + .stylelintrc.json | 8 + CHANGELOG.md | 6 + CODE_OF_CONDUCT.md | 74 + LICENSE.md | 201 + README.md | 201 + documentation/audiences.md | 114 + documentation/campaigns.md | 98 + documentation/experiments.md | 170 + documentation/images/audiences-overlay.png | Bin 0 -> 58760 bytes documentation/images/campaigns-overlay.png | Bin 0 -> 66540 bytes documentation/images/experiments-overlay.png | Bin 0 -> 84980 bytes package-lock.json | 10354 ++++++++++++++++ package.json | 47 + playwright.config.js | 54 + src/index.js | 888 ++ src/preview.css | 289 + src/preview.js | 612 + src/ued.js | 193 + tests/audiences.test.js | 194 + tests/campaigns.test.js | 206 + tests/coverage.js | 37 + tests/experiments.test.js | 321 + tests/fixtures/aem.js | 759 ++ .../audiences/fragment-level--alt.html | 23 + .../audiences/fragment-level--async.html | 25 + .../fragment-level--invalid-url.html | 23 + tests/fixtures/audiences/fragment-level.html | 23 + tests/fixtures/audiences/fragments--alt.json | 17 + tests/fixtures/audiences/fragments.json | 29 + .../fixtures/audiences/page-level--async.html | 18 + .../fixtures/audiences/page-level--empty.html | 18 + .../audiences/page-level--invalid-url.html | 18 + .../audiences/page-level--invalid.html | 18 + tests/fixtures/audiences/page-level.html | 18 + tests/fixtures/audiences/section-level.html | 22 + tests/fixtures/audiences/variant-1.html | 9 + tests/fixtures/audiences/variant-2.html | 9 + .../campaigns/fragment-level--alt.html | 17 + .../campaigns/fragment-level--async.html | 19 + .../fragment-level--invalid-url.html | 17 + tests/fixtures/campaigns/fragment-level.html | 17 + tests/fixtures/campaigns/fragments--alt.json | 17 + tests/fixtures/campaigns/fragments.json | 17 + .../campaigns/page-level--audiences.html | 11 + ...vel--backward-compatibility--audience.html | 11 + .../fixtures/campaigns/page-level--empty.html | 12 + .../campaigns/page-level--invalid-url.html | 12 + tests/fixtures/campaigns/page-level.html | 12 + tests/fixtures/campaigns/section-level.html | 16 + tests/fixtures/campaigns/variant-1.html | 9 + tests/fixtures/campaigns/variant-2.html | 9 + .../experiments/fragment-level--alt.html | 17 + .../experiments/fragment-level--async.html | 19 + .../fragment-level--invalid-url.html | 17 + .../fixtures/experiments/fragment-level.html | 17 + .../fixtures/experiments/fragments--alt.json | 19 + tests/fixtures/experiments/fragments.json | 33 + .../experiments/page-level--audiences.html | 11 + ...vel--backward-compatibility--audience.html | 11 + ...ard-compatibility--instant-experiment.html | 10 + .../experiments/page-level--code.html | 10 + .../experiments/page-level--empty.html | 10 + .../experiments/page-level--empty2.html | 10 + .../experiments/page-level--inactive.html | 11 + .../experiments/page-level--invalid-url.html | 10 + .../experiments/page-level--split.html | 11 + .../page-level--time-bound-end.html | 11 + .../page-level--time-bound-start.html | 11 + .../experiments/page-level--time-bound.html | 12 + tests/fixtures/experiments/page-level-v1.html | 7 + tests/fixtures/experiments/page-level-v2.html | 7 + tests/fixtures/experiments/page-level.html | 10 + .../experiments/section-level-v1.html | 9 + .../experiments/section-level-v2.html | 9 + tests/fixtures/experiments/section-level.html | 22 + tests/fixtures/global.html | 8 + tests/fixtures/scripts.js | 103 + tests/global.test.js | 20 + tests/setup.js | 5 + tests/teardown.js | 5 + tests/utils.js | 34 + 86 files changed, 15882 insertions(+) create mode 100644 .eslintrc.js create mode 100644 .github/workflows/release.yaml create mode 100644 .github/workflows/run-tests.yaml create mode 100644 .gitignore create mode 100644 .releaserc create mode 100644 .stylelintrc.json create mode 100644 CHANGELOG.md create mode 100644 CODE_OF_CONDUCT.md create mode 100644 LICENSE.md create mode 100644 README.md create mode 100644 documentation/audiences.md create mode 100644 documentation/campaigns.md create mode 100644 documentation/experiments.md create mode 100644 documentation/images/audiences-overlay.png create mode 100644 documentation/images/campaigns-overlay.png create mode 100644 documentation/images/experiments-overlay.png create mode 100644 package-lock.json create mode 100644 package.json create mode 100644 playwright.config.js create mode 100644 src/index.js create mode 100644 src/preview.css create mode 100644 src/preview.js create mode 100644 src/ued.js create mode 100644 tests/audiences.test.js create mode 100644 tests/campaigns.test.js create mode 100644 tests/coverage.js create mode 100644 tests/experiments.test.js create mode 100644 tests/fixtures/aem.js create mode 100644 tests/fixtures/audiences/fragment-level--alt.html create mode 100644 tests/fixtures/audiences/fragment-level--async.html create mode 100644 tests/fixtures/audiences/fragment-level--invalid-url.html create mode 100644 tests/fixtures/audiences/fragment-level.html create mode 100644 tests/fixtures/audiences/fragments--alt.json create mode 100644 tests/fixtures/audiences/fragments.json create mode 100644 tests/fixtures/audiences/page-level--async.html create mode 100644 tests/fixtures/audiences/page-level--empty.html create mode 100644 tests/fixtures/audiences/page-level--invalid-url.html create mode 100644 tests/fixtures/audiences/page-level--invalid.html create mode 100644 tests/fixtures/audiences/page-level.html create mode 100644 tests/fixtures/audiences/section-level.html create mode 100644 tests/fixtures/audiences/variant-1.html create mode 100644 tests/fixtures/audiences/variant-2.html create mode 100644 tests/fixtures/campaigns/fragment-level--alt.html create mode 100644 tests/fixtures/campaigns/fragment-level--async.html create mode 100644 tests/fixtures/campaigns/fragment-level--invalid-url.html create mode 100644 tests/fixtures/campaigns/fragment-level.html create mode 100644 tests/fixtures/campaigns/fragments--alt.json create mode 100644 tests/fixtures/campaigns/fragments.json create mode 100644 tests/fixtures/campaigns/page-level--audiences.html create mode 100644 tests/fixtures/campaigns/page-level--backward-compatibility--audience.html create mode 100644 tests/fixtures/campaigns/page-level--empty.html create mode 100644 tests/fixtures/campaigns/page-level--invalid-url.html create mode 100644 tests/fixtures/campaigns/page-level.html create mode 100644 tests/fixtures/campaigns/section-level.html create mode 100644 tests/fixtures/campaigns/variant-1.html create mode 100644 tests/fixtures/campaigns/variant-2.html create mode 100644 tests/fixtures/experiments/fragment-level--alt.html create mode 100644 tests/fixtures/experiments/fragment-level--async.html create mode 100644 tests/fixtures/experiments/fragment-level--invalid-url.html create mode 100644 tests/fixtures/experiments/fragment-level.html create mode 100644 tests/fixtures/experiments/fragments--alt.json create mode 100644 tests/fixtures/experiments/fragments.json create mode 100644 tests/fixtures/experiments/page-level--audiences.html create mode 100644 tests/fixtures/experiments/page-level--backward-compatibility--audience.html create mode 100644 tests/fixtures/experiments/page-level--backward-compatibility--instant-experiment.html create mode 100644 tests/fixtures/experiments/page-level--code.html create mode 100644 tests/fixtures/experiments/page-level--empty.html create mode 100644 tests/fixtures/experiments/page-level--empty2.html create mode 100644 tests/fixtures/experiments/page-level--inactive.html create mode 100644 tests/fixtures/experiments/page-level--invalid-url.html create mode 100644 tests/fixtures/experiments/page-level--split.html create mode 100644 tests/fixtures/experiments/page-level--time-bound-end.html create mode 100644 tests/fixtures/experiments/page-level--time-bound-start.html create mode 100644 tests/fixtures/experiments/page-level--time-bound.html create mode 100644 tests/fixtures/experiments/page-level-v1.html create mode 100644 tests/fixtures/experiments/page-level-v2.html create mode 100644 tests/fixtures/experiments/page-level.html create mode 100644 tests/fixtures/experiments/section-level-v1.html create mode 100644 tests/fixtures/experiments/section-level-v2.html create mode 100644 tests/fixtures/experiments/section-level.html create mode 100644 tests/fixtures/global.html create mode 100644 tests/fixtures/scripts.js create mode 100644 tests/global.test.js create mode 100644 tests/setup.js create mode 100644 tests/teardown.js create mode 100644 tests/utils.js diff --git a/.eslintrc.js b/.eslintrc.js new file mode 100644 index 00000000..76f220db --- /dev/null +++ b/.eslintrc.js @@ -0,0 +1,21 @@ +module.exports = { + root: true, + extends: 'airbnb-base', + env: { + browser: true, + }, + parser: '@babel/eslint-parser', + parserOptions: { + allowImportExportEverywhere: true, + sourceType: 'module', + requireConfigFile: false, + }, + rules: { + // allow reassigning param + 'no-param-reassign': [2, { props: false }], + 'linebreak-style': ['error', 'unix'], + 'import/extensions': ['error', { + js: 'always', + }], + }, +}; diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml new file mode 100644 index 00000000..a72f6cd6 --- /dev/null +++ b/.github/workflows/release.yaml @@ -0,0 +1,36 @@ +name: Release +on: + push: + branches: + - main + +permissions: + contents: read + +jobs: + release: + name: Release + runs-on: ubuntu-latest + permissions: + contents: write + issues: write + pull-requests: write + id-token: write + steps: + - name: Checkout + uses: actions/checkout@v3 + with: + fetch-depth: 0 + - name: Setup Node.js + uses: actions/setup-node@v3 + with: + node-version: "lts/*" + - name: Install dependencies + run: npm ci + - name: Verify the integrity of provenance attestations and registry signatures for installed dependencies + run: npm audit signatures + - name: Release + env: + # Token taken from: https://app.codecov.io/github/adobe/aem-experimentation/settings + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: npx semantic-release \ No newline at end of file diff --git a/.github/workflows/run-tests.yaml b/.github/workflows/run-tests.yaml new file mode 100644 index 00000000..5eb55c09 --- /dev/null +++ b/.github/workflows/run-tests.yaml @@ -0,0 +1,28 @@ +name: Linting + +on: [pull_request] + +jobs: + build: + runs-on: ubuntu-latest + container: + image: mcr.microsoft.com/playwright:v1.44.1-jammy + steps: + - uses: actions/checkout@v3 + - name: Use Node.js + uses: actions/setup-node@v3 + with: + node-version: '20' + - run: npm ci + - run: npm run lint + env: + CI: true + - run: npm run test + env: + CI: true + - name: Codecov + uses: codecov/codecov-action@v4 + with: + token: ${{ secrets.CODECOV_TOKEN }} + slug: adobe/aem-experimentation + files: ./coverage/codecov.json diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..c059a6ff --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +coverage/ +playwright-report/ +test-results/ \ No newline at end of file diff --git a/.releaserc b/.releaserc new file mode 100644 index 00000000..904333e4 --- /dev/null +++ b/.releaserc @@ -0,0 +1,13 @@ +{ + "branches": ["main"], + "plugins": [ + "@semantic-release/commit-analyzer", + "@semantic-release/release-notes-generator", + "@semantic-release/changelog", + "@semantic-release/npm", + ["@semantic-release/git", { + "assets": ["CHANGELOG.md", "package.json"], + "message": "chore(release): ${nextRelease.version} [skip ci]\n\n${nextRelease.notes}" + }] + ] +} \ No newline at end of file diff --git a/.stylelintrc.json b/.stylelintrc.json new file mode 100644 index 00000000..153d9d99 --- /dev/null +++ b/.stylelintrc.json @@ -0,0 +1,8 @@ +{ + "extends": [ + "stylelint-config-standard" + ], + "rules": { + "declaration-block-no-redundant-longhand-properties": null + } +} diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 00000000..27eb2494 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,6 @@ +## [1.0.1](https://github.com/adobe/aem-experimentation/compare/v1.0.0...v1.0.1) (2024-05-24) + + +### Bug Fixes + +* semantic release ([5040fa8](https://github.com/adobe/aem-experimentation/commit/5040fa88c7a01b032431967e230abaaf6d69f9d6)) diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 00000000..75f92707 --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,74 @@ +# Adobe Code of Conduct + +## Our Pledge + +In the interest of fostering an open and welcoming environment, we as +contributors and maintainers pledge to making participation in our project and +our community a harassment-free experience for everyone, regardless of age, body +size, disability, ethnicity, gender identity and expression, level of experience, +nationality, personal appearance, race, religion, or sexual identity and +orientation. + +## Our Standards + +Examples of behavior that contributes to creating a positive environment +include: + +* Using welcoming and inclusive language +* Being respectful of differing viewpoints and experiences +* Gracefully accepting constructive criticism +* Focusing on what is best for the community +* Showing empathy towards other community members + +Examples of unacceptable behavior by participants include: + +* The use of sexualized language or imagery and unwelcome sexual attention or +advances +* Trolling, insulting/derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or electronic + address, without explicit permission +* Other conduct which could reasonably be considered inappropriate in a + professional setting + +## Our Responsibilities + +Project maintainers are responsible for clarifying the standards of acceptable +behavior and are expected to take appropriate and fair corrective action in +response to any instances of unacceptable behavior. + +Project maintainers have the right and responsibility to remove, edit, or +reject comments, commits, code, wiki edits, issues, and other contributions +that are not aligned to this Code of Conduct, or to ban temporarily or +permanently any contributor for other behaviors that they deem inappropriate, +threatening, offensive, or harmful. + +## Scope + +This Code of Conduct applies both within project spaces and in public spaces +when an individual is representing the project or its community. Examples of +representing a project or community include using an official project e-mail +address, posting via an official social media account, or acting as an appointed +representative at an online or offline event. Representation of a project may be +further defined and clarified by project maintainers. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be +reported by contacting the project team at Grp-opensourceoffice@adobe.com. All +complaints will be reviewed and investigated and will result in a response that +is deemed necessary and appropriate to the circumstances. The project team is +obligated to maintain confidentiality with regard to the reporter of an incident. +Further details of specific enforcement policies may be posted separately. + +Project maintainers who do not follow or enforce the Code of Conduct in good +faith may face temporary or permanent repercussions as determined by other +members of the project's leadership. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, +available at [http://contributor-covenant.org/version/1/4][version] + +[homepage]: http://contributor-covenant.org +[version]: http://contributor-covenant.org/version/1/4/ \ No newline at end of file diff --git a/LICENSE.md b/LICENSE.md new file mode 100644 index 00000000..f49a4e16 --- /dev/null +++ b/LICENSE.md @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 00000000..c75967c0 --- /dev/null +++ b/README.md @@ -0,0 +1,201 @@ +# AEM Edge Delivery Services Experimentation + +The AEM Experimentation plugin helps you quickly set up experimentation and segmentation on your AEM project. +It is currently available to customers in collaboration with AEM Engineering via co-innovation VIP Projects. +To implement experimentation or personalization use-cases, please reach out to the AEM Engineering team in the Slack channel dedicated to your project. + +## Features + +The AEM Experimentation plugin supports: +- :busts_in_silhouette: serving different content variations to different audiences, including custom audience definitions for your project that can be either resolved directly in-browser or against a trusted backend API. +- :money_with_wings: serving different content variations based on marketing campaigns you are running, so that you can easily track email and/or social campaigns +- :chart_with_upwards_trend: running A/B test experiments on a set of variants to measure and improve the conversion on your site. This works particularly with our :chart: [RUM conversion tracking plugin](https://github.com/adobe/franklin-rum-conversion). +- :rocket: easy simulation of each experience and basic reporting leveraging in-page overlays + +## Installation + +Add the plugin to your AEM project by running: +```sh +git subtree add --squash --prefix plugins/experimentation git@github.com:adobe/aem-experimentation.git main +``` + +If you later want to pull the latest changes and update your local copy of the plugin +```sh +git subtree pull --squash --prefix plugins/experimentation git@github.com:adobe/aem-experimentation.git main +``` + +If you prefer using `https` links you'd replace `git@github.com:adobe/aem-experimentation.git` in the above commands by `https://github.com/adobe/aem-experimentation.git`. + +## Project instrumentation + +### On top of a regular boilerplate project + +Typically, you'd know you don't have the plugin system if you don't see a reference to `window.aem.plugins` or `window.hlx.plugins` in your `scripts.js`. In that case, you can still manually instrument this plugin in your project by falling back to a more manual instrumentation. To properly connect and configure the plugin for your project, you'll need to edit your `scripts.js` in your AEM project and add the following: + +1. at the start of the file: + ```js + const experimentationConfig = { + prodHost: 'www.my-site.com', + audiences: { + mobile: () => window.innerWidth < 600, + desktop: () => window.innerWidth >= 600, + // define your custom audiences here as needed + } + }; + + let runExperimentation; + let showExperimentationOverlay; + const isExperimentationEnabled = document.head.querySelector('[name^="experiment"],[name^="campaign-"],[name^="audience-"]') + || [...document.querySelectorAll('.section-metadata div')].some((d) => d.textContent.match(/Experiment|Campaign|Audience/i)); + if (isExperimentationEnabled) { + const { + loadEager: runExperimentation, + loadLazy: showExperimentationOverlay, + } = await import('../plugins/experimentation/src/index.js'); + } + ``` +2. Early in the `loadEager` method you'll need to add: + ```js + async function loadEager(doc) { + … + // Add below snippet early in the eager phase + if (runExperimentation) { + await runExperimentation(document, experimentationConfig); + } + … + } + ``` + This needs to be done as early as possible since this will be blocking the eager phase and impacting your LCP, so we want this to execute as soon as possible. +3. Finally at the end of the `loadLazy` method you'll have to add: + ```js + async function loadLazy(doc) { + … + // Add below snippet at the end of the lazy phase + if (showExperimentationOverlay) { + await showExperimentationOverlay(document, experimentationConfig); + } + } + ``` + This is mostly used for the authoring overlay, and as such isn't essential to the page rendering, so having it at the end of the lazy phase is good enough. + +### On top of the plugin system + +The easiest way to add the plugin is if your project is set up with the plugin system extension in the boilerplate. +You'll know you have it if either `window.aem.plugins` or `window.hlx.plugins` is defined on your page. + +If you don't have it, you can follow the proposal in https://github.com/adobe/aem-lib/pull/23 and https://github.com/adobe/aem-boilerplate/pull/275 and apply the changes to your `aem.js`/`lib-franklin.js` and `scripts.js`. + +Once you have confirmed this, you'll need to edit your `scripts.js` in your AEM project and add the following at the start of the file: +```js +const experimentationConfig = { + prodHost: 'www.my-site.com', + audiences: { + mobile: () => window.innerWidth < 600, + desktop: () => window.innerWidth >= 600, + // define your custom audiences here as needed + } +}; + +window.aem.plugins.add('experimentation', { // use window.hlx instead of your project has this + condition: () => document.head.querySelector('[name^="experiment"],[name^="campaign-"],[name^="audience-"]') + || [...document.querySelectorAll('.section-metadata div')].some((d) => d.textContent.match(/Experiment|Campaign|Audience/i)), + options: experimentationConfig, + url: '/plugins/experimentation/src/index.js', +}); +``` + +### Increasing sampling rate for low traffic pages + +When running experiments during short periods (i.e. a few days or 2 weeks) or on low-traffic pages (<100K page views a month), it is unlikely that you'll reach statistical significance on your tests with the default RUM sampling. For those use cases, we recommend adjusting the sampling rate for the pages in question to 1 out of 10 instead of the default 1 out of 100 visits. + +Edit your html `` and set configure the RUM sampling like: +```html + +... + + + + +``` + +Then double-check your `aem.js` file around line 20 and look for: +```js +const weight = new URLSearchParams(window.location.search).get('rum') === 'on' ? 1 : defaultSamplingRate; +``` + +If this is not present, please apply the following changes to the file: https://github.com/adobe/helix-rum-js/pull/159/files#diff-bfe9874d239014961b1ae4e89875a6155667db834a410aaaa2ebe3cf89820556 + +### Custom options + +There are various aspects of the plugin that you can configure via options you are passing to the 2 main methods above (`runEager`/`runLazy`). +You have already seen the `audiences` option in the examples above, but here is the full list we support: + +```js +runEager.call(document, { + // Lets you configure the prod environment. + // (prod environments do not get the pill overlay) + prodHost: 'www.my-website.com', + // if you have several, or need more complex logic to toggle pill overlay, you can use + isProd: () => !window.location.hostname.endsWith('hlx.page') + && window.location.hostname !== ('localhost'), + + // the storage type used to persist data between page views + // (for instance to remember what variant in an experiment the user was served) + storage: window.SessionStorage, + + /* Audiences related properties */ + // See more details on the dedicated Audiences page linked below + audiences: {}, + audiencesMetaTagPrefix: 'audience', + audiencesQueryParameter: 'audience', + + /* Campaigns related properties */ + // See more details on the dedicated Campaigns page linked below + campaignsMetaTagPrefix: 'campaign', + campaignsQueryParameter: 'campaign', + + /* Experimentation related properties */ + // See more details on the dedicated Experiments page linked below + experimentsMetaTagPrefix: 'experiment', + experimentsQueryParameter: 'experiment', +}); +``` + +For detailed implementation instructions on the different features, please read the dedicated pages we have on those topics: +- [Audiences](/documentation/audiences.md) +- [Campaigns](/documentation/campaigns.md) +- [Experiments](/documentation/experiments.md) + +## Extensibility & integrations + +If you need to further integrate the experimentation plugin with custom analytics reporting or other 3rd-party libraries, you can listen for the `aem:experimentation` event: +```js +document.addEventListener('aem:experimentation', (ev) => console.log(ev.detail)); +``` + +The event details will contain one of 3 possible sets of properties: +- For experiments: + - `type`: `experiment` + - `element`: the DOM element that was modified + - `experiment`: the experiment name + - `variant`: the variant name that was served +- For audiences: + - `type`: `audience` + - `element`: the DOM element that was modified + - `audience`: the audience that was resolved +- For campaigns: + - `type`: `campaign` + - `element`: the DOM element that was modified + - `campaign`: the campaign that was resolved + +Additionally, you can leverage the following global JS objects `window.hlx.experiments`, `window.hlx.audiences` and `window.hlx.campaigns`. +Those will each be an array of objects containing: + - `type`: one of `page`, `section` or `fragment` + - `el`: the DOM element that was modified + - `servedExperience`: the URL for the content that was inlined for that experience + - `config`: an object containing the config details diff --git a/documentation/audiences.md b/documentation/audiences.md new file mode 100644 index 00000000..1caac7b5 --- /dev/null +++ b/documentation/audiences.md @@ -0,0 +1,114 @@ +# Using audiences to personalize the experience + +## Overview + +With audiences you can serve different versions of your content to different groups of users based on the information you can glean from there current session. For instance, you can optimize the experience for: +- mobile vs. desktop +- Chrome vs. Firefox +- 1st vs. returning visitor +- fast vs slow connections +- different geographies +- etc. + +## Set up + +First, you need to define audiences for the project. This is done directly in the project codebase. Audiences are defined as a `Map` of audience names and boolean evaluating (async) functions that check whether the given audience is resolved in the current browsing session. + +You'd typically define the mapping in your AEM's `scripts.js` as follows: +```js +const geoPromise = (async () => { + const resp = await fetch(/* some geo service*/); + return resp.json(); +})(); + +const AUDIENCES = { + mobile: () => window.innerWidth < 600, + desktop: () => window.innerWidth >= 600, + us: async () => (await geoPromise).region === 'us', + eu: async () => (await geoPromise).region === 'eu', +} +``` + +As you can see in the example above, functions need to return a boolean value. If the value is truthy, the audience is considered resolved, and if it's falsy then it isn't. You can also use any browser API directly, or rely on external services to resolve an audience. + +:warning: Using external services will have a performance impact on the initial page load as the call will be blocking the page rendering until the async function is fully evaluated. + +The audiences for the project then need to be passed to the plugin initialization as follows: + +```js +const { loadEager } = await import('../plugins/experimentation/src/index.js'); +await loadEager(document, { audiences: AUDIENCES }); +``` + +### Custom options + +By default, the audience feature looks at the `Audience` metadata tags and `audience` query parameters, but if this clashes with your existing codebase or doesn't feel intuitive to your authors, you can adjust this by passing new options to the plugin. + +For instance, here is an alternate configuration that would use `segment` instead of `audience`: +```js +const { loadEager } = await import('../plugins/experimentation/src/index.js'); +await loadEager(document, { + audiences: AUDIENCES, + audiencesMetaTagPrefix: 'segment', + audiencesQueryParameter: 'segment', +}); +``` + +## Authoring + +Once the above steps are done, your authors are ready to start using audiences for their experiences. + +### Page-level audiences + +Each Page can have several page-level audiences defined in the page metadata. +The audiences are set up directly in the page metadata block as follows: + +| Metadata | | +|-------------------|---------------------------------------------------------------| +| Audience: Mobile | [https://{ref}--{repo}--{org}.hlx.page/my-page-for-mobile]() | +| Audience: Desktop | [https://{ref}--{repo}--{org}.hlx.page/my-page-for-desktop]() | + +The notation is pretty flexible and authors can also use `Audience (Mobile)` or `Audience Mobile` if this is a preferred notation. + +### Section-level audiences + +Each section in a page can also run any number of audiences. Section-level audiences are run after the page-level audiences have run, i.e. after the variants have been processed and their markup was pulled into the main page, so the section-level audiences that will run are dictated by the document from the current page-level experiment/audience/campaign, and not necessarily just the main page. + +Section-level audiences are authored essentially the same way that page-level audiences are, but leverage the `Section Metadata` block instead: + +| Section Metadata | | +|-------------------|---------------------------------------------------------------| +| Audience: Mobile | [https://{ref}--{repo}--{org}.hlx.page/my-page-for-mobile]() | +| Audience: Desktop | [https://{ref}--{repo}--{org}.hlx.page/my-page-for-desktop]() | + +### Fragment-level audiences + +Fragment-level audiences are handled differently than page and section-level audiences. They target a specific CSS selector instead of the whole page or the section. Whenever the desired CSS `selector` is resolved in the DOM tree (i.e. whenever the element is added to the page), the audiences will be run. For AEM, this typically happens even before the `decorate` method from the block's JS file is run. + +Fragment-level audiences are also authored differently than page and section-level audiences. First, you need to specify a new metadata entry: + +| Metadata | | +|---------------------|-------------------------------------------------------------------------------| +| Audience Manifest | [https://{ref}--{repo}--{org}.hlx.page/my-audiences.json?sheet=mobile]() | + +The spreadsheet then needs to be defined as follows: + +| Page | Audience | Selector | Url | +|-----------|----------|----------|---------------------------------| +| /my-page/ | Mobile | .hero | /fragments/my-page-hero-mobile | +| /my-page/ | Desktop | .hero | /fragments/my-page-hero-desktop | + +The same spreadsheet can also contain the configuration for several pages at once. The engine will filter out the entries in the spreadsheet that match the current page. + + +### Simulation + +Once all of this is set up, authors will have access to an overlay on `localhost` and on the stage environments (i.e. `*.hlx.page`) that lets them see what audiences have been configured for the page and switch between each to visualize the content variations accordingly. + +![audience overlay](./images/audiences-overlay.png) + +The simulation capabilities leverage the `audience` query parameter that is appended to the URL and forcibly let you see the specific content variant. + +## Development + +To help developers in designing variants for each audience, when audiences are resolved on the page it will automatically add a new CSS class named `audience-` for each to the `` element, i.e. `audience-mobile audience-iphone`. diff --git a/documentation/campaigns.md b/documentation/campaigns.md new file mode 100644 index 00000000..fe62759b --- /dev/null +++ b/documentation/campaigns.md @@ -0,0 +1,98 @@ +# Running marketing campaigns that personalize the experience + +## Overview + +With campaigns you can send out emails or social media posts that link back to your site and that will serve specific offers or versions of your content to the targeted audience. + +## Set up + +The setup is pretty minimal. Once you've instrumented the experimentation plugin in your AEM website, you are essentially good to go. + +Just keep in mind that if you want to only target specific audiences for that campaign, you'll also need to set up the [audiences](Audiences) accordingly for your project. + +### Custom options + +By default, the campaigns feature looks at the `Campaign` metadata tags and `campaign` query parameter, but if this clashes with your existing codebase or doesn't feel intuitive to your authors, you can adjust this by passing new options to the plugin. + +For instance, here is an alternate configuration that would use `sale` instead of `campaign`: +```js +const { loadEager } = await import('../plugins/experimentation/src/index.js'); +await loadEager(document, { + campaignsMetaTagPrefix: 'sale', + campaignsQueryParameter: 'sale', +}); +``` + +:mega: The campaign feature also supports the industry-standard Urchin Tracking Module (UTM) `utm_campaign` as query parameter. There is nothing special you need to do to get this working and it will be seamlessly handled the same way as the `campaignsQueryParameter`. This means that both: + +- [https://{ref}--{repo}--{org}.hlx.page/my-page?campaign=xmas]() +- [https://{ref}--{repo}--{org}.hlx.page/my-page?utm_campaign=xmas]() + +would essentially serve you the `xmas` variant of the experience. + +## Authoring + +Once the above steps are done, your authors are ready to start using campaigns for their experiences. + +### Page-level campaigns + +Each Page can have several page-level campaigns defined in the page metadata. +The campaigns are set up directly in the page metadata block as follows: + +| Metadata | | +|---------------------|-----------------------------------------------------------------| +| Campaign: Xmas | [https://{ref}--{repo}--{org}.hlx.page/my-page-for-xmas]() | +| Campaign: Halloween | [https://{ref}--{repo}--{org}.hlx.page/my-page-for-halloween]() | + +The notation is pretty flexible and authors can also use `Campaign (Xmas)` or `Campaign Halloween` if this is a preferred notation. + +If you wanted to additionally restrict the campaign to specific audiences, so that for instance your campaigns are only accessible on mobile phone or on iPhone, you'd leverage the [audiences](Audiences) feature and use the following metadata: + +| Metadata | | +|---------------------|-----------------------------------------------------------------| +| Campaign: Xmas | [https://{ref}--{repo}--{org}.hlx.page/my-page-for-xmas]() | +| Campaign: Halloween | [https://{ref}--{repo}--{org}.hlx.page/my-page-for-halloween]() | +| Campaign Audience | mobile, iphone | + +If any of the listed audiences is resolved, then the campaign will run and the matching content will be served. +If you needed both audiences to be resolved, you'd define a new `mobile-iphone` audience in your project and use that in the metadata instead. + +### Section-level audiences + +Each section in a page can also run any number of campaigns. Section-level campaigns are run after the page-level campaigns have run, i.e. after the variants have been processed and their markup was pulled into the main page, so the section-level campaigns that will run are dictated by the document from the current page-level experiment/audience/campaign, and not necessarily just the main page. + +Section-level campaigns are authored essentially the same way that page-level campaigns are, but leverage the `Section Metadata` block instead: + +| Section Metadata | | +|---------------------|-----------------------------------------------------------------| +| Campaign: Xmas | [https://{ref}--{repo}--{org}.hlx.page/my-page-for-xmas]() | +| Campaign: Halloween | [https://{ref}--{repo}--{org}.hlx.page/my-page-for-halloween]() | + +### Fragment-level campaigns + +Fragment-level campaigns are handled differently than page and section-level campaigns. They target a specific CSS selector instead of the whole page or the section. Whenever the desired CSS `selector` is resolved in the DOM tree (i.e. whenever the element is added to the page), the campaigns will be run. For AEM, this typically happens even before the `decorate` method from the block's JS file is run. + +Fragment-level campaigns are also authored differently than page and section-level campaigns. First, you need to specify a new metadata entry: + +| Metadata | | +|-------------------|------------------------------------------------------------------------| +| Campaign Manifest | [https://{ref}--{repo}--{org}.hlx.page/my-campaigns.json?sheet=2024]() | + +The spreadsheet then needs to be defined as follows: + +| Page | Campaign | Selector | Url | +|-----------|--------------|----------|---------------------------------| +| /my-page/ | XMas | .hero | /fragments/my-page-hero-xmas | +| /my-page/ | ThanksGiving | .hero | /fragments/my-page-hero-thxgivn | + +The same spreadsheet can also contain the configuration for several pages at once. The engine will filter out the entries in the spreadsheet that match the current page. + +### Simulation + +Once all of this is set up, authors will have access to an overlay on `localhost` and on the stage environments (i.e. `*.hlx.stage`) that lets them see what campaigns have been configured for the page and switch between each to visualize the content variations accordingly. + +![audience overlay](./images/campaigns-overlay.png) + +## Development + +To help developers in designing variants for each campaign, when a campaign is resolved on the page it will automatically add a new CSS class named `campaign-` to the `` element, i.e. `campaign-xmas`. diff --git a/documentation/experiments.md b/documentation/experiments.md new file mode 100644 index 00000000..538f3bcc --- /dev/null +++ b/documentation/experiments.md @@ -0,0 +1,170 @@ +# Running A/B tests to compare variants of an experience + +## Overview + +With experiments (also called A/B tests) you can randomly serve different versions of your content to your end users to test out alternate experiences or validate conversion hypotheses. For instance, you can: +- compare how the wording in a hero block impacts the conversion on the call-to-action element +- compare how 2 different implementations of a specific block impact the overall performance, engagement and/or user conversion + +## Set up + +The setup is pretty minimal. Once you've instrumented the experimentation plugin in your AEM website, you are essentially good to go. + +Just keep in mind that if you want to only target specific audiences for that experiment, you'll also need to set up the [audiences](Audiences) accordingly for your project. + +### Custom options + +By default, the experiments feature looks at the `Experiment` metadata tags and the `experiment` query parameter, but if this clashes with your existing codebase or doesn't feel intuitive to your authors, you can adjust this by passing new options to the plugin. + +For instance, here is an alternate configuration that would use `abtest` instead of `experiment`: +```js +const { loadEager } = await import('../plugins/experimentation/src/index.js'); +await loadEager(document, { + experimentsMetaTagPrefix: 'abtest', + experimentsQueryParameter: 'abtest', +}); +``` + +### Tracking custom conversion events + +By default, the engine will consider any `click` a conversion. If you want to be more granular in your tests, the plugin integrates with the https://github.com/adobe/aem-rum-conversion plugin as well and will automatically detect its `Conversion Name` property (for both page level and section level metadata). + +## Authoring + +Once the above steps are done, your authors are ready to start using experiments for their experiences. + +### Page-level experiments + +Each Page can have 1 page-level experiment that is controlled via the page metadata. +The experiment is set up directly in the page metadata block as follows: + +| Metadata | | +|---------------------|--------------------------------------------------------------| +| Experiment | Hero Test | +| Experiment Variants | [https://{ref}--{repo}--{org}.hlx.page/my-page-variant-1](), [https://{ref}--{repo}--{org}.hlx.page/my-page-variant-2](), [https://{ref}--{repo}--{org}.hlx.page/my-page-variant-3]() | + +The page that is instrumented is called the `control`, and the content variations are `variants` or `challengers`. +Variants are evenly split by default, so the above would give us: +- 25% for the control (the page that has the metadata) +- 25% for each of the 3 variants that are defined + +If you want to control the split ratio, you can use: + +| Metadata | | +|---------------------|--------------------------------------------------------------| +| Experiment | Hero Test | +| Experiment Variants | [https://{ref}--{repo}--{org}.hlx.page/my-page-variant-1](), [https://{ref}--{repo}--{org}.hlx.page/my-page-variant-2](), [https://{ref}--{repo}--{org}.hlx.page/my-page-variant-3]() | +| Experiment Split | 10, 20, 30 | + +This would give us the following split: + +- 10% on variant 1 +- 20% on variant 2 +- 30% on variant 3 +- 40% on the control (i.e 100% - 10% - 20% - 30% = 40%) + +A `30, 30, 40` split, would respectively give us: + +- 30% on variant 1 +- 30% on variant 2 +- 40% on variant 3 +- 0% on the control (i.e 100% - 30% - 30% - 40% = 0%) + +which would essentially disable the control page. + +If you need to be really granular, decimal numbers are also supported, like `33.34, 33.33, 33.33`. + +#### Code-level experiments + +Note that the above assumes you have different content variants to serve, but if you want to run a pure code-based A/B Test, this is also achievable via: + +| Metadata | | +|---------------------|-----------| +| Experiment | Hero Test | +| Experiment Variants | 2 | + +This will create just 2 variants, without touching the content, and you'll be able to target those based on the `experiment-hero-test` and `variant-control`/`variant-challenger-1`/`variant-challenger-2` CSS classes that will be set on the `` element + +#### Audience-based experiments + +If you wanted to additionally restrict the experiments to specific audiences, so that for instance your experiment is only run on iPad or on iPhone, you'd leverage the [audiences](Audiences) feature and use the following metadata: + +| Metadata | | +|---------------------|--------------------------------------------------------------| +| Experiment | Hero Test | +| Experiment Variants | [https://{ref}--{repo}--{org}.hlx.page/my-page-variant-1](), [https://{ref}--{repo}--{org}.hlx.page/my-page-variant-2](), [https://{ref}--{repo}--{org}.hlx.page/my-page-variant-3]() | +| Experiment Audience | iPad, iPhone | + +If any of the listed audiences is resolved, then the experiment will run and the matching content will be served. The list is essentially treated as an "or". +If you needed both audiences to be resolved (i.e. treated as "and"), for say a "US" audience and the "iPad" audience, you'd define a new custom "us-ipad" audience in your project that checks for both conditions and use that in the metadata instead. + +#### Time bound experiments + +You can also specify start and end dates, as well as toggle the experiment status. + +| Metadata | | +|-----------------------|--------------------------------------------------------------| +| Experiment | Hero Test | +| Experiment Variants | [https://{ref}--{repo}--{org}.hlx.page/my-page-variant-1](), [https://{ref}--{repo}--{org}.hlx.page/my-page-variant-2](), [https://{ref}--{repo}--{org}.hlx.page/my-page-variant-3]() | +| Experiment Status | Active | +| Experiment Start Date | 2024-01-01 | +| Experiment End Date | 2024-03-31 | + +The status defaults to `Active`, and supports `Active`/`True`/`On` as well as `Inactive`/`False`/`Off`. +Start and end dates are in the flexible JS [Date Time String Format](https://tc39.es/ecma262/multipage/numbers-and-dates.html#sec-date-time-string-format). If the start and/or end dates are specified, the experiment will not run if the user's time lies outside the given window. + +So you can both use generic dates, like `2024-01-31` or `2024/01/31`, and time-specific dates like `2024-01-31T13:37` or `2024/01/31 1:37 pm`. You can even enforce a specific timezone so your experiment activates when, say, it's 2am GMT+1 by using `2024/1/31 2:00 pm GMT+1` or similar notations. + +### Section-level experiments + +Each section in a page can also run 1 experiment, so you can have as many section-level experiments as you have sections. +Section-level experiments are run after the page-level experiment has run, i.e. after the variant has been processed and its markup pulled into the main page, so the section-level experiments that will run are dictated by the document from the current page-level experiment/audience/campaign, and not necessarily just the control page. + +Section-level experiments are authored essentially the same way that page-level experiments are, but leverage the `Section Metadata` block instead: + +| Section Metadata | | +|---------------------|--------------------------------------------------------------| +| Experiment | Hero Test | +| Experiment Variants | [https://{ref}--{repo}--{org}.hlx.page/my-page-variant-1](), [https://{ref}--{repo}--{org}.hlx.page/my-page-variant-2](), [https://{ref}--{repo}--{org}.hlx.page/my-page-variant-3]() | + +### Fragment-level experiments + +Fragment-level experiments are handled differently than page and section-level experiments. You can essentially have as many you want and they can target any CSS selector. Whenever the desired CSS `selector` is resolved in the DOM tree (i.e. whenever the element is added to the page), the experiment will be run. For AEM, this typically happens even before the `decorate` method from the block's JS file is run. + +Fragment-level experiments are also authored differently than page and section-level experiments. First, you need to specify a new metadata entry: + +| Metadata | | +|---------------------|-------------------------------------------------------------------------------| +| Experiment Manifest | [https://{ref}--{repo}--{org}.hlx.page/my-experiments.json?sheet=hero-test]() | + +The spreadsheet then needs to be defined as follows: + +| Page | Experiment | Variant | Selector | Url | +|-----------|------------|--------------|----------|-----------------------------------| +| /my-page/ | Hero Test | Challenger 1 | .hero | /fragments/my-page-hero-variant-1 | +| /my-page/ | Hero Test | Challenger 2 | .hero | /fragments/my-page-hero-variant-2 | +| /my-page/ | Hero Test | Challenger 3 | .hero | /fragments/my-page-hero-variant-3 | + +Like with regular experiments, you can also define the `Split`, `Start Date`, `End Date`, etc. + +The same spreadsheet can also contain the configuration for several pages at once. The engine will filter out the entries in the spreadsheet that match the current page + +### Simulation + +Once all of this is set up, authors will have access to an overlay on `localhost` and on the stage environments (i.e. `*.hlx.stage`) that lets them see what experiment and variants have been configured for the page and switch between each to visualize the content variations accordingly. + +![audience overlay](./images/experiments-overlay.png) + +The simulation capabilities leverage the `audience` query parameter that is appended to the URL and forcibly let you see the specific content variant. + +### Inline Reporting + +AEM Experiments performance is automatically tracked via RUM data, and can be reported directly in the overlay pill UI. Since the RUM data is not public, you'll need to obtain a **domain key** for your website and configure the pill accordingly for the data to show up. + +1. Generate a domain key for your site using https://aemcs-workspace.adobe.com/rum/generate-domain-key (make sure to use exactly the same domain name that you used in your project config for go-live) +2. Click the ⚙️ icon in the pill header, and paste the provided domain key in the popup dialog + - alternatively, you can also just run `window.localStorage.setItem('aem-domainkey', )` in the JS console + +## Development + +To help developers in designing variants for each experiment, when an experiment is running on the page it will automatically add new CSS classes named `experiment-` and `variant-` to the `` element, i.e. `experiment-hero variant-fullpage`. diff --git a/documentation/images/audiences-overlay.png b/documentation/images/audiences-overlay.png new file mode 100644 index 0000000000000000000000000000000000000000..7788a28dadec45f6e24c009dd8264e69a3403e3d GIT binary patch literal 58760 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 Lw>B+1i-`U|>u>a| literal 0 HcmV?d00001 diff --git a/documentation/images/experiments-overlay.png b/documentation/images/experiments-overlay.png new file mode 100644 index 0000000000000000000000000000000000000000..a8e19ae1efad14766d849976e58bea511591b74c GIT binary patch literal 84980 zcmeEu_dnHd{5L0+6~{VM0h;lD_x-2i(7WJ#fx>pL1RBYrN+3^}J5B{-p~?XphlSP*5Dv(nK0kP(Uyg z6bGiM4}mKVuiW^-1Esg&1$BzDF3wr-0%wQPve(t6I1QdtQ&3SJqc}+Z2>4T`JpT9j zc}gLQ1HZ3BC@7+wD5(B?<`Q@$|0IGxa-07isgffp4ueTHx`rjhCIBo42F84>h#*E4V=8p=snzK><5S{-e|~J{zFK`}-4T!E^FuF<$uZ zkN7w%@uGC~;TrBTB`|q278Y+sB zXa3Jh{I|@%uYz?}rd1UCyJyO@^S%x`U>iA|ka}0ZBM><959KQOC-mPV`FS!`I_?A? z1%)bw7E0Oi8{!&$87hNI}92d})s$irjgvGPHOIw<>(sz}VIuf3C;$vSti!l5av z|CD`4O!h2&ZrbZxaG^-|oU@-AGlsLvC6yW^D|UbUv={dA^?l#}LUK1$*mv_mo4h;| zlyd)fGez|<4N{4Y7Y_OR%R@;+NQ`Xy`x-pC1TkPlQ)6!J{i-scBUv!V4AZ^C*qHXZ zb36dyI_u+j=ZU?4TO>1vIci9W(F_Zy)mE{Xx=^1 zEOA1kqQ5+u99`gMyeG6bmYx&TS9qy~hO%BFpQ@+?JtA;HLQqWt`ZFhpEhmE~a(E3k!!Nw)S^WpB62(3@eIQwjTc`_dyKCIL|S2 zB;nrivU*hn|C=Tom`u*0!U%0$Y`3iH_!dsUVt@6F)#18#Bb=PZ4f`KOO-ZZhXg_gC z6I%?>?tgq5x*ClaA8VTKr=UxnkFq0Jk?A4@`65m)BS37%+ z&p)dGr7M$T;L&boZ1zJ~WK1z8L|G|tb6@{580NhrmeA6^EXj_+Z{{1~uEpq`*dDBd zCH$9Ci%hXe*n;0SXiDY+w9mLzrZCQm1w+F`?$$bwY<%A*h(yrZ*lSHQp zJXX&;AJG(GESCd~?VqT<$F}X)sU8{-TQ2`LnPpFS94)B&kXO^}$JLdIv>`fB<7~NX zT$fq-ceyN>;1QzyRPD2a))}{A`VraFDX=h|&GhbNan9D&LZTg{r4K<~S-E)c$v?Ub zhRKeWQe%4v1~VbL$BBnT19TvT-c7R}T0D)O>7Gj55vk-CEWL}Ixk zo4uQS=%R=sE+5XQ=m>Ul&f>MTopD84h^oOWIKPW&_EtM`E>2s7`-PcMshm}WODMP` ztdhe>pg>ayjl0MiqwCjPpZ&Zk*NgUWZBLV{Cmk zski}zUJCR^Sv<+qKyi^(n=YiulhgBpafW--Q&SbhhqC+KMOvI#Gh^elqQPbHr~3x8 zN-H-_^P+;A(`JjZz?=^CHIjE}`E&709P9%`Ql8#m)_t30DV2UvdltRTE#*9MDIQI8 zy502=cdaxjY$o@^A^ALayNC}na-uqXE>6nO9lVX2;idAy<*bgFzc%30I_nC0dw^csD*paoq;5ob5aE%K$B|h*1afwBUe5WCD zBab=dxi^XG?id{lZS)x4T9zi=4EMaFVZ6}SM^fC^U?~`|9IOx1zg%3kS+>s?WetM0 zcC$|_D!`)p%aX3KKk;6O@^6oiaDsJRfk%>r>52J?HhEtr0ytz1IJR+OIyF+k+xp7m zJ&f}m5WkKEABp9tCOT_eu1eVyyl@L;iAju70`*0lN0r;hXsjr29oqtebY z#m}D~&5Gz0RH8Rg-k0V$T{x=_u&y|kcok}yKI?H9_AHeZVy8)pY!-AiNkqG0>BS$O zV~7(2N{x3Wqs3fR!fhXH(G*R>Da4*n)VH8Aj4}NgY3C+&NTqSN!%Kn(|gDp;h2lHu)%5RBxHf^q}r7CVB&+foFB z4A_fIM!V?RcP3NxMjshG7?u4LJkc6=d`93>R@z+~-yijr!$<(vX*REg76gd6L*14ce#BA7PE!qoz2rMD9wY?H@Cj- zd&`UwsMX=faJNpZjab&;aUcQ76QIU!`7tO%zIDoe^5G8op2QxZ^7DI2mF{0>af|vL z720jAJ`g|H;O|~DXpIe|bh_Og%n}|E%o62y=@hR73=_S%-GAG08G5&{3I%T^C92z~ zp&rX2zwpp%SUE0NO09(b+L~D^Of~n)3H?!=B1G?A{Eu$yP~hcevb^i3a3)=yG9xb0 z@0qMPVl=QsCjo{|F@9#7C%mT6uxJYUCZ3APfRx(pPcCur3t29n!P|*rO?g6<gX{`l&vPz1&HrZq*lJJ`ZK!RvwKzp){PNcWKYVs8Y=(y}En(((H7a4MR;6t#H6= z4%#MhoksC^aj9MoERqD;av00$atNq@({s-E)alElGH-+Q65tW2!C+)AjYcp_gaEUR zCkLG>OVlPzpnG$9Vr(KoWl4GS^MQ@kZWWWC{{}y1ENM3$7n|lNhm0CKmrgxQx6eS* z^U~{bW^mKCp!hT7q_Fv*&psV^1|#rKaH&L?STS};sv!FHU_wM54H9W31Z4^?7|*1p zKbRM>I0!UzsUhX%&vlb0HNkrUA0?Bc5TsvE<;7P&bFa3OFEpjlj-(zEwT3pfG@4qC zB}RZ=Bab{$dQFxHtJ+7Zu`N7;nW{)?W*M~OH4V}hAusx+KK;W8?$AxEjV^_+0TOM} zQ-3`ZGS`3x{tIU8$W!z2=6oQNW4?H&Y+jlke}*c3LlzUdAX6^fhO=7gt1QiPd$SIl zt@2SCVvatXmmxZ{r6;(8!#LGT2s(R4z)gAl>&xAbO5a``aGQLSWP0tNjTt_I4xCOW zu6_OVX>DOhk}1aL93N|^EE?m^O~^Nbf*U$E^#rp-P9HZV$>n_H|KUZIf38!I&k8#c z)zs5uuS6eVgH?Xl$29j)!cF%{1<;Xp0K}4Q}C(#rRiZ*zEeO$kb1&H>Y)M~ zw)6Dmui-K8Zl#YiH@)^_!X9&)4#m|Dw-j9&&rJbnCu75Xrl>rWRFWe}e8HaK9C@ov zC0}ZNXJf}Z9E5n#rjU_Q^Ih_d@Ki(xv|w=w;(t|tI!}C zH%V@Hj>x=WipHOmV8sY9>%vJy2ve^kDX|?TcLDw|TH{QnP;3ZG^gvat99de$mkedv zd7414Po6f;vA-60nziR*Kx&}s4WU+s^_$?qI1l17Er#V+P+pK$=k$vDbR+U+^Mh~nw z9j|f|GzlY4UmAr6uShR8KF)s(-CoR^Kh3-6I6wxNc*$}+g5B@9`*S>d6g453mx+$o zn#n+Ous)4!+UmU2(2n`N;XIxdoTMm{c;$%<)z}CtMQmht z7G*YiFL1L7=5g)|D;z?D{`exOp|pDVG!rK8WKy}Wl0^rMeJyZx^k}07a{l)x5y=3Gq@#XNng&;ZZ?EG z-%}Hra)g)jWeuZ2Ute5jy>;eqga)2S3HH>uTht8MXP&%pc}wMO1qaD?i)5$su<=k1ErbA<>0L}VNUf@`lPW#y>ME+z!U3k(wxQPWXo?HG-U6B$!IB~f@)PUYa* zAX2nojEw2ge>+`aL3wvdkI@R3^Z>)oCSf645sjp>+Qf@a6Wp0Y+9(L+Sb5f{a1GBi z0Vq?{78S2qd$3#G6inriM3}cPa^GDcb2%tm;cgY3GUo7MIl^EJW-T#6_lkrz??7`f zjPM)+M2C$o!b$>-dEY~2?I_Rh0`ct0Rhu&x^&|S4?spUe&CLw_`eNe}8^-<|J&|lP z=&XgHoyizELSPby2}t#kh$!lFnRTWYH=ac|Gb(SsI>L3fQq$Y_Z+-?6s$5nGuo)g9 zKfY_RMawYsA~1M1CIb#EA^9M$bx#RKfT1+#=%>~bk?kXs6(`QDe`{g4Koq`s%lD5; z=!dJm4E@Pz!!&Ch-;k~$%uDJ~#;8~DM)ERwYI0uhx$THU&Kt{o0@G1K!iPKTGIMWF z0WnUm>gYPf9k%0{^lee$PZN~e69w!B3^{Lp9&R4ASmm}bh%c|Wf9RxD9@3HnHAhNkVb7Xk{F&dO1JxldbcZR?_I z<;p%Na*KLW@YdjnLrzGt1cv&2Nt6IH=qlwZN7$RdJaHuFuppjSCiyT@vZ zpmVbhjQaNAip=FivMBC{iwcJ%K*!oaj+N33+Yw%5hn6VJU!T3pIUrVab3I=D_?n{ z)vQD25R(OruyEqgJ^p>!fm+J4fz=1DL>t5e&0421!1@_JWRG6vK(b(_Gc~0=G45s^ z_DWJo9Nm@-2T69RX0885GOAQ(c*{SS2TieI#;u3I<_Q!NAQJc!&tTTt2lIW!W-@b` z{Ul5_&ZsZ1w2O69N5t&=2}-70ud;)dhFs{uy>;OajiCJkkMAO&oi`noN#Z#NnXEL~ zD|9bOaC^Rq^8LS;%W@w0s&;CmGPMRW--vM;j6K{n@c1fA66(!u5ZUZlL-6|S6;#%K zjCU?F@0(KUG*u)NXoi(z&NVj7R(%?t(^%G9?vMe151;LONLy{VE}WOXG*jMmu601I zQUa5Xg1RPOlshDmRbW_x4gB``^$@dx)Bfi7bkQs{ZZ8$vKv#VwMiA4WiH~GWEw+vo zje3MNg5d9~yuR@_3s9Y=(t+cKTTI!|sJ9%1TI`TOG5ygq{N6&R_4kd;up}CN;IIG; zdHfECp9G7j)FBD;!*~RpwKAIHYyRz%5}aY0CW+uaCrn=39_hiM2De*^t6<5Wvx z@m>Gmi}k#4H0pYd_C2=0TZ*1zNmMOSwlP!NU%0uLTU6F&W1?5D?O%JWrwYOUi1j_V zKfg!95N3?8Z^IR%f37J5Y~wcmHFVP#)!^p94>M?A{{oFw+4-iC_AYV!V$Kt5{kMTj{7|gH zdruIl7=tZJdp-8Z4jr)CDchhN@`Jy0XQ85d^kJr324Uo^$7l56dM>{~p5jB-ln5rp zWm()e-nubDJWHzvyvU1odqrh;D`CW~VKF&?@9^o6vKaiSnYt8J#QCd407Bk~CQra$ z1A-66-20VCRCyOG_I&r(Hr+MMicg@lE){_Wo5Rje>xkT8&y}QxYVdtCk2xNB zWjBE3Zy)m{a<#+^fU#0CJ)!{;aC9^hSPKxWy5WrMwaUJa`G2Y-CnUZLgS{dZ9cLQp z(%fENHxF$2x&3MP(n{gM&DRz#_?A%!9pbZqUiQMru-y=qZy_CN67oZBvWu1d^%Y%b z+nHo8G#+4(dvyUXR2bLHr(*M-oFs3&KFlo_I;i~P3!gAA@#|Pa4L~5glkM%g z;-m+@***WcKC%?SZvJL=cwwlbX#V|^)RDlM`(yRqVhNx zChSqzk6FQ*;Tum1?K-vY{M=dX&PiE+f8C-EB!|jc+U=`TsTM!{#3derSX}EPh}(NA zOhH;Z79(8trIy$ndBi&>>{noNk-lZ!6wX`mf@FvI9ZB=MNz)|fu$^ThLvOp1iQkaj z&!0CZlP;KUERBtoRCHyqQfBI@{Cr0ox^;isIbI9#?w*Xv@z!{*dBIh}T3YCj*`Ec7 zY^UtFREyBMFCnC}B2G5WO4mcS*L@EhX7FJVyySD|Fyp07j@01Lx^6S$Ksu4iL=)@i zlcPXZmdd}q{NAS>KT~|=`s`Mr`GqZ@jl=9fGwGN7CC~xuLk>ZB+f;R*pYs;GULYWd zn(xWGb25nApmHWVNQMQrlX%~!Pb;3gOKRg|(APSaOLDL2&c~}P6IjgQ52vc6T6vY% z-d$FX5zoyQe){~`{JY{5JFQ@Q+nnH)Hmy*FTXNK6zqY@AjhCP1Akq)_@a$|-Hj-k5 zgI99Z?mV}oUL}kl<__*jWh;tW_6mE%B;R4nu*HWN01x^xdt19{6=6k&Slu@SY5TpPIU!1q_L zN3?0xX312ydbePElr~0F-m%QDK7LX*Cx0?J5Hh9gZ{@u~UePG_?TxQFlf?YygoC_giOt8}1Sprp zh%jMLqGgRgZbUhro@M}sAgk={X4La{t0Ts6!)_KmMTsa$r`REzQyeAk3CcelV1qBhU|{N6tXBByNI=!4c?pSy3puSir? zTzSJchBI+Hnv)?Le~WOM(-=F^f$1Wi2to+fjsBi##q+fRlbLrL0JZa#{TN_#$=JBS z5RH*$v*N}sZyG;1A9wME-o0#YiwnQi9YdoDZ$-YvIEX-t)g8y0hc#t=zd-Le-DbkF z;UaL0_SQZtp2vd0&vcxu4rF{naiSI)E z_bB}O5$Cx>45gty(!A5%D!V)OBoS6(3(`3F=VsK2C%gmohMXNt4^sqmSB9`=BiU%g zLF-d%u@)|;fjTH&r$46(jdUxz@3&&MV`Xey%Zz^WEfHW+$}>}Zi^p(&8)N?49}i%! z-)y|c_q*an%ao{!Ko${frl^til<8I-2`aZ~gw4M!TtG|z+LWN>IxvPmEz$aogcb9P zRiovy`2kgml~nlpd^ICZZPfo$NQhr+8IP3FyP%j;4>e;{2|VUsycDMHUfvn3owU4c z2~wK%i2_aSZJr{<`m&>pQG>K1uBHh`3Do8YL!YN*FMs{eT1ItLkNKH!7oA`c(9w)9 zJV@f6t5mc)HnGrT=acqc`?}YcY@kQ>FpJ28s26WC1^O(}2jj}L5q0=mvdd~e0M3)z zoaHB(o!~4vME)f$C!=e~-jt^VrzwDE#9`J72Wl~Ra_zA)oH(RUMNR%-zYK5Q~2Jak4dyvVN6lJ51 zR9sE=H1J6nCvkgGF`LCrr}5j2J;Oy(Jmc=a=#csFr~Zg<-wq0%JcB-b!coTlj3WDZ zGlVGf`i>1=^G-9!p6+EuirYJ?eW`UARap8792NVC6){Q-n|IBq7xoin3n}(OWt-x1 zRWWx~ou2*B)N>pPdg{(pf{Wo1F~swN@OT=KuD&WTVX?Gw!dr|w-5c`w12)<%_wJ$LLjLlW#PA_?W$ z>DkSJO_LF2#ERG)?zEbsCsOn7xV&E799C2S8eeihV-tUiPOz8&Ba{aVe+EI&vX~ew zA)@1$bIG`%%#dfWeW4@^SsvEB*{V;8n3k#98U!@@Xb@k>Sh>wAdXJ}B3grDi?6GlLv7N@hkyC!cSyw$F=FgTm#wLHKN_ADYd(v18|at#mi z!o+YdPuW>a07FrqK6F6NXQyZRPE@-woYyCkf$NyLs9=Zh?8R8Flv_9et;r2_JD#KF zDN|?1R!X5Yl|WMcaZ<{pAWI91`Gz|yP^q6_Sf)F4kCuS?+zMeb_n_mNV3@sBS{VnR z%&MFx<+@Jepxs8O^2Sob*B|4oB~(y`;#^s)t*KOZzhhv(Ytt%H-(KvlS@~V8Qk4KU zyoLIn$Ma!G(&+*tThilRySS=^B~9-_FyQk>bY)krw?leEHML!_Q#Ng><<6shonAJc ztJ+LXcun;;{Ri9oPLB`Yy=E_wgMS>`j+h$0`yL0u_sI-osv_3vu)7HwPuv1_kIFRF z%lGFVNT2q?iRaXH6LMzrp$6H6AT7(tMXZYqV6wfTl ze&a~%m_+o0QPJreCO56MFBPl2<58&pn!d*6cQ}f;B^aIh=+wCa2?6oSH^bMQJ1pY_ zVOCnFr_(%cZ;JgLj?80K#f9?b<|C#Mks5t#px+#iu^h+c!H;(xrO2cDZV!QBKE?UxhzwJT>ng8Gm$Q zoJuIZrTxnC?WR=U!kMTKSAT;&e~mVIH0GuruMehVlv_$jB0KS=Bj?!7Yz@9vNFA{` z=80FWlwR2Z1$P~|6>qe>eZ?7UU+btuCY#!zF$_8PI^d0U`v@vTxC;JEn3@IBq@{Yz z?@L8HJ)*OPH%{b`(HSDA%8v`&A(iJ|=$WM##{#6~UU|6Ib4N+ZL8GFC?W3ZqTowwt zSzfP84)RJaGM@dCTc8`!3coho3NGBc6jT;KX%p}o)L?$PtOwA$_YDf^FL|?n{iu$w zwnm%r>QX(^|KU`0e>zGayy0c#_uz)e-$fIl^B}k4$YYMbei?oO#EhZ$3FXHy=auPW zR7e=U7f78<~IB^!y=%6_9u}fO1RS5=C1AFdt%P5I zh@qJq`_v3emT?d`Nq0*1Z_Z%rNdc$SkT?=)rtGA~@xfxjk7rVLFJyE5nnA%%2m5h^ zzA9%LVQJ`F)pp8R`HiK5grr+l`XI@tUw3AMUetd4nf;)pAGXL<(4L6uPAo&TVyg)F zh4@8?;Vk1;K2~(DtZq8vUHeQXoY_7;>`}8#L=!b7ZY6r7zG^C>57r~4dFimA4k?u=F;;b%nIu$Dp)I9(4IAU_C{)qKZpL=Q-wM+Q9MMAqCoALOr9-h?Ht8&! z^DJjP38ooUJlV@XKxDpsuy8SJX{=#;jIH*X;+>=8O;psak9o|kiG8Puvc6Y|GiIS% zQ*ELmI@zk>DF5Sj`l8OCtY$40&UhD$;BG841`fKd^j|&p^&PX@@$=b%8PzPdoKqmJ zxhUo7BS9Sd)b?8CfYX?(XLhBW;%2z0`AmWg!!aqL4w8dk|JZS?R6PM7dFEj+XI8o9 z5KKu8Y_j7P@!px^ zI5&@M1#g0e+P&&mavIDZ182AtTDGSu@zUAC0XA(FYZtTwKbBZ6dw)n?auPlus<>gQ z@_d7HrttRiW01j>+qq9)zZqHqx%ZnDM+q_`it{h1wtDR$%~vk#PN8o3fB(|k340Si z(!>ZgdmI~*fBeVV2May>vr&O<{Y84*8=ykHsaVJ`%-Aj@+rfBZ05u9AjWHMhXs`Ct z)<6JX3ZKw`)XM7IRGq90&#B_J8tn6a(%X9D?hwqi(z!3YawdlBPAI5DzuS$vA+9N$ zlFDD*iP+dJ>s#%gE06+6z`8E53L&4usv30wHe{XNG7GN$#%&&*0um|ht8gX#CJz8~ z#QZO=vHpHTC<^!y`FB2-8U*3!!6j}=N^%2qqyTu;Q*%A;2@K5iM$*-~|A4nDRd5H` z((O5Yf2uTj&aQ7sQahgRE*sU+G~v z5LVZVR1Y?NHPGF1@h2k^S0@ZlU;fi}I2_#ZUb%bK`)lz^=ALApKm*8J@d>U zIpjsv0<~eU>ANUwG!Xf1-T=P-rMFpEY3*J1E&#R5x>iyNK>P2-`fl6#Tv~gSta+ zDX@WBAJ0?2d!Rb`s{_R5G`|48EJGu_$Mmd1g6*aCpI9bxcMsX!(cS?BB)1l}>pCUD z_spvkRSR6G=0qD7NaZK80U;t@;%3|=KlJ#l+hdVG;sM-}#Du~#0<*SUYja_pWVd4f z*v^l1>#WFB@ z;gT=C4?;e;6ho3$e|(>vIJk{r;(Kl>8hmo5VQG7PaehS3Yx0f#P&?P1L1sE$vtEyE z#lUAlGxz-sbI|r|+mdLRRZg!2j+^kk^0~-KAYO*n=T^YIT7Cm@ooj7^Ih#XIiw|cq zli@#qfVb2GcPrDj0$?9G^{joNmYI-`mpb6km{@EtBN#~MR-*klY^fhY< z6!eR9_fQC|`^>$IE+B+#jz`6d1`9m+OiM!mg7%4w!^nS_{M88-|JP`x%J}BHssZD6 zPYe4j&(^FGkQ$UKEY(izgdAbCJX#&3u0%}W{%Rq5*5}LT3Lf#N4NLXcGGDO_=vw_Y z9q1om(bC3WG<&Url)vuO!?dQ<7!I{89-$5%$QC}q%!Mg7fsd8R38e9N*`dpxSb(UE zndgd6C;j*gb*D}koQtfL+x&cI@ybRMoftpq%f_d$4HlC$9sHQzNFX}HHWq?`)>l@T z+aF2_e}828T1NyVN$YGD`z2Czw*zyp!3D0VlyRyWBZvFaT{yz{OJHoaqt9oMY5QwP*jDVpWgTVJqu(*-=59kjNG zp_!NipOGZ}3L64xXvl`h zFUrH5iMDF2{UKe(*t|`$7alu1Uy^b|jnH%)YlLW|c0l06w%RRBKa`ny%dJ4r6*G4V z6Rqd%42$7VV@_>0jK>H-wMNq_zHV=SMu8!rQ2py#_)`yp(xI@43N_;}tuYl^2R*_41 zf_!*806At#yKYR=MZjniS10@qrOJ?5#{uOm5yLezC1cdbnN+E?vG7pI2Iin`WH2A>!4 z#1oCjcayb6J=+l#v1}79!eV^2DEP2?P+46k&L=a$dy$C)m0jvu1uNSv(lyyKbb zQ`>PQeHGB24s&}`v$SqX40uEywg1-UBgPm0t=Vm+)(zAU!nz>6g_oM}&g?4_ZOUXU zxa*lRM$XH^%&QwJ5e(k56Mpuz|IO6tb4KD>1!%FYKE?PrsUt?I4q zVkZx?{TCBJ(YJsQtFn;^hog!tF@ke$IRv^XV@cHDy74_~91yw<~>i2`F++VJuGe zqhs5-gVxG+LGYOV!W6~<$ZjO-wB^*1hS!1P zsyl3;3q{wyD=tr`)G?vZL{)mryT?r(^CEU86LDGHNH&4X0CF*GpcH1p;LoM3 zt+*T#%Wnnjfvs5S4o?p)8atFyld~ z&RK~I>|e_omgZ8ao-LUxMD7BYzPhNpX&vj_amm>q8Nog}QBsY6{mMpV(joKM;&c{DY zw27B*#eeojK#hVDXoRL|X$~Mm;ARiD|apO*DcinXlb|ffo8g)%h^a5RhuaSp*(hE*EAhaqdQ| z+AnaY1UG4&W{nw4Aa1nS=mJgaVvIO(8&_t{QthKw;mfPe993RLBQhT7$u6nQEAe2= zbhE=KV~=U5$p;ksd|`xB-m8f#^=n_cuv|^ut?8Z}_E2I93bir~QbjLNfx_lg9XGBh zpX=>x>lg);PDCA2QKKqRb+TYH;~MmuSc%2-7a99Nm^Y~SH0HF#CfZsvz?xfNCLK>t zX>!rZ58IfH=zJEcWC0wNQN0YWQa6ljy{+y$&kj(sUDdIah*&2a7=QKAL`cBIr>YRQIszFQp;6{#YfJE*%>R%fu6 zpTCQ_Z=;-l(8_Y;1^zp2gAIW+4#u|DKFG>~ap`UikJm@`_;wy(Qosf0IoBlyP2Ib` zb4f(tM&Al~nO6&^Dk{DF4Yf=Jd*4cNquZ%C>m6sk?9rYk)5Mi zMYj|wfl&{Om1x(Ja@kRjJM8PrldN5gW{TAk3)T#)Emrk4&Ftx$wWK{YX9jBSR4E=S zN0%x%?gJwNo?Xpl?TajS+~qAZ$CRfn1$g_UXkoPEo>RZ-!D-O0@);T-IJ-~|tDX!8^K}i;5=|VGJ2|^M zf{1H-BN8H4v$fLh78^pS2R(4o+lqXRlc)I-1)##h1`dCiPp`scw_fF(P1t{>k-r%l(^<}-e2ph{dz`SkA zHr~7uw>rjn8j)DLO1s42O2hj94z;L`k%=1HCXWv7^AA<4fhnk%D(?G-ZLtJ&YT&2H zl>__N;3nWcLn~MQ;oInMfR^*WV2>&P2sN1;Dgsh*`haIgxDp<k68L#qdbMkHB zlGy#ML<38JCawgDtU{8f0e^TrM-o<)`iJKVPULCAaq7jI+2`3X7$an99gy8uCLIX# z;)Km0z$Mv{QM|hb2>12UA50}rt%DR^C!UAl1ITYCQ6f~=Og+!}_nu=vc{LEE9iyNQ zkxek+yT!&LJPwj$i*H_J_5d&ej;|HZ?wyGQNq4X2mCv$|Rmt=P1yE-<`_vdR25iA( z{Mk97Pi&@?kL`=x0PNwGYUZ~*&0Qv7yK$^ z8U*HP4Dcqhyo*7uJBkmpPdK5J>{DHD3W7?>mtk!OS^oGhfG(Q4^OU(ZL}VDuhitcirpo%4h9V(J<&eJ z>|TZMlujJ-0Dwz9nK{6|4ZsX}WTSleCMfXR8SI^%NlXR0Yc5sD{l*Z!1ab_9C;A}u zNujm;X%$p|hvDoSy7LSrAn0ELCnU61$b)qQv@zwz)??1K04f@ZB7(Ci;PhG2k|u%C zttp(w4Mf^C8lAxcW-c$*2DEDkUi!)kY%3~OpN3e$j5*BdaccymjjQHKT8Co!G%)2w5)*GbUaY(ocI#H! z_}&X(s_xSIxyOEQTqDxm@1H1KA9EX z&-{y(AYF@-9|YptsC=xtJ-%oQO!eUiNDERlrUsNweeR|ZqXZVtf>-l>3nz==e?;G0 zC@?4LJ{J{XbV$Onu~K}d|Hr^FUMwP+KdK_FzcqRJftzITVu4nQKpp7ngP80px!OR6 zr8V-T5ik^@rHLv9@H&R^cVp|UE0W2H7{dDPC>csieVw=c&YsH~QIawh_fuapT{T>A z?8#WYZ+lyOZpHcxCp9nLk&Z!{E)s(0{Iy*5mI-qurcJgyrrr74IGm>>C~@J=b4AP9 zDu+9SayQS=mOoG?9DtS_ET{NR&=Cx=)CaAF*5z{6C;(r``V*JV);Q`JKwFyiPSk7$Kv?+}DOt)Dwx11PR0%Wix@D^p~W z>bnI^+%nBjt$aR?HzWwmSdC`^+ExkmCuOQdAdw4#cf%{5X(U}`*hTe3@FGeS?y1Gv zaM_y9-n(v|E*XAn8&cynpDnfC{R+epTw;9FU+O;rT)GYEllHbQbhxWM;mIUe)a=2U6;><9e z_054lM^zEX#HhuumDEYr)(hFb14f|_SIN|1 zbtD$YM{?-^2UEPZQcpuC{9d0n?K+&-9q`&~&aI@wVTW{!@&ICvm=2^1=LYCrS{c7b z3p~%?`X}JYG~Ce1lEV+BBb1oqOC{-e+Y7S5NgSjnt!0ykD2J+d5 zq2){l1g)1hGdRnf?~Ac?Rz{>_8o?r? z@6jT033;8aKQt58Mgu~Ae|>L1m37@t1uG_2{)h;sa6rlS;&u6Uj`VG! z%C96zpVxhRC(ZUN>4xYx=JgnLZ<*E}5*?yk^-`+Hfc(I_=2F0eAtMUaCD94uwk5~S zdX`;2>sty47Epnuu-|!>a3=m|RJ!Hs5*vX#;S--+7HsmAZUG3)XXGgWu1-~T=+Y9G zJ^8aSDFV>;shmPpTauop$U4;t_HzBX{jInW@CX-&O5Rj_kR^FoQOJ&*bZQ zhXjvCy{AUokHz2)Q${D!JDeTCGx435a|@OLNq^+nScks7h}sAn|H8_{V1bdrrcS31 z!dKzEXVM2>lRie6Dza>Xh;GeBM4lTv$Dpu~nB|soMN=p$Yyg5Etrt9UgSMPQM(hZ^ ztmW8SYqOp4I@&!NJ^=ltnAtV~VM0JeJdno+BW6DuNn+$_EubAZAhiKN=Z2&9X|MC; z6$%I};%^8m@;**5Z%_alE!Dk`^2t0Kj&+EFAU;(Aq)1>|TusnN{B?4go=|IkoHyQf z1&>d^W{!I4wMqQYbT++O-%qjnjB7G2j8OaBaNcdvDk>c?Zr|jKW-r|3)ZaUk9s__2 z1mw}(W-zL<<_?SclvQ~o!}h|NJRToZ49aDQvuQ3-gJIbK$uuBgG8}k)YJ=;%~=`%0oKR-C6NC4 zl20!%3#xKD<4UJ49J9u{8N;sFA59-@xz-c_^A!rVHegL3q)i1Xe%ln7Vy zq6=}xZ;zZ%to_0^v=)I+^VuDUc`{S~fmY+a#_u{C{5Uyv@VIhHTK$$$_nkvWRutY& zK4F&3HELf5L0Efgp>E%N-I6Orhy6cJ`J-b%@gC=0eeJ4sYst1geFm_0U+T+gFT<(R zhqOO<Ff74NwF-9)J4We#!C}xn=X{Md^P|Mm-~A%ttQV`{%IT5zrEEKwx}=#DNB(o|f0yllmu;`u`~OMW-n~%e zlyN~dkJA6E4L8uQ$h^Xb**9-|sB*skq0~fncebw(n=rAO?)COmir!4ueXg8K_s{+= zL2iSRw$J)3prEhjd+$6GT>l?dbvVRSJfSh`(USZldV?CN=)3#rYC%=KVAsz6)5qs`O{wA6Y;EbuWti6+mO;3{?e4tRG;s zSL`MZytxFyANuM>W=6lethZS2w>bAO%j@m2lDx-znAc+FEAV9zB=B7uUj%?W3+QIN z^AHD8J&ChsS|ESBhJA(;Kdtj*_M>BeWCSE31QPlC9%?-&p10uddf!k=pt3&xi6`8u zJ6p*NL>%wzMq4-3Q`!G3grYA}_niFM%&1aJE^{nJfHP<(_0%I~cxj6=-Oj3HmpA46 z)bB}$Y8=#Zltiutw^+wrDQ?Ec7@EFZ1{n_y;Bb@6FDmG#+Foy$RMb5kFr zJ1X_r1oo60aGFrE%i#F_68dCQ->JijZT#`? z<6U4zk8B`S$^r%u{6)r8d*SOeB{6>v%b^eP=(ks7f+pV*@m=G9WMmMLe6`^3xcHbj zly3UymZb=xQ4vKhfT!@Dckt@x$Gm@_h1_21^0ak!i(muq&Sce&O>=tcd6Msq4P)=Xw9U z`@gu}be-qV@BEJAdwh@2IOvS<|NGMsHFHkb*EqEHV~7P4A;=m7ijRUPtJzmI>A&h* ziFBfe>vJk%2k5Dxmyr_f8_J5nPWoill}r}%A?-f_W%R5MO!CAN04DhQ)Ns+SY_SI$ zD&~{NoEN(3(g`2@cQifeHh>&celJ~S;1%&bOs@26_-%9~QvV_}Fd)nUXGo;jf=VF9 z@>JrnSv73&|BuPU-Ag`5R4!OiV!w&#i*6%}+`6bE=9b)l1It@cqJ1bHj6?Y^%#wWbQY^zxb_;i`Wjgi$9fPmW&kRcD1llYzpjb1I!fMsW%!I6Z)&FjoXE;Z( zpON~F82n%UMmir&I`7gUP)6PNd$;hPKY~H9&*=lCoesOIp%{_Vhk+!+@?`cr+5f!B z3Bf~yxiBbEKgG2{MM&hJJk}>_SlMp9|Mw0FiX#pmAh|FLq(&PN1`=b&!iU}}BOBd^ zoL(ZY8;JOeNbO!=<`qvRwWvq=C%vl5&Nsr@WgkM;iPTHL@24t==-RJwnWk4{Gl(zA z-s1a|(u$H?a&rb$;;#{{3lYaIwjwnA*`@f01Y1)+pHJWeM*%mBy!xn&cN5t_wRyYpi;OxRq? z)DIqB1$4>EI@uJB43B0CNfx-PKIA(;2GII$Qyh!oXP(0U_Db zUH{e(Ye9Z(vaXIsBW_*ICI5SXJJ3A6Q>TF;(TQ)ChDY>;ZpZ}-Ax{OI$ro%y_{e1y zZvYXel&tXp9zvNR$hCYufq1m^X;}+?2iLk}?%6-_cmy>JoP=@EX{TskF&Z;)pC#U# zOSG$my~@BBMrf7zS=X^+7PO>XW$oN;Kd88&gvePA+{2<$3c`NyU&Q2cqx{S3`5N&V ziL#|5rW66s0;vY;fs50M$Z!fTHQ6umhDHOcQNszOrrKE#!bzV&y|yugO1N}RhuH^$ z&o=(Y>!)bK&Yfp#fKz?rDp5EvIQbPzlbC5c<56AIxcus_an2$TD#zJ)^bokZhDN4) z<>5ufJGAn&gWWS9vUmx7V7@0->rRdt`7Gd4xdxwRXUXFZk`P5nP##a7{5B|Bli4k+ zfx_}Yv@X5?m#>ha-~L9@(}X6 zabPoQsp^{$`eeMAoJ1P63hV2_Jj)Sx>p^v~dY^hwf1zR8?GV{(MQ$A?!1eR@U7c&zrZQn>Czh(D#%4ln@oeCxw z%_wk$a^uaTB-&*a7I$txqf&+HQht&{fa0ABs3?PPj=rrS>p*0zX_Hw1k;WBEC*+{% z4+WD1!ob|0oT+V))%6JCO8w^KrT0N7gt-Mxq~ zM;QH&R1^IfQH&^^-xw>9q61&?;2Ur@W+vYT7Cl@6wi#vH8$?sfo<(G51Z9Z#Iv__o z_4yKVSy_m^gpgIf!4aa{OECibKECq9BEo-It`~Pid^L)Q$au_mjzCbiHCW=gw-#FJ zXNypA^{QMhMt-wX>iUjNs{1<9G#up8har>f)Q8sVQsa^W4%1S5Q1B}lOYY%ayi9mvGXDEF_t}&{NI^%HCxCgBN8|n@ zTrkFAP|)jVkL+?TOO_og;eMOJaYT_ay_MnC@0-BcRL_w9g4E~fRsFmxLM)-IB9qm`0H1jVAzeN8XyH(<59To97& z&a8l=y$4Z8TLgRqn%bE4#p3=~*o46y_QD50BB}IrQhi5YPpvhd%w`K9pwgRaEBrZ~ z2KMSpdqD*cuFAZ^i42CR2&Px{7rKhl!FQh$h49^9qHDHSP?8<&Fawy>S1#rL2so!9 zgg!XFHmGgI-aMu%@+h^tapd{=@VGh67w%9YeOz4;J3YK`3`T4Y2h?t*^|#HNLVw>I z(J6Wj79&GPgK`eZY*^FpQ@ocrDt<(iFEAuCp$deKfs`mca$^p=fTRi*X_sqsv`60Y z@AaouPmi}#juRZTEF8dg>biWk8Rq86FTihS5Ol%ARyA?p2~ujmuf!K!CpLM{4or9w z2j1~d0ujMiT*fm8s3}OUn*Hp7H>Xav@`aJNq`~@SATBw;uXzlpe7CP@3LH_w zVsC_;xBQ8`JT9*`*d?6s{+8g^vO3vV{S3gJ+i1X=C>!0rX52n4(+Ur;3!4LMg}rR4 zX{JF;Y5(DOsZ)*To^4xOtdkA3_c5;a64aBaFEwpBZ0jtcbOJvO&w?3IZSl=65^+?4 zANO(39pN%fZ9&We&3G5^DM4V>P|k%Ip?_u!;4ou+!{nn$$Yhd5gt^&n;!UG0w3wk@ zK)pqEQ>E|j8_?$OJCg!++H4P)!9x0@`G!rQC#yhu8$Nm4>uV2CU!&Hj2(`EPhOj5F zp^Dw#WNBewwEGEr8roV>bs?;%YM-nky``mi6e*+qp3dOiXVA@P@}E)cNm?!vGnlh zBOhsA$X67rhso$DvMJPe$PmrzZ>)&o;0^3u$lwkI^c5Scu_4bn>KtrQAktHeLg>JK zFC8HXe2171RWsUwDZ)midM|h30I^zL3%&f!&&l(O9~zUKnu^wGV< z)Ro7-4?T(8;{35AI6m@%p~He2m>nuD8qU3o!gVuJrJ% z$z5@_*^`5=r<6uSBhSQ=uSkk{2YyiDB0WB%sgEmlm9B0Ar<>}^v3PM)yU8G_iK;%A z?D{Y;<6~C#Jb_+awIRF+m$2M;T!O)vjl)#HDArpbNSjJm!EYVH=aVP2WI%P9&sCA1 zmDCYN!gH3WuOC`BRe+&(A5rd#`_IGvZu@8;_9cFhxC(%?{rF}T%bCcF=`G~YO?TazGL=8lrmey8uAEl>9hKspc>e`VWsqS*ujbgv!+pPL-@yMFLq9603(>_n0kUM$TBW&gV1dGMq5KC{^V<*mVttFguS@?Hi^;^qGh0yZ-;1L;ph`XNCFk_W_VH&knTRb zD@Np4E;iXnnI8Lf$;_FX=3a|yhG3H;eRadSbL)@8l~&fgpOLEUb|pu{Z+po(DH=!V zk(_XajOEa+cI|u2OVaE!!D8>78*2fyT!SpA&{|MzW_BOF237$MnpMbW!JGb4gOc+jK5#ya+HN1G%X()pOY z-nldBHWQK-8`MlYdLl553fF9Z#BR)opW|w=hUDkq<@HwlvOzG1nj=m%V)2pYT}IYq zJ6*pXaF@1_tR6`OtuMH$-nswGVf9tE6fFrkK9%=m4nkEkb=6e9;?LO-aNGB`n@IKz ztHCvpt;;zy4t`eRR_CHceric`FeeR@Bs#QAXQESkDGptKd#r%9SaSy${HtzlVdF6O zGYFS~K`=$)N3hSPUuw3q&lT^F{yQ9(L+jdGDC%~a=ih5d9&pdrl0Kfoe>RI(m(LC! zr2RsmI3e9rR7*cT$l0sT;69EG@~{~H($9D-Zue1wZ7|vXv9wpNJoYpQ)ED6X6_at^ zYp8opGpEq^q7mz2&!gW}!@XZ08^6+$ZRf09NDI|kIA9BL;i~M8C(u`F{y`TPAAF5K z+r#P?lFdEvoB+nphyKQdHsU}<{Zvmn7mFDzcKl#n{3|y;rv=e;y|!iW(R@kFiLq(+ zY~W~Qk;#cLknWyax6Chc08oYT-ds_{AhB0vji;oa73HD$DC0Civ3^G$Xvq$V#*ASP&4bI zB(t@EY1N>{0cC$&nbfv=(2Ai!`+Ng`$m>F*i%(yc#~ma)vBcN>_S=y3y6b9g@rY+s z%NFY^B00x{N@XxTY)WFE9<7ovHs$vnGYW`)&9TfIJJ{Hcf8OASpYA9F%|CuceDO&* z{X{;)`1hb~p3Re<-ZKs~bFVez|$+OGo>< zr68KKE3(26PW`-u+CR}F&x?qL8q&wYSdGBC*B`y;9K!8t^4$gQct;G!pGb6HTixte=d%#`-BwT4%&i0OSo zgefZ5WoaK9mOH61f4)gVfw}PVodSQY`a8^UtDU8RHamr8H>pxJ1uHwvy4#ps)aT?5 zrffBFn(eV)XHh3f&bhzdp?_JE=6$( z)-)ui>s9hO9CNW%KULH*xz=O~J-$T#);@U5+e}E@4w$n*b6*U0;dZWzWqjOQD8W+%NJGky34&sz~(Uqst$h)Ys9#RwBM**EZb(>0&zLP|FJNM<`c&Sqf8)~Y)_(|sad%=Hhhh5>Sw>#TBM%0$GQNa1ljULxzL*>Q7g*xUO z>&k=_kbys4*X#?k4diXs*1sTgNzV#bs`mB1;Y+HnYX&Z_#&L7aX}mUWh29MAYLll` z<={cbvrr2!`J24{WLo+{8%hWF8z1dAQpOTAksTqlu>d)_E2&`v+(&71Pdl0<8OeyD zibRWY%`0u<7D(j_J5gfde{sV3Fje+Bjk;s0n32wT^j(qW@v13wME=->e=^$e(!Ic2 zpLM@798tfliktLY7i~`7yeTD9?!un%eLu5A?_d?5s!DOQM%U)OiERQ=40eHFB+0w} zN(rgWZGNk>K03YSygpwK4%mF(MNx6Swwy1HkudJ&@l8>1KB#nCJp$X8gxN2j?!UBC ze`)AGBmFpdc3u{x5CTDh+^1BNInj2?{@_MVU?6qO%(Qf3D$So|P{;=fbV2+%}fpWF??Ke>vP0HNC z@#}itRp8r1dZJ3HV)^r$+0ixqNmV?Pw&$9gSJjs>!~dDn$*I(w0ajXj%PZ*%LuJ?1 zNtzE-Z$g>oNvu>-T?rO_jLL-S0X=79Nv1@G*k-H^i!%ehxR`~`)~xV}-P1#zPJF3a zuM7oRlC*Rq8@adarK36^W(1{)%}@?0HlF5a@J&%ZQx+>FpRYIQNK!9RowQlhhyz=J zCyp$cNGS2{?O4Nw_N6=8){G1xLJv*QsulgJ3WBwVMzWmBH(&TW=4%>0{16jtz+XI& zj9AWTg9M(u#p8wIbDWdKmwaMy0E*=3!JSZ}F#3K$;S~~zy)L-Mh9{K3+mpVpdcnD` zs##nrk>Pz|LWVi>Nw}kk3upDl^QX(9eRz#zGSB>c=*~7m#h>f8(1beH^pmg=e6f|a z9Q7K_bKy2p!A}A<>KcM6jA|XUaM0biW#b(LsyYm1$~U=nb3&u;Dbhw<(`QaB<_)-O z%Kf&YSk58U-1OsHw>PrFLtgsN0xpnE2V`n#4~i94BQl`NI+kIIk8cxWYR}0SK^b22 z9cjxLWm{+d7f-rPpEyaUeDc~F#?06ST}1q%V_C~dS4#^lqH@XFn_CrL3R^E`Ojo`Y zb0%%%4r~!`6?hj8u^9IJGn!fQ2&r&^%~YGt<-?FByY8tgN!8a#1V5KkG%@%aXl}9; zlYO%Arp`R| z-)wXJ<`7`;PkShrcVdh0oHdE#w>Bb9X_8R9SJza~V^03d-#Q^1(f{hdGvgV@)p)c% zw*DEhUI(8nuabJJO`S6alrdqq^S!gwwbt6PLi3xR4TckssHWGgYJG1!?9QbW z+PVnl;+*HHGtH<>tp#q6QO?lz#Sj$D+(f`T zug+gxd5(}ChioFtJzdso^WB$>mzFNLQFn7IyPliRDkOiI$SL9nQ7k8pR#J7GTi#() zHU|A&OdmHzsHchR4UBxUcrbm^Uwarg9vqz)Ln-=?*U&bV!J;eoV;j@Ft_-6@QktzS8^Jk6B`ylT}-5h#XN z#K#Tesg8Q)6vd~1)D>xyYbaf^HFVwlu#wuP`aaI$X))e>5=-;B-#g8AE-k;BMiXgX z`mH{khoZ)u%l0_}R;=Ps7_%7B5miD`nE@Ihy;ECB@}M(BGMd?aOnTj=_V_q75^*HEP+}~a zA%>)QBIo`>Da5FU>g;V_ht*RrH@<>mS*@mC2eG{k`hEfLI>?Jdu|Ibdcy$AwZc&nNq8&7#QL0XlT2H7qu`-!^94LWQmc6L|wwd|x z>@yUl*J9who!)N1a<{PNE%~3=eNJ_6h zl2`Ewga6KKd~P)qO6L^sq*|~AJ^`P$gH;o&l8>j~|7FduRucpC&bkqikm=k_D6v|8 z*!{=_&+NdZC4|k_Y#Jl=xKMf8C`^>e%FxmJV)*j`d&GrOYrdPj$?h}MN1;o}>q>c8 z8>2jl@m&-|nLo+Ql6p8P+vZl%Wy4$m%B?)i4RZB#V)M2PUQkZD+4IJ}9(R?%ca#nM z+s}-5fL~(Bj3<}NO8FMl6)NUap6cJ`^1uJyp>|#a`2UEr;Oxq4!;VMoQ|x8mREx%2 z)m2WXZ^Qiqb35r2q6+w>a_bAiaL~a)#I(eE?;|3GUDs9+gZ>Phi67oTTxHPD1ysM} zYnCp-2YgJ6qQu-eCxKd^gs*`Wh1yWjt&cn@q|Xo*FJijb;ZLl2-_p6XaDa0csWQ!& zrRD4+s1QOF9RebJ+I-opbuGAUxAu%%As!q^xuH-xdk(PDi@E1Xd@AWa3kCf?+*4V7 zTq^VM!H69^FG*5+3Gk-^%jd>As3+2}tJ`bwRO4*?{A* zxAtb}#_b1OQX)WrT|=ax=?Sr}TFAoPN>2LDc5DIufN`dFN(cqcz;cBRh1U$Fp(-fz z-C%y_{2a>J4O$w&xVUreb13U8B?Rh;d~|J5Fj{*ZYgp$1?vg)^l%D?H8LG5`SPaJ- z{wmVdU=VDyGANtK=+DT8QZDwP0yIerxDyaJf^o)JUBe#Aluwpo?YlD_6^x-|zSail zF#)6Bh8m#~r!YHm_a4F@|B;Ho{ojBwztpV$Sg97(o5U7qp%%r2xf*+Bl9e^LIAVDy z&!8xFc~{{bmv-lCAEf#VwH`;r3BY-b8TpwnX(lA`Mf+9m6g&r8ABVlKSHm>>4{<)) z8~$T=|75>eJVGS!j_Kjf>X^WME_uNLtb|`Sf%O9UU?w`;0Y&&@uS)%e>oP}=js*g+ zBTcZxPL3Q;7^`8Dhf__(PQE%lp>aSHv~V#EbUS}06%76I!-?oSiJsHFI;Stieag!- zy8%|cVq=oSgKRnnO{Nu+{qkeW788L^!j z4STzN&pIlJ`XvpUxsyPEVdwc#q!3tsar%ca)TAT45Q#z=T5Do>J|*nP^d90TRUOUM zN!l#9UOp4LUDV1yVjQ_|Pxut}{kQx_4V1HUj!a&pnh!C`pbRpHGqO*KH4noT$q?|0 zH(2mX8sefT^$?6)c50CI8~k+BG*B7zAXG#v){HL}E=%hKovG9LNxwZ;As0N%51PUj+V)RQ?qb!oVD@U2xmJ`NCFHMpg52`AT71 zgslrM8YeXE57@^C-Yjr3q@9b}bk#g*e>5e$m=VdQ-Mhyh4gmjx zhA~En`)66;W4+3Zj)Et>5dLS=p@=5^mo_O1OeH`?7X(eFaY^_b0WeNS3UcrsW*y9I zo^#-c$5$8lp^+faX)%EU+~Lb`nlLv%q=(86@)(PBL7Hjy-i?)dP()V&YZ}3>fibHV zU>E8TSsF@j2uiE49lcAGVa-~Fwe&mna7e*I;TUIT6tBNU3&2o$D_BV$7I#t@Ma zoLkBLK5~pxSoo&F_bEREoBVC%3?u-aB_W zai`@9DVY$KQTg5yU?THF+>sI&SpK%Vxx4)54|&T-ZZ^2priY1D{@|WzVL@tiMpj~u zYiJGc=27rc^n1rONtSElt|~<=YGbYYgg9n?+4m(Dnq@re`Ms zAQqf0RG9^iKx9Vz9YY@*l2Lxr^#>JS{-M~XI=6DOt>+sIWV{xNC79b`lOei1I9>!t z>IMBJD;B-h{hO7^@o$Zq3BG9ZI}ip^`yT({nf2ph{E0RXcGE@R>if9$)1=dzh zFsteyDKJf^8itruqag_Zb9 z(47BZvyc?BVxs4jeRbs)uS2Rt#_y>$9yzA}m<`F`9Ep3HVcI-+(6kvwNQO;K|ByB< zRWQ~+p~y7z!|XFjvfl5nUnWGeJ6_PZBxkN=%F(Ra_c&QTR`3ySL}q-Ej69t$Hy(x$ z!AZzr{(8mygzLKdUajXuMV(!4v#420&7R<4S(oS0dfDDFKPG{XW~|0NuCoD`sFu{( zt!5n}nAx0XVq!=rzyeAsMND+-N=$1azuxp+M@r{Bi@wbG`uPklTphoXdry9u$dCF8 zDb+;zoWY_!gMq^vaR#0@{BKXj&>sy#OQo!XgP@u;B^Dk$7WC$f_=}{C1 z#}0Nl5`R9&edml%phWw3tCp*`{(iIj&gnO=PKvKx#Q5_$iGOfuQ3QcxUhM7+|9+EP z4*90_kHh8~I(P--d0%NUu;?)hIP%_2(^}fiz}C;>*tu`9gH^2bJx8l3i}Mcd>F3Oa zPX9uOfyZhKat|uY{t707YTLgOQ|o~yGx}cq_u_|-=lMUq(d$hpy&?h$ncl`GDA`N1 zKF?aL%L$%7WuY7k6^MgQsI3`&@Z$xMa^SAeV9etwj_c5jq5$%|UZBa$xoE|UdX~x^ znXgaF=h{uy@_X%XFjuwKK@!$eajDXE-4-4mhNxkbKOp8%{0`IT=OS8S;a|l7fJu{u zcp{Kdy-f`G?N3^zT09Ue&8{ z+cb1#`{LC^W+vrn+?6EQ=l!cMrPAu??4PL#BtoWsW?gD&JN&BbD3CwaTM_FYD6hm; z7zIfN5xL{HjkHFyDjCX}D2zZJbZV^fWwu;G1Xw;f8hQF0UFWiYX>8N&Tqp$drv78d zo+^#px$p&lpun!I%DOd*g@c{-BnseNpPWZWet4vnvUNb1NH3MAJl+Tpf0e)hD|hj| zFtvO&*o1Kptt~tfM3(9qAOF*ZX|;vfYUK=DU3Nk;NRsns>8K?u1)rtbmnU;wDeL~; zVC77MOK!qEKeE)59w2wrDC+CrvmhN&9pS;`ez_TFRBP+o@;4Ab+?Ls+@g*@+o^DJ| zl0^TFV-Vl2RD)DWsSq(=_HdeXVMJr6^&-R$b2sm`Zxyy5v=*#wFxtaN5wk=k8ip1p7CBUZ{ zD7cO9ye|CJ9W3_7dF`9vR)U}8x2?jK$eU)Jl!u#PPp!cWi+!tbSuI_EvhJzO@a|1)IZSk= z^bJDY)E29~0P&;Lhdm+HabhX;?QD9L{kVGKEA00KAJtOAIXLYwXN24yi{i%RW9RJ=saNruCbIQ@>#tMOa>ztL znjjLeMcc~Ya(QhQ^0tsdG&a&^Yc+B5$duvylO}9DlA9{yq;>n!vAphE#)!$^@7b4P zPeg8|XmzDmcoCXuvrs0eJ8|liw!3rvZk^unIMQ^sU_L@_4wl%{h&P0~izmVAa*V`a zm{gX4JI$=$PbU2Lb5@3@5&sN^3NnU2*KaR%A)p?-wSY!#37yWx68YB*S_{tGLo<$- zPu0d=hvVzsLuM>nv`f!lBpIGuq`cW3#M>e31;ovyYpT;~&+pt;Ps<@kZ2LR#6r=HK zyuso-p(-VBy{ztc?r-p=2DXz&=p^{ME30`Qj!kl0AwLEeJzFG`8Nlr6dh)Yj*~33W z`ug#R_s?{i1Ia3=A*_Ipe`x2QJ&%EdoG3QO>^P*U=o=Mu^zHtKTwDmLy_IkTXN-gd^iv&AJ9qmx`^?f*)Y1 z%d8daugy1qx1sfA8!3&)#egTo>vtP^CW^VWSu^@@(02n{68C{RBspMP^TvP>yE ze)bEi8DV(>J{f+=RiEsNSI~guB|_-htvmV6nZ-jgTA6Yb=Z>DtPF=G#?*LXVw zVa16AatF29H-18gVf7Z`60R9Eg!D3=2lj}-kGiL?t{?9^^^A3_lX^nKrxPtWR-29*&Q^JwLr>{jN~l~lYadv zkA`Cze2AMcqORS2E=MhH=iu`}ntY4IlJPNL3RN|%dUXrZ?u?g-vzR!(dx;+N{EWHY5iCJvHLOJ~Z6{`| z!i;iO(wVVf*44igGz3k>4(V+#8Rx2VDZC2PE3ta{!rpw#O+Lz#X#H;fp_ABYGWFK| zG~u%GK5UQ}A!JNgzveT)T9ooT=Lyij_TKlr-)agl)xnEQuaD+X?b-F#e#DMPTK9rA zo$p6Zbd$G9p&_H?*Rm)-E}Cdro7Y1sDVtB;A!ZGR3{BW+obS8xe`iTfKM?+$0n2eh zdw{dATA@Sm=WPdI?&gCCx7@1IthbYIjsD~`O_b>Sdp>UkY%l!42+sS5qa^IHo1^ z+Z3^ka!bmN0Ha-|mkV_3t~ z0L%T%^3)+WlP%pFE6$?p#G`9#h3zA~NqheLfI>Cs*BlDgbqvG z=T6M2Q_)E)z>Sf!R#>?86Y_mKzx{XtyX1~IuB#sk_yZE&vow*5ks6I_WR9EcesffD zrR@CTg!^xDw|_cBnnecw-K_6Pmw~|hNo$;{B8|akIB=KwYuQ}DukSy|F^BHn{2K-T zCmRH_2Vsn9Qhmh)-WJ3IqDBz`u|G3#25U6_3}%5Zp495>^88`Rc2&db-?u@1rNi*c z?%OR1;q^1Vk0Tm#$C4n&`!bWt{ICA70!ro=XU-6m%Sqi*yWMnva3B-CFVAb>@$7sY zt~-|1Zuy;aUaUInNw#Zex7mLBXY{cwhJOirk{B_ovUmb|{pn>{WpRZVHiwi1$xNCz ztlpDE*_f09y>aFxWij=_j&vg-Iw1k#+J+(S8gctNmi&pPCq1nr* zCfA>2WVR$|2cI2(|KdB&y-uzsP5kd$@N!{DJH+$bXg9z-SaoBM z%H)CpCf|pk>;I0qxhWGe@V$_G@aOG)nCM^oeIKT? z#WK8;9@4x;f1N2!jO#z6cNZ7K{UY(<4b}-sQ69{Kh~#Ygu=;W4m5YD(58PU=)7^k{ z{=Qox8yRN7rJ4c+&ju>((p{bhe=}Oz*Viy%O%#yvm>PeQ!$AuSg_yaR(~Uc`01K#zPA@+e>P~1OGmyy9c*DS#*qqLpQF)loqu-%x?Wf zL$+M)@7;XiGge{YJAIZHIA~R4%czOEr%#thip)YR)5-t+IYL4{(!nGnz_&_VgeQ!p zdV;^^L*TQT2M9ah{rjmx#fO{Ijr>-FIc(x-p8Qyb!p;QAXcx>5o4?aZ#@J0D5Su1-|>* z&!y);IIF}E=R!qypYP9g>+Kh;%UC*98OB_lkF3m5fw=@(GtM?`L%qHA6CKXRiUWV2 zv&-~WGmz# zdp=RhP!@iWjEBnYd)q|BJohBK|K9b^U{d)$^M74(TdOL~$?4HT&{dRZ(1j;1tD^&r zO8u15XhVM?f7!oP7Oy)JX?Gnj5D(ddlD1;zxkS5L>?iO79t0oiy}k-Zv%U)N9}dQM zgl66}&zx3MBm$V;(iyp9Y2;{5dB<=X*diNST)wS{4z>NQs`%ocr3$G~2JJHmMT`*o zfA^LIZ5M=3_cguI|E@Sylmu<&GZ}(^Cye&B872-|WRJtre_lEj_bYr|9!*f@MLV>mw)#&-1J4D4l!5ZYC-Xz zH@tHTo{UK@{og;H4DsauhUafh?f-`7|5gvOpZ@>ZTv_z_033_~JZKGW{l(zvHwwj0 zD^btgVlY@AgG!~^13lwU>^{+~8l#|oFwiMB5ATTQX*TUlvVbh62uQ$f|=rTf-7E@R#2_w*z97@h#GItrHYwr#PTT?$2`xl}l47s-y0 z(|GeX9E&$f1U#7q^78u~k#iRMI}s;xo4iDN0+d1pyNiTP^C5YC)c4QivJ#FGeAsUx z$teX$cLZ3h4`~2Hwh3l0&4*G#wAYOejcOQ9G7k~T{%!h>Kn5hBR z=7){|X@{0y-J#>JE%~h;X+nB97;v!9MH7}ozW(y|EfJ`yt?6jJbM6;50Ls^DgaXIM z1%41fX*aqfesqVuv9)UVYFx*iW4D#nqT&@HZ&$*-Ly7pANjHR?9LP9Vsd9!88um1NrDk);p50EYj zNUcBZr>QcksKBV1#QhTVPLw-r!EMWOu zN&Ws7yiU;s#HqJw)n5cD;$rcR9D_Gg!7bl^;_C~ecsf#%Vppq)MWq#~uKlf^q=s|U zZl4j>b*9lR-ysx;)QhPAwX`Bsr?OC<7MxGI|GKHg63QMmtt5vX?da7q!>*4Zzte_zJSFnmBtVT&VHZmI8b=+9teyV&G`5lfmz*Wbpv@FiT-T%4 zQY))mRb%lB3Kte82w%Nhd3N?vK2lL%%_BQb z<%~8sOoz&09dF~qoc@Sp(O{r%Nb6^m=LeTFdH*h)b8FpK4l5on19IksF(2a>Jx4h>n4zCsN?f3+dV7~ zO@bLpbA9><`8*=f(RIpMb$O$UqXQ_~|#~ z{H%+rBgNn+IoK3Jp}`+k7Y9p&DA3^dl7g{NTEXC<2pf_&zqu{)(V0AYIo19dxMhr}EEPQHW%U zH(W%YiEBGc3KwH1_jzP&kt*gr&yDNFih_NjKZX05C23=r@;(nuk-nj@E&oF8weh7F zyIeKmS#5^v@?eMFP<6Fx-3cS>!b4K9*M0QTZdnPVcxRT3N0OHRi_Tpo`+1ZsA0`)@ z#+n<@$~vv0qpsyjsOcfqeI=q^ouV8(DI2^}h$O{>uhNzYITIeT7f_Tj_+06_zoe@# z=x!L1lQe&W<*7(+lte$xyGUgrmgJf=NB4q~JX;o4MwG%Vejh;~UC0V$vj)eqxZ4wg z2Tupae%K7Ey+LY8O4&V8SV|vzc&XgEW|%g2O7fm`D3!h5tLx<~-Sk*;r#=qpk3G06 zGO%46lBHwdgcuM$=e&|*u0Kw(Ll}5+?#!8!lc@9m*#GP2xbglr74mpy|{`%$2t{$KHYDi>2>|8qg2gyyGX;`t7X-6rH&yOiI$nQz zGKRF|h;LRKy#Y@D<;W(sE`z=z!*4(rYqDIV-i`6_UzPAa~HhUnCNsMeF z9G*n*^JpE^sG3IhA*5V;@-9e=j&X46SdAOB0>Vtl*rNa{`AalbIR)PUz*z(EqB>%y z^kG*N+a(c6NQJCUC<~107jds8eK$>ZpR<23u$|-y`!LJnL}vYF!v&slgqWB!44_`$ zWN_g{Y^?&Yd#D5|Aa})R9e_z|Ko3!jN#rX6UP%=o_uSiB(2M9!vui+C#RxD1elR7w z8R|G8a68gdCSq1S4mTzIsL8gdgWp*rc->-uiJ49H?9X*4xfZp#j6gBgJL&Lai4gJ^k?GgUPjQ%F~Yju@fC89uRNS>?XJn$g*gK?|b zG$NV@Z-yKL0qBw=_~Hvgq+-O15s#P4ut3LkTq*sB`(KWS>W*i{e*e6`2ZW54qFdDp zw3!5}znrVlyDK9+AHO1f6V?q1({Oo`e9cT4XZ&Un%Vsdt-mcoJNCNU^L<8b(+w52# z&E_TJ0y1YDbyE=vaQ=4Fv5se{3qSf4w^==67|d>6kbfT+ZR@pMByvf23sDE67%ZA% zJz%GAiElwmtNSAyQ)d~zxxsmVvo!t<*wNZ1SY#G78hZ>s3aEhnD6CZ)5BqI=^Nc%; zq0NJ(DEw8(__Rweu9N8(izsA!vf`j2H}5)mjdoTcy0_vh0Y1xjtE)U=ZpQ)C(<~HI zpha|bYmmyx?KUPNJ;WH>_!|_^2xm3eo80rZ^^ExOCcY~)gc(aC4GJ9ORWb6isn*g5 z2CNA+*^3d-Fwa3xuHXz^QxrDP>@4EX%*wjMB4r&JBH6;C-x&e8Qb9z_g>vs)0mW9K z%^SXsUt**qzBeI@u1XITx?X|pCDWUHvE|amxOm_=x7Ff%$pBqxYIrbPBQK&T-y1QX zUY<*GR4xNUh^io_gs*i;laR|Y9)iWd{wubZ5-&WDk|=Kifeu;`Yfr^EX;CqtsxCa) zR(W;ppD;yhs^7f<_$b!Ia}45dU!0HY;q8Hnp^jpv*&F8=L_HocTTF(oM?A8i-MtXv zOD&Yps${GPy8Dk4a#)LCNFJ}QTgZ{SmP?C*3yfnKa5CDY0S;9KX0Nj+=K7Ef2N=wP6n$oIK4;HQkwAX#@xUtrW~#j zV-=dw4*M^=o^_B)e;A3qR&*6P@wbyXw zxcdi%zVKnbB9Z;5*(}mS4RM3ejk3#93BHAn^xZ4ezDnuq$XnmLrlnm0gQYf2<1AM9 zLV&k#dTthY30pl-b1@SjreqFUd0@F-IZoxf6f=1u5qL{f{8Drgr`a{D2KVV-k9j? zw7Ngd;y$-6QsyySYELfasG(!SH@Stf#h;&Q+lw?xuyBaOe{}bSB=HDr;mvVbwjN3f z3jC`Rol7Mf7=|X@ZPA(NZcBo|YJ$F~UV`+Igmd=E?*>G@G-s(2OL7Tn;s|)B#vBJL zvb1QLJ2P<6IX7!8v8E9bwvpOQWrn+|bqenq$Re-ZWTSY5Twks#bCT0zVx<%Rgr^JsaehEC!Tl0Y=cOo2cf zVRrG4Z$O*7WXF+vF;JSv+x5fM&91-$#u&|dVUj|T5EtFi^xL;$KKu6%B;G7 zw~`A%Ao_KWT9lc{E4N6g;qE75>=)&Q@uYemXXxFhj?A&a$pv2<(UEWFK3AHFM}h)R z7%uU4^u91-Lmhm1yRCH98Zg#1@N{Bhy{-Vbc66bysyg&xl~{cKzyaU1H~KY6?ug9I zuRsRVWg=Xy#vvDSX?(Mp1$`xygvK|iZvEtd=&fFy65;;r27a}^Tg7c3lS|KJ&P(-1 z*^3F|cNtD+%4x`om=1eUc}z^3Nq-9#3{7WJz?jr|!Te^mK6Wm&)GPXoqSp5VicHz_ zjV`TgewvIv!y$H#-;NApM|-~MSWLVv7O1uq4dkUUeut*(Vw|R5`63?>Fs##3^580} zPe=oWQsNx(U{?-*INMLy5HT>57@(Fb^Xl&KVrma2S1#!_XNEaWc8;){*F{8OwT53& z@4eb+%6V?{SG7s?O$$*e3Px0sNBH~zixq`jVnE(x1gsw7DTTrpIeq; z!=Y#Ar_SO%+i$fg8UI*_9#u5GUKkPm2{QPP;vWWZq^1q)nedmWn?~|=vm5d4g^z)o zzlkwenj{c%cGAY+vBSVs!d16SSY1)^yJUeh8!G`eqM2qq4l)Ie;!c4L<>^Gt-*M*y zN(ly;0qw5r*Y=10s|EXx!||9smXggvBHeB^?G2`5asF@Sm%z-0z~j3lMpNl9!L#`g z{SJ6;Qn2D#`~oF?Q{>vW$LAhgJzQ|!h$VxVwoP^5NTTLNv-q=^ zt6d}4bI5V&L2@{}(f}h~qlQ`}#?Qk1#Wmt>Qy-`@zfV zC+B=RC(C2;Rw6%31u9G<*7G?H`d+MOPHgIy#P|gT1@f=V^d`?h05NDtq34H^UB$n9 zVR)V(Vw%S9YGTB+-^g9lN3_#?)Tftduf zbh6@9b=5giLO1E$1ji3Y#ecL+>KclsjFscH>dNa~eOxRYS0x1EyRqX~3*)rM4=(4SG#A(Sk()ZXk>__+a9MJ^)u2P@U zEU0mcNiX!r=_te6DDH(95z=mpsIfGRYMKbDrnEX7Z1m%gje&=9n~}6z^@;F9ws?O6 zG_|qRHtn&9nX}Y^L;!qg7TFvtTX^=6be;b`aJ4+@Sq+xQx(fLhS3sz)mH zp26v7bW92#IUBiJ?S#M2(2;a2I3&uYKY{5pw%y4j!F`Ye^;0dA2#67R*|9AL-Jhmb z+j+^%ong3_QB*x${K+8K*y@-1W?so`inETeY99KjnWCiupvUB3m__}ONX`n7Zz z<%8Afo3KnS8J}en8p|sw_)gxyXTWQ(&==dI<#}(7-F9tU{sZb>b#+lo^joB{dvEW@ zTB8~fV@UjZm%}|TtG&_q`$OpMuWucQ)$3#*++7MMdvG`48F3iWsSw|-8*X8~A(&CV zzH631#%8T$9z(p!B}dkouW#@oO+t-Dn=FyoJtvg8()w>VxDrM`k6IrA)M+)+~+c(!)$k_OyA+8YZ^&vVk}qXA8$B@ z*Sid?hUgtZC-~8%-?cCBE`)XLC#Medg2O%4C3vN-wu-!2NFR9lRcdM@eEV^{LoWQ8 z+EA{cOLx;vVhGv3_qa!s&l5yYuR%|_g7q#d> z?na4x#X3uAo$+lgMmq)#Oxe0$A8Za6RD{);#68tWavt~YQHhB6y}{P5;_732gyPCY zn5e7sGU&*z&EwS$k`43`VZh?IG0~IIOeD*sPE^0c*GKwNk;R$B;VO|6hL9T~p<4ol zTD9Gq-V@*9jwKp<;`UmMo6H=;u$J=p7+cs_(7kA}fbW;OwQNmwV(oG=XwVPB?l9x? zwcSR(iieFgmiHDrXA5mhHkaEQtUrEvlI^|sxD?5@^2|#C2TQopt5GE*6ZzGatvp8x zJPMtJI2p50QgDJstMRB)wMFNJWpuoL5U;Q%`5Hc1`IHzxp~sX`V0yN2HG%%^^@cR9 zH9<>vt)MGPh@;*8eK1G6tY@j8xO$ySD3kO+W=ZOg>fAN&(208S*j~R?|G~sh;$dQ@ zJjrXX?p#d9)gviFHILuh zsXIvdd?NS2``&rcnG|yQsFVRJ6ic!@W@V)C@M!IE({?E`J3`b0TzMw!6N_FH;K^>} z*!K3dmP$XN@Oc-`Nb*5cS?!Q)v;Zv{<3}%X=awq>vsHsuHwS`{{DR3yH7*)e8-s+ZS8*x?$>v3p)`O z-FkA2&UG<(+ip_OdK4yRk54AVJQVFuWf7vl9j@rCR42bBe6Z{ET5q^08^Zvw&G?Rpg-$xRUZ5ft=x+0a>J^cI%fTO$&npvX38A$rf^?qVdA zv6Plg^hKKEDNm}pCEUp9I5wqH{fVS1D`R?IoZ3`Vsx`!iGUF;c4}o>R zM9$0|Nyk_@+rX-HiAQq5lq~*-v#}peD7!F=cjJW8>yF8GC8J|+2eWH$O8CkRr6uUN zHq4$)cC?mIJVcC7%g`$JI2U&ad3QZO|JxF3cj^A*JkP6gjOtPqntuVy;lv0TzDhBca|Ko5j z-%piLooo{bO(myP!z{JYz805yJzW)Wpe9Dui_ujjm5T$9r0EUA_`Na%W9O(xj29_a zZOvty5ZGW9FxzXk^fsl238J#qkwu6VbAy5E)2CMX-yIKN8{RXBJExCk+(W*N7XLv7 z1kQ6~S~Xp2oddS$q3c||$II%&>uk!$0_ZCNCHXox14{}d+{ujn-k9Wk4SmR=oeOQw z5h)NY?^2Z)>@_gkecz7+tsx0dm58BpQcHopqP7K5*Sdisb`T?jP1)uIOsuvQ$9-`VDXHyK{;)F`)`~;qjRlE7>#g5|gqA6H3$Kea63{2X3j_Z2C_{)1^0vi33 z8}2?}7yD7KW}=k#>AX&g8|WzRfSSG_2_hHvg&qq$fW{?vH~ON6we}mRTZa(|#Ca-* z?jk^h%!MA$X^oo(iS#*7oAJ~w1icz)D%DkwB(^J;Lg1-t=?|%<>%@#71c~vyf=2uV zKRMswc<62OeUY8mN0WSfmM6Jf$0+pHmZ5pqMRexwkP$In;#tW6EBJO^A!GHZ+vHZb z1Bk0_U!wXEmS#;bvGZYgUmdS6F7r_Y8nM8=RC@m|`BylE%b^c#6iC?C6og-N zQ$|>(8X+jd4RkmR3QX$jXl24IuSqO*q-Gf9l=+0nJy>Pei`Kf&%dU9Tq0JCXo{CBf ziqE1Cu>bhFGCB&)?AMD^m3K7xO6U*z&@*|=vMP(ghReIhzQ-Zq8=QldysWou1^PiF z?ttc#SM|l`7y~S+NunVM0h)g#90!>E{A|Dar2{r^Cixb7uQ~AXMAgz3-YTf4-jL7X z^bb$i1sLvLhav>NY3jKtuuzzffHXFe>nqU7d!*O!l*`aL*Cagid=M5zH39=kl+-?-J&OXd{#K`3nkwK>svtO|b1 zTL)(sp2?sVcrqY=Vn824v?<=7hUmKPLZYi&a@`vgYP@6ACRo!^Kf_(3rOw-g*a9Dz z_YOm7Pfo_aW25T+k@ZBj+4;~ z?opX*El+;H7qbUa^`+9!+OpM8A?nW3*;eWyD$~R;ATDCWZMsJa2`L0_bll=O@a1-d z5Ped-xm+=`#SdBr;V6f^XPl|v|9b@@{U(>vR}b!L1ro1TZ2}dt3fi#WM`OS-fVCpz z<45@7fzA2{Uw~^^&AoWI3vRfXS1|ibADO08*Si`YloW60_6El#VaM3o_{-OmjiTgoW23izXNG3^1Ezzo*vRq5h_fd2t7Tc0*HL?;-qjBm1= zM3fa+#2Pjr#?7WHxZF^Yfe-vhJ{4z8!|HSL&$P!`hJN5wbD4Z;J(Uq5iyQRZ%Yk0n z%i5-nPZS7)3YY6Oy9SxCKeOYzgKy659e+IoWc{Xcf%XGWU9-DRWp2U^( z@=wbr2s~ii4%-WdKbDyMa{MYm0UO&AEZfM+eH21L-~sJo#rLAGKc+iaL6mu$j~eIn zd=WyzvhX~(#uM%I8p*;!W_SXG7b$Z_w7>&TI8dtP*8>TE*ozWzdtma>ICsJ{L{3B= zSIcgTL6YhjH5M!p;%t(6q^fOaBL!OvOwLa+TYWe(ACh@8JgXn_9^>$`iE_D_KKN4s z8ZFU^&mA*1;|Vd+pYHt5CXnNVT$320k{#Fe3#{WUwU#>9;zaW}P?}O}3ZJXoR?>;^ zAtxR-(q`fWrCfyXT20+FFK5ry^NsHf2~}?A4I_R&BNEGv>V9?f3Zv_M>WqjbuRA16z(%G$~r>^Y=V*9UR(WEZ(KAAF)ix9zE3(+q#Q}p?cX^Q&!`}Y zv2@%xyWn#AYu3X>61sK(^0wK{Oosy3U+7q^X87u4V%Lfp}woHT~!*mp5EG7G9@KULV{`HXU20`azABV1vscnS3jgf#<*=PERWrp?w;9@S zQ-zH>yxrd;I;t0|A%3IpOoPM>oaF9x7B;^Et;IrHf{0zC1#Vv=sGSkKf?N)iRkoXw zS1tBepECjz(g#;vEsv50uKp8GfSc^u!`bW0iFLbN?RBRuOPPg@00x`3vge#f#BH(f zJr1*3=<^iH`x@BnbD%bspO^jyHWecYl6n=CCtfy!lJ5&_611k9>Lwb*nsLJGKN9Lw zihv_Df{=zv``cl%-qIwvdywwRVR;VcR~>aqR#Zxwh5)FJG6NOR_yk2zumVd$r)q#l zgtjG2e2RN~ZiEqsru5_Y{A)7EtJ2e1rz1SfNTMv}>7R3<>3d+e*#v% zxfNoMWn|iw=58tVkO$T@PO2*GRKr`GbG(RdCXG0WR1^Z8YM8y#J7;FQGs8V$I$Fc> z#I~?$2nj(4Joy}I#1boC6fkAux}Qs$_~=(y5l&7B9vhLUS0C+p2=Eqy=}Zq2O$LBo zT)^y5c@Gi^7`;?@?m#_S)>D#Q_`9NJ(>e}k)aaJ=sJ$ACePUas);ez&38P52)l$yp zpC9RX1+Rv|&9>~36P$A00<8@&uC}qPxN}(?2t|xduPpxlTrzyT>r7RSO-{mr)+S-0 zZjc6!rO%koO0QFyzyc@p9^2|af8f^x0O@i5Bo`m47}4`9E9u)mE+{#i^*HP6O7No7qN{S;r*o6z-#oWWUX(-O8i>n;x@? z+~gzDbB>|3_F*HXUn_^f9xHj>g#0)yV4WFnkP11ouj{|ofLG2kBp5n|d=!Lf){CZW zn)I;WZ>HIk@L|ahDmE?)!icmI1cRLN^)N|s<;0jnY_TIy$I6pHw&Be`45d2024=j= z2%j=;^Mzbw~ny8)P~Eb^c&<+ z2%O5K?~1;MI7|S0Q<&xVk^#*_#qXQC(`({s_m)|n3ix zs6Hj#x!hHF-DB>B{S&8#HLIJ8Q^=^VU5H}@1R>M@rUP?yHxMC$8}hg{SxVhNM6PCu zmXQ9P&AfocSNF}@R#1P2rK5|PuWcB7w! z$P#o=+-8rbdzj!A+y@Gl*)6zr(@9!?GgfeNJV?0Li>l7|l^supAgA%hu{!(`R8u}o zPFUc2i&Y1@Z-M@;k<}G+e9LZ0rU7(Ah$y820ywJcs)+`mFdl}LXL?)ymS7mV;R8F7 z;{5$#=VrcTIDxAhShQQ8>Cw@ziBmyeC0*aYmGZ@Pm@Qfhm4}0Ojo;bMH4i5*Rc^`P z0+0nPQ?BHER+^x6zH3Ov--ii6rZT-r$N{y@Uu{?BVU^2Dk{4 zBrk?hL~_xNFf+@+DYVPA0P>F(2Zxw@?gSB*d$55W(Gc!bSca{j8@#-1wC$=~_3#7{ zcSS~oHbOpJ)G7MCT+0y}g~A$=GaMnY@bIRg`&7(+Cz6AHl-bKso8p1(`@=NqvCP;n z2i>4v{ce%?5Nx4+=7XBD`;(=8nB#BNUCtA<*?xKFi!jAjgYjPgVs^Xq47m^Nchvnb zeRyvG@4K&E()kK3hB;{)1U@61vhj)jsY;Q=TEr(Lp-ZzmUbSA(a&{`T<2&3#j2Q7! zDPP(Z`g8geIAOF9TX2wb;!4m|^xxE_zZc)P@;cl_s*Cg*)qp8;)E+>_nTYJjd>8gS z>kmHaLCDK_RUtu>TBNdbFoG>>b=l*?5_(@ah1vZ{TVGfbgL2&*7GL{~r^(=CptO4h3-J*Q_faT|V`4Qs!Y+7`H!JI4`xx3>6?iLHa;R|8ih)rGUB%KD zr;kz+b`Mn2v{Vp$-WyV`S)FBxx2AY~=JzU!^8JsB$I>zMeD5mf)!T)NUpglfEltTL zu#zJe3H5D-pR$D^uZlpBXpeI zL^4A5cXOqxU&7jJo*D@$51l(L zLS%bOUz2Ed#c&Q=3QV-4X-}JUuK;!DuoutQ_MBdaCpNf8?pq=qp;)Rj?4r1D9TDB%Q+rRUcP8-ic4XBr= zwjVdHvvKjwuxfPS86(LAT2ZfYLsHkUWB&W6ISR^4%x=BO=>HCN?$?})=vY_p*av~h zt#y62zACxgXMFRGRuW`Ye*V3ugWzdPA}T9-WGN=?{LR$;B43V7>O1qN2q?oF>Se>K z@0&QGM8(!9+DvC+GD~6dW_Mg1!p#hNR-dGzJ`Qs8C9(ppk=31I_qMld4fK+c_u0ep zm`Yz0OULpM<2xSSYN|=%L&;z90G*=e>&zbGf3C;BcZ0x^TH?E78wa{hs%hIvXvM<- z|MDq#H^(Bt6I+_mA~)b{T#7aG{Sa_MbV#7zUPxHEQJhR8pIr79U8UEiy+c+g8SSp(^We)P2FUpx<})mgW*L= z5XH)%8ADTlsz|QE;*=uO5VjsH9JO}~%l9sxKBdbAXUEsfuFV>n(Kn^fd8@75XfWY= znwsD~V%wjA(||Lx`aG_La}&zU*WTib!B!Dc53Dub=}~ugT>I!OmV!=c2S8#-&&aA{ z*Fii!6R4mAI90rjnC(q=Pc(Z2ozoFkhEq(M3Ket@l4;d{m-+XJ{#N9SS<3OJ>8})m zT<^Pq1dlV6E^1231$Wi^MeP$$bWe74$2&#Kt4RhdStnonP=x)!8n{zew}fXI$YLjw z_c%3pns@S2%OlP7X96?q&7Y3GKGTi8ZrvcxrHtW4Es14}ZR#AUjU&G~Z-*hRDTxm6 z^!1OH;X3&l(3R=j=Vyu|Y<^Ug{rHpgCifY3AB*2SJ073%8l&_%O3_lS{TU%Qlx^`iDIQa9R;DcpE zBAK4qR0Ne=1Db;=mJ8J#_QI;hXozP7N068)nk7Bu9t zVy`7lGaMLaF|^E*QgeBjW%(BPtPvVPutXje(-^(e^8VHjB=RqEU-&nikcA*m4pLpI zmMk7_EbknF-jOx%U0SynkZPw7E^W*UmBZQ_@bTIOY9#Z-_5Z&s;o z^~C<53C-^?+m2FXZ?V<;LjQ@udyu#A%q82LvFX}A*D#=m!kKmpwhj%kOJsfcyCD5( zOU&I&hSU%7QK8u4vqbpk^vMn%hH>N$bXARsxOMXqBsVUk7tyCB_#Bih)#mGd_r^FGnZFev-R>?_V0{2MsC z4yWaxX~(Y(z-b29In@q38|VM~o0ISqw9KUC{kw6}5`%@rziO)T=AVOtt-}Xy$oFkm zzV>Iwgy4%E;UJE?HQ#;z?{7ZVghtQP@X|jQ2HE0|LCHbA9J}z~-``|;3dbtLZ1?Bw zf$U3aVFSQB#P|8|f21(Vz_EJC44nPdPW#nV^Jj-SPx-Z1$EkmPn_oK`FF4j+uVUSQ zzxFZcHWfIQU8mvw_c#CRg#EpgzW;T?{@(j?|8B_tzmzfMgQMg z^yPesS^yMi4?|8DWcGz*ehoi*wln4$*{qjdiS@46F08|-=+V2;bdzNn_r&{{V{!P(8>4Q=#t z1UbA9yL7%QnXWJW0R1w|*Yo>b`OKa`m=p3Lre$6URP?cAa3it7)f= z5{8FM7vR(~0-~56z!>lyt>^6+FH%EeAy7pdX)AD@>cmZX^ zg7eKJVLrj|U~haYu1=m*JUzE!4a`n=2)3SZJvToZZ*_Ezk zqhIzTVVbTu>jaQO-7IY4azR-8NGuK`zob*7rG#3CH9_i!?KLpBz1loE>~SwK27m=0 z1ltjB;xcq%8Qf1)Z4UFl6{`*cqjM63BTrot8CRWjc|JW&!Q1qJ5cA-oP!9#{t8P%8 zg>Xj!>rC7`q^C@6aMSme-H-7P5$rXq?ruoOd8FwRUrTm{m!7vAovJ24>W} zi_N;HKpG-^)+kPmMZ>(rh&v|txJphHA%>bSZ{-*P7lPSag86{G8^S?FTA1l)u^;;R z?MO_O4yt;Zo;mZ3{+ulgUhQFrd9Fgxh&+0yk}!z+hw}ZAR%k)16Ne+7LnN(;bKy}n zobh*6u$7yrf;q@%WDxb^#3Kue2GHVV{>mFi+=}O7gd;2nBFeB7(d$!5x1I+LA$w$G z_Jr7rUyin5tG;hM{kaHX6-!C>bDgS;h!(&ziQH@xc3huhQdq!g#)~39088!Lw>Rzq z)tKSAFY7zh!J!-wDe-Na6p*9Ij|ahQs&mw(lpnYwDWdYao&COr6*o%KwNt$kN0C9N zD8vIuNT|Vm%Kk&BUi`Et;26wA(24Rn;zysJsV?@iv`VrQxhM5hw2Kn9Z#K(d;??|^ zD=aTPMm_+Vig|EOkLf#|i(GVOn%@Jp`i>12E|v7kYPn^ri%&TMsjkRW`R+S$pv&!X zZ<H$DxQqj1#sFrEnGQynh4I!kQTj%uvqpFr(j9kcSwSB1Ty%J%jh*ujyoF zi?%ZRmk-DOhey0`k2YzmlnIMKI5=o zfK{4^Of7j7lnr~{YJ)q#BdtQ@@5V6HBweFAHHeFA7M!oQ3ZU_qny3#j$q7lg*7PA% z98d~zOG+1wrL?Mt(!G7epJ{tHA6xRHvVLl{yaeclUScbUWF7p7ya`s-rgp}Fi@=a@ zCwYvHHf(~IfBa{6q}<*;>R}Ii7!lm9=F?@bCLxs9GKMB>X}o&3Pc+KM+T{7SFM>t!1o49o z-4jI5K_=&VQ30Noqe05&Hs7In&WJWg)mzO$2WB;;CU?THUF`^l|4kXu9;0g?>t+WC zxy1;YCd{x6yQf$XD>QtuVE8OG!Qd5WRKMDR2ev7+D!+3tX1;*evr>L@qI{>ea;7(`e+X7|A&>Cn9-fq1wiTIia;Y!( z4~^F$P6L1RMN(G6)U`SlqKkSiw&f1JUWsxHe>~?V)UR(@^o9FSAC*emJ0PS{w9JOG zel?@qDkVKu()Hvg3>E@%DmV9_^|lau-FZa1edjL=plR}yB+m>hLGlw1!>5Yl?z_vY z;-V8He&~E?c;0B9$^%OtBNZ;6ILU#0r5IbBSYJU-T=1OIpc4!~N%sg=IaV!`ET!Hp zzy0aMJljroBAFGDWLi}a*ihm2up5p(NWKcd!Q=bQ13y0$UFuV35%i<2X#Usotwdn@ z>daE06No0W`>ff$b`0O=v7t02mxM)Oq;Rby^30}uUq?vz{rS(YpVC}#QfEH;1PVQi z1%*hY;be&HVOS>G&YB;79x$=UF(eG`R? zvCxsB#48xN(3sHwvUOvsIJ&E=-9SgrFL39<^BJCk&^sg#PK+nFyX6R@yCvgRZrgfg z5*PAEk{{_VvTC1m(O-Z>BG%L^Kvl=Qp=La#B+|eAL)b9|nY4Vt ziGIglve0Jr3DO%<4lo)Fj?KQIud6^%kn_Q<)_vEv&Eq)R^sx((mR{MaBF*7@8luBj zOVxG`5Q{d{9BERG?PU!x4W%79ErMyo-oJWEKbFkSh>~MOsQQ+Btll>C%|NI4^e1c3 zLJHUOzN5av0L#R>jaGescZiJF5R3`OmO)*8E%ET?t}*Zzc1Iyc2VR zs~_;ao&4Tl8!mL0TR(Iv!?@{@Hv-&0yA`I$s}6o@h;zzt0rE*+TK15_ku!W<5+_+y zRFxyGtnWG;_AQ4Vc@?~Pi*o1P3k0ldqPhukCyqW%CiGRUj_yaYlcE|23N?ZjlZB zVx4*P*sg6#J9pDddeii|Y*(yQ^&U>HjrrPu_oMAO`{u6_WYW^^BNIx-o=;A3{$OZ) zetxOnz|I&u&3cwNRn^mJ4D8k0`)KR8r!2;V1Xs!k(CW{vjYMW!A}vciP~>gJH_5-- zW@mPNv}>r`F??W^s8`GeMUm*6?}o`l65rmFF|!2l^Bq>%TP^hlPSLTa2l`^`=71V7 z?QdzMV^e-(z-#fn`XKi&NBWvN5-)9`%S9bvsYyvV7X5BV>|YOcx+`&L;p{#geZ>)Z z{u8oBMEJf!49hOLs*T>Gdj{4L%IWnD`>9Q$)vjBn30z-_+mFpTeW0Yf1_QfawrTk+ zr!Xah0ckZJnlL~8zF_TgGJ+^<>2t%qv=O?RxQS^C3B|D{($Ml1z$i%>*3X1Fh6#jl zoD4Hh=tIP}`__-9JsDyz6mc6K-jP8t-7>~e-rT2yN$-1oZUx))7`fAe_6{T2(+IH1 z(Y^mq+w{!LVe;29=#P4`IZ+xD@lNC7?o9rv^3ke|^4bPh!Y!{2B~=KSh$MPzF!J3X zC`co`wzHGFBM%;!b#lGRbTABm*Jhdu=q+;?{e;betj|M-9SmtZ7-Dr>_W&O@c@C%+ zL&n|nBgY^Iw^3(+sLq96Mys0;6MMP>#$C-XQ9rQx5u$s2X&=7vYBI}GIEI5z(NJS( z&8des)4M_JoEl5l`yl4L+j&KY*`A)jUoaYAuI3Xqb=C~F#07Rl(Ry=S*i7&}br z@B@_3x@&ieQ#u4OmQLLT`dy`sI?HGRUi*g9eca$17&Gr-7*=TCpc+O^P2Tb933w?5 z5JZSckDsZ-YD&J=;5!mKQ_)jb>fgPZpmvGhh^dg|jhC!=Mgn!IO|JuxQI^)|Gj0}49$M4wrnQXMYl*MELoKj zXXxYs$SbitT+f--D9m72c_Tr@*x1c}qBI(Qr$`_XD11*1+io{nR`*rG9_B|`%eL&X ztbnFQS2WbhShMO?xb)rpTcwY`cp?O+IQK@BeFzi21D>$=0?S!)xp$t{{!hHqZ_X1q zh+;ZJMj7W-_JlAgopFx5=I*DK%8N&7279y4)JpH|KkJv`=`Fi5W4q}Lo8NuXyU%=< z*idmWOkh@vb<6(kq5h&66lgcm=Sq!3c24u>r_fCU0UelfsUoH0c(GR>+T{1Rot|08 za!J9+k?csa!zoiFrU{gzriNDx0o?v7nlZZYc@ZI-hR0qY5j&#=F+Jf4M#J$oEcoc~T*=EjVJsdKLs{lbEG>s#>oY{%{^g}E z%BD*3n=+EEEXt(?F>%mD;|CxNl z)1`LConRXq-U(}L<#)|yY^{lzK5@yjE~odQ%EkqwOv-r#4I_b9?0XnPN_NK!mv;)3 zs1f;Il z!|c-9wp-4q*X`FDf}?uniy^!*hsNC`xv+H2EGd@$WH_try6K1%&%^i|i7}G$B>m#o zoKDFGt25kHGM)>0fNQ?J{DRb}PpyO?Vv#)d!h>QlFVdFr6%F1(tTl_G4*OxY8LlJL zsW@c1p2<=tDF!>JIP5}RLc%_5hF9Gg%5Hab+UAw?KBsjcviI;2Z64R6txonzd1Q-x z|K%vN;}O*KWV(q5=Sy}{)x{afafWMdhE11%P_y)j`O|GeHYc=c)X}?S6SfAgdd82I zGyVj?&dvdwYi&slzAL5t(!vYmL9SBWO2-vGs(&ZJlVP{&aQtj-r%QJNNuA#l0h5g9*Y?C0)qQU*&KU$AJ@q=yz0a1uJAdQ4 zG(m*mMKZ6`@A{}E30A8+b1FIsB3vS@@3+u?O_@H-wdAp8d(El{WIl}-w0(ARCnQk~ zLk*aueR^wvPze9B=_Z}$d0k!DUO{yOb>m_pW_=vByFStX&Xe-mo|dJjG9gB9kFgfb zx0=LMQeD%i7b>UTJbE-xOi}Z?>xlE-%>r+mHFe7u6{f`@2y^dIOEQ~Rh1Ht3T>zj& zD8eNJS085vTJ>Eury)O%&lMIeA+q~8T}1z*qi;99^r773hQg1o;*oxez_H;wKDpTC zGDEBL=)v9EGaAv=)m`kOxs?BSt>feF2~BF{$+et1E6B_9B$GyLbks5-F}@ixwqu3n zL~K;Flc^|`2((6|*1qAD3Mca#vEC}t8ZRI8o#I1v6OzoR)0ZVoi~RLkeUXkXz_4K3r_40Twt-ZV7^b&`f;7%$4}#> z#mi@j-a77?OW+v*1NHMpD%xdoeL_*#OUbaYz?BMjU6kK{?EKhCEOckQ#ni-1JmEek zJ!^WK>zD7k5Ft;!MVZ^J%zE6_KEn;^Yi;S*@>ux}`nFg%key(EiIQv>q^!a177bl1 zAu0JxPR7Re=-JP{RRRR)ulj$?dp*=5)NWh#t+HVguKlD5>ifwbH#uTxg&yX=NO6bf ze5>{2aFa+pI+|T)`MCU-_xEYFJY)xVX?sIR39WnQ2_o9a7#Z_8c{0$U%2ls}lk_Fo zTQznl>fM08X3&S?r;*8Aecs*tmYe{6^5)Rnc;EBr#+hTD*v8hXn64o_=3HA9ognc7 zjVKz)KvEU_A+~b1oy4HQsU#iCmQmQBAuKxO_s5womA+cuA8y4*^BI=h<-;_eBkmlM zlEO89{O!CBp~N@LJc`>rn8l@4(RCg_^{??dq&X8zoEvy>&T^UVP6&0 z-jta(ZnakXbxD!jb@K?tp$kVDudclKKC$zvBi)d2;gLeWlPgg}aHCG!ajw*p*n){v zCcYv$-T~ekigwx*R?D?*F}3>z_hRKj-af51kCaLpB?u$F!3#ncv1Lhyj3_bdBZ>mx zz~HUKE~C}Yw(IgP`?nnz;2-=HIC}2Q@#+I9&;_CjyjimGSyK1;qO&tR;p&yci6=z* z-mU59+>Mn}K#|+fym9($q`&oAiKXyHEKQJIfi4fK;z;7e1gU_Nd+8G{RKF7C_S32nLWhNd>!cfL^S5()6gcZNR>LO_v<^**0m(lw{H%l7hggM*sd=G^ zBoj)uARlb#Ow!uPNcV-6SJqC(r+;=9XJ$QftL!cXZppQAK9^rKk?FbV>-r@gZ_%S}wp|rcdeo$ifx1`k=UtuT--atRrIJFW-*8 zV}Q*{wDbC`TB1AW{&9wRg%v$&0Dr@eUY<=N*;b7@L>oL*PThj@2 zGwvbHC1Z!@X1jTVZ>00t7aPvl1UmoiKvlPrk18zcrJ%k8N{ulnpo!heA;^@fOCsA( zgS3=CML-HuV6oZ4`6@KOFniRtM|;>% z;sF^~{KU`?LheUwI%XI?67A(>??^Ua^K%)g8OJhxz>AGbvr;KA)KUIC?L@L2labn2 zo54G%r@@aQWSo=1nZ8)Ao^xTS>8SYM8>WqpJ~mo$GB8P-p^vyP`NP-#4&$}F>hgq0 z(yK%%mh__zCK#d(o;a#SGFN`q z!kihypc+a!6KyVADAqxopU~hEYxU5uccZhE#^S86L9`^JF?RtL@tM&GeieBk$|O5a zBt0%y*)^-7lzE7W7pEi@u(vA2_x$~#G5>t4lt2*zq6-Q`-7p;J?=lz+O<$Uc3=`>g4vp>s1!>|Nw{*MbE+nJ+w5-p~9lrWC z*K2*2po9X~cqH?%IdoMtsaQ&4^Y*J`4_0S6k$CBmjx1}YeLV&oNcUT+APKodV0ww# zC;EoR9OvjKjc#BruMutMOmMT_bE#O)QS)#53IQypfjsFk%<&ZV7=QGSoqyr1opl=VXm+ z6rPFwYoJE`_XcXN|2GC|Qq$Iaj1-X>dmv4#6{4iCR&8d}xz->5UPc22b}# zh^sOn*H>H02Y-Utk+^mtDOSA6d7i5*D?!!oy8D^s{-R98B{B>&!8syLwvd~k^l!QoqNS4xj@mTm&R+pF6rNti0} zGHjQSS=py|D@x!C)Kt)skS4dLepwGA6A|X8%DE<-W;67Zu`ATB%h5R?yy=P74)DA9pq;D|2ljW`As}?_1gZoO&-sR zFxMVT68V?1F|dp{`{^L606V?!z1gn_F$+V%l{U4g3%KJ#9y7x*zb>84gv=9gt#K^i zbO-+jr**K?#Q$NZwS343q&h!dv=T~}|8kW5YdM<|`8#2&n^InV{KdByl#7Vm`&wqj z6!v!tYLP6<(UX|Lx-*SV)pQdqftYQWyr}Iswu?aI+@LPVntd4vgr&R3f@$~?1uT}7 z@5hb*3WA4u-0e&D9ZOMiwx|!Uc#oiIA2DNWyN)o(PRE;hh3n5hy3gWtx;566f4X`> zPHRms03qxmpxiaH6-&m4+>{4Z_l|<=R9Mrh*BwVUfT&k3@xAYS4;8uc86v6oo?|vV zb6(%cHEMK0?c!^bn(N_A(vdT^cAU3Yl*qrhEr1Ep72efbZ+Xle z-qBrXZU*{pXI6LClb?tiY9qY%ug7}wY>QBQZk7P0D0*<&i(KQ*fJ9uIkcfu>Y`K84;=*XqLXS-%>T^WK(ZpIZ zu`l;OEr^2#B9dcdaTO#79;VHMXXntheQ&i`dX3)3lg&IJUo3Z%|+Q7J^Q<&OS zWh~KK(myFjXh`~`k*MLYf}IKdy5;e_HvqBkg~^);M~&_ z=-8=O!JV|NS`pO4&ec)s|GZES`W2KE4$4ExbhWg;wgLK-Os13@07G27Wh7b!Ec#(! z=VF3oVo|29Fa+NblNZsll6rwvXsz9mp~P)|3OA_B4@xM!bjX159hv=V^v@>W78;aA? zEfeMFvSge$o9Gk@HhVBz5jurjy$e?ZlRe-cp9PAAeGN4Cag8L0*$RXvd2<_a%IS3C zBrmy{xW7jB>bwdg|09kC?CvTZ(Lavs8@e?F5h-m%I#K~Kxh7zMOKU1OO6&g))A!eg zEM4l}BknVtnTYn>;8b=MARc^!+E!*&OF-s1AEm)L#rGTz= zGJRkd?~>X{l8_(7H-#Nn9+YNcOBMEwXP->5AwIEWA8aKItZPH zR5`;gv`|!=lCVv!Ku8KFaV<2-r8k2mvp)^s)rDlXMOp$?_SnV+LJ~;mtbe=EY=BEZIc`%p<%}mC=$(yug(@HNjI1ZpAu&RglD8tph>vK5lK-UtuTvFq+VlG z&2>Z1ywqoDz&t91iNO_SeidG3#;YnC50&je&9lW;VB$-=jmeO2K|+p|uLPN$$cwrJ z#}l5d$Wj|kdS)!&BR{iIu!6-b$AU0^$AIs*dirD%=&MC5e*Q6Rk2}3oX6eE+czlvm z+2ChXsm-vLZ^rRGDeAp^mLYuS!k31I-P+6OUhzy5-}u<0UlE D?X62a>I0b{u+1db1<>T`vuL}Put_2;h1bA18fp4U`?_}= z+jTp<+vl&Q+_$e)<`4oxp%=I*m%vRHPCvoR-Zk5CliITl^O}+=3z9VYUAO<&{%xEZ zhbyVCxe_LNQj8wtKdpZl0Pz? zS1g#IckOL^q)aXwq^56_s%i zZ2}PV_Z;mIeG+uoVDMKChUP&KADUHgCj)6@Z`B<%GvO=!!Q3GQJ~u!-^=X0&5;n>Z zGE;(OV$*TmfNBtveb?T$tB+Yj`5`gFG_IdwOxhskrevnk(Ulwc_w{NwPrpGznN}LL z{Gr$m{0{mG9;Qsjzm5_fI7P09H@T9dih1F=%BF{aoIN^P&s~^{Y;BMPK`js{?q`~a zeuGf#S5iQl5!s4;gW%X3gQ(dH?G2iq zeB=H7TN)jgJ+hW>;Obo3#2d$?TZ)hfAkqRMuN}v?gP_&>a#?JQP!z-y(~Q%K9Z-7D zLW+s#Tjq;VP9bO|rVFRFk1m2^#t8sH520#a&aWeVGk3n3a?Wk>0ob6)QycrbEghKw zj&);lV9|&?5bM|~HXS0=wkl=d1{(njkDE)h8h>x|v%gIL2az zpqw9q%Sre@^8oY~COcpw`6Nu=CVbKlrRy-1k7G1J@2^2RuB{H+-hX57 zEu*4ryRc#925A^VK&fE}>F$o9OOTYhK~h5L1_z0u1*A(rQaYtohLDCKq-E%qZulU; zJE9PP1kziUT0_`}tI)V|9OD?pb`Le!}mKfI7s+)$6pt~`ZkNKrqC1F@xQ&}$5KWLVXk5$ z?mEh-OI;te`FV}p$5=Htws1M%;d?(MX)Y`-yiawD<*MYpw*@lf&$_?B2Vs)R2RyW zGaj*H-2Q2?vZ79u2_)BQ&vP-!}ou^@IT8ex>XG@hcZ<;0MUX6K;`FXt<3Lu*Dhy%=JT*Dt_Z*w zGvDR4Agh`45Q>Q_9_O`9X6EOd9Xyk!JQZgBg2V?Xn@`?*L*!(WeV5JdyIC4=M+u&% z_?pA|9DRoZL0;v@9}+gO=%9#*$E|)2Q!;cDJ_jo0UjptvhB-9B)Aqa&@ z!!XExHIIA}Axlh*vAMiUMn{NNM}@u9pk=sFc#q2DdyBCjnuEEYY!={b9&4wNnR8>E zL{l`uwE7&wf|&t;i!?leXx!-GzZRPlNM8Q2((qyF;fETmOa*QQb`d}U^5Qa56U^A@ z6)5u$I;V_ps}9PF!x1FJf#ia;^qh9Q(FqP=iC7rqt?9Jh%S2{0#TJ!Xc?yj{&3^yl z*FHXU&ep6BYv+?f0)FSE@Vt(}z4qHIQW6|QWpe!vC_=zKmvE~uU{Q(Hjt5=`{8odj z^+;P;)8$k0AD?+x7cj8R5q^ISsSpGgO)Jv*esAG@S4gk>NQxfXZjFh)RauE~= z3&68TQ1{MKMSNTl|EQeyS?=I|!6VeexO5v_u9iyL5C*aa54?d%e&2Q=V<|wFxofn1 zNc&f1jW-2QGaY`+zzEXYk~qZN$o}mk@y7wmgJjV|Zv?Lp=&j7IS!6Z-gfwN_^~-(C z&wyNl?LFIRoE2({yor}|I2XT0Fv=7e*LRQP0unSp)2d3Si1S_Ks_t?Ef5g6Llb7`Lrkf*C1_yzcPt| zIgNChg>s2HCQgk3cvN`_sAqNoYE83tP`)R-fameug&j0i37B)H8OPAob>X!fY(W%e z*^=tCC>wnSZ#Ax+KXckhe>G30JTRCVC82$Bw$e)3QOooRSHUQ)kB@;-*T+7xH1olj>0!~67Y}g2 zm9Tf9PvviYwQ=3|qi>mypKmCgV}`WKPK1!i^r*W2<2*ouSH~6Rzt0}8$X$m0qu1iG zkE$U-H(%FbBapmTHBCvQA^IletQO#lq~rzZ{RK-ZWA5`J3JFM$+?R! z4zTb@wHVKT|24k@WQdxAt7w(8mHp+07R4!nE;}Q$4FtA8fb$UbHwj`0^BDHhax%v2D9m^qtbfoV}LVjyR-H%_;3=&X9L@r$F4 zXGzZ=$b^5$OOP)E@}4ix378h0Ct4`W`_j6%0Mqg*FODvIQ$sfiBh zmo%0dSOa<@v{Iu0td_y;ieH3cfVs6q@Ct0yR%9QLe%uy>&M29 zS2KV)T8*XG{|V5R_985&8xJPv3QA7}GA%5e(>zNZ>0>~zAd^=>h>_&hR^=}Xv*n4& zNGFv7{651@ni)L}j%V>6d{J}*Yj?4K>a6w$iI=t_}v_)sW+tkWw{`ovp}yMNf~#{ zh;6d4`XK2jUp4*BC?v<1Ey#c7Je>sW(9C?(Q3MIwX8?p^Y<19b<8gRi zkecob#eDd$|MlCIr7lGROf74^UGaJtFax)|L;OZc9u!AM@Iq#1mp0KI&gujtdj`y| z4~jMn{;7wr17fn$M1%Bg&C!kdR$nm-BC9f)H|F;REL7}gamQuTy{_FxuNtX9w1F!OyfLoz1)tkGz zzwK85T;YBd4TN?7uwfzZxYwo@Xm5UDuHD{Iq1;CCm^~_3Tu5;oyt#{5PJtj^v;bgp ziM+i8yyeVmI=n!jE(S^kAy%j2O_VO(2(Y*LE$MgHQA%J{FoYPW2i%a)4VNp(gaD0> zu%N+ofvXah5zKh`}RjsY*6nXKo9`bZ;7!m zAoFsERMVud05+#tQkbnX+>5Zxd#VM_1X5>6ldjzW;u@gyh1~9T=%CrH4*Ml&7bQ(NdzeGcRyO7K!myI7Jo_Mv#R{omB4xI0&&AABIM8^ zfrgnnk6A$*15~FLf?O8Q@qoohCwRmQ71I9ix1k?k=z7M^od{Q3NL7*sYtCsUCn3P? z(V@X=j%T4qQuBX!z7h%CTfN^I&!P|u(ZU2=&-lmu50p@at_Ds!9ZpNGNlT%GfRxjy znR;VhfRJe^a)h}8TqJJ+?n6SsB)H0N2BJGQf*=wDyZl6z12E79AT_nURvd1~16Rg; zsPOC&{k`t>FGq1Yqv*NOABlx{mLzJk`my9l!UX*Rv;-#r*ZqH4=?u_-oHrLkJYcCE zl&d+$)z@V{V!Hl_Y-EKg9S`{Skeb^DCap4^fYX%JNZ^3@2EGU{;{UJgFbl(U^$Z!G z-OT`+i(eC_#P3Xj14R*4ja8*gy;Vx(0?|yg4l1rZlj2m z<$+*#o^`G?|6We?M+;ydzZrm;Oc6Y}ucFAVZken%fn*zX27oGbRR%zngSeyQ7;fH4 zq3326%Bbo5hcfgZ?m*I{dlrM}7C)3bM`u$oN6>Q_zt`uSSU9JouRiDnnm7QngzyZ! zr4SSVnt3Jv2@(FGX^0__{+TLWJIEq9u=&9P68D0V2{aH1XXcNCpT1iG=v(FQwmgmk zdXo4XH~;62ZW;HoWGq1Hq$qj*J#%IdQOLGEYFHfZOn^`$gy;(F<){;dFyT4AM1g>% z%#p@RPvLm550G8D1Gn#+!uW~*>K)*RpG;}CkW-*xAY-@;e-8XkkaLG`N)uG5-liaE zpQlk$82Np`mP=2Q=66=&t8&-oai;JEAxG!#Saf%R0zl*r>A%Diz_Q+h-NAy#8^}T^ zI8C^p7(OAxSQaj#3)a>o30dSPg)Kvhv4b=1*<^NFojPkSbASrC-}cd7yjig zl^>`(`3eO?aP}dgsCO}}t0I<aLnEHyK z`!e2NPvn=9ccK}!QC1ijxYc} zKde5b8hxAE&VwR6)Wt9CpP_~DT&a@4`2}pSpQSVstifxTo(Hs7_cy}l&&|_Mn%gmbeAvzsuIGFAk zNf?&EpV(`!}?!X(Lg_CVt2d-jLvO;WDigs0`D-m+XUu#{!6pli{wm= zyGz$w`#rUvjwKhjw*vgBYb=)A5V^Oi*zzGdQ08cOFS687Q=)y-&d=v@_RZs9Ys+$I z1YWojvkC=7x(Km=7J?S1gj6+ib#HJGm3>gb)LDVi1(f-9H$a&^PX zFp^nPQ)q9lIhjc_Ya2_|jzkjc&AmULH)8i`upJiKBpz~^id!!a*Pjdv`rJJ^l$~Nq zS^On=jazspSd1tFLeOcGQxpq!Ns*_EgaU11BBe>q6o{tGn%r1846C7O!GymDdNnExj~Je;>3it^ zehexB{N7Nf%A&K!$;!~P2Q5xM=Zqb1r6Vt-9-no!D2E=)doG6s^r$uJaj!jyhuI@M zQkXPbJ_ioncZc<$o&s%I*g=L=5$zV8IL~Wsv!Gbg-S4uC- zLWtdA%#gUw98S;xKHKX1nkaC@-x+*11dh|S;pwoy{w(Z07=4y>BCGB?fEalqa^SMA z%kMC9qNu95p7mC*a>tFxJ;-_|y^IFPLaZXg=Cc6^$ckSpIA?b#OJc?_xo77q>|eq9 z5~uQJlCs`*1foI}p~SC&-ycDa#4}$KnGS~QnPQo zLAEiF2qjW8ayZol2Bdp!Ff%d^8cKlqXR@!M#6ROYRtM4*Cnz?*z3Twp&lhp#lo!T+ zbL1Yz+u8rxJ&xJATVIw-1zfGAhKh_{x=_4ZO1#d7GQ}~B+$biXIa^#2u40>=)j*oS zEIZYogK!UviU-|mz&wFTJtIzzC zPAsSfY0YlBxd}Kzm^8%N)|+w1iS?}10qh8B2mOaY0Q@8ar}%I;usK{B=+qYNp^x2dNi$qv`!o69{Mm; z4fFdrC?EU&&P;U#N-l_L+n*jQc5ujk2LS*(i^aBglRC%D~*i*l$ce$~TBc8gEgjh^I ziZD=90=r-|agQziBg{GK%++Unow+Q46jZkd-Ue9Y^w^U$O8)N}MWP!Z_MgjHNcNVBOsl62OAdQ0FO+y9HLs(7B>p_iv`CVL5QsR1x|e4PWZQZHzs8D=LTYyt~RN(AiJqms|f*$dZO<}x5*A=k{;NNRl z5=4QJtE10$$dDW?St9sqPYzt}gg$rg7b%|{agHro)X2}Vrw%5 zaBc~vY|=R&$TLs-wNiyOIL;`f3%&C2gUcU2q$l_zvF~Qk4M_Ehp2Ar5%eT)8dX_$O zqR*k&?;Te+ar1Z5MT!%_A?TepG(<$UQ8WtqEIi4>Sh;VKEVlc?I>BM?X2H2|xqZW* z&Ob=~smQ&eMo>iZx2*(A zbw-jG#xtrCzmhbE6-A1Wc~ebxW<4VNYCD~uVM-e&kJoFPvjM11sb(zs%(p*`C&4P# zL_x$hW)2WM$2K@GpzF7SGze#c!G-A_Ec6g96iSuSCw*2ZX6C|HGIHn9wS$l7x8Ljg z&JKN|%t-M{gxDCU>48h_ixSEC1R$B5=hiB3Mle$00z^&)DNCQ>Q0y()VQb`J`mwUF z5A9J~s(FB3ed=KCIna0PO=sc;^tEym0+@d)=MOcWC(cCv5S*#<8HVh$_%8QI^;e4D zW@!nwuH!4kNxD}=)Y1`)Z~vouq)i#Wq>G>XEnaP(T}jU$#g!mK;)6TannWA|+?)$= z1qmWQBvh(zhpV3+SB`yc8>2V3i@ijc*SsR0ymaD4i5Enwf?eo{w0tm{hT|(YB85r5 zGPQATGW54$NlB%DboHl7@=-Ut=Cf}dXE>)XFNbRPJnJ+LE3P*WDX))Dvp46ciHB2f#Mf#6QFzh^=&U!- zBhM1DXD5~>K!FHqVp)vh*I)D2e|&qX{`Vq8XFCO@bCnXWbMS*#=i*1TPQ9&si9ria zB8T=@7HbmarU5+Km-IdiTIgxJk?&rZcbgM=p=KQ73zFmfP_CC$tFgh3{=}403}Nav zHOg7i7!duJBo+=NIR$rrgF_|Q1&M;=3uYWw932~vmBFu@HXH=`Gz&Tnuga#Yq9%53 zvLu+zX8c)}p&vI3{ z8hARKy25avPHKn*&SAu$Aep^W8@$ERztyzW-^kzs(Y7mGk$k9n%1Ws-EtI}Ge1*@q zu|?bd!9Q>tzvTJYU;k*M*XV;$^uG7*37#uMWps#&Dx1j?Z&_YNAa?TK3$tf_6plKj zX2aLrUPq19zEtfkpGeavcJUdr&46l!J8^_fq;vY2nbM+Q&!s zOe7U-!M{xyOb7e@LNOFo-oi-SkZdS7(^sHH_58u)55yLk(WHZ><4ZGXUDff|!&|xi zWE1k4kH~U*Rv6gZoDwR>xQ+qm(Sta-@`boVa^;z}0!mPd15NAkXvpIks9U%RG>e8j z9WEmg-O*%n5MgpE!tUr|AZg)BJbufNjTms7%c5MwNN@Y7%%*_Mpe2|-aYE-F+>nt8(SJ$E3)jOS609gF4kgan$rtf494>%=)svKoH%sww^w zrO6{Z#1lxye*eYFv!*#7nw#w9{hEypDh(B|%U7@9#O11U2RJDR7ved`#!8ai4I2 z26`QWR1j&)<4g6GEEf#1c0x<>Lr0A!_1@<`X$kwkZa-!?;nItHUa#@{jo8>93^t-qhN{g`v`@oDO*hs@=09Nq*a^)lPzR#r&--;p z+%#P7_&bLU5@sn-Li6%ueyU+qYVfm^!uG!FXKZOASL>$t;oWQEsE?B2Pc|_*L5+Wz zqEtr_lZTPf{(S6$bDUO7RnDf)@e3TBCvKND6Y4qS))LE94w<|4Po;kQqX^Xx+g;Cf z6#QL~J0&HEoD0ifBqG~BkYLSO{J1?WU-RRPk(6xN%lb&TEGOHy0n(s?xqh~t&GRGi z_+4uxatS+(6O{i9GK#Qi4t8JQa9BiRa3rK(#f8E-CXj|_U@E64Zj@o>D_pq^+}^OZddXW`^j7N*$qL7ehh~4F!yvP zKnw82{vg>$LO}U{IR&XUs2ccjvMmC-iGZ))8L2E*AVKZiw!gf9d@vl(@gp;Xpsncl z0TV{EnqZ47k~D8J8J`3N^7h&V4K#8N<=>UkrBY97V!Oa; z6S`*l7!#)3?blbV;j;Su{CU6Wu;Y{6K`)PtZn)2%iMXM~DCx-ZP&+jchkBb*;iL#d zExLW?*4xS3)I)H|lC-t*!YuHNNL8A*0TF1_de&d1o?(}-@!G^nEt7C*<)oq0|rr4r8Nz$$dM0y+TUYAW3|s!eR7aktY)S0 zb#6`(a=TB0np8)I_#r((t(nm5$ziE3kG#a0cGX(ugFil57crJL z!>YG)5u0SJko7=8l;H~H$n6$yT1j$=Bel$X)>cIBGWPTk7EpM*U^PZ+44(xhb|O`@CW6(kl}DAESK_ zYgq&>-@8dfIj#rwPU?Kn8%w6brcA4V6MsW;`bqP% zR~HU6AYLcfl+}u)pa|!e)5@pNY`H_hezgMO-roR?bQZ%qxYBG{uz4Gm2;TaDmHsRF zy`v0;5FApRqORpn-)&(jJugByum;-Zco((PK5zRYqlEuRqc7S%96_%~#U#8lTV?9$ zQ+3#5e4F}R2rW)|HA%_OrP|BEJ5 z^i62Lui*Dl<_EvO4vg>y{laoVo~Yxo;-L8tWm0*f|Ay#F@Gn1| zXtmR)$r*H*#`{5VWsrl^=lf;TjqKs^%xM38UN}+FvwBJO-DdtOS(epMX*JMKB;SM4 z4_vgGm88|b1s(`R01x{j+nIK5>Y@r5VI?p^v@c1Hmr0ydJ}zjC?;ida9}1%TWxf}p z(=MCvH|t?B2HFVbyR6wj2mK4n6@$58?%%r!NJOyghq-VQ+o#DqIkgxtiYL|%YT+cL z)&F8HAETuWDD}XgCBKm5)|s?b$CO7lPL}_|1ovP+u`TuOolmzmFVR%C9-J4B1kzmE$410xoTZ+1*bpT zaQL@xi9N4fVN1JQT05FCYfsaqqj>^ziuOS!P=_H>#cmuxaL!T<|2Dkqs~M+cos{3+ z#69%jFNRMtG^w{tRUGY2p%^%%AXnoXfZNe-bDGc=bxLo0K}g%J`ykZ?>%DkAKgVZx z{TR9rAoN@ehC#_%Y1jrFJp57H)#u|tpH7bLLssKo%oj^v_KtQY8r_E8o7S$KX2)PX z@KOTZgPmc!6(OU`U%K#FB|4G@(#2-5d2kjqwE4#|l|5dG!&PR2xn+c7!ECkl_7w{W zKF}Rz)qSLDEI9S;r^^ym3iGwPAvs#?Jss5&*i?HXT{ddSpL^-R`r(FeuH3BQSy;ms zasl&JFad;lUmwkI!6Ws;&HgZ~Sia6xyQs5u zeH%Y}K&(halIBf)tI6R`c&SN}zCIw*CU%(_XHJ zfg=LyPIZzUm@k=ZuMQe)7n4LL+=Q0CCu$T99+&4vYHZsL9CS4dAtPOBs|&uS$o+j1 zO-a3<`9hfk9cKIM(sl}~$?BU`=tC_m#MLby_v)y(POGKkBqnwJFOiD{eZuAfdOBmY z?&KnwB`%|%)3!`eXR_d?wk+|~*QcqPTCoWiT}S@Y(}Wv|71WBg)~CEuFvyMCCy{x)&1i80I~Od1cvl{xxzG}S>V z+7KuDM$^Qe{9i_$<%Jzexk4)+Ch26sk6XBW8w3VsxRI3*99YV2-~${oX6TYH=ZD_T zl1}k$VFAaZy+O}!Ls+zi0naf=Q7Wtf2DO?8p*$!oox%mojbM54lYbs+Tqg_ zlM2`cv6_9<)`?Rb_i-;(j*=w~|Dy`S3m?Cc=Eo8Ys7Jp(=r-+$C`y*T+S-${JC9i= z?hwXg9&wvffo)@dphR zx8CmBdltYMwp)&$jAxCM-6#1u*W1CB`ml~Jq;qkAq&Z(ae|r))%O#*{sfanQhf<%D za*nt;o#R&ojY$UCTw8a1d8dV;rQ5UqG%e14BbygQ2Rn%uuqK3!ZoY=7r@ED zijfWg!C#de?wY1tR{Z?%q2LR4%j=s<9>uAn%wZl!`moi%ekq}TYK;7a<%d4VLF*}0 z11ZN+YYup*%eB&$Bu=CRfBpd7~mnh=^eRCZzhOuO<- zdlmQ0K`^Z}gf{4Uuf9TI{C$i-m=?YPq+THWHp7RS09jv&b6{$X1;zh$7l6`d&lMPg zNYOUP;JOjn(o39|&(k9J1FsLsMb`#I5y&Y)q5TNP7_Z9ws+~|mF*cqfjH;iM9{Z&B zf^C$wTW|-(DDjVjPHeu$7_0^#{#G+>Gg*$rf3^-Qo_yjS$Q=1?Mk6rzdG_$v#xjNi zSjU5`fJ?UlVIQ9p{}@~6zO`dD-+%@6wKl_KQ7aP}&w8(*2t;6X%Ndu}V(&7t?P`bzucbC+rC3L7 zn_@Z5)K(((Jo^1IQ_BciqXPQzZ~NyZS=K1xM!S>p2sv*jeC`E2ReZcsAiW$&-cp6C z?d2%DjY&nq+HZ5S17_s;CN(``USC}PyiaX5yU0Bg(fsVbrQcfohL+Grz-4YOFs7Cs z2-n}wKAex5p6eGXH|Du0MX>d*G13UHiENJZryQd|@M%I^4{m$zsK1*qAVNYLy;fO} zS4X2cM`xvCQCUPLt_Njqu6(Coia>nI1olYa~;H8g$A@+W- zYh(^= z^`J>zy&JM?2oV$?lD}(xWLg0Y;F%-!^!i?p;WqHumHynU@ikheUcMEB(}O0wS1Obz zr91=Jovw1=1FXfZOi3nFv1ItnW%m&OFQom_&1t`T*pwb*h!|?xW^~@ZsT#Y>Njc8D zvqf-xa>N~bL$D{PDkRb#=tuCb!WQMy>@{3X9ru+R9aWq-^iiMd z;!7ge?TGkZ8OestakLqgCSkz5J$2RI>Vp6e4*zPO(u8fsg4tf*sYXrq$5#cJs#MP+ z=66M-y*~0AcIy+j)&DF`K^2RWL{{U@J1&nss+Eq~u%!y^oLT)ul$kl!YsE15DZ*E3 zr%VCT?Q5lF^Z7WhdC>2h?wAjmUbx@N&-}e?<>tT{qJ(i(aF=Ba^7T&e;l>PyD}Ccz zQh0#7gw&c0YGYN$_y^iP)SZ^QLZ45um&7}?ky5HKU22z1AkC4D*4n841nKB|Fl+9n zQKk`ReFoYN8)FW15~cB& z65+{#T@tPa+LiNH6}Ci1rYI$KBNKd~cz)63w?rSjqLuoDn#)uIrILHi0^ z^t2Yo->uVPas)i+yK%{pJ5iVqDF_Z3SaS~&mvD5At@RHXtU%5sy|0XpMPGD}Z&F=J z72LUoiMD!1JToyRhhKp%Y^w%~`khzChsHg#>?Mz{0u}>{1cJ=2g(X;xMA0EaA8ySF zw81g04wCz!I6|IVA5}LZk57)9oUGJ*Q_x2Cn7}o!0-Q}7w(FHy`s=SQQe)g)eNqD# zJSaDAI_D|~*#Z96!1oE!iZ;)P!t;Fkqnnyjlh6N76IsI_V=>BRIyFgqp+tucEBY$7 zl+Rl0xL`dH^a1pX7@iR}*~ExCOJC^h(9CmecZgtF^~}TEV`wwx(4ZOhj<31oEePre zwc8pC+SJS?*Lead@VZD5>hw}KQ=Jjt8A!KP>(0v&XWd-$%A{-lh7s%XuvGR+ny=!TMeD&_pMZ?aSNxg zc0vOor*$jGyu@$-{aC;p3x#`4$Q(E_`?2AOnIc*2w<1dF;HIi%UL{#WpGbt{Icg{l z)CYG+ZN}G?ZguS~9Ao-2Z$17p(v}sJg7tJKw%C-`9NGU}n6|pMaKEYfWK66$5D9Dg z{&-cLrJe0$UrpvPZMpu{Sj-d!xwX+m7}i(Y`Lu5UONQ!eUJb;eRtUk|qnkCDR0hkH zr93M0<DbG7undkH+(eteU!(Z-%M|p0N0|w2`SaC)09WR?@Pw71yXkxX>IoU=xUj}jtSGi zgv~p}Udj!;*o+*>;mU2vyAGsQ^qq$dNQJeKjkpC2Jsi^YW&i1=ZoQwUDmu=$CU4a4 zVo>=-ZTuV?VYzAJJcl}7Kjl466L`s|!!o&fwlJkm!WCZnaFxry1w#Dt*Uiwy=<@gr;$4|>Vu7*gt)a{Tai2xtmMDj9+~twvJd4(3xre^b zcE;B@3t*R$_t%IT^w;HVH4VUP?i#wIl0q(M)G=b5X zaewmx$un`6QA72{UU-%%Y@uA!)$wucgTXeBnk_i^mS>e3!5*yUDTll)+AH=|-z9js!DvkZ@whM?_c@qXZhqK&2K&;qAyucLUwPCmY6z{q z4_+{67;X)rEn5;iu#T|dy!>g%CE9(J0^9=$)mOp=sN1FH?{$6~TlLa+t#DqGkH11k z`7X4o-DXmY^>(%o7n-(CyIbm-J$Y=Wh7kmUYtu@xoyslTW3nqg+W^6@YW%u>W^7GX zk3CA-VKCs?c^;UYUXUw|< zyg&BDm>pJ$0XhBhDq6>Zi_p;Eb)7F;U)uJQf|d#DebIW&F>4Yb8x64&;o=HctSX~` zcDW#%SjCEvxz!1XX)9KmC;Nll2e{ry&<05u5%&I2YfUBG+fxm zrZA)FH*ky%`Dm*5{47f#2g^fqt4^=vgV~t&o0?F)SVZj6z3kYg&0V<~f#T{n z(qmW?0o8BF7`xQzeq~AXK{YY=J zc*4?^p-&Zjkh6BxHaA;CJ?|bWAPc`}Q9YadihCd2J4@dJW7vCUCmOYx^@5 zOR2$9O!5Wrn_g$|Q!kySzlLoMFaps)l#gHwT|pFu8*KfQ@hwoUf4;VQ78^IIVMgX; zjM=P%j(V}yqOtRGCWIB;;%J5^L?o8!`{UmAjIf*N)aIK3@c=W(QT~1NdaDz@ey?h@ z5mhQl{_A0dPl1`oQY!KcvS6QE25#CYun(UK>qC3cT$MLAG;7q~=cIKvgo7opDAQqo z_Ow^%p`Xw3X}PR&MVcZmr%sq;--CM+>feeZSjd>zpU!5q2@czD_Lljzc-%~IbZdOP zP#d)lAceCx8TjS*?LUT^M)nY(@g%v37NiWsU5NNMG~ERJ{A=4AeR#-!{8iZ2bMw|1 zAPC%Y6-6ebTEr+)sbm9|KE;A8!h_Zxv}3GYZ$VxoCd&moyDn!ObJbxx{l-#orp}^r z%r5Nxq$F8YSMA&}Yh)&M))HBPpodU@L@(zRS(Hyzf z(`)qe0!!3R#6niY%iC+efD(}#*?u9uf5i!EEw~^_wOEbjW+z6j935wZ;8pLh(Q_9R z%6>e4!C~5-ew0s9#pudzO8M<<71H(i3Y`$EN^U5_q0Q#4>ds(r-Vb-ukmjd{cpVAGz@ z3aWVNM>6Mg(V_53L`(9mW{kV?%0y(w;~hFI#MuP+qLoW*?yL+1pD+Cef}0{c%$zb* zgfzET=adsg_eAShEQwNZFhkp(mH<1<(jN<9;9`yit>Ciody7Ns zy0ijd1&dS#yGdb$vukfprvOW36!@+3aPb$P@2e=$O$DjlCsC3=rhm?qKJZMVP)2dt zm4)i*>O0>&uA<(6#T+*wBQq5r1l{kRwWXl_&#j7H4Hy9Z$>8DJrb&_!dv)m|4|zKM zQ7<@W3v&D4ChXar({9dx@rU_|r@uT)Ju6BN*wjnR!OgC_fvByd20ywy*8(574(v1! z94E!g3DsME%5w_%S(;TowQnP$AF6J02@^0Yz(y$A%qqM{ZnxX9H|XL|#wnCiI;s3b;8fbKtc*q2RUajVb*@cRd&FX(9l@-W*O&T~d;XS4}M`Ix> z#nZWk$@OStR#g5DB+?EO-Q7w}a=HyIr}5SJsNBwXCY-mB_8mw5)3A|AfvAwguf}k{ zT72BU=guV(Cf&+RH3J^PP4n8WuEb7X$U7X^9?i=n@f4;u z?pl`5;+ANx?pl?f#(dWwKBAQ*C<*t|8v1KZT(LE6{&7!@H25V&Vc8A*BBtr--4t8U zA({!2JZ$^Le;20@Jwg^fzb?Qq1n<+$T!k&{fbGg>Jn|wIXwf+v{JI<55}yAU3^YLC zI~?P=mo2E~>Y26QXz>0T_w$p_PEOzNV7OQt3#h#vGJ{Nc)y7W_&E-#s)9C(Mhnq+x zs7D11y(h=W-I@D-$OPo$T5;;o6WkUm(6ms|rXN%c-4ac~IK9tp_D_(sIR&~dG0v#$ z_BN8iCpW~o&6OAy#V`6qZGt!bhdWx@syk-zjb9Nh28z))4|(jmP4w*_N}P9^@cV2$ zoy*Yqq4^Y}Dzfo!SP-K5U8@G(Pq6~u7^kv9r8!b>f;OClTmQxZtk+!|TTG+W*~_!j zB-Tc8F{>6osofKFlbS|UW^3zcM@^oUC)pO=1P=NpOpo=SU-sLFRZ#fr75VqzM&s|E z(A5?D%YaRQD4x6g)=r?#J3q!+<|&pJHuQT!=}`BRUpzRdF0=YKG5TVQv$Meu_l7%= zuL>yBC8S$5>lcputh_CY0H7|nWS``jk2RUY<;@Q{tHdvCI+c|``T2zB!>w@Yt&ppi>@uXe-sOx zQ&1!q4^^SnA3XkLNn^MvcyQG7;2|evz4WqRYr&96<}33>`x^tiYT;2K2l0X!9J|68 zyebj0@STMcMF0&kSB;q=1K6Mk&p6iJ5gd}=Z+n)qXFAdDrQEc8*!~@N-j2fcS3rv6 z#`X7T?xB=l{o%V_{z4Up1jzkl*PHnA=0J_s7~l#iKOLlpUSQH50bJ!%W8q>!|Dq@8 z6MRDzQ=kuCrLx{?_&ekFO}0d-f~5{(Ym;qPl#6pseie0vc)zSV7HHYU!5?rwGhq?% zEMr1evdexPYoftuRkZOc3mYvCK1tZ-_LX921VX#a^Zmk6Fe8N$jmLDc@0w3Y>pTto?S zWm?>^Vt@s!wlmuOtX})e&`Tk~c_Lu|_|-wBXk(9UX1VWZvTcl>8bK%e&m~CEQFKZA zLXD|Tb~o?DexPf6xrI+k?H}B8ZlnX9M?E!_qKM_gK#ke!eaikmS}uRS@aWc8wKIef z)EL`B^>e2jiFQu>B|Yg5_1MY_n@X~OBCAqlQXq-nZmBmGv$}KHAiSn}z$3fi*0TGn zGbXRdFHR-S+H38=D$i*2Wt}M*XPWdo#o576Mk5rMq=iUgarm z==iKF!@EEK&|*SsBk@;gP;((w$)u**#tI7ikn@KmiRf^=Bd&POp*Q?hv6Sfrm*@~0 zXZTgvr!Bbk;8>33zHdPbGw60-i~M4YFC6kZ;Xr!6tb zZ0f^@82~Ay{Dzqg8+By*7q&QvJ5cyxWFzhUJTrP`cZSU{7Et4>GR<}A7QKO2%J50o zU+p}m6-8!iHhurVZXLDmTJ6bu`t8~7-H`n@%}Y>4q(<0MTu1j1HSwWX!VnF0I;zJ* z^dcSG{Xyf~)ND+&5wB0Q9F#H*YM=WnA!$yqv)K&H^^QLB#`1HN&}$?@)fNcmwT$KsXbO*kEb$zBCar$K|2m=S0{;Q{3kJp~CKlM`o0cWfj z4YVPQ+DKdAlL0Hx_mz*PWxYIo@KCDB(oL4CisMpn^qzpr=TVo>9!^-$-Gi0r3nTy; z9PhNUfP6FkDCfquW$Z=f_h(L`pU34>O{h6jbdbSk^P8+RT#`u690_XNvny69xz7)J z)>}AYodDmkb#4|bz2TD*?PwL#Nd4-&nT|3R*}2{JVLM@yr?=X^7Q}kMshghgm(q?* zE_tj6Z7t7LNhGM46MOxOYslo=g?~}~iPvLPREeXba*X<5UxcDs;xpVIw^J7wtS&lQ z_Wt58g|xt|pB0L)KkJlHJMvsaxPj?n#ovmLx;nF`1_La98yNqaxWV)~uk+t>q1N$(v4l_4z*XnAqu^Qla(w zaODH>4*~O{lYLVhY#t}-=7ojIpJmRUWyJAS5Xk`kVy>p=m21z=rkJ<)=?w?%DOj?e zMYns625OCh=0sT^sE4u-=ackSf1GUCMKHVH+Ixfjdr8Q-_C zJkDS6-H+Gye($qu*LCfB@BMsz-m_oRyEYfup6rl)=Db_yYgL!@O)vcJ`ReFL1<>zX zA8kXEes~mPAlDo@a(n0Y-5h`D3z{WNuke$5EPW2EOe*;5#`@$DjR^1be!VsI$(Y?hmtZ`)A#3p^R1Qc)0T$JX)^L9CNzi!2OFL^&qHo<=6WV3 zV|u~siH1QZxBH#DVw2Aw3Y^~is^RTZS7pF7FeY7+je8u~qvzx$`qJ=U*a&W2=gZ|k zf8Tc*Nk6mGC0_;G($bGE_6>Xn8`6P&WgXKP73wxMoh-Y@oUTDt|| zp+$~O+K|Pk$aid+&vI#lgH?)Wx@i;b*+Rei$>MwE(E)rs6Kr<(=s1ly59;KH5`-D0 zW(Y_lx8e{Fh^%l}^!R9>EnRQ8E|pn{0T9D# z2Ps|GA?%u!s7xhC9l}J+4h8kP1M0*#9szD`5=YcGsqi7h$$yd9?iDn@Rq}-y!m-xr zX!CX3O9b<+<=Ft`csQES9&WT#e(;W%pFIIVy>I&Bb|d%)hz{LM;ISD8j-1GO;*+P+HhC@S}*#Ppt$klIhKXqNT@)EERPji_zU zWssVB3+K+B%1j{oX5deppoh+!t=xK3Dp4$NG1q|-Uo7Gu+JTxX>)LWt<;zeK7o{4XVN@{pJ{E4C zBw#_4nLNddqH1zqztZu=ZO>gF0@rzXiSvcOv9{idZx*BGx$L&sXCQmRVcv75>svA6 zSW$qy7VX|!G?=>RK-j|dZ=#F8*WYjQ(rQ(`%lZA`ou2@}%7h z(1|dSt=pmiK^Eyf(&fWlZJJ({a{8CmqQ)M}WTM zct|^^-nEc2S-RmYZ1EkYdV-~#(xO+}^W$_h>aEbM4TxYS$D??r{u~k9N=B?GS>-$T zMZ&6>CnKUu0_68)U$D8LZ>#}ce<=18kJvTs^I?O>A)oK_*5JoiXhA=5d^iq+L@coS zFExAkEn;EQ3}}@V`)I8ECU@5E!q~fG990oCD`fnGcDbnOsfBBB(PO#Q>8Ogo!GM7s zsA4Pn@f-0NWPq@!qTg#|fj*I@u&zbLE`8X`Jr%BGWx(cw?#*B7X`63$xU}FvGTS{C7tJ#j0avZj#|GhGrVAuw6aEi6Ic1#-WBtsko`Xs+Fl!$j;? z-E^8>=%^_%KX(OPC4O0k3$0{KJNn7)VgHW5TJS^Cw!V*^g42g)hUj@0_mnZme@oincK757CEY(_a5bZDAeGybo{Et7LBxoh!3)MW5Xv zLhMe{{?@Yg1bueat5&6X2q3eBcs%E_SO8-#FmLp@OaJ|8?ket=Xb$~ic~zr6)&Msg#rD(b7!Vi=X@HZ3SGvG zIu>4U>?jKs9hv1T6L8awW1`nmkim8ey?B5sV}U8?0#WzWrq0AcG#p`6ESgwa_6@ zdlJD&Mg^WH_1&hw4MCONo2acIfD<6M;`Y3 j?jj(4#Qp!e?c*YHM*am6PVX#0fX5L-Gg6NJ>FfUkNb}cq literal 0 HcmV?d00001 diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 00000000..86c031f9 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,10354 @@ +{ + "name": "@adobe/aem-experimentation", + "version": "1.15.1", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "@adobe/aem-experimentation", + "version": "1.15.1", + "license": "Apache-2.0", + "devDependencies": { + "@babel/eslint-parser": "7.22.15", + "@playwright/test": "1.44.0", + "@semantic-release/changelog": "6.0.3", + "@semantic-release/git": "10.0.1", + "@semantic-release/npm": "12.0.1", + "eslint": "8.48.0", + "eslint-config-airbnb-base": "15.0.0", + "eslint-plugin-import": "2.28.1", + "http-server": "14.1.1", + "monocart-coverage-reports": "2.8.2", + "semantic-release": "23.1.1", + "stylelint": "15.10.3", + "stylelint-config-standard": "34.0.0" + } + }, + "node_modules/@aashutoshrathi/word-wrap": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz", + "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@ampproject/remapping": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.1.tgz", + "integrity": "sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==", + "dev": true, + "peer": true, + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.0", + "@jridgewell/trace-mapping": "^0.3.9" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.6.tgz", + "integrity": "sha512-ZJhac6FkEd1yhG2AHOmfcXG4ceoLltoCVJjN5XsWN9BifBQr+cHJbWi0h68HZuSORq+3WtJ2z0hwF2NG1b5kcA==", + "dev": true, + "dependencies": { + "@babel/highlight": "^7.24.6", + "picocolors": "^1.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.22.20.tgz", + "integrity": "sha512-BQYjKbpXjoXwFW5jGqiizJQQT/aC7pFm9Ok1OWssonuguICi264lbgMzRp2ZMmRSlfkX6DsWDDcsrctK8Rwfiw==", + "dev": true, + "peer": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.23.0.tgz", + "integrity": "sha512-97z/ju/Jy1rZmDxybphrBuI+jtJjFVoz7Mr9yUQVVVi+DNZE333uFQeMOqcCIy1x3WYBIbWftUSLmbNXNT7qFQ==", + "dev": true, + "peer": true, + "dependencies": { + "@ampproject/remapping": "^2.2.0", + "@babel/code-frame": "^7.22.13", + "@babel/generator": "^7.23.0", + "@babel/helper-compilation-targets": "^7.22.15", + "@babel/helper-module-transforms": "^7.23.0", + "@babel/helpers": "^7.23.0", + "@babel/parser": "^7.23.0", + "@babel/template": "^7.22.15", + "@babel/traverse": "^7.23.0", + "@babel/types": "^7.23.0", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/core/node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true, + "peer": true, + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@babel/eslint-parser": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/eslint-parser/-/eslint-parser-7.22.15.tgz", + "integrity": "sha512-yc8OOBIQk1EcRrpizuARSQS0TWAcOMpEJ1aafhNznaeYkeL+OhqnDObGFylB8ka8VFF/sZc+S4RzHyO+3LjQxg==", + "dev": true, + "dependencies": { + "@nicolo-ribaudo/eslint-scope-5-internals": "5.1.1-v1", + "eslint-visitor-keys": "^2.1.0", + "semver": "^6.3.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || >=14.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.11.0", + "eslint": "^7.5.0 || ^8.0.0" + } + }, + "node_modules/@babel/eslint-parser/node_modules/eslint-visitor-keys": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", + "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/@babel/generator": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.24.6.tgz", + "integrity": "sha512-S7m4eNa6YAPJRHmKsLHIDJhNAGNKoWNiWefz1MBbpnt8g9lvMDl1hir4P9bo/57bQEmuwEhnRU/AMWsD0G/Fbg==", + "dev": true, + "peer": true, + "dependencies": { + "@babel/types": "^7.24.6", + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25", + "jsesc": "^2.5.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.15.tgz", + "integrity": "sha512-y6EEzULok0Qvz8yyLkCvVX+02ic+By2UdOhylwUOvOn9dvYc9mKICJuuU1n1XBI02YWsNsnrY1kc6DVbjcXbtw==", + "dev": true, + "peer": true, + "dependencies": { + "@babel/compat-data": "^7.22.9", + "@babel/helper-validator-option": "^7.22.15", + "browserslist": "^4.21.9", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets/node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "peer": true, + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/@babel/helper-compilation-targets/node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true, + "peer": true + }, + "node_modules/@babel/helper-environment-visitor": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.24.6.tgz", + "integrity": "sha512-Y50Cg3k0LKLMjxdPjIl40SdJgMB85iXn27Vk/qbHZCFx/o5XO3PSnpi675h1KEmmDb6OFArfd5SCQEQ5Q4H88g==", + "dev": true, + "peer": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-function-name": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.24.6.tgz", + "integrity": "sha512-xpeLqeeRkbxhnYimfr2PC+iA0Q7ljX/d1eZ9/inYbmfG2jpl8Lu3DyXvpOAnrS5kxkfOWJjioIMQsaMBXFI05w==", + "dev": true, + "peer": true, + "dependencies": { + "@babel/template": "^7.24.6", + "@babel/types": "^7.24.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-hoist-variables": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.24.6.tgz", + "integrity": "sha512-SF/EMrC3OD7dSta1bLJIlrsVxwtd0UpjRJqLno6125epQMJ/kyFmpTT4pbvPbdQHzCHg+biQ7Syo8lnDtbR+uA==", + "dev": true, + "peer": true, + "dependencies": { + "@babel/types": "^7.24.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.22.15.tgz", + "integrity": "sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w==", + "dev": true, + "peer": true, + "dependencies": { + "@babel/types": "^7.22.15" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.23.0.tgz", + "integrity": "sha512-WhDWw1tdrlT0gMgUJSlX0IQvoO1eN279zrAUbVB+KpV2c3Tylz8+GnKOLllCS6Z/iZQEyVYxhZVUdPTqs2YYPw==", + "dev": true, + "peer": true, + "dependencies": { + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-module-imports": "^7.22.15", + "@babel/helper-simple-access": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/helper-validator-identifier": "^7.22.20" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-simple-access": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz", + "integrity": "sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==", + "dev": true, + "peer": true, + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-split-export-declaration": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.24.6.tgz", + "integrity": "sha512-CvLSkwXGWnYlF9+J3iZUvwgAxKiYzK3BWuo+mLzD/MDGOZDj7Gq8+hqaOkMxmJwmlv0iu86uH5fdADd9Hxkymw==", + "dev": true, + "peer": true, + "dependencies": { + "@babel/types": "^7.24.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.6.tgz", + "integrity": "sha512-WdJjwMEkmBicq5T9fm/cHND3+UlFa2Yj8ALLgmoSQAJZysYbBjw+azChSGPN4DSPLXOcooGRvDwZWMcF/mLO2Q==", + "dev": true, + "peer": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.6.tgz", + "integrity": "sha512-4yA7s865JHaqUdRbnaxarZREuPTHrjpDT+pXoAZ1yhyo6uFnIEpS8VMu16siFOHDpZNKYv5BObhsB//ycbICyw==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.22.15.tgz", + "integrity": "sha512-bMn7RmyFjY/mdECUbgn9eoSY4vqvacUnS9i9vGAGttgFWesO6B4CYWA7XlpbWgBt71iv/hfbPlynohStqnu5hA==", + "dev": true, + "peer": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.23.1", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.23.1.tgz", + "integrity": "sha512-chNpneuK18yW5Oxsr+t553UZzzAs3aZnFm4bxhebsNTeshrC95yA7l5yl7GBAG+JG1rF0F7zzD2EixK9mWSDoA==", + "dev": true, + "peer": true, + "dependencies": { + "@babel/template": "^7.22.15", + "@babel/traverse": "^7.23.0", + "@babel/types": "^7.23.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.24.6.tgz", + "integrity": "sha512-2YnuOp4HAk2BsBrJJvYCbItHx0zWscI1C3zgWkz+wDyD9I7GIVrfnLyrR4Y1VR+7p+chAEcrgRQYZAGIKMV7vQ==", + "dev": true, + "dependencies": { + "@babel/helper-validator-identifier": "^7.24.6", + "chalk": "^2.4.2", + "js-tokens": "^4.0.0", + "picocolors": "^1.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/@babel/highlight/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true + }, + "node_modules/@babel/highlight/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/@babel/highlight/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/parser": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.24.6.tgz", + "integrity": "sha512-eNZXdfU35nJC2h24RznROuOpO94h6x8sg9ju0tT9biNtLZ2vuP8SduLqqV+/8+cebSLV9SJEAN5Z3zQbJG/M+Q==", + "dev": true, + "peer": true, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/template": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.24.6.tgz", + "integrity": "sha512-3vgazJlLwNXi9jhrR1ef8qiB65L1RK90+lEQwv4OxveHnqC3BfmnHdgySwRLzf6akhlOYenT+b7AfWq+a//AHw==", + "dev": true, + "peer": true, + "dependencies": { + "@babel/code-frame": "^7.24.6", + "@babel/parser": "^7.24.6", + "@babel/types": "^7.24.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.24.6.tgz", + "integrity": "sha512-OsNjaJwT9Zn8ozxcfoBc+RaHdj3gFmCmYoQLUII1o6ZrUwku0BMg80FoOTPx+Gi6XhcQxAYE4xyjPTo4SxEQqw==", + "dev": true, + "peer": true, + "dependencies": { + "@babel/code-frame": "^7.24.6", + "@babel/generator": "^7.24.6", + "@babel/helper-environment-visitor": "^7.24.6", + "@babel/helper-function-name": "^7.24.6", + "@babel/helper-hoist-variables": "^7.24.6", + "@babel/helper-split-export-declaration": "^7.24.6", + "@babel/parser": "^7.24.6", + "@babel/types": "^7.24.6", + "debug": "^4.3.1", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse/node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true, + "peer": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/types": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.24.6.tgz", + "integrity": "sha512-WaMsgi6Q8zMgMth93GvWPXkhAIEobfsIkLTacoVZoK1J0CevIPGYY2Vo5YvJGqyHqXM6P4ppOYGsIRU8MM9pFQ==", + "dev": true, + "peer": true, + "dependencies": { + "@babel/helper-string-parser": "^7.24.6", + "@babel/helper-validator-identifier": "^7.24.6", + "to-fast-properties": "^2.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@colors/colors": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz", + "integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==", + "dev": true, + "optional": true, + "engines": { + "node": ">=0.1.90" + } + }, + "node_modules/@csstools/css-parser-algorithms": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/@csstools/css-parser-algorithms/-/css-parser-algorithms-2.3.1.tgz", + "integrity": "sha512-xrvsmVUtefWMWQsGgFffqWSK03pZ1vfDki4IVIIUxxDKnGBzqNgv0A7SB1oXtVNEkcVO8xi1ZrTL29HhSu5kGA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "engines": { + "node": "^14 || ^16 || >=18" + }, + "peerDependencies": { + "@csstools/css-tokenizer": "^2.2.0" + } + }, + "node_modules/@csstools/css-tokenizer": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@csstools/css-tokenizer/-/css-tokenizer-2.2.0.tgz", + "integrity": "sha512-wErmsWCbsmig8sQKkM6pFhr/oPha1bHfvxsUY5CYSQxwyhA9Ulrs8EqCgClhg4Tgg2XapVstGqSVcz0xOYizZA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "engines": { + "node": "^14 || ^16 || >=18" + } + }, + "node_modules/@csstools/media-query-list-parser": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@csstools/media-query-list-parser/-/media-query-list-parser-2.1.4.tgz", + "integrity": "sha512-V/OUXYX91tAC1CDsiY+HotIcJR+vPtzrX8pCplCpT++i8ThZZsq5F5dzZh/bDM3WUOjrvC1ljed1oSJxMfjqhw==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "engines": { + "node": "^14 || ^16 || >=18" + }, + "peerDependencies": { + "@csstools/css-parser-algorithms": "^2.3.1", + "@csstools/css-tokenizer": "^2.2.0" + } + }, + "node_modules/@csstools/selector-specificity": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@csstools/selector-specificity/-/selector-specificity-3.0.0.tgz", + "integrity": "sha512-hBI9tfBtuPIi885ZsZ32IMEU/5nlZH/KOVYJCOh7gyMxaVLGmLedYqFN6Ui1LXkI8JlC8IsuC0rF0btcRZKd5g==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "engines": { + "node": "^14 || ^16 || >=18" + }, + "peerDependencies": { + "postcss-selector-parser": "^6.0.13" + } + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", + "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", + "dev": true, + "dependencies": { + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.8.0", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.8.0.tgz", + "integrity": "sha512-JylOEEzDiOryeUnFbQz+oViCXS0KsvR1mvHkoMiu5+UiBvy+RYX7tzlIIIEstF/gVa2tj9AQXk3dgnxv6KxhFg==", + "dev": true, + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.2.tgz", + "integrity": "sha512-+wvgpDsrB1YqAMdEUCcnTlpfVBH7Vqn6A/NT3D8WVXFIaKMlErPIZT3oCIAVCOtarRpMtelZLqJeU3t7WY6X6g==", + "dev": true, + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.6.0", + "globals": "^13.19.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/js": { + "version": "8.48.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.48.0.tgz", + "integrity": "sha512-ZSjtmelB7IJfWD2Fvb7+Z+ChTIKWq6kjda95fLcQKNS5aheVHn4IkfgRQE3sIIzTcSLwLcLZUD9UBt+V7+h+Pw==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/@humanwhocodes/config-array": { + "version": "0.11.11", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.11.tgz", + "integrity": "sha512-N2brEuAadi0CcdeMXUkhbZB84eskAc8MEX1By6qEchoVywSgXPIjou4rYsl0V3Hj0ZnuGycGCjdNgockbzeWNA==", + "dev": true, + "dependencies": { + "@humanwhocodes/object-schema": "^1.2.1", + "debug": "^4.1.1", + "minimatch": "^3.0.5" + }, + "engines": { + "node": ">=10.10.0" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/object-schema": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", + "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", + "dev": true + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", + "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", + "dev": true, + "peer": true, + "dependencies": { + "@jridgewell/set-array": "^1.2.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.24" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz", + "integrity": "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==", + "dev": true, + "peer": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/set-array": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", + "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", + "dev": true, + "peer": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.4.15", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", + "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", + "dev": true, + "peer": true + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "dev": true, + "peer": true, + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@nicolo-ribaudo/eslint-scope-5-internals": { + "version": "5.1.1-v1", + "resolved": "https://registry.npmjs.org/@nicolo-ribaudo/eslint-scope-5-internals/-/eslint-scope-5-internals-5.1.1-v1.tgz", + "integrity": "sha512-54/JRvkLIzzDWshCWfuhadfrfZVPiElY8Fcgmg1HroEly/EDSszzhBAsarCux+D/kOslTRquNzuyGSmUSTTHGg==", + "dev": true, + "dependencies": { + "eslint-scope": "5.1.1" + } + }, + "node_modules/@nicolo-ribaudo/eslint-scope-5-internals/node_modules/eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/@nicolo-ribaudo/eslint-scope-5-internals/node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@octokit/auth-token": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-5.1.1.tgz", + "integrity": "sha512-rh3G3wDO8J9wSjfI436JUKzHIxq8NaiL0tVeB2aXmG6p/9859aUOAjA9pmSPNGGZxfwmaJ9ozOJImuNVJdpvbA==", + "dev": true, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/core": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/@octokit/core/-/core-6.1.2.tgz", + "integrity": "sha512-hEb7Ma4cGJGEUNOAVmyfdB/3WirWMg5hDuNFVejGEDFqupeOysLc2sG6HJxY2etBp5YQu5Wtxwi020jS9xlUwg==", + "dev": true, + "dependencies": { + "@octokit/auth-token": "^5.0.0", + "@octokit/graphql": "^8.0.0", + "@octokit/request": "^9.0.0", + "@octokit/request-error": "^6.0.1", + "@octokit/types": "^13.0.0", + "before-after-hook": "^3.0.2", + "universal-user-agent": "^7.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/endpoint": { + "version": "10.1.1", + "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-10.1.1.tgz", + "integrity": "sha512-JYjh5rMOwXMJyUpj028cu0Gbp7qe/ihxfJMLc8VZBMMqSwLgOxDI1911gV4Enl1QSavAQNJcwmwBF9M0VvLh6Q==", + "dev": true, + "dependencies": { + "@octokit/types": "^13.0.0", + "universal-user-agent": "^7.0.2" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/graphql": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-8.1.1.tgz", + "integrity": "sha512-ukiRmuHTi6ebQx/HFRCXKbDlOh/7xEV6QUXaE7MJEKGNAncGI/STSbOkl12qVXZrfZdpXctx5O9X1AIaebiDBg==", + "dev": true, + "dependencies": { + "@octokit/request": "^9.0.0", + "@octokit/types": "^13.0.0", + "universal-user-agent": "^7.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/openapi-types": { + "version": "22.2.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-22.2.0.tgz", + "integrity": "sha512-QBhVjcUa9W7Wwhm6DBFu6ZZ+1/t/oYxqc2tp81Pi41YNuJinbFRx8B133qVOrAaBbF7D/m0Et6f9/pZt9Rc+tg==", + "dev": true + }, + "node_modules/@octokit/plugin-paginate-rest": { + "version": "11.3.0", + "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-11.3.0.tgz", + "integrity": "sha512-n4znWfRinnUQF6TPyxs7EctSAA3yVSP4qlJP2YgI3g9d4Ae2n5F3XDOjbUluKRxPU3rfsgpOboI4O4VtPc6Ilg==", + "dev": true, + "dependencies": { + "@octokit/types": "^13.5.0" + }, + "engines": { + "node": ">= 18" + }, + "peerDependencies": { + "@octokit/core": ">=6" + } + }, + "node_modules/@octokit/plugin-retry": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/@octokit/plugin-retry/-/plugin-retry-7.1.1.tgz", + "integrity": "sha512-G9Ue+x2odcb8E1XIPhaFBnTTIrrUDfXN05iFXiqhR+SeeeDMMILcAnysOsxUpEWcQp2e5Ft397FCXTcPkiPkLw==", + "dev": true, + "dependencies": { + "@octokit/request-error": "^6.0.0", + "@octokit/types": "^13.0.0", + "bottleneck": "^2.15.3" + }, + "engines": { + "node": ">= 18" + }, + "peerDependencies": { + "@octokit/core": ">=6" + } + }, + "node_modules/@octokit/plugin-throttling": { + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/@octokit/plugin-throttling/-/plugin-throttling-9.3.0.tgz", + "integrity": "sha512-B5YTToSRTzNSeEyssnrT7WwGhpIdbpV9NKIs3KyTWHX6PhpYn7gqF/+lL3BvsASBM3Sg5BAUYk7KZx5p/Ec77w==", + "dev": true, + "dependencies": { + "@octokit/types": "^13.0.0", + "bottleneck": "^2.15.3" + }, + "engines": { + "node": ">= 18" + }, + "peerDependencies": { + "@octokit/core": "^6.0.0" + } + }, + "node_modules/@octokit/request": { + "version": "9.1.1", + "resolved": "https://registry.npmjs.org/@octokit/request/-/request-9.1.1.tgz", + "integrity": "sha512-pyAguc0p+f+GbQho0uNetNQMmLG1e80WjkIaqqgUkihqUp0boRU6nKItXO4VWnr+nbZiLGEyy4TeKRwqaLvYgw==", + "dev": true, + "dependencies": { + "@octokit/endpoint": "^10.0.0", + "@octokit/request-error": "^6.0.1", + "@octokit/types": "^13.1.0", + "universal-user-agent": "^7.0.2" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/request-error": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-6.1.1.tgz", + "integrity": "sha512-1mw1gqT3fR/WFvnoVpY/zUM2o/XkMs/2AszUUG9I69xn0JFLv6PGkPhNk5lbfvROs79wiS0bqiJNxfCZcRJJdg==", + "dev": true, + "dependencies": { + "@octokit/types": "^13.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/types": { + "version": "13.5.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-13.5.0.tgz", + "integrity": "sha512-HdqWTf5Z3qwDVlzCrP8UJquMwunpDiMPt5er+QjGzL4hqr/vBVY/MauQgS1xWxCDT1oMx1EULyqxncdCY/NVSQ==", + "dev": true, + "dependencies": { + "@octokit/openapi-types": "^22.2.0" + } + }, + "node_modules/@playwright/test": { + "version": "1.44.0", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.44.0.tgz", + "integrity": "sha512-rNX5lbNidamSUorBhB4XZ9SQTjAqfe5M+p37Z8ic0jPFBMo5iCtQz1kRWkEMg+rYOKSlVycpQmpqjSFq7LXOfg==", + "dev": true, + "dependencies": { + "playwright": "1.44.0" + }, + "bin": { + "playwright": "cli.js" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/@pnpm/config.env-replace": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@pnpm/config.env-replace/-/config.env-replace-1.1.0.tgz", + "integrity": "sha512-htyl8TWnKL7K/ESFa1oW2UB5lVDxuF5DpM7tBi6Hu2LNL3mWkIzNLG6N4zoCUP1lCKNxWy/3iu8mS8MvToGd6w==", + "dev": true, + "engines": { + "node": ">=12.22.0" + } + }, + "node_modules/@pnpm/network.ca-file": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@pnpm/network.ca-file/-/network.ca-file-1.0.2.tgz", + "integrity": "sha512-YcPQ8a0jwYU9bTdJDpXjMi7Brhkr1mXsXrUJvjqM2mQDgkRiz8jFaQGOdaLxgjtUfQgZhKy/O3cG/YwmgKaxLA==", + "dev": true, + "dependencies": { + "graceful-fs": "4.2.10" + }, + "engines": { + "node": ">=12.22.0" + } + }, + "node_modules/@pnpm/network.ca-file/node_modules/graceful-fs": { + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", + "dev": true + }, + "node_modules/@pnpm/npm-conf": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/@pnpm/npm-conf/-/npm-conf-2.2.2.tgz", + "integrity": "sha512-UA91GwWPhFExt3IizW6bOeY/pQ0BkuNwKjk9iQW9KqxluGCrg4VenZ0/L+2Y0+ZOtme72EVvg6v0zo3AMQRCeA==", + "dev": true, + "dependencies": { + "@pnpm/config.env-replace": "^1.1.0", + "@pnpm/network.ca-file": "^1.0.1", + "config-chain": "^1.1.11" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@sec-ant/readable-stream": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@sec-ant/readable-stream/-/readable-stream-0.4.1.tgz", + "integrity": "sha512-831qok9r2t8AlxLko40y2ebgSDhenenCatLVeW/uBtnHPyhHOvG0C7TvfgecV+wHzIm5KUICgzmVpWS+IMEAeg==", + "dev": true + }, + "node_modules/@semantic-release/changelog": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/@semantic-release/changelog/-/changelog-6.0.3.tgz", + "integrity": "sha512-dZuR5qByyfe3Y03TpmCvAxCyTnp7r5XwtHRf/8vD9EAn4ZWbavUX8adMtXYzE86EVh0gyLA7lm5yW4IV30XUag==", + "dev": true, + "dependencies": { + "@semantic-release/error": "^3.0.0", + "aggregate-error": "^3.0.0", + "fs-extra": "^11.0.0", + "lodash": "^4.17.4" + }, + "engines": { + "node": ">=14.17" + }, + "peerDependencies": { + "semantic-release": ">=18.0.0" + } + }, + "node_modules/@semantic-release/changelog/node_modules/@semantic-release/error": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@semantic-release/error/-/error-3.0.0.tgz", + "integrity": "sha512-5hiM4Un+tpl4cKw3lV4UgzJj+SmfNIDCLLw0TepzQxz9ZGV5ixnqkzIVF+3tp0ZHgcMKE+VNGHJjEeyFG2dcSw==", + "dev": true, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/@semantic-release/changelog/node_modules/aggregate-error": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", + "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", + "dev": true, + "dependencies": { + "clean-stack": "^2.0.0", + "indent-string": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@semantic-release/changelog/node_modules/clean-stack": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", + "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/@semantic-release/changelog/node_modules/indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@semantic-release/commit-analyzer": { + "version": "12.0.0", + "resolved": "https://registry.npmjs.org/@semantic-release/commit-analyzer/-/commit-analyzer-12.0.0.tgz", + "integrity": "sha512-qG+md5gdes+xa8zP7lIo1fWE17zRdO8yMCaxh9lyL65TQleoSv8WHHOqRURfghTytUh+NpkSyBprQ5hrkxOKVQ==", + "dev": true, + "dependencies": { + "conventional-changelog-angular": "^7.0.0", + "conventional-commits-filter": "^4.0.0", + "conventional-commits-parser": "^5.0.0", + "debug": "^4.0.0", + "import-from-esm": "^1.0.3", + "lodash-es": "^4.17.21", + "micromatch": "^4.0.2" + }, + "engines": { + "node": ">=20.8.1" + }, + "peerDependencies": { + "semantic-release": ">=20.1.0" + } + }, + "node_modules/@semantic-release/error": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@semantic-release/error/-/error-4.0.0.tgz", + "integrity": "sha512-mgdxrHTLOjOddRVYIYDo0fR3/v61GNN1YGkfbrjuIKg/uMgCd+Qzo3UAXJ+woLQQpos4pl5Esuw5A7AoNlzjUQ==", + "dev": true, + "engines": { + "node": ">=18" + } + }, + "node_modules/@semantic-release/git": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/@semantic-release/git/-/git-10.0.1.tgz", + "integrity": "sha512-eWrx5KguUcU2wUPaO6sfvZI0wPafUKAMNC18aXY4EnNcrZL86dEmpNVnC9uMpGZkmZJ9EfCVJBQx4pV4EMGT1w==", + "dev": true, + "dependencies": { + "@semantic-release/error": "^3.0.0", + "aggregate-error": "^3.0.0", + "debug": "^4.0.0", + "dir-glob": "^3.0.0", + "execa": "^5.0.0", + "lodash": "^4.17.4", + "micromatch": "^4.0.0", + "p-reduce": "^2.0.0" + }, + "engines": { + "node": ">=14.17" + }, + "peerDependencies": { + "semantic-release": ">=18.0.0" + } + }, + "node_modules/@semantic-release/git/node_modules/@semantic-release/error": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@semantic-release/error/-/error-3.0.0.tgz", + "integrity": "sha512-5hiM4Un+tpl4cKw3lV4UgzJj+SmfNIDCLLw0TepzQxz9ZGV5ixnqkzIVF+3tp0ZHgcMKE+VNGHJjEeyFG2dcSw==", + "dev": true, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/@semantic-release/git/node_modules/aggregate-error": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", + "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", + "dev": true, + "dependencies": { + "clean-stack": "^2.0.0", + "indent-string": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@semantic-release/git/node_modules/clean-stack": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", + "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/@semantic-release/git/node_modules/execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/@semantic-release/git/node_modules/human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "dev": true, + "engines": { + "node": ">=10.17.0" + } + }, + "node_modules/@semantic-release/git/node_modules/indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@semantic-release/git/node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@semantic-release/git/node_modules/mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/@semantic-release/git/node_modules/npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dev": true, + "dependencies": { + "path-key": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@semantic-release/git/node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dev": true, + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@semantic-release/git/node_modules/p-reduce": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/p-reduce/-/p-reduce-2.1.0.tgz", + "integrity": "sha512-2USApvnsutq8uoxZBGbbWM0JIYLiEMJ9RlaN7fAzVNb9OZN0SHjjTTfIcb667XynS5Y1VhwDJVDa72TnPzAYWw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@semantic-release/git/node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true + }, + "node_modules/@semantic-release/git/node_modules/strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/@semantic-release/github": { + "version": "10.0.5", + "resolved": "https://registry.npmjs.org/@semantic-release/github/-/github-10.0.5.tgz", + "integrity": "sha512-hmuCDkfru/Uc9+ZBNOSremAupu6BCslvOVDiG0wYcL8TQodCycp6uvwDyeym1H0M4l3ob9c0s0xMBiZjjXQ2yA==", + "dev": true, + "dependencies": { + "@octokit/core": "^6.0.0", + "@octokit/plugin-paginate-rest": "^11.0.0", + "@octokit/plugin-retry": "^7.0.0", + "@octokit/plugin-throttling": "^9.0.0", + "@semantic-release/error": "^4.0.0", + "aggregate-error": "^5.0.0", + "debug": "^4.3.4", + "dir-glob": "^3.0.1", + "globby": "^14.0.0", + "http-proxy-agent": "^7.0.0", + "https-proxy-agent": "^7.0.0", + "issue-parser": "^7.0.0", + "lodash-es": "^4.17.21", + "mime": "^4.0.0", + "p-filter": "^4.0.0", + "url-join": "^5.0.0" + }, + "engines": { + "node": ">=20.8.1" + }, + "peerDependencies": { + "semantic-release": ">=20.1.0" + } + }, + "node_modules/@semantic-release/github/node_modules/@sindresorhus/merge-streams": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/merge-streams/-/merge-streams-2.3.0.tgz", + "integrity": "sha512-LtoMMhxAlorcGhmFYI+LhPgbPZCkgP6ra1YL604EeF6U98pLlQ3iWIGMdWSC+vWmPBWBNgmDBAhnAobLROJmwg==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@semantic-release/github/node_modules/globby": { + "version": "14.0.1", + "resolved": "https://registry.npmjs.org/globby/-/globby-14.0.1.tgz", + "integrity": "sha512-jOMLD2Z7MAhyG8aJpNOpmziMOP4rPLcc95oQPKXBazW82z+CEgPFBQvEpRUa1KeIMUJo4Wsm+q6uzO/Q/4BksQ==", + "dev": true, + "dependencies": { + "@sindresorhus/merge-streams": "^2.1.0", + "fast-glob": "^3.3.2", + "ignore": "^5.2.4", + "path-type": "^5.0.0", + "slash": "^5.1.0", + "unicorn-magic": "^0.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@semantic-release/github/node_modules/path-type": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-5.0.0.tgz", + "integrity": "sha512-5HviZNaZcfqP95rwpv+1HDgUamezbqdSYTyzjTvwtJSnIH+3vnbmWsItli8OFEndS984VT55M3jduxZbX351gg==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@semantic-release/github/node_modules/slash": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-5.1.0.tgz", + "integrity": "sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg==", + "dev": true, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@semantic-release/npm": { + "version": "12.0.1", + "resolved": "https://registry.npmjs.org/@semantic-release/npm/-/npm-12.0.1.tgz", + "integrity": "sha512-/6nntGSUGK2aTOI0rHPwY3ZjgY9FkXmEHbW9Kr+62NVOsyqpKKeP0lrCH+tphv+EsNdJNmqqwijTEnVWUMQ2Nw==", + "dev": true, + "dependencies": { + "@semantic-release/error": "^4.0.0", + "aggregate-error": "^5.0.0", + "execa": "^9.0.0", + "fs-extra": "^11.0.0", + "lodash-es": "^4.17.21", + "nerf-dart": "^1.0.0", + "normalize-url": "^8.0.0", + "npm": "^10.5.0", + "rc": "^1.2.8", + "read-pkg": "^9.0.0", + "registry-auth-token": "^5.0.0", + "semver": "^7.1.2", + "tempy": "^3.0.0" + }, + "engines": { + "node": ">=20.8.1" + }, + "peerDependencies": { + "semantic-release": ">=20.1.0" + } + }, + "node_modules/@semantic-release/npm/node_modules/hosted-git-info": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-7.0.2.tgz", + "integrity": "sha512-puUZAUKT5m8Zzvs72XWy3HtvVbTWljRE66cP60bxJzAqf2DgICo7lYTY2IHUmLnNpjYvw5bvmoHvPc0QO2a62w==", + "dev": true, + "dependencies": { + "lru-cache": "^10.0.1" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/@semantic-release/npm/node_modules/lru-cache": { + "version": "10.2.2", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.2.tgz", + "integrity": "sha512-9hp3Vp2/hFQUiIwKo8XCeFVnrg8Pk3TYNPIR7tJADKi5YfcF7vEaK7avFHTlSy3kOKYaJQaalfEo6YuXdceBOQ==", + "dev": true, + "engines": { + "node": "14 || >=16.14" + } + }, + "node_modules/@semantic-release/npm/node_modules/normalize-package-data": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-6.0.1.tgz", + "integrity": "sha512-6rvCfeRW+OEZagAB4lMLSNuTNYZWLVtKccK79VSTf//yTY5VOCgcpH80O+bZK8Neps7pUnd5G+QlMg1yV/2iZQ==", + "dev": true, + "dependencies": { + "hosted-git-info": "^7.0.0", + "is-core-module": "^2.8.1", + "semver": "^7.3.5", + "validate-npm-package-license": "^3.0.4" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/@semantic-release/npm/node_modules/parse-json": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-8.1.0.tgz", + "integrity": "sha512-rum1bPifK5SSar35Z6EKZuYPJx85pkNaFrxBK3mwdfSJ1/WKbYrjoW/zTPSjRRamfmVX1ACBIdFAO0VRErW/EA==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.22.13", + "index-to-position": "^0.1.2", + "type-fest": "^4.7.1" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@semantic-release/npm/node_modules/read-pkg": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-9.0.1.tgz", + "integrity": "sha512-9viLL4/n1BJUCT1NXVTdS1jtm80yDEgR5T4yCelII49Mbj0v1rZdKqj7zCiYdbB0CuCgdrvHcNogAKTFPBocFA==", + "dev": true, + "dependencies": { + "@types/normalize-package-data": "^2.4.3", + "normalize-package-data": "^6.0.0", + "parse-json": "^8.0.0", + "type-fest": "^4.6.0", + "unicorn-magic": "^0.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@semantic-release/npm/node_modules/semver": { + "version": "7.6.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", + "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@semantic-release/npm/node_modules/type-fest": { + "version": "4.18.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.18.2.tgz", + "integrity": "sha512-+suCYpfJLAe4OXS6+PPXjW3urOS4IoP9waSiLuXfLgqZODKw/aWwASvzqE886wA0kQgGy0mIWyhd87VpqIy6Xg==", + "dev": true, + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@semantic-release/release-notes-generator": { + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/@semantic-release/release-notes-generator/-/release-notes-generator-13.0.0.tgz", + "integrity": "sha512-LEeZWb340keMYuREMyxrODPXJJ0JOL8D/mCl74B4LdzbxhtXV2LrPN2QBEcGJrlQhoqLO0RhxQb6masHytKw+A==", + "dev": true, + "dependencies": { + "conventional-changelog-angular": "^7.0.0", + "conventional-changelog-writer": "^7.0.0", + "conventional-commits-filter": "^4.0.0", + "conventional-commits-parser": "^5.0.0", + "debug": "^4.0.0", + "get-stream": "^7.0.0", + "import-from-esm": "^1.0.3", + "into-stream": "^7.0.0", + "lodash-es": "^4.17.21", + "read-pkg-up": "^11.0.0" + }, + "engines": { + "node": ">=20.8.1" + }, + "peerDependencies": { + "semantic-release": ">=20.1.0" + } + }, + "node_modules/@semantic-release/release-notes-generator/node_modules/get-stream": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-7.0.1.tgz", + "integrity": "sha512-3M8C1EOFN6r8AMUhwUAACIoXZJEOufDU5+0gFFN5uNs6XYOralD2Pqkl7m046va6x77FwposWXbAhPPIOus7mQ==", + "dev": true, + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@semantic-release/release-notes-generator/node_modules/hosted-git-info": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-7.0.2.tgz", + "integrity": "sha512-puUZAUKT5m8Zzvs72XWy3HtvVbTWljRE66cP60bxJzAqf2DgICo7lYTY2IHUmLnNpjYvw5bvmoHvPc0QO2a62w==", + "dev": true, + "dependencies": { + "lru-cache": "^10.0.1" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/@semantic-release/release-notes-generator/node_modules/lru-cache": { + "version": "10.2.2", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.2.tgz", + "integrity": "sha512-9hp3Vp2/hFQUiIwKo8XCeFVnrg8Pk3TYNPIR7tJADKi5YfcF7vEaK7avFHTlSy3kOKYaJQaalfEo6YuXdceBOQ==", + "dev": true, + "engines": { + "node": "14 || >=16.14" + } + }, + "node_modules/@semantic-release/release-notes-generator/node_modules/normalize-package-data": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-6.0.1.tgz", + "integrity": "sha512-6rvCfeRW+OEZagAB4lMLSNuTNYZWLVtKccK79VSTf//yTY5VOCgcpH80O+bZK8Neps7pUnd5G+QlMg1yV/2iZQ==", + "dev": true, + "dependencies": { + "hosted-git-info": "^7.0.0", + "is-core-module": "^2.8.1", + "semver": "^7.3.5", + "validate-npm-package-license": "^3.0.4" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/@semantic-release/release-notes-generator/node_modules/parse-json": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-8.1.0.tgz", + "integrity": "sha512-rum1bPifK5SSar35Z6EKZuYPJx85pkNaFrxBK3mwdfSJ1/WKbYrjoW/zTPSjRRamfmVX1ACBIdFAO0VRErW/EA==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.22.13", + "index-to-position": "^0.1.2", + "type-fest": "^4.7.1" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@semantic-release/release-notes-generator/node_modules/read-pkg": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-9.0.1.tgz", + "integrity": "sha512-9viLL4/n1BJUCT1NXVTdS1jtm80yDEgR5T4yCelII49Mbj0v1rZdKqj7zCiYdbB0CuCgdrvHcNogAKTFPBocFA==", + "dev": true, + "dependencies": { + "@types/normalize-package-data": "^2.4.3", + "normalize-package-data": "^6.0.0", + "parse-json": "^8.0.0", + "type-fest": "^4.6.0", + "unicorn-magic": "^0.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@semantic-release/release-notes-generator/node_modules/read-pkg-up": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-11.0.0.tgz", + "integrity": "sha512-LOVbvF1Q0SZdjClSefZ0Nz5z8u+tIE7mV5NibzmE9VYmDe9CaBbAVtz1veOSZbofrdsilxuDAYnFenukZVp8/Q==", + "deprecated": "Renamed to read-package-up", + "dev": true, + "dependencies": { + "find-up-simple": "^1.0.0", + "read-pkg": "^9.0.0", + "type-fest": "^4.6.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@semantic-release/release-notes-generator/node_modules/semver": { + "version": "7.6.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", + "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@semantic-release/release-notes-generator/node_modules/type-fest": { + "version": "4.18.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.18.2.tgz", + "integrity": "sha512-+suCYpfJLAe4OXS6+PPXjW3urOS4IoP9waSiLuXfLgqZODKw/aWwASvzqE886wA0kQgGy0mIWyhd87VpqIy6Xg==", + "dev": true, + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@sindresorhus/is": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.6.0.tgz", + "integrity": "sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/is?sponsor=1" + } + }, + "node_modules/@sindresorhus/merge-streams": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/merge-streams/-/merge-streams-4.0.0.tgz", + "integrity": "sha512-tlqY9xq5ukxTUZBmoOp+m61cqwQD5pHJtFY3Mn8CA8ps6yghLH/Hw8UPdqg4OLmFW3IFlcXnQNmo/dh8HzXYIQ==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@types/json5": { + "version": "0.0.29", + "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", + "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", + "dev": true + }, + "node_modules/@types/minimist": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.2.tgz", + "integrity": "sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ==", + "dev": true + }, + "node_modules/@types/normalize-package-data": { + "version": "2.4.4", + "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.4.tgz", + "integrity": "sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==", + "dev": true + }, + "node_modules/acorn": { + "version": "8.10.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz", + "integrity": "sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/agent-base": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz", + "integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==", + "dev": true, + "dependencies": { + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/aggregate-error": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-5.0.0.tgz", + "integrity": "sha512-gOsf2YwSlleG6IjRYG2A7k0HmBMEo6qVNk9Bp/EaLgAJT5ngH6PXbqa4ItvnEwCm/velL5jAnQgsHsWnjhGmvw==", + "dev": true, + "dependencies": { + "clean-stack": "^5.2.0", + "indent-string": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ansi-escapes": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-6.2.1.tgz", + "integrity": "sha512-4nJ3yixlEthEJ9Rk4vPcdBRkZvQZlYyu8j4/Mqz5sgIkddmEnH2Yj2ZrnP9S3tQOvSNRUIgVNF/1yPpRAGNRig==", + "dev": true, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/any-promise": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", + "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==", + "dev": true + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "node_modules/argv-formatter": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/argv-formatter/-/argv-formatter-1.0.0.tgz", + "integrity": "sha512-F2+Hkm9xFaRg+GkaNnbwXNDV5O6pnCFEmqyhvfC/Ic5LbgOWjJh3L+mN/s91rxVL3znE7DYVpW0GJFT+4YBgWw==", + "dev": true + }, + "node_modules/array-buffer-byte-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.1.tgz", + "integrity": "sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.5", + "is-array-buffer": "^3.0.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array-ify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-ify/-/array-ify-1.0.0.tgz", + "integrity": "sha512-c5AMf34bKdvPhQ7tBGhqkgKNUzMr4WUs+WDtC2ZUGOUncbxKMTvqxYctiseW3+L4bA8ec+GcZ6/A/FW4m8ukng==", + "dev": true + }, + "node_modules/array-includes": { + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.6.tgz", + "integrity": "sha512-sgTbLvL6cNnw24FnbaDyjmvddQ2ML8arZsgaJhoABMoplz/4QRhtrYS+alr1BUM1Bwp6dhx8vVCBSLG+StwOFw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4", + "get-intrinsic": "^1.1.3", + "is-string": "^1.0.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/array.prototype.findlastindex": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.2.tgz", + "integrity": "sha512-tb5thFFlUcp7NdNF6/MpDk/1r/4awWG1FIz3YqDf+/zJSTezBb+/5WViH41obXULHVpDzoiCLpJ/ZO9YbJMsdw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4", + "es-shim-unscopables": "^1.0.0", + "get-intrinsic": "^1.1.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.flat": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.1.tgz", + "integrity": "sha512-roTU0KWIOmJ4DRLmwKd19Otg0/mT3qPNt0Qb3GWW8iObuZXxrjB/pzn0R3hqpRSWg4HCwqx+0vwOnWnvlOyeIA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4", + "es-shim-unscopables": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.flatmap": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.1.tgz", + "integrity": "sha512-8UGn9O1FDVvMNB0UlLv4voxRMze7+FpHyF5mSMRjWHUMlpoDViniy05870VlxhfgTnLbpuwTzvD76MTtWxB/mQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4", + "es-shim-unscopables": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/arraybuffer.prototype.slice": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.3.tgz", + "integrity": "sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A==", + "dev": true, + "dependencies": { + "array-buffer-byte-length": "^1.0.1", + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", + "es-abstract": "^1.22.3", + "es-errors": "^1.2.1", + "get-intrinsic": "^1.2.3", + "is-array-buffer": "^3.0.4", + "is-shared-array-buffer": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/arrify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", + "integrity": "sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/astral-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", + "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/async": { + "version": "2.6.4", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz", + "integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==", + "dev": true, + "dependencies": { + "lodash": "^4.17.14" + } + }, + "node_modules/available-typed-arrays": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", + "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", + "dev": true, + "dependencies": { + "possible-typed-array-names": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true + }, + "node_modules/basic-auth": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.1.tgz", + "integrity": "sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==", + "dev": true, + "dependencies": { + "safe-buffer": "5.1.2" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/before-after-hook": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-3.0.2.tgz", + "integrity": "sha512-Nik3Sc0ncrMK4UUdXQmAnRtzmNQTAAXmXIopizwZ1W1t8QmfJj+zL4OA2I7XPTPW5z5TDqv4hRo/JzouDJnX3A==", + "dev": true + }, + "node_modules/bottleneck": { + "version": "2.19.5", + "resolved": "https://registry.npmjs.org/bottleneck/-/bottleneck-2.19.5.tgz", + "integrity": "sha512-VHiNCbI1lKdl44tGrhNfU3lup0Tj/ZBMJB5/2ZbNXRCPuRCO7ed2mgcK4r17y+KB2EfuYuRaVlwNbAeaWGSpbw==", + "dev": true + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "dependencies": { + "fill-range": "^7.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browserslist": { + "version": "4.22.1", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.22.1.tgz", + "integrity": "sha512-FEVc202+2iuClEhZhrWy6ZiAcRLvNMyYcxZ8raemul1DYVOVdFsbqckWLdsixQZCpJlwe77Z3UTalE7jsjnKfQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "peer": true, + "dependencies": { + "caniuse-lite": "^1.0.30001541", + "electron-to-chromium": "^1.4.535", + "node-releases": "^2.0.13", + "update-browserslist-db": "^1.0.13" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/call-bind": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", + "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", + "dev": true, + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/camelcase-keys": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-7.0.2.tgz", + "integrity": "sha512-Rjs1H+A9R+Ig+4E/9oyB66UC5Mj9Xq3N//vcLf2WzgdTi/3gUu3Z9KoqmlrEG4VuuLK8wJHofxzdQXz/knhiYg==", + "dev": true, + "dependencies": { + "camelcase": "^6.3.0", + "map-obj": "^4.1.0", + "quick-lru": "^5.1.1", + "type-fest": "^1.2.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/camelcase-keys/node_modules/type-fest": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-1.4.0.tgz", + "integrity": "sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001543", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001543.tgz", + "integrity": "sha512-qxdO8KPWPQ+Zk6bvNpPeQIOH47qZSYdFZd6dXQzb2KzhnSXju4Kd7H1PkSJx6NICSMgo/IhRZRhhfPTHYpJUCA==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "peer": true + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/char-regex": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz", + "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/clean-stack": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-5.2.0.tgz", + "integrity": "sha512-TyUIUJgdFnCISzG5zu3291TAsE77ddchd0bepon1VVQrKLGKFED4iXFEDQ24mIPdPBbyE16PK3F8MYE1CmcBEQ==", + "dev": true, + "dependencies": { + "escape-string-regexp": "5.0.0" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/clean-stack/node_modules/escape-string-regexp": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz", + "integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-highlight": { + "version": "2.1.11", + "resolved": "https://registry.npmjs.org/cli-highlight/-/cli-highlight-2.1.11.tgz", + "integrity": "sha512-9KDcoEVwyUXrjcJNvHD0NFc/hiwe/WPVYIleQh2O1N2Zro5gWJZ/K+3DGn8w8P/F6FxOgzyC5bxDyHIgCSPhGg==", + "dev": true, + "dependencies": { + "chalk": "^4.0.0", + "highlight.js": "^10.7.1", + "mz": "^2.4.0", + "parse5": "^5.1.1", + "parse5-htmlparser2-tree-adapter": "^6.0.0", + "yargs": "^16.0.0" + }, + "bin": { + "highlight": "bin/highlight" + }, + "engines": { + "node": ">=8.0.0", + "npm": ">=5.0.0" + } + }, + "node_modules/cli-highlight/node_modules/cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "dev": true, + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "node_modules/cli-highlight/node_modules/yargs": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "dev": true, + "dependencies": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/cli-table3": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.6.5.tgz", + "integrity": "sha512-+W/5efTR7y5HRD7gACw9yQjqMVvEMLBHmboM/kPWam+H+Hmyrgjh6YncVKK122YZkXrLudzTuAukUw9FnMf7IQ==", + "dev": true, + "dependencies": { + "string-width": "^4.2.0" + }, + "engines": { + "node": "10.* || >= 12.*" + }, + "optionalDependencies": { + "@colors/colors": "1.5.0" + } + }, + "node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dev": true, + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/colord": { + "version": "2.9.3", + "resolved": "https://registry.npmjs.org/colord/-/colord-2.9.3.tgz", + "integrity": "sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw==", + "dev": true + }, + "node_modules/compare-func": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/compare-func/-/compare-func-2.0.0.tgz", + "integrity": "sha512-zHig5N+tPWARooBnb0Zx1MFcdfpyJrfTJ3Y5L+IFvUm8rM74hHz66z0gw0x4tijh5CorKkKUCnW82R2vmpeCRA==", + "dev": true, + "dependencies": { + "array-ify": "^1.0.0", + "dot-prop": "^5.1.0" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true + }, + "node_modules/config-chain": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.13.tgz", + "integrity": "sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==", + "dev": true, + "dependencies": { + "ini": "^1.3.4", + "proto-list": "~1.2.1" + } + }, + "node_modules/confusing-browser-globals": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/confusing-browser-globals/-/confusing-browser-globals-1.0.11.tgz", + "integrity": "sha512-JsPKdmh8ZkmnHxDk55FZ1TqVLvEQTvoByJZRN9jzI0UjxK/QgAmsphz7PGtqgPieQZ/CQcHWXCR7ATDNhGe+YA==", + "dev": true + }, + "node_modules/console-grid": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/console-grid/-/console-grid-2.2.2.tgz", + "integrity": "sha512-ohlgXexdDTKLNsZz7DSJuCAwmRc8omSS61txOk39W3NOthgKGr1a1jJpZ5BCQe4PlrwMw01OvPQ1Bl3G7Y/uFg==", + "dev": true + }, + "node_modules/conventional-changelog-angular": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/conventional-changelog-angular/-/conventional-changelog-angular-7.0.0.tgz", + "integrity": "sha512-ROjNchA9LgfNMTTFSIWPzebCwOGFdgkEq45EnvvrmSLvCtAw0HSmrCs7/ty+wAeYUZyNay0YMUNYFTRL72PkBQ==", + "dev": true, + "dependencies": { + "compare-func": "^2.0.0" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/conventional-changelog-writer": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/conventional-changelog-writer/-/conventional-changelog-writer-7.0.1.tgz", + "integrity": "sha512-Uo+R9neH3r/foIvQ0MKcsXkX642hdm9odUp7TqgFS7BsalTcjzRlIfWZrZR1gbxOozKucaKt5KAbjW8J8xRSmA==", + "dev": true, + "dependencies": { + "conventional-commits-filter": "^4.0.0", + "handlebars": "^4.7.7", + "json-stringify-safe": "^5.0.1", + "meow": "^12.0.1", + "semver": "^7.5.2", + "split2": "^4.0.0" + }, + "bin": { + "conventional-changelog-writer": "cli.mjs" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/conventional-changelog-writer/node_modules/meow": { + "version": "12.1.1", + "resolved": "https://registry.npmjs.org/meow/-/meow-12.1.1.tgz", + "integrity": "sha512-BhXM0Au22RwUneMPwSCnyhTOizdWoIEPU9sp0Aqa1PnDMR5Wv2FGXYDjuzJEIX+Eo2Rb8xuYe5jrnm5QowQFkw==", + "dev": true, + "engines": { + "node": ">=16.10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/conventional-changelog-writer/node_modules/semver": { + "version": "7.6.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", + "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/conventional-commits-filter": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/conventional-commits-filter/-/conventional-commits-filter-4.0.0.tgz", + "integrity": "sha512-rnpnibcSOdFcdclpFwWa+pPlZJhXE7l+XK04zxhbWrhgpR96h33QLz8hITTXbcYICxVr3HZFtbtUAQ+4LdBo9A==", + "dev": true, + "engines": { + "node": ">=16" + } + }, + "node_modules/conventional-commits-parser": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/conventional-commits-parser/-/conventional-commits-parser-5.0.0.tgz", + "integrity": "sha512-ZPMl0ZJbw74iS9LuX9YIAiW8pfM5p3yh2o/NbXHbkFuZzY5jvdi5jFycEOkmBW5H5I7nA+D6f3UcsCLP2vvSEA==", + "dev": true, + "dependencies": { + "is-text-path": "^2.0.0", + "JSONStream": "^1.3.5", + "meow": "^12.0.1", + "split2": "^4.0.0" + }, + "bin": { + "conventional-commits-parser": "cli.mjs" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/conventional-commits-parser/node_modules/meow": { + "version": "12.1.1", + "resolved": "https://registry.npmjs.org/meow/-/meow-12.1.1.tgz", + "integrity": "sha512-BhXM0Au22RwUneMPwSCnyhTOizdWoIEPU9sp0Aqa1PnDMR5Wv2FGXYDjuzJEIX+Eo2Rb8xuYe5jrnm5QowQFkw==", + "dev": true, + "engines": { + "node": ">=16.10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/convert-hrtime": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/convert-hrtime/-/convert-hrtime-5.0.0.tgz", + "integrity": "sha512-lOETlkIeYSJWcbbcvjRKGxVMXJR+8+OQb/mTPbA4ObPMytYIsUbuOE0Jzy60hjARYszq1id0j8KgVhC+WGZVTg==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true, + "peer": true + }, + "node_modules/core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", + "dev": true + }, + "node_modules/corser": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/corser/-/corser-2.0.1.tgz", + "integrity": "sha512-utCYNzRSQIZNPIcGZdQc92UVJYAhtGAteCFg0yRaFm8f0P+CPtyGyHXJcGXnffjCybUCEx3FQ2G7U3/o9eIkVQ==", + "dev": true, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/cosmiconfig": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.2.0.tgz", + "integrity": "sha512-3rTMnFJA1tCOPwRxtgF4wd7Ab2qvDbL8jX+3smjIbS4HlZBagTlpERbdN7iAbWlrfxE3M8c27kTwTawQ7st+OQ==", + "dev": true, + "dependencies": { + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "parse-json": "^5.0.0", + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/d-fischer" + } + }, + "node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/crypto-random-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-4.0.0.tgz", + "integrity": "sha512-x8dy3RnvYdlUcPOjkEHqozhiwzKNSq7GcPuXFbnyMOCHxX8V3OgIg/pYuabl2sbUPfIJaeAQB7PMOK8DFIdoRA==", + "dev": true, + "dependencies": { + "type-fest": "^1.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/crypto-random-string/node_modules/type-fest": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-1.4.0.tgz", + "integrity": "sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/css-functions-list": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/css-functions-list/-/css-functions-list-3.2.0.tgz", + "integrity": "sha512-d/jBMPyYybkkLVypgtGv12R+pIFw4/f/IHtCTxWpZc8ofTYOPigIgmA6vu5rMHartZC+WuXhBUHfnyNUIQSYrg==", + "dev": true, + "engines": { + "node": ">=12.22" + } + }, + "node_modules/css-tree": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.3.1.tgz", + "integrity": "sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw==", + "dev": true, + "dependencies": { + "mdn-data": "2.0.30", + "source-map-js": "^1.0.1" + }, + "engines": { + "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0" + } + }, + "node_modules/cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", + "dev": true, + "bin": { + "cssesc": "bin/cssesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/data-view-buffer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.1.tgz", + "integrity": "sha512-0lht7OugA5x3iJLOWFhWK/5ehONdprk0ISXqVFn/NFrDu+cuc8iADFrGQz5BnRK7LLU3JmkbXSxaqX+/mXYtUA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/data-view-byte-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.1.tgz", + "integrity": "sha512-4J7wRJD3ABAzr8wP+OcIcqq2dlUKp4DVflx++hs5h5ZKydWMI6/D/fAot+yh6g2tHh8fLFTvNOaVN357NvSrOQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/data-view-byte-offset": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.0.tgz", + "integrity": "sha512-t/Ygsytq+R995EJ5PZlD4Cu56sWa8InXySaViRzw9apusqsOO2bQP+SbYzAhR0pFKoB+43lYy8rWban9JSuXnA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decamelize": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-5.0.1.tgz", + "integrity": "sha512-VfxadyCECXgQlkoEAjeghAr5gY3Hf+IKjKb+X8tGVDtveCjN+USwprd2q3QXBR9T1+x2DG0XZF5/w+7HAtSaXA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/decamelize-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/decamelize-keys/-/decamelize-keys-1.1.1.tgz", + "integrity": "sha512-WiPxgEirIV0/eIOMcnFBA3/IJZAZqKnwAwWyvvdi4lsr1WCN22nhdf/3db3DoZcUjTV2SqfzIwNyp6y2xs3nmg==", + "dev": true, + "dependencies": { + "decamelize": "^1.1.0", + "map-obj": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/decamelize-keys/node_modules/decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/decamelize-keys/node_modules/map-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", + "integrity": "sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "dev": true, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true + }, + "node_modules/define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "dev": true, + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/define-properties": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", + "dev": true, + "dependencies": { + "define-data-property": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "dependencies": { + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/dot-prop": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz", + "integrity": "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==", + "dev": true, + "dependencies": { + "is-obj": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/duplexer2": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", + "integrity": "sha512-asLFVfWWtJ90ZyOUHMqk7/S2w2guQKxUI2itj3d92ADHhxUSbCMGi1f1cBcJ7xM1To+pE/Khbwo1yuNbMEPKeA==", + "dev": true, + "dependencies": { + "readable-stream": "^2.0.2" + } + }, + "node_modules/eight-colors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/eight-colors/-/eight-colors-1.3.0.tgz", + "integrity": "sha512-hVoK898cR71ADj7L1LZWaECLaSkzzPtqGXIaKv4K6Pzb72QgjLVsQaNI+ELDQQshzFvgp5xTPkaYkPGqw3YR+g==", + "dev": true + }, + "node_modules/electron-to-chromium": { + "version": "1.4.539", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.539.tgz", + "integrity": "sha512-wRmWJ8F7rgmINuI32S6r2SLrw/h/bJQsDSvBiq9GBfvc2Lh73qTOwn73r3Cf67mjVgFGJYcYtmERzySa5jIWlg==", + "dev": true, + "peer": true + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/emojilib": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/emojilib/-/emojilib-2.4.0.tgz", + "integrity": "sha512-5U0rVMU5Y2n2+ykNLQqMoqklN9ICBT/KsvC1Gz6vqHbz2AXXGkG+Pm5rMWk/8Vjrr/mY9985Hi8DYzn1F09Nyw==", + "dev": true + }, + "node_modules/env-ci": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/env-ci/-/env-ci-11.0.0.tgz", + "integrity": "sha512-apikxMgkipkgTvMdRT9MNqWx5VLOci79F4VBd7Op/7OPjjoanjdAvn6fglMCCEf/1bAh8eOiuEVCUs4V3qP3nQ==", + "dev": true, + "dependencies": { + "execa": "^8.0.0", + "java-properties": "^1.0.2" + }, + "engines": { + "node": "^18.17 || >=20.6.1" + } + }, + "node_modules/env-ci/node_modules/execa": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-8.0.1.tgz", + "integrity": "sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^8.0.1", + "human-signals": "^5.0.0", + "is-stream": "^3.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^5.1.0", + "onetime": "^6.0.0", + "signal-exit": "^4.1.0", + "strip-final-newline": "^3.0.0" + }, + "engines": { + "node": ">=16.17" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/env-ci/node_modules/get-stream": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-8.0.1.tgz", + "integrity": "sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==", + "dev": true, + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/env-ci/node_modules/human-signals": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-5.0.0.tgz", + "integrity": "sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==", + "dev": true, + "engines": { + "node": ">=16.17.0" + } + }, + "node_modules/env-ci/node_modules/is-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", + "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", + "dev": true, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/env-ci/node_modules/strip-final-newline": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", + "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/env-paths": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", + "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/es-abstract": { + "version": "1.23.3", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.3.tgz", + "integrity": "sha512-e+HfNH61Bj1X9/jLc5v1owaLYuHdeHHSQlkhCBiTK8rBvKaULl/beGMxwrMXjpYrv4pz22BlY570vVePA2ho4A==", + "dev": true, + "dependencies": { + "array-buffer-byte-length": "^1.0.1", + "arraybuffer.prototype.slice": "^1.0.3", + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", + "data-view-buffer": "^1.0.1", + "data-view-byte-length": "^1.0.1", + "data-view-byte-offset": "^1.0.0", + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "es-set-tostringtag": "^2.0.3", + "es-to-primitive": "^1.2.1", + "function.prototype.name": "^1.1.6", + "get-intrinsic": "^1.2.4", + "get-symbol-description": "^1.0.2", + "globalthis": "^1.0.3", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.0.3", + "has-symbols": "^1.0.3", + "hasown": "^2.0.2", + "internal-slot": "^1.0.7", + "is-array-buffer": "^3.0.4", + "is-callable": "^1.2.7", + "is-data-view": "^1.0.1", + "is-negative-zero": "^2.0.3", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.3", + "is-string": "^1.0.7", + "is-typed-array": "^1.1.13", + "is-weakref": "^1.0.2", + "object-inspect": "^1.13.1", + "object-keys": "^1.1.1", + "object.assign": "^4.1.5", + "regexp.prototype.flags": "^1.5.2", + "safe-array-concat": "^1.1.2", + "safe-regex-test": "^1.0.3", + "string.prototype.trim": "^1.2.9", + "string.prototype.trimend": "^1.0.8", + "string.prototype.trimstart": "^1.0.8", + "typed-array-buffer": "^1.0.2", + "typed-array-byte-length": "^1.0.1", + "typed-array-byte-offset": "^1.0.2", + "typed-array-length": "^1.0.6", + "unbox-primitive": "^1.0.2", + "which-typed-array": "^1.1.15" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", + "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.2.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.0.0.tgz", + "integrity": "sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==", + "dev": true, + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.3.tgz", + "integrity": "sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.2.4", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.1" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-shim-unscopables": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.0.tgz", + "integrity": "sha512-Jm6GPcCdC30eMLbZ2x8z2WuRwAws3zTBBKuusffYVUrNj/GVSUAZ+xKMaUpfNDR5IbyNA5LJbaecoUVbmUcB1w==", + "dev": true, + "dependencies": { + "has": "^1.0.3" + } + }, + "node_modules/es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "dev": true, + "dependencies": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint": { + "version": "8.48.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.48.0.tgz", + "integrity": "sha512-sb6DLeIuRXxeM1YljSe1KEx9/YYeZFQWcV8Rq9HfigmdDEugjLEVEa1ozDjL6YDjBpQHPJxJzze+alxi4T3OLg==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.6.1", + "@eslint/eslintrc": "^2.1.2", + "@eslint/js": "8.48.0", + "@humanwhocodes/config-array": "^0.11.10", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.2.2", + "eslint-visitor-keys": "^3.4.3", + "espree": "^9.6.1", + "esquery": "^1.4.2", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "globals": "^13.19.0", + "graphemer": "^1.4.0", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", + "js-yaml": "^4.1.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3", + "strip-ansi": "^6.0.1", + "text-table": "^0.2.0" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-config-airbnb-base": { + "version": "15.0.0", + "resolved": "https://registry.npmjs.org/eslint-config-airbnb-base/-/eslint-config-airbnb-base-15.0.0.tgz", + "integrity": "sha512-xaX3z4ZZIcFLvh2oUNvcX5oEofXda7giYmuplVxoOg5A7EXJMrUyqRgR+mhDhPK8LZ4PttFOBvCYDbX3sUoUig==", + "dev": true, + "dependencies": { + "confusing-browser-globals": "^1.0.10", + "object.assign": "^4.1.2", + "object.entries": "^1.1.5", + "semver": "^6.3.0" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + }, + "peerDependencies": { + "eslint": "^7.32.0 || ^8.2.0", + "eslint-plugin-import": "^2.25.2" + } + }, + "node_modules/eslint-import-resolver-node": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz", + "integrity": "sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==", + "dev": true, + "dependencies": { + "debug": "^3.2.7", + "is-core-module": "^2.13.0", + "resolve": "^1.22.4" + } + }, + "node_modules/eslint-import-resolver-node/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-module-utils": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.8.0.tgz", + "integrity": "sha512-aWajIYfsqCKRDgUfjEXNN/JlrzauMuSEy5sbd7WXbtW3EH6A6MpwEh42c7qD+MqQo9QMJ6fWLAeIJynx0g6OAw==", + "dev": true, + "dependencies": { + "debug": "^3.2.7" + }, + "engines": { + "node": ">=4" + }, + "peerDependenciesMeta": { + "eslint": { + "optional": true + } + } + }, + "node_modules/eslint-module-utils/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-plugin-import": { + "version": "2.28.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.28.1.tgz", + "integrity": "sha512-9I9hFlITvOV55alzoKBI+K9q74kv0iKMeY6av5+umsNwayt59fz692daGyjR+oStBQgx6nwR9rXldDev3Clw+A==", + "dev": true, + "dependencies": { + "array-includes": "^3.1.6", + "array.prototype.findlastindex": "^1.2.2", + "array.prototype.flat": "^1.3.1", + "array.prototype.flatmap": "^1.3.1", + "debug": "^3.2.7", + "doctrine": "^2.1.0", + "eslint-import-resolver-node": "^0.3.7", + "eslint-module-utils": "^2.8.0", + "has": "^1.0.3", + "is-core-module": "^2.13.0", + "is-glob": "^4.0.3", + "minimatch": "^3.1.2", + "object.fromentries": "^2.0.6", + "object.groupby": "^1.0.0", + "object.values": "^1.1.6", + "semver": "^6.3.1", + "tsconfig-paths": "^3.14.2" + }, + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8" + } + }, + "node_modules/eslint-plugin-import/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-plugin-import/node_modules/doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dev": true, + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/eslint-scope": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", + "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/espree": { + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", + "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", + "dev": true, + "dependencies": { + "acorn": "^8.9.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esquery": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", + "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", + "dev": true, + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/eventemitter3": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", + "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", + "dev": true + }, + "node_modules/execa": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-9.1.0.tgz", + "integrity": "sha512-lSgHc4Elo2m6bUDhc3Hl/VxvUDJdQWI40RZ4KMY9bKRc+hgMOT7II/JjbNDhI8VnMtrCb7U/fhpJIkLORZozWw==", + "dev": true, + "dependencies": { + "@sindresorhus/merge-streams": "^4.0.0", + "cross-spawn": "^7.0.3", + "figures": "^6.1.0", + "get-stream": "^9.0.0", + "human-signals": "^7.0.0", + "is-plain-obj": "^4.1.0", + "is-stream": "^4.0.1", + "npm-run-path": "^5.2.0", + "pretty-ms": "^9.0.0", + "signal-exit": "^4.1.0", + "strip-final-newline": "^4.0.0", + "yoctocolors": "^2.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/execa/node_modules/get-stream": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-9.0.1.tgz", + "integrity": "sha512-kVCxPF3vQM/N0B1PmoqVUqgHP+EeVjmZSQn+1oCRPxd2P21P2F19lIgbR3HBosbB1PUhOAoctJnfEn2GbN2eZA==", + "dev": true, + "dependencies": { + "@sec-ant/readable-stream": "^0.4.1", + "is-stream": "^4.0.1" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/execa/node_modules/is-plain-obj": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-4.1.0.tgz", + "integrity": "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, + "node_modules/fast-glob": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", + "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-glob/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true + }, + "node_modules/fastest-levenshtein": { + "version": "1.0.16", + "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz", + "integrity": "sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==", + "dev": true, + "engines": { + "node": ">= 4.9.1" + } + }, + "node_modules/fastq": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", + "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==", + "dev": true, + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/figures": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-6.1.0.tgz", + "integrity": "sha512-d+l3qxjSesT4V7v2fh+QnmFnUWv9lSpjarhShNTgBOfA0ttejbQUAlHLitbjkoRiDulW0OPoQPYIGhIC8ohejg==", + "dev": true, + "dependencies": { + "is-unicode-supported": "^2.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dev": true, + "dependencies": { + "flat-cache": "^3.0.4" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/find-up-simple": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/find-up-simple/-/find-up-simple-1.0.0.tgz", + "integrity": "sha512-q7Us7kcjj2VMePAa02hDAF6d+MzsdsAWEwYyOpwUtlerRBkOEPBCRZrAV4XfcSN8fHAgaD0hP7miwoay6DCprw==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/find-versions": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/find-versions/-/find-versions-6.0.0.tgz", + "integrity": "sha512-2kCCtc+JvcZ86IGAz3Z2Y0A1baIz9fL31pH/0S1IqZr9Iwnjq8izfPtrCyQKO6TLMPELLsQMre7VDqeIKCsHkA==", + "dev": true, + "dependencies": { + "semver-regex": "^4.0.5", + "super-regex": "^1.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/flat-cache": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.1.0.tgz", + "integrity": "sha512-OHx4Qwrrt0E4jEIcI5/Xb+f+QmJYNj2rrK8wiIdQOIrB9WrrJL8cjZvXdXuBTkkEwEqLycb5BeZDV1o2i9bTew==", + "dev": true, + "dependencies": { + "flatted": "^3.2.7", + "keyv": "^4.5.3", + "rimraf": "^3.0.2" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/flatted": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz", + "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==", + "dev": true + }, + "node_modules/follow-redirects": { + "version": "1.15.6", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", + "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/for-each": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", + "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "dev": true, + "dependencies": { + "is-callable": "^1.1.3" + } + }, + "node_modules/from2": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz", + "integrity": "sha512-OMcX/4IC/uqEPVgGeyfN22LJk6AZrMkRZHxcHBMBvHScDGgwTm2GT2Wkgtocyd3JfZffjj2kYUDXXII0Fk9W0g==", + "dev": true, + "dependencies": { + "inherits": "^2.0.1", + "readable-stream": "^2.0.0" + } + }, + "node_modules/fs-extra": { + "version": "11.2.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", + "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=14.14" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true + }, + "node_modules/fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/function-timeout": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/function-timeout/-/function-timeout-1.0.2.tgz", + "integrity": "sha512-939eZS4gJ3htTHAldmyyuzlrD58P03fHG49v2JfFXbV6OhvZKRC9j2yAtdHw/zrp2zXHuv05zMIy40F0ge7spA==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/function.prototype.name": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.6.tgz", + "integrity": "sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "functions-have-names": "^1.2.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/functions-have-names": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", + "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true, + "peer": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true, + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-intrinsic": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", + "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", + "dev": true, + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "hasown": "^2.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/get-symbol-description": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.2.tgz", + "integrity": "sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.5", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/git-log-parser": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/git-log-parser/-/git-log-parser-1.2.0.tgz", + "integrity": "sha512-rnCVNfkTL8tdNryFuaY0fYiBWEBcgF748O6ZI61rslBvr2o7U65c2/6npCRqH40vuAhtgtDiqLTJjBVdrejCzA==", + "dev": true, + "dependencies": { + "argv-formatter": "~1.0.0", + "spawn-error-forwarder": "~1.0.0", + "split2": "~1.0.0", + "stream-combiner2": "~1.1.1", + "through2": "~2.0.0", + "traverse": "~0.6.6" + } + }, + "node_modules/git-log-parser/node_modules/split2": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/split2/-/split2-1.0.0.tgz", + "integrity": "sha512-NKywug4u4pX/AZBB1FCPzZ6/7O+Xhz1qMVbzTvvKvikjO99oPN87SkK08mEY9P63/5lWjK+wgOOgApnTg5r6qg==", + "dev": true, + "dependencies": { + "through2": "~2.0.0" + } + }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/global-modules": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-2.0.0.tgz", + "integrity": "sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A==", + "dev": true, + "dependencies": { + "global-prefix": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/global-prefix": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-3.0.0.tgz", + "integrity": "sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg==", + "dev": true, + "dependencies": { + "ini": "^1.3.5", + "kind-of": "^6.0.2", + "which": "^1.3.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/global-prefix/node_modules/which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "which": "bin/which" + } + }, + "node_modules/globals": { + "version": "13.21.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.21.0.tgz", + "integrity": "sha512-ybyme3s4yy/t/3s35bewwXKOf7cvzfreG2lH0lZl0JB7I4GxRP2ghxOK/Nb9EkRXdbBXZLfq/p/0W2JUONB/Gg==", + "dev": true, + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/globalthis": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz", + "integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==", + "dev": true, + "dependencies": { + "define-properties": "^1.1.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "dev": true, + "dependencies": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/globjoin": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/globjoin/-/globjoin-0.1.4.tgz", + "integrity": "sha512-xYfnw62CKG8nLkZBfWbhWwDw02CHty86jfPcc2cr3ZfeuK9ysoVPPEUxf21bAD/rWAgk52SuBrLJlefNy8mvFg==", + "dev": true + }, + "node_modules/gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.1.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true + }, + "node_modules/graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "dev": true + }, + "node_modules/handlebars": { + "version": "4.7.8", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.8.tgz", + "integrity": "sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==", + "dev": true, + "dependencies": { + "minimist": "^1.2.5", + "neo-async": "^2.6.2", + "source-map": "^0.6.1", + "wordwrap": "^1.0.0" + }, + "bin": { + "handlebars": "bin/handlebars" + }, + "engines": { + "node": ">=0.4.7" + }, + "optionalDependencies": { + "uglify-js": "^3.1.4" + } + }, + "node_modules/hard-rejection": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/hard-rejection/-/hard-rejection-2.1.0.tgz", + "integrity": "sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/has-bigints": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", + "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "dev": true, + "dependencies": { + "es-define-property": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-proto": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", + "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "dev": true, + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "dev": true, + "bin": { + "he": "bin/he" + } + }, + "node_modules/highlight.js": { + "version": "10.7.3", + "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-10.7.3.tgz", + "integrity": "sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/hook-std": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/hook-std/-/hook-std-3.0.0.tgz", + "integrity": "sha512-jHRQzjSDzMtFy34AGj1DN+vq54WVuhSvKgrHf0OMiFQTwDD4L/qqofVEWjLOBMTn5+lCD3fPg32W9yOfnEJTTw==", + "dev": true, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/hosted-git-info": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz", + "integrity": "sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/html-encoding-sniffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-3.0.0.tgz", + "integrity": "sha512-oWv4T4yJ52iKrufjnyZPkrN0CH3QnrUqdB6In1g5Fe1mia8GmF36gnfNySxoZtxD5+NmYw1EElVXiBk93UeskA==", + "dev": true, + "dependencies": { + "whatwg-encoding": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/html-escaper": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", + "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", + "dev": true + }, + "node_modules/html-tags": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/html-tags/-/html-tags-3.3.1.tgz", + "integrity": "sha512-ztqyC3kLto0e9WbNp0aeP+M3kTt+nbaIveGmUxAtZa+8iFgKLUOD4YKM5j+f3QD89bra7UeumolZHKuOXnTmeQ==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/http-proxy": { + "version": "1.18.1", + "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz", + "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==", + "dev": true, + "dependencies": { + "eventemitter3": "^4.0.0", + "follow-redirects": "^1.0.0", + "requires-port": "^1.0.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/http-proxy-agent": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", + "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", + "dev": true, + "dependencies": { + "agent-base": "^7.1.0", + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/http-server": { + "version": "14.1.1", + "resolved": "https://registry.npmjs.org/http-server/-/http-server-14.1.1.tgz", + "integrity": "sha512-+cbxadF40UXd9T01zUHgA+rlo2Bg1Srer4+B4NwIHdaGxAGGv59nYRnGGDJ9LBk7alpS0US+J+bLLdQOOkJq4A==", + "dev": true, + "dependencies": { + "basic-auth": "^2.0.1", + "chalk": "^4.1.2", + "corser": "^2.0.1", + "he": "^1.2.0", + "html-encoding-sniffer": "^3.0.0", + "http-proxy": "^1.18.1", + "mime": "^1.6.0", + "minimist": "^1.2.6", + "opener": "^1.5.1", + "portfinder": "^1.0.28", + "secure-compare": "3.0.1", + "union": "~0.5.0", + "url-join": "^4.0.1" + }, + "bin": { + "http-server": "bin/http-server" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/http-server/node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "dev": true, + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/http-server/node_modules/url-join": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/url-join/-/url-join-4.0.1.tgz", + "integrity": "sha512-jk1+QP6ZJqyOiuEI9AEWQfju/nB2Pw466kbA0LEZljHwKeMgd9WrAEgEGxjPDD2+TNbbb37rTyhEfrCXfuKXnA==", + "dev": true + }, + "node_modules/https-proxy-agent": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.4.tgz", + "integrity": "sha512-wlwpilI7YdjSkWaQ/7omYBMTliDcmCN8OLihO6I9B86g06lMyAoqgoDpV0XqoaPOKj+0DIdAvnsWfyAAhmimcg==", + "dev": true, + "dependencies": { + "agent-base": "^7.0.2", + "debug": "4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/human-signals": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-7.0.0.tgz", + "integrity": "sha512-74kytxOUSvNbjrT9KisAbaTZ/eJwD/LrbM/kh5j0IhPuJzwuA19dWvniFGwBzN9rVjg+O/e+F310PjObDXS+9Q==", + "dev": true, + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "dev": true, + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ignore": { + "version": "5.2.4", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", + "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/import-from-esm": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/import-from-esm/-/import-from-esm-1.3.4.tgz", + "integrity": "sha512-7EyUlPFC0HOlBDpUFGfYstsU7XHxZJKAAMzCT8wZ0hMW7b+hG51LIKTDcsgtz8Pu6YC0HqRVbX+rVUtsGMUKvg==", + "dev": true, + "dependencies": { + "debug": "^4.3.4", + "import-meta-resolve": "^4.0.0" + }, + "engines": { + "node": ">=16.20" + } + }, + "node_modules/import-lazy": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-4.0.0.tgz", + "integrity": "sha512-rKtvo6a868b5Hu3heneU+L4yEQ4jYKLtjpnPeUdK7h0yzXGmyBTypknlkCvHFBqfX9YlorEiMM6Dnq/5atfHkw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/import-meta-resolve": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/import-meta-resolve/-/import-meta-resolve-4.1.0.tgz", + "integrity": "sha512-I6fiaX09Xivtk+THaMfAwnA3MVA5Big1WHF1Dfx9hFuvNIWpXnorlkzhcQf6ehrqQiiZECRt1poOAkPmer3ruw==", + "dev": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/indent-string": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-5.0.0.tgz", + "integrity": "sha512-m6FAo/spmsW2Ab2fU35JTYwtOKa2yAwXSwgjSv1TJzh4Mh7mC3lzAOVLBprb72XsTrgkEIsl7YrFNAiDiRhIGg==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/index-to-position": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/index-to-position/-/index-to-position-0.1.2.tgz", + "integrity": "sha512-MWDKS3AS1bGCHLBA2VLImJz42f7bJh8wQsTGCzI3j519/CASStoDONUBVz2I/VID0MpiX3SGSnbOD2xUalbE5g==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "dev": true, + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "dev": true + }, + "node_modules/internal-slot": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.7.tgz", + "integrity": "sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==", + "dev": true, + "dependencies": { + "es-errors": "^1.3.0", + "hasown": "^2.0.0", + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/into-stream": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/into-stream/-/into-stream-7.0.0.tgz", + "integrity": "sha512-2dYz766i9HprMBasCMvHMuazJ7u4WzhJwo5kb3iPSiW/iRYV6uPari3zHoqZlnuaR7V1bEiNMxikhp37rdBXbw==", + "dev": true, + "dependencies": { + "from2": "^2.3.0", + "p-is-promise": "^3.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-array-buffer": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.4.tgz", + "integrity": "sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "dev": true + }, + "node_modules/is-bigint": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", + "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", + "dev": true, + "dependencies": { + "has-bigints": "^1.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-boolean-object": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", + "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-callable": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-core-module": { + "version": "2.13.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.0.tgz", + "integrity": "sha512-Z7dk6Qo8pOCp3l4tsX2C5ZVas4V+UxwQodwZhLopL91TX8UyyHEXafPcyoeeWuLrwzHcr3igO78wNLwHJHsMCQ==", + "dev": true, + "dependencies": { + "has": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-data-view": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.1.tgz", + "integrity": "sha512-AHkaJrsUVW6wq6JS8y3JnM/GJF/9cf+k20+iDzlSaJrinEo5+7vRiteOSwBhHRiAyQATN1AmY4hwzxJKPmYf+w==", + "dev": true, + "dependencies": { + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-date-object": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", + "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-negative-zero": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", + "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-number-object": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", + "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-obj": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", + "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-plain-obj": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", + "integrity": "sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-plain-object": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", + "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-regex": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", + "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-shared-array-buffer": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.3.tgz", + "integrity": "sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-stream": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-4.0.1.tgz", + "integrity": "sha512-Dnz92NInDqYckGEUJv689RbRiTSEHCQ7wOVeALbkOz999YpqT46yMRIGtSNl2iCL1waAZSx40+h59NV/EwzV/A==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-string": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", + "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-symbol": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", + "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", + "dev": true, + "dependencies": { + "has-symbols": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-text-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-text-path/-/is-text-path-2.0.0.tgz", + "integrity": "sha512-+oDTluR6WEjdXEJMnC2z6A4FRwFoYuvShVVEGsS7ewc0UTi2QtAKMDJuL4BDEVt+5T7MjFo12RP8ghOM75oKJw==", + "dev": true, + "dependencies": { + "text-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-typed-array": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.13.tgz", + "integrity": "sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==", + "dev": true, + "dependencies": { + "which-typed-array": "^1.1.14" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-unicode-supported": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-2.0.0.tgz", + "integrity": "sha512-FRdAyx5lusK1iHG0TWpVtk9+1i+GjrzRffhDg4ovQ7mcidMQ6mj+MhKPmvh7Xwyv5gIS06ns49CA7Sqg7lC22Q==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-weakref": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", + "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true + }, + "node_modules/issue-parser": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/issue-parser/-/issue-parser-7.0.0.tgz", + "integrity": "sha512-jgAw78HO3gs9UrKqJNQvfDj9Ouy8Mhu40fbEJ8yXff4MW8+/Fcn9iFjyWUQ6SKbX8ipPk3X5A3AyfYHRu6uVLw==", + "dev": true, + "dependencies": { + "lodash.capitalize": "^4.2.1", + "lodash.escaperegexp": "^4.1.2", + "lodash.isplainobject": "^4.0.6", + "lodash.isstring": "^4.0.1", + "lodash.uniqby": "^4.7.0" + }, + "engines": { + "node": "^18.17 || >=20.6.1" + } + }, + "node_modules/istanbul-lib-coverage": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", + "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-report": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", + "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", + "dev": true, + "dependencies": { + "istanbul-lib-coverage": "^3.0.0", + "make-dir": "^4.0.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-reports": { + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.7.tgz", + "integrity": "sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g==", + "dev": true, + "dependencies": { + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/java-properties": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/java-properties/-/java-properties-1.0.2.tgz", + "integrity": "sha512-qjdpeo2yKlYTH7nFdK0vbZWuTCesk4o63v5iVOlhMQPfuIZQfW/HI35SjfhA+4qpg36rnFSvUK5b1m+ckIblQQ==", + "dev": true, + "engines": { + "node": ">= 0.6.0" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "dev": true, + "peer": true, + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true + }, + "node_modules/json-parse-better-errors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", + "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", + "dev": true + }, + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "dev": true + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true + }, + "node_modules/json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==", + "dev": true + }, + "node_modules/json5": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", + "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", + "dev": true, + "dependencies": { + "minimist": "^1.2.0" + }, + "bin": { + "json5": "lib/cli.js" + } + }, + "node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dev": true, + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/jsonparse": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", + "integrity": "sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg==", + "dev": true, + "engines": [ + "node >= 0.2.0" + ] + }, + "node_modules/JSONStream": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz", + "integrity": "sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==", + "dev": true, + "dependencies": { + "jsonparse": "^1.2.0", + "through": ">=2.2.7 <3" + }, + "bin": { + "JSONStream": "bin.js" + }, + "engines": { + "node": "*" + } + }, + "node_modules/keyv": { + "version": "4.5.3", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.3.tgz", + "integrity": "sha512-QCiSav9WaX1PgETJ+SpNnx2PRRapJ/oRSXM4VO5OGYGSjrxbKPVFVhB3l2OCbLCk329N8qyAtsJjSjvVBWzEug==", + "dev": true, + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/known-css-properties": { + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/known-css-properties/-/known-css-properties-0.28.0.tgz", + "integrity": "sha512-9pSL5XB4J+ifHP0e0jmmC98OGC1nL8/JjS+fi6mnTlIf//yt/MfVLtKg7S6nCtj/8KTcWX7nRlY0XywoYY1ISQ==", + "dev": true + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "dev": true + }, + "node_modules/load-json-file": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", + "integrity": "sha512-Kx8hMakjX03tiGTLAIdJ+lL0htKnXjEZN6hk/tozf/WOuYGdZBJrZ+rCJRbVCugsjB3jMLn9746NsQIf5VjBMw==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.2", + "parse-json": "^4.0.0", + "pify": "^3.0.0", + "strip-bom": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/load-json-file/node_modules/parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==", + "dev": true, + "dependencies": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "dev": true + }, + "node_modules/lodash-es": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz", + "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==", + "dev": true + }, + "node_modules/lodash.capitalize": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/lodash.capitalize/-/lodash.capitalize-4.2.1.tgz", + "integrity": "sha512-kZzYOKspf8XVX5AvmQF94gQW0lejFVgb80G85bU4ZWzoJ6C03PQg3coYAUpSTpQWelrZELd3XWgHzw4Ck5kaIw==", + "dev": true + }, + "node_modules/lodash.escaperegexp": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/lodash.escaperegexp/-/lodash.escaperegexp-4.1.2.tgz", + "integrity": "sha512-TM9YBvyC84ZxE3rgfefxUWiQKLilstD6k7PTGt6wfbtXF8ixIJLOL3VYyV/z+ZiPLsVxAsKAFVwWlWeb2Y8Yyw==", + "dev": true + }, + "node_modules/lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==", + "dev": true + }, + "node_modules/lodash.isstring": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", + "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==", + "dev": true + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true + }, + "node_modules/lodash.truncate": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz", + "integrity": "sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw==", + "dev": true + }, + "node_modules/lodash.uniqby": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/lodash.uniqby/-/lodash.uniqby-4.7.0.tgz", + "integrity": "sha512-e/zcLx6CSbmaEgFHCA7BnoQKyCtKMxnuWrJygbwPs/AIn+IMKl66L8/s+wBUn5LRw2pZx3bUHibiV1b6aTWIww==", + "dev": true + }, + "node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/lz-utils": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/lz-utils/-/lz-utils-2.0.2.tgz", + "integrity": "sha512-i1PJN4hNEevkrvLMqNWCCac1BcB5SRaghywG7HVzWOyVkFOasLCG19ND1sY1F/ZEsM6SnGtoXyBWnmfqOM5r6g==", + "dev": true + }, + "node_modules/make-dir": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", + "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", + "dev": true, + "dependencies": { + "semver": "^7.5.3" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/make-dir/node_modules/semver": { + "version": "7.6.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", + "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/map-obj": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-4.3.0.tgz", + "integrity": "sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/marked": { + "version": "12.0.2", + "resolved": "https://registry.npmjs.org/marked/-/marked-12.0.2.tgz", + "integrity": "sha512-qXUm7e/YKFoqFPYPa3Ukg9xlI5cyAtGmyEIzMfW//m6kXwCy2Ps9DYf5ioijFKQ8qyuscrHoY04iJGctu2Kg0Q==", + "dev": true, + "bin": { + "marked": "bin/marked.js" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/marked-terminal": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/marked-terminal/-/marked-terminal-7.0.0.tgz", + "integrity": "sha512-sNEx8nn9Ktcm6pL0TnRz8tnXq/mSS0Q1FRSwJOAqw4lAB4l49UeDf85Gm1n9RPFm5qurCPjwi1StAQT2XExhZw==", + "dev": true, + "dependencies": { + "ansi-escapes": "^6.2.0", + "chalk": "^5.3.0", + "cli-highlight": "^2.1.11", + "cli-table3": "^0.6.3", + "node-emoji": "^2.1.3", + "supports-hyperlinks": "^3.0.0" + }, + "engines": { + "node": ">=16.0.0" + }, + "peerDependencies": { + "marked": ">=1 <13" + } + }, + "node_modules/marked-terminal/node_modules/chalk": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", + "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", + "dev": true, + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/mathml-tag-names": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/mathml-tag-names/-/mathml-tag-names-2.1.3.tgz", + "integrity": "sha512-APMBEanjybaPzUrfqU0IMU5I0AswKMH7k8OTLs0vvV4KZpExkTkY87nR/zpbuTPj+gARop7aGUbl11pnDfW6xg==", + "dev": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/mdn-data": { + "version": "2.0.30", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.30.tgz", + "integrity": "sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==", + "dev": true + }, + "node_modules/meow": { + "version": "10.1.5", + "resolved": "https://registry.npmjs.org/meow/-/meow-10.1.5.tgz", + "integrity": "sha512-/d+PQ4GKmGvM9Bee/DPa8z3mXs/pkvJE2KEThngVNOqtmljC6K7NMPxtc2JeZYTmpWb9k/TmxjeL18ez3h7vCw==", + "dev": true, + "dependencies": { + "@types/minimist": "^1.2.2", + "camelcase-keys": "^7.0.0", + "decamelize": "^5.0.0", + "decamelize-keys": "^1.1.0", + "hard-rejection": "^2.1.0", + "minimist-options": "4.1.0", + "normalize-package-data": "^3.0.2", + "read-pkg-up": "^8.0.0", + "redent": "^4.0.0", + "trim-newlines": "^4.0.2", + "type-fest": "^1.2.2", + "yargs-parser": "^20.2.9" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/meow/node_modules/type-fest": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-1.4.0.tgz", + "integrity": "sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/micromatch": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", + "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "dev": true, + "dependencies": { + "braces": "^3.0.2", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/mime": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/mime/-/mime-4.0.3.tgz", + "integrity": "sha512-KgUb15Oorc0NEKPbvfa0wRU+PItIEZmiv+pyAO2i0oTIVTJhlzMclU7w4RXWQrSOVH5ax/p/CkIO7KI4OyFJTQ==", + "dev": true, + "funding": [ + "https://github.com/sponsors/broofa" + ], + "bin": { + "mime": "bin/cli.js" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/mimic-fn": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", + "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/min-indent": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", + "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/minimist-options": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/minimist-options/-/minimist-options-4.1.0.tgz", + "integrity": "sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==", + "dev": true, + "dependencies": { + "arrify": "^1.0.1", + "is-plain-obj": "^1.1.0", + "kind-of": "^6.0.3" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "dev": true, + "dependencies": { + "minimist": "^1.2.6" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, + "node_modules/monocart-code-viewer": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/monocart-code-viewer/-/monocart-code-viewer-1.1.3.tgz", + "integrity": "sha512-v1dbT8fDr9vjyjEYE035JSC4JXBA/Z034mogVJWRO3khX0/guVwGb69iSIYSzTbR9+KpRKV/C/AscRAkUwP32w==", + "dev": true + }, + "node_modules/monocart-coverage-reports": { + "version": "2.8.2", + "resolved": "https://registry.npmjs.org/monocart-coverage-reports/-/monocart-coverage-reports-2.8.2.tgz", + "integrity": "sha512-7PjHQlH47IvF+IVMLvO3dmTEOyiJpRVn67X2NY7gx8qQO0fW+j4cClojQwjcDaV4WWlAnOIsukcODxfxMUlC+Q==", + "dev": true, + "dependencies": { + "console-grid": "^2.2.2", + "eight-colors": "^1.3.0", + "istanbul-lib-coverage": "^3.2.2", + "istanbul-lib-report": "^3.0.1", + "istanbul-reports": "^3.1.7", + "lz-utils": "^2.0.2", + "monocart-code-viewer": "^1.1.3", + "monocart-formatter": "^3.0.0", + "monocart-locator": "^1.0.0", + "turbogrid": "^3.0.13" + }, + "bin": { + "mcr": "lib/cli.js" + } + }, + "node_modules/monocart-formatter": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/monocart-formatter/-/monocart-formatter-3.0.0.tgz", + "integrity": "sha512-91OQpUb/9iDqvrblUv6ki11Jxi1d3Fp5u2jfVAPl3UdNp9TM+iBleLzXntUS51W0o+zoya3CJjZZ01z2XWn25g==", + "dev": true + }, + "node_modules/monocart-locator": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/monocart-locator/-/monocart-locator-1.0.0.tgz", + "integrity": "sha512-qIHJ7f99miF2HbVUWAFKR93SfgGYpFPUCQPmW9q1VXU9onxMUFJxhQDdG3HkEteogUbsKB7Gr5MRgjzcIxwTaQ==", + "dev": true + }, + "node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/mz": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", + "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", + "dev": true, + "dependencies": { + "any-promise": "^1.0.0", + "object-assign": "^4.0.1", + "thenify-all": "^1.0.0" + } + }, + "node_modules/nanoid": { + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", + "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true + }, + "node_modules/neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", + "dev": true + }, + "node_modules/nerf-dart": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/nerf-dart/-/nerf-dart-1.0.0.tgz", + "integrity": "sha512-EZSPZB70jiVsivaBLYDCyntd5eH8NTSMOn3rB+HxwdmKThGELLdYv8qVIMWvZEFy9w8ZZpW9h9OB32l1rGtj7g==", + "dev": true + }, + "node_modules/node-emoji": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/node-emoji/-/node-emoji-2.1.3.tgz", + "integrity": "sha512-E2WEOVsgs7O16zsURJ/eH8BqhF029wGpEOnv7Urwdo2wmQanOACwJQh0devF9D9RhoZru0+9JXIS0dBXIAz+lA==", + "dev": true, + "dependencies": { + "@sindresorhus/is": "^4.6.0", + "char-regex": "^1.0.2", + "emojilib": "^2.4.0", + "skin-tone": "^2.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/node-releases": { + "version": "2.0.13", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.13.tgz", + "integrity": "sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ==", + "dev": true, + "peer": true + }, + "node_modules/normalize-package-data": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-3.0.3.tgz", + "integrity": "sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA==", + "dev": true, + "dependencies": { + "hosted-git-info": "^4.0.1", + "is-core-module": "^2.5.0", + "semver": "^7.3.4", + "validate-npm-package-license": "^3.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/normalize-package-data/node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/normalize-url": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-8.0.1.tgz", + "integrity": "sha512-IO9QvjUMWxPQQhs60oOu10CRkWCiZzSUkzbXGGV9pviYl1fXYcvkzQ5jV9z8Y6un8ARoVRl4EtC6v6jNqbaJ/w==", + "dev": true, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/npm": { + "version": "10.8.0", + "resolved": "https://registry.npmjs.org/npm/-/npm-10.8.0.tgz", + "integrity": "sha512-wh93uRczgp7HDnPMiLXcCkv2hagdJS0zJ9KT/31d0FoXP02+qgN2AOwpaW85fxRWkinl2rELfPw+CjBXW48/jQ==", + "bundleDependencies": [ + "@isaacs/string-locale-compare", + "@npmcli/arborist", + "@npmcli/config", + "@npmcli/fs", + "@npmcli/map-workspaces", + "@npmcli/package-json", + "@npmcli/promise-spawn", + "@npmcli/redact", + "@npmcli/run-script", + "@sigstore/tuf", + "abbrev", + "archy", + "cacache", + "chalk", + "ci-info", + "cli-columns", + "fastest-levenshtein", + "fs-minipass", + "glob", + "graceful-fs", + "hosted-git-info", + "ini", + "init-package-json", + "is-cidr", + "json-parse-even-better-errors", + "libnpmaccess", + "libnpmdiff", + "libnpmexec", + "libnpmfund", + "libnpmhook", + "libnpmorg", + "libnpmpack", + "libnpmpublish", + "libnpmsearch", + "libnpmteam", + "libnpmversion", + "make-fetch-happen", + "minimatch", + "minipass", + "minipass-pipeline", + "ms", + "node-gyp", + "nopt", + "normalize-package-data", + "npm-audit-report", + "npm-install-checks", + "npm-package-arg", + "npm-pick-manifest", + "npm-profile", + "npm-registry-fetch", + "npm-user-validate", + "p-map", + "pacote", + "parse-conflict-json", + "proc-log", + "qrcode-terminal", + "read", + "semver", + "spdx-expression-parse", + "ssri", + "supports-color", + "tar", + "text-table", + "tiny-relative-date", + "treeverse", + "validate-npm-package-name", + "which", + "write-file-atomic" + ], + "dependencies": { + "@isaacs/string-locale-compare": "^1.1.0", + "@npmcli/arborist": "^7.5.2", + "@npmcli/config": "^8.3.2", + "@npmcli/fs": "^3.1.1", + "@npmcli/map-workspaces": "^3.0.6", + "@npmcli/package-json": "^5.1.0", + "@npmcli/promise-spawn": "^7.0.2", + "@npmcli/redact": "^2.0.0", + "@npmcli/run-script": "^8.1.0", + "@sigstore/tuf": "^2.3.3", + "abbrev": "^2.0.0", + "archy": "~1.0.0", + "cacache": "^18.0.3", + "chalk": "^5.3.0", + "ci-info": "^4.0.0", + "cli-columns": "^4.0.0", + "fastest-levenshtein": "^1.0.16", + "fs-minipass": "^3.0.3", + "glob": "^10.3.15", + "graceful-fs": "^4.2.11", + "hosted-git-info": "^7.0.2", + "ini": "^4.1.2", + "init-package-json": "^6.0.3", + "is-cidr": "^5.0.5", + "json-parse-even-better-errors": "^3.0.2", + "libnpmaccess": "^8.0.6", + "libnpmdiff": "^6.1.2", + "libnpmexec": "^8.1.1", + "libnpmfund": "^5.0.10", + "libnpmhook": "^10.0.5", + "libnpmorg": "^6.0.6", + "libnpmpack": "^7.0.2", + "libnpmpublish": "^9.0.8", + "libnpmsearch": "^7.0.5", + "libnpmteam": "^6.0.5", + "libnpmversion": "^6.0.2", + "make-fetch-happen": "^13.0.1", + "minimatch": "^9.0.4", + "minipass": "^7.1.1", + "minipass-pipeline": "^1.2.4", + "ms": "^2.1.2", + "node-gyp": "^10.1.0", + "nopt": "^7.2.1", + "normalize-package-data": "^6.0.1", + "npm-audit-report": "^5.0.0", + "npm-install-checks": "^6.3.0", + "npm-package-arg": "^11.0.2", + "npm-pick-manifest": "^9.0.1", + "npm-profile": "^10.0.0", + "npm-registry-fetch": "^17.0.1", + "npm-user-validate": "^2.0.1", + "p-map": "^4.0.0", + "pacote": "^18.0.6", + "parse-conflict-json": "^3.0.1", + "proc-log": "^4.2.0", + "qrcode-terminal": "^0.12.0", + "read": "^3.0.1", + "semver": "^7.6.2", + "spdx-expression-parse": "^4.0.0", + "ssri": "^10.0.6", + "supports-color": "^9.4.0", + "tar": "^6.2.1", + "text-table": "~0.2.0", + "tiny-relative-date": "^1.3.0", + "treeverse": "^3.0.0", + "validate-npm-package-name": "^5.0.1", + "which": "^4.0.0", + "write-file-atomic": "^5.0.1" + }, + "bin": { + "npm": "bin/npm-cli.js", + "npx": "bin/npx-cli.js" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm-run-path": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.3.0.tgz", + "integrity": "sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==", + "dev": true, + "dependencies": { + "path-key": "^4.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/npm-run-path/node_modules/path-key": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", + "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/npm/node_modules/@isaacs/cliui": { + "version": "8.0.2", + "inBundle": true, + "license": "ISC", + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/npm/node_modules/@isaacs/cliui/node_modules/ansi-regex": { + "version": "6.0.1", + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/npm/node_modules/@isaacs/cliui/node_modules/emoji-regex": { + "version": "9.2.2", + "inBundle": true, + "license": "MIT" + }, + "node_modules/npm/node_modules/@isaacs/cliui/node_modules/string-width": { + "version": "5.1.2", + "inBundle": true, + "license": "MIT", + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/npm/node_modules/@isaacs/cliui/node_modules/strip-ansi": { + "version": "7.1.0", + "inBundle": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/npm/node_modules/@isaacs/string-locale-compare": { + "version": "1.1.0", + "inBundle": true, + "license": "ISC" + }, + "node_modules/npm/node_modules/@npmcli/agent": { + "version": "2.2.2", + "inBundle": true, + "license": "ISC", + "dependencies": { + "agent-base": "^7.1.0", + "http-proxy-agent": "^7.0.0", + "https-proxy-agent": "^7.0.1", + "lru-cache": "^10.0.1", + "socks-proxy-agent": "^8.0.3" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/@npmcli/arborist": { + "version": "7.5.2", + "inBundle": true, + "license": "ISC", + "dependencies": { + "@isaacs/string-locale-compare": "^1.1.0", + "@npmcli/fs": "^3.1.1", + "@npmcli/installed-package-contents": "^2.1.0", + "@npmcli/map-workspaces": "^3.0.2", + "@npmcli/metavuln-calculator": "^7.1.1", + "@npmcli/name-from-folder": "^2.0.0", + "@npmcli/node-gyp": "^3.0.0", + "@npmcli/package-json": "^5.1.0", + "@npmcli/query": "^3.1.0", + "@npmcli/redact": "^2.0.0", + "@npmcli/run-script": "^8.1.0", + "bin-links": "^4.0.4", + "cacache": "^18.0.3", + "common-ancestor-path": "^1.0.1", + "hosted-git-info": "^7.0.2", + "json-parse-even-better-errors": "^3.0.2", + "json-stringify-nice": "^1.1.4", + "lru-cache": "^10.2.2", + "minimatch": "^9.0.4", + "nopt": "^7.2.1", + "npm-install-checks": "^6.2.0", + "npm-package-arg": "^11.0.2", + "npm-pick-manifest": "^9.0.1", + "npm-registry-fetch": "^17.0.1", + "pacote": "^18.0.6", + "parse-conflict-json": "^3.0.0", + "proc-log": "^4.2.0", + "proggy": "^2.0.0", + "promise-all-reject-late": "^1.0.0", + "promise-call-limit": "^3.0.1", + "read-package-json-fast": "^3.0.2", + "semver": "^7.3.7", + "ssri": "^10.0.6", + "treeverse": "^3.0.0", + "walk-up-path": "^3.0.1" + }, + "bin": { + "arborist": "bin/index.js" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/@npmcli/config": { + "version": "8.3.2", + "inBundle": true, + "license": "ISC", + "dependencies": { + "@npmcli/map-workspaces": "^3.0.2", + "ci-info": "^4.0.0", + "ini": "^4.1.2", + "nopt": "^7.2.1", + "proc-log": "^4.2.0", + "read-package-json-fast": "^3.0.2", + "semver": "^7.3.5", + "walk-up-path": "^3.0.1" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/@npmcli/fs": { + "version": "3.1.1", + "inBundle": true, + "license": "ISC", + "dependencies": { + "semver": "^7.3.5" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/@npmcli/git": { + "version": "5.0.7", + "inBundle": true, + "license": "ISC", + "dependencies": { + "@npmcli/promise-spawn": "^7.0.0", + "lru-cache": "^10.0.1", + "npm-pick-manifest": "^9.0.0", + "proc-log": "^4.0.0", + "promise-inflight": "^1.0.1", + "promise-retry": "^2.0.1", + "semver": "^7.3.5", + "which": "^4.0.0" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/@npmcli/installed-package-contents": { + "version": "2.1.0", + "inBundle": true, + "license": "ISC", + "dependencies": { + "npm-bundled": "^3.0.0", + "npm-normalize-package-bin": "^3.0.0" + }, + "bin": { + "installed-package-contents": "bin/index.js" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/@npmcli/map-workspaces": { + "version": "3.0.6", + "inBundle": true, + "license": "ISC", + "dependencies": { + "@npmcli/name-from-folder": "^2.0.0", + "glob": "^10.2.2", + "minimatch": "^9.0.0", + "read-package-json-fast": "^3.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/@npmcli/metavuln-calculator": { + "version": "7.1.1", + "inBundle": true, + "license": "ISC", + "dependencies": { + "cacache": "^18.0.0", + "json-parse-even-better-errors": "^3.0.0", + "pacote": "^18.0.0", + "proc-log": "^4.1.0", + "semver": "^7.3.5" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/@npmcli/name-from-folder": { + "version": "2.0.0", + "inBundle": true, + "license": "ISC", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/@npmcli/node-gyp": { + "version": "3.0.0", + "inBundle": true, + "license": "ISC", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/@npmcli/package-json": { + "version": "5.1.0", + "inBundle": true, + "license": "ISC", + "dependencies": { + "@npmcli/git": "^5.0.0", + "glob": "^10.2.2", + "hosted-git-info": "^7.0.0", + "json-parse-even-better-errors": "^3.0.0", + "normalize-package-data": "^6.0.0", + "proc-log": "^4.0.0", + "semver": "^7.5.3" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/@npmcli/promise-spawn": { + "version": "7.0.2", + "inBundle": true, + "license": "ISC", + "dependencies": { + "which": "^4.0.0" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/@npmcli/query": { + "version": "3.1.0", + "inBundle": true, + "license": "ISC", + "dependencies": { + "postcss-selector-parser": "^6.0.10" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/@npmcli/redact": { + "version": "2.0.0", + "inBundle": true, + "license": "ISC", + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/@npmcli/run-script": { + "version": "8.1.0", + "inBundle": true, + "license": "ISC", + "dependencies": { + "@npmcli/node-gyp": "^3.0.0", + "@npmcli/package-json": "^5.0.0", + "@npmcli/promise-spawn": "^7.0.0", + "node-gyp": "^10.0.0", + "proc-log": "^4.0.0", + "which": "^4.0.0" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=14" + } + }, + "node_modules/npm/node_modules/@sigstore/bundle": { + "version": "2.3.1", + "inBundle": true, + "license": "Apache-2.0", + "dependencies": { + "@sigstore/protobuf-specs": "^0.3.1" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/@sigstore/core": { + "version": "1.1.0", + "inBundle": true, + "license": "Apache-2.0", + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/@sigstore/protobuf-specs": { + "version": "0.3.2", + "inBundle": true, + "license": "Apache-2.0", + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/@sigstore/sign": { + "version": "2.3.1", + "inBundle": true, + "license": "Apache-2.0", + "dependencies": { + "@sigstore/bundle": "^2.3.0", + "@sigstore/core": "^1.0.0", + "@sigstore/protobuf-specs": "^0.3.1", + "make-fetch-happen": "^13.0.1", + "proc-log": "^4.2.0", + "promise-retry": "^2.0.1" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/@sigstore/tuf": { + "version": "2.3.3", + "inBundle": true, + "license": "Apache-2.0", + "dependencies": { + "@sigstore/protobuf-specs": "^0.3.0", + "tuf-js": "^2.2.1" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/@sigstore/verify": { + "version": "1.2.0", + "inBundle": true, + "license": "Apache-2.0", + "dependencies": { + "@sigstore/bundle": "^2.3.1", + "@sigstore/core": "^1.1.0", + "@sigstore/protobuf-specs": "^0.3.1" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/@tufjs/canonical-json": { + "version": "2.0.0", + "inBundle": true, + "license": "MIT", + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/@tufjs/models": { + "version": "2.0.1", + "inBundle": true, + "license": "MIT", + "dependencies": { + "@tufjs/canonical-json": "2.0.0", + "minimatch": "^9.0.4" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/abbrev": { + "version": "2.0.0", + "inBundle": true, + "license": "ISC", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/agent-base": { + "version": "7.1.1", + "inBundle": true, + "license": "MIT", + "dependencies": { + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/npm/node_modules/aggregate-error": { + "version": "3.1.0", + "inBundle": true, + "license": "MIT", + "dependencies": { + "clean-stack": "^2.0.0", + "indent-string": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/ansi-regex": { + "version": "5.0.1", + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/ansi-styles": { + "version": "6.2.1", + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/npm/node_modules/aproba": { + "version": "2.0.0", + "inBundle": true, + "license": "ISC" + }, + "node_modules/npm/node_modules/archy": { + "version": "1.0.0", + "inBundle": true, + "license": "MIT" + }, + "node_modules/npm/node_modules/balanced-match": { + "version": "1.0.2", + "inBundle": true, + "license": "MIT" + }, + "node_modules/npm/node_modules/bin-links": { + "version": "4.0.4", + "inBundle": true, + "license": "ISC", + "dependencies": { + "cmd-shim": "^6.0.0", + "npm-normalize-package-bin": "^3.0.0", + "read-cmd-shim": "^4.0.0", + "write-file-atomic": "^5.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/binary-extensions": { + "version": "2.3.0", + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/npm/node_modules/brace-expansion": { + "version": "2.0.1", + "inBundle": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/npm/node_modules/cacache": { + "version": "18.0.3", + "inBundle": true, + "license": "ISC", + "dependencies": { + "@npmcli/fs": "^3.1.0", + "fs-minipass": "^3.0.0", + "glob": "^10.2.2", + "lru-cache": "^10.0.1", + "minipass": "^7.0.3", + "minipass-collect": "^2.0.1", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "p-map": "^4.0.0", + "ssri": "^10.0.0", + "tar": "^6.1.11", + "unique-filename": "^3.0.0" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/chalk": { + "version": "5.3.0", + "inBundle": true, + "license": "MIT", + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/npm/node_modules/chownr": { + "version": "2.0.0", + "inBundle": true, + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/npm/node_modules/ci-info": { + "version": "4.0.0", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/cidr-regex": { + "version": "4.0.5", + "inBundle": true, + "license": "BSD-2-Clause", + "dependencies": { + "ip-regex": "^5.0.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/npm/node_modules/clean-stack": { + "version": "2.2.0", + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/npm/node_modules/cli-columns": { + "version": "4.0.0", + "inBundle": true, + "license": "MIT", + "dependencies": { + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/npm/node_modules/cmd-shim": { + "version": "6.0.3", + "inBundle": true, + "license": "ISC", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/color-convert": { + "version": "2.0.1", + "inBundle": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/npm/node_modules/color-name": { + "version": "1.1.4", + "inBundle": true, + "license": "MIT" + }, + "node_modules/npm/node_modules/common-ancestor-path": { + "version": "1.0.1", + "inBundle": true, + "license": "ISC" + }, + "node_modules/npm/node_modules/cross-spawn": { + "version": "7.0.3", + "inBundle": true, + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/npm/node_modules/cross-spawn/node_modules/which": { + "version": "2.0.2", + "inBundle": true, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/npm/node_modules/cssesc": { + "version": "3.0.0", + "inBundle": true, + "license": "MIT", + "bin": { + "cssesc": "bin/cssesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/npm/node_modules/debug": { + "version": "4.3.4", + "inBundle": true, + "license": "MIT", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/npm/node_modules/debug/node_modules/ms": { + "version": "2.1.2", + "inBundle": true, + "license": "MIT" + }, + "node_modules/npm/node_modules/diff": { + "version": "5.2.0", + "inBundle": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/npm/node_modules/eastasianwidth": { + "version": "0.2.0", + "inBundle": true, + "license": "MIT" + }, + "node_modules/npm/node_modules/emoji-regex": { + "version": "8.0.0", + "inBundle": true, + "license": "MIT" + }, + "node_modules/npm/node_modules/encoding": { + "version": "0.1.13", + "inBundle": true, + "license": "MIT", + "dependencies": { + "iconv-lite": "^0.6.2" + } + }, + "node_modules/npm/node_modules/env-paths": { + "version": "2.2.1", + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/npm/node_modules/err-code": { + "version": "2.0.3", + "inBundle": true, + "license": "MIT" + }, + "node_modules/npm/node_modules/exponential-backoff": { + "version": "3.1.1", + "inBundle": true, + "license": "Apache-2.0" + }, + "node_modules/npm/node_modules/fastest-levenshtein": { + "version": "1.0.16", + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">= 4.9.1" + } + }, + "node_modules/npm/node_modules/foreground-child": { + "version": "3.1.1", + "inBundle": true, + "license": "ISC", + "dependencies": { + "cross-spawn": "^7.0.0", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/npm/node_modules/fs-minipass": { + "version": "3.0.3", + "inBundle": true, + "license": "ISC", + "dependencies": { + "minipass": "^7.0.3" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/function-bind": { + "version": "1.1.2", + "inBundle": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/npm/node_modules/glob": { + "version": "10.3.15", + "inBundle": true, + "license": "ISC", + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^2.3.6", + "minimatch": "^9.0.1", + "minipass": "^7.0.4", + "path-scurry": "^1.11.0" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "engines": { + "node": ">=16 || 14 >=14.18" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/npm/node_modules/graceful-fs": { + "version": "4.2.11", + "inBundle": true, + "license": "ISC" + }, + "node_modules/npm/node_modules/hasown": { + "version": "2.0.2", + "inBundle": true, + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/npm/node_modules/hosted-git-info": { + "version": "7.0.2", + "inBundle": true, + "license": "ISC", + "dependencies": { + "lru-cache": "^10.0.1" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/http-cache-semantics": { + "version": "4.1.1", + "inBundle": true, + "license": "BSD-2-Clause" + }, + "node_modules/npm/node_modules/http-proxy-agent": { + "version": "7.0.2", + "inBundle": true, + "license": "MIT", + "dependencies": { + "agent-base": "^7.1.0", + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/npm/node_modules/https-proxy-agent": { + "version": "7.0.4", + "inBundle": true, + "license": "MIT", + "dependencies": { + "agent-base": "^7.0.2", + "debug": "4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/npm/node_modules/iconv-lite": { + "version": "0.6.3", + "inBundle": true, + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/npm/node_modules/ignore-walk": { + "version": "6.0.5", + "inBundle": true, + "license": "ISC", + "dependencies": { + "minimatch": "^9.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/imurmurhash": { + "version": "0.1.4", + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/npm/node_modules/indent-string": { + "version": "4.0.0", + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/ini": { + "version": "4.1.2", + "inBundle": true, + "license": "ISC", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/init-package-json": { + "version": "6.0.3", + "inBundle": true, + "license": "ISC", + "dependencies": { + "@npmcli/package-json": "^5.0.0", + "npm-package-arg": "^11.0.0", + "promzard": "^1.0.0", + "read": "^3.0.1", + "semver": "^7.3.5", + "validate-npm-package-license": "^3.0.4", + "validate-npm-package-name": "^5.0.0" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/ip-address": { + "version": "9.0.5", + "inBundle": true, + "license": "MIT", + "dependencies": { + "jsbn": "1.1.0", + "sprintf-js": "^1.1.3" + }, + "engines": { + "node": ">= 12" + } + }, + "node_modules/npm/node_modules/ip-regex": { + "version": "5.0.0", + "inBundle": true, + "license": "MIT", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/npm/node_modules/is-cidr": { + "version": "5.0.5", + "inBundle": true, + "license": "BSD-2-Clause", + "dependencies": { + "cidr-regex": "^4.0.4" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/npm/node_modules/is-core-module": { + "version": "2.13.1", + "inBundle": true, + "license": "MIT", + "dependencies": { + "hasown": "^2.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/npm/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/is-lambda": { + "version": "1.0.1", + "inBundle": true, + "license": "MIT" + }, + "node_modules/npm/node_modules/isexe": { + "version": "2.0.0", + "inBundle": true, + "license": "ISC" + }, + "node_modules/npm/node_modules/jackspeak": { + "version": "2.3.6", + "inBundle": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, + "node_modules/npm/node_modules/jsbn": { + "version": "1.1.0", + "inBundle": true, + "license": "MIT" + }, + "node_modules/npm/node_modules/json-parse-even-better-errors": { + "version": "3.0.2", + "inBundle": true, + "license": "MIT", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/json-stringify-nice": { + "version": "1.1.4", + "inBundle": true, + "license": "ISC", + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/npm/node_modules/jsonparse": { + "version": "1.3.1", + "engines": [ + "node >= 0.2.0" + ], + "inBundle": true, + "license": "MIT" + }, + "node_modules/npm/node_modules/just-diff": { + "version": "6.0.2", + "inBundle": true, + "license": "MIT" + }, + "node_modules/npm/node_modules/just-diff-apply": { + "version": "5.5.0", + "inBundle": true, + "license": "MIT" + }, + "node_modules/npm/node_modules/libnpmaccess": { + "version": "8.0.6", + "inBundle": true, + "license": "ISC", + "dependencies": { + "npm-package-arg": "^11.0.2", + "npm-registry-fetch": "^17.0.1" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/libnpmdiff": { + "version": "6.1.2", + "inBundle": true, + "license": "ISC", + "dependencies": { + "@npmcli/arborist": "^7.5.2", + "@npmcli/installed-package-contents": "^2.1.0", + "binary-extensions": "^2.3.0", + "diff": "^5.1.0", + "minimatch": "^9.0.4", + "npm-package-arg": "^11.0.2", + "pacote": "^18.0.6", + "tar": "^6.2.1" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/libnpmexec": { + "version": "8.1.1", + "inBundle": true, + "license": "ISC", + "dependencies": { + "@npmcli/arborist": "^7.5.2", + "@npmcli/run-script": "^8.1.0", + "ci-info": "^4.0.0", + "npm-package-arg": "^11.0.2", + "pacote": "^18.0.6", + "proc-log": "^4.2.0", + "read": "^3.0.1", + "read-package-json-fast": "^3.0.2", + "semver": "^7.3.7", + "walk-up-path": "^3.0.1" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/libnpmfund": { + "version": "5.0.10", + "inBundle": true, + "license": "ISC", + "dependencies": { + "@npmcli/arborist": "^7.5.2" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/libnpmhook": { + "version": "10.0.5", + "inBundle": true, + "license": "ISC", + "dependencies": { + "aproba": "^2.0.0", + "npm-registry-fetch": "^17.0.1" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/libnpmorg": { + "version": "6.0.6", + "inBundle": true, + "license": "ISC", + "dependencies": { + "aproba": "^2.0.0", + "npm-registry-fetch": "^17.0.1" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/libnpmpack": { + "version": "7.0.2", + "inBundle": true, + "license": "ISC", + "dependencies": { + "@npmcli/arborist": "^7.5.2", + "@npmcli/run-script": "^8.1.0", + "npm-package-arg": "^11.0.2", + "pacote": "^18.0.6" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/libnpmpublish": { + "version": "9.0.8", + "inBundle": true, + "license": "ISC", + "dependencies": { + "ci-info": "^4.0.0", + "normalize-package-data": "^6.0.1", + "npm-package-arg": "^11.0.2", + "npm-registry-fetch": "^17.0.1", + "proc-log": "^4.2.0", + "semver": "^7.3.7", + "sigstore": "^2.2.0", + "ssri": "^10.0.6" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/libnpmsearch": { + "version": "7.0.5", + "inBundle": true, + "license": "ISC", + "dependencies": { + "npm-registry-fetch": "^17.0.1" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/libnpmteam": { + "version": "6.0.5", + "inBundle": true, + "license": "ISC", + "dependencies": { + "aproba": "^2.0.0", + "npm-registry-fetch": "^17.0.1" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/libnpmversion": { + "version": "6.0.2", + "inBundle": true, + "license": "ISC", + "dependencies": { + "@npmcli/git": "^5.0.7", + "@npmcli/run-script": "^8.1.0", + "json-parse-even-better-errors": "^3.0.2", + "proc-log": "^4.2.0", + "semver": "^7.3.7" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/lru-cache": { + "version": "10.2.2", + "inBundle": true, + "license": "ISC", + "engines": { + "node": "14 || >=16.14" + } + }, + "node_modules/npm/node_modules/make-fetch-happen": { + "version": "13.0.1", + "inBundle": true, + "license": "ISC", + "dependencies": { + "@npmcli/agent": "^2.0.0", + "cacache": "^18.0.0", + "http-cache-semantics": "^4.1.1", + "is-lambda": "^1.0.1", + "minipass": "^7.0.2", + "minipass-fetch": "^3.0.0", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "negotiator": "^0.6.3", + "proc-log": "^4.2.0", + "promise-retry": "^2.0.1", + "ssri": "^10.0.0" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/minimatch": { + "version": "9.0.4", + "inBundle": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/npm/node_modules/minipass": { + "version": "7.1.1", + "inBundle": true, + "license": "ISC", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/npm/node_modules/minipass-collect": { + "version": "2.0.1", + "inBundle": true, + "license": "ISC", + "dependencies": { + "minipass": "^7.0.3" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/npm/node_modules/minipass-fetch": { + "version": "3.0.5", + "inBundle": true, + "license": "MIT", + "dependencies": { + "minipass": "^7.0.3", + "minipass-sized": "^1.0.3", + "minizlib": "^2.1.2" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + }, + "optionalDependencies": { + "encoding": "^0.1.13" + } + }, + "node_modules/npm/node_modules/minipass-flush": { + "version": "1.0.5", + "inBundle": true, + "license": "ISC", + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/npm/node_modules/minipass-flush/node_modules/minipass": { + "version": "3.3.6", + "inBundle": true, + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/minipass-json-stream": { + "version": "1.0.1", + "inBundle": true, + "license": "MIT", + "dependencies": { + "jsonparse": "^1.3.1", + "minipass": "^3.0.0" + } + }, + "node_modules/npm/node_modules/minipass-json-stream/node_modules/minipass": { + "version": "3.3.6", + "inBundle": true, + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/minipass-pipeline": { + "version": "1.2.4", + "inBundle": true, + "license": "ISC", + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/minipass-pipeline/node_modules/minipass": { + "version": "3.3.6", + "inBundle": true, + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/minipass-sized": { + "version": "1.0.3", + "inBundle": true, + "license": "ISC", + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/minipass-sized/node_modules/minipass": { + "version": "3.3.6", + "inBundle": true, + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/minizlib": { + "version": "2.1.2", + "inBundle": true, + "license": "MIT", + "dependencies": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/npm/node_modules/minizlib/node_modules/minipass": { + "version": "3.3.6", + "inBundle": true, + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/mkdirp": { + "version": "1.0.4", + "inBundle": true, + "license": "MIT", + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/npm/node_modules/ms": { + "version": "2.1.3", + "inBundle": true, + "license": "MIT" + }, + "node_modules/npm/node_modules/mute-stream": { + "version": "1.0.0", + "inBundle": true, + "license": "ISC", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/negotiator": { + "version": "0.6.3", + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/npm/node_modules/node-gyp": { + "version": "10.1.0", + "inBundle": true, + "license": "MIT", + "dependencies": { + "env-paths": "^2.2.0", + "exponential-backoff": "^3.1.1", + "glob": "^10.3.10", + "graceful-fs": "^4.2.6", + "make-fetch-happen": "^13.0.0", + "nopt": "^7.0.0", + "proc-log": "^3.0.0", + "semver": "^7.3.5", + "tar": "^6.1.2", + "which": "^4.0.0" + }, + "bin": { + "node-gyp": "bin/node-gyp.js" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/node-gyp/node_modules/proc-log": { + "version": "3.0.0", + "inBundle": true, + "license": "ISC", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/nopt": { + "version": "7.2.1", + "inBundle": true, + "license": "ISC", + "dependencies": { + "abbrev": "^2.0.0" + }, + "bin": { + "nopt": "bin/nopt.js" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/normalize-package-data": { + "version": "6.0.1", + "inBundle": true, + "license": "BSD-2-Clause", + "dependencies": { + "hosted-git-info": "^7.0.0", + "is-core-module": "^2.8.1", + "semver": "^7.3.5", + "validate-npm-package-license": "^3.0.4" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/npm-audit-report": { + "version": "5.0.0", + "inBundle": true, + "license": "ISC", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/npm-bundled": { + "version": "3.0.1", + "inBundle": true, + "license": "ISC", + "dependencies": { + "npm-normalize-package-bin": "^3.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/npm-install-checks": { + "version": "6.3.0", + "inBundle": true, + "license": "BSD-2-Clause", + "dependencies": { + "semver": "^7.1.1" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/npm-normalize-package-bin": { + "version": "3.0.1", + "inBundle": true, + "license": "ISC", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/npm-package-arg": { + "version": "11.0.2", + "inBundle": true, + "license": "ISC", + "dependencies": { + "hosted-git-info": "^7.0.0", + "proc-log": "^4.0.0", + "semver": "^7.3.5", + "validate-npm-package-name": "^5.0.0" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/npm-packlist": { + "version": "8.0.2", + "inBundle": true, + "license": "ISC", + "dependencies": { + "ignore-walk": "^6.0.4" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/npm-pick-manifest": { + "version": "9.0.1", + "inBundle": true, + "license": "ISC", + "dependencies": { + "npm-install-checks": "^6.0.0", + "npm-normalize-package-bin": "^3.0.0", + "npm-package-arg": "^11.0.0", + "semver": "^7.3.5" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/npm-profile": { + "version": "10.0.0", + "inBundle": true, + "license": "ISC", + "dependencies": { + "npm-registry-fetch": "^17.0.1", + "proc-log": "^4.0.0" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/npm/node_modules/npm-registry-fetch": { + "version": "17.0.1", + "inBundle": true, + "license": "ISC", + "dependencies": { + "@npmcli/redact": "^2.0.0", + "make-fetch-happen": "^13.0.0", + "minipass": "^7.0.2", + "minipass-fetch": "^3.0.0", + "minipass-json-stream": "^1.0.1", + "minizlib": "^2.1.2", + "npm-package-arg": "^11.0.0", + "proc-log": "^4.0.0" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/npm-user-validate": { + "version": "2.0.1", + "inBundle": true, + "license": "BSD-2-Clause", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/p-map": { + "version": "4.0.0", + "inBundle": true, + "license": "MIT", + "dependencies": { + "aggregate-error": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/npm/node_modules/pacote": { + "version": "18.0.6", + "inBundle": true, + "license": "ISC", + "dependencies": { + "@npmcli/git": "^5.0.0", + "@npmcli/installed-package-contents": "^2.0.1", + "@npmcli/package-json": "^5.1.0", + "@npmcli/promise-spawn": "^7.0.0", + "@npmcli/run-script": "^8.0.0", + "cacache": "^18.0.0", + "fs-minipass": "^3.0.0", + "minipass": "^7.0.2", + "npm-package-arg": "^11.0.0", + "npm-packlist": "^8.0.0", + "npm-pick-manifest": "^9.0.0", + "npm-registry-fetch": "^17.0.0", + "proc-log": "^4.0.0", + "promise-retry": "^2.0.1", + "sigstore": "^2.2.0", + "ssri": "^10.0.0", + "tar": "^6.1.11" + }, + "bin": { + "pacote": "bin/index.js" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/parse-conflict-json": { + "version": "3.0.1", + "inBundle": true, + "license": "ISC", + "dependencies": { + "json-parse-even-better-errors": "^3.0.0", + "just-diff": "^6.0.0", + "just-diff-apply": "^5.2.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/path-key": { + "version": "3.1.1", + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/path-scurry": { + "version": "1.11.1", + "inBundle": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.18" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/npm/node_modules/postcss-selector-parser": { + "version": "6.0.16", + "inBundle": true, + "license": "MIT", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/npm/node_modules/proc-log": { + "version": "4.2.0", + "inBundle": true, + "license": "ISC", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/proggy": { + "version": "2.0.0", + "inBundle": true, + "license": "ISC", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/promise-all-reject-late": { + "version": "1.0.1", + "inBundle": true, + "license": "ISC", + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/npm/node_modules/promise-call-limit": { + "version": "3.0.1", + "inBundle": true, + "license": "ISC", + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/npm/node_modules/promise-inflight": { + "version": "1.0.1", + "inBundle": true, + "license": "ISC" + }, + "node_modules/npm/node_modules/promise-retry": { + "version": "2.0.1", + "inBundle": true, + "license": "MIT", + "dependencies": { + "err-code": "^2.0.2", + "retry": "^0.12.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/npm/node_modules/promzard": { + "version": "1.0.2", + "inBundle": true, + "license": "ISC", + "dependencies": { + "read": "^3.0.1" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/qrcode-terminal": { + "version": "0.12.0", + "inBundle": true, + "bin": { + "qrcode-terminal": "bin/qrcode-terminal.js" + } + }, + "node_modules/npm/node_modules/read": { + "version": "3.0.1", + "inBundle": true, + "license": "ISC", + "dependencies": { + "mute-stream": "^1.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/read-cmd-shim": { + "version": "4.0.0", + "inBundle": true, + "license": "ISC", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/read-package-json-fast": { + "version": "3.0.2", + "inBundle": true, + "license": "ISC", + "dependencies": { + "json-parse-even-better-errors": "^3.0.0", + "npm-normalize-package-bin": "^3.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/retry": { + "version": "0.12.0", + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/npm/node_modules/safer-buffer": { + "version": "2.1.2", + "inBundle": true, + "license": "MIT" + }, + "node_modules/npm/node_modules/semver": { + "version": "7.6.2", + "inBundle": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/npm/node_modules/shebang-command": { + "version": "2.0.0", + "inBundle": true, + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/shebang-regex": { + "version": "3.0.0", + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/signal-exit": { + "version": "4.1.0", + "inBundle": true, + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/npm/node_modules/sigstore": { + "version": "2.3.0", + "inBundle": true, + "license": "Apache-2.0", + "dependencies": { + "@sigstore/bundle": "^2.3.1", + "@sigstore/core": "^1.0.0", + "@sigstore/protobuf-specs": "^0.3.1", + "@sigstore/sign": "^2.3.0", + "@sigstore/tuf": "^2.3.1", + "@sigstore/verify": "^1.2.0" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/smart-buffer": { + "version": "4.2.0", + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">= 6.0.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/npm/node_modules/socks": { + "version": "2.8.3", + "inBundle": true, + "license": "MIT", + "dependencies": { + "ip-address": "^9.0.5", + "smart-buffer": "^4.2.0" + }, + "engines": { + "node": ">= 10.0.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/npm/node_modules/socks-proxy-agent": { + "version": "8.0.3", + "inBundle": true, + "license": "MIT", + "dependencies": { + "agent-base": "^7.1.1", + "debug": "^4.3.4", + "socks": "^2.7.1" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/npm/node_modules/spdx-correct": { + "version": "3.2.0", + "inBundle": true, + "license": "Apache-2.0", + "dependencies": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/npm/node_modules/spdx-correct/node_modules/spdx-expression-parse": { + "version": "3.0.1", + "inBundle": true, + "license": "MIT", + "dependencies": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/npm/node_modules/spdx-exceptions": { + "version": "2.5.0", + "inBundle": true, + "license": "CC-BY-3.0" + }, + "node_modules/npm/node_modules/spdx-expression-parse": { + "version": "4.0.0", + "inBundle": true, + "license": "MIT", + "dependencies": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/npm/node_modules/spdx-license-ids": { + "version": "3.0.17", + "inBundle": true, + "license": "CC0-1.0" + }, + "node_modules/npm/node_modules/sprintf-js": { + "version": "1.1.3", + "inBundle": true, + "license": "BSD-3-Clause" + }, + "node_modules/npm/node_modules/ssri": { + "version": "10.0.6", + "inBundle": true, + "license": "ISC", + "dependencies": { + "minipass": "^7.0.3" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/string-width": { + "version": "4.2.3", + "inBundle": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "inBundle": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/strip-ansi": { + "version": "6.0.1", + "inBundle": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "inBundle": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/supports-color": { + "version": "9.4.0", + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/npm/node_modules/tar": { + "version": "6.2.1", + "inBundle": true, + "license": "ISC", + "dependencies": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^5.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/npm/node_modules/tar/node_modules/fs-minipass": { + "version": "2.1.0", + "inBundle": true, + "license": "ISC", + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/npm/node_modules/tar/node_modules/fs-minipass/node_modules/minipass": { + "version": "3.3.6", + "inBundle": true, + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/tar/node_modules/minipass": { + "version": "5.0.0", + "inBundle": true, + "license": "ISC", + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/text-table": { + "version": "0.2.0", + "inBundle": true, + "license": "MIT" + }, + "node_modules/npm/node_modules/tiny-relative-date": { + "version": "1.3.0", + "inBundle": true, + "license": "MIT" + }, + "node_modules/npm/node_modules/treeverse": { + "version": "3.0.0", + "inBundle": true, + "license": "ISC", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/tuf-js": { + "version": "2.2.1", + "inBundle": true, + "license": "MIT", + "dependencies": { + "@tufjs/models": "2.0.1", + "debug": "^4.3.4", + "make-fetch-happen": "^13.0.1" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/unique-filename": { + "version": "3.0.0", + "inBundle": true, + "license": "ISC", + "dependencies": { + "unique-slug": "^4.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/unique-slug": { + "version": "4.0.0", + "inBundle": true, + "license": "ISC", + "dependencies": { + "imurmurhash": "^0.1.4" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/util-deprecate": { + "version": "1.0.2", + "inBundle": true, + "license": "MIT" + }, + "node_modules/npm/node_modules/validate-npm-package-license": { + "version": "3.0.4", + "inBundle": true, + "license": "Apache-2.0", + "dependencies": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "node_modules/npm/node_modules/validate-npm-package-license/node_modules/spdx-expression-parse": { + "version": "3.0.1", + "inBundle": true, + "license": "MIT", + "dependencies": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/npm/node_modules/validate-npm-package-name": { + "version": "5.0.1", + "inBundle": true, + "license": "ISC", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/walk-up-path": { + "version": "3.0.1", + "inBundle": true, + "license": "ISC" + }, + "node_modules/npm/node_modules/which": { + "version": "4.0.0", + "inBundle": true, + "license": "ISC", + "dependencies": { + "isexe": "^3.1.1" + }, + "bin": { + "node-which": "bin/which.js" + }, + "engines": { + "node": "^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/which/node_modules/isexe": { + "version": "3.1.1", + "inBundle": true, + "license": "ISC", + "engines": { + "node": ">=16" + } + }, + "node_modules/npm/node_modules/wrap-ansi": { + "version": "8.1.0", + "inBundle": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/npm/node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", + "inBundle": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/npm/node_modules/wrap-ansi-cjs/node_modules/ansi-styles": { + "version": "4.3.0", + "inBundle": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/npm/node_modules/wrap-ansi/node_modules/ansi-regex": { + "version": "6.0.1", + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/npm/node_modules/wrap-ansi/node_modules/emoji-regex": { + "version": "9.2.2", + "inBundle": true, + "license": "MIT" + }, + "node_modules/npm/node_modules/wrap-ansi/node_modules/string-width": { + "version": "5.1.2", + "inBundle": true, + "license": "MIT", + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/npm/node_modules/wrap-ansi/node_modules/strip-ansi": { + "version": "7.1.0", + "inBundle": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/npm/node_modules/write-file-atomic": { + "version": "5.0.1", + "inBundle": true, + "license": "ISC", + "dependencies": { + "imurmurhash": "^0.1.4", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/yallist": { + "version": "4.0.0", + "inBundle": true, + "license": "ISC" + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-inspect": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", + "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.assign": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.5.tgz", + "integrity": "sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", + "has-symbols": "^1.0.3", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.entries": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.7.tgz", + "integrity": "sha512-jCBs/0plmPsOnrKAfFQXRG2NFjlhZgjjcBLSmTnEhU8U6vVTsVe8ANeQJCHTl3gSsI4J+0emOoCgoKlmQPMgmA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.fromentries": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.7.tgz", + "integrity": "sha512-UPbPHML6sL8PI/mOqPwsH4G6iyXcCGzLin8KvEPenOZN5lpCNBZZQ+V62vdjB1mQHrmqGQt5/OJzemUA+KJmEA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.groupby": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.1.tgz", + "integrity": "sha512-HqaQtqLnp/8Bn4GL16cj+CUYbnpe1bh0TtEaWvybszDG4tgxCJuRpV8VGuvNaI1fAnI4lUJzDG55MXcOH4JZcQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "get-intrinsic": "^1.2.1" + } + }, + "node_modules/object.values": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.7.tgz", + "integrity": "sha512-aU6xnDFYT3x17e/f0IiiwlGPTy2jzMySGfUB4fq6z7CV8l85CWHDk5ErhyhpfDHhrOMwGFhSQkhMGHaIotA6Ng==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/onetime": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", + "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", + "dev": true, + "dependencies": { + "mimic-fn": "^4.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/opener": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/opener/-/opener-1.5.2.tgz", + "integrity": "sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A==", + "dev": true, + "bin": { + "opener": "bin/opener-bin.js" + } + }, + "node_modules/optionator": { + "version": "0.9.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", + "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==", + "dev": true, + "dependencies": { + "@aashutoshrathi/word-wrap": "^1.2.3", + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/p-each-series": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-each-series/-/p-each-series-3.0.0.tgz", + "integrity": "sha512-lastgtAdoH9YaLyDa5i5z64q+kzOcQHsQ5SsZJD3q0VEyI8mq872S3geuNbRUQLVAE9siMfgKrpj7MloKFHruw==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-filter": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-filter/-/p-filter-4.1.0.tgz", + "integrity": "sha512-37/tPdZ3oJwHaS3gNJdenCDB3Tz26i9sjhnguBtvN0vYlRIiDNnvTWkuh+0hETV9rLPdJ3rlL3yVOYPIAnM8rw==", + "dev": true, + "dependencies": { + "p-map": "^7.0.1" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-is-promise": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-is-promise/-/p-is-promise-3.0.0.tgz", + "integrity": "sha512-Wo8VsW4IRQSKVXsJCn7TomUaVtyfjVDn3nUP7kE967BQk0CwFpdbZs0X0uk5sW9mkBa9eNM7hCMaG93WUAwxYQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-map": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-7.0.2.tgz", + "integrity": "sha512-z4cYYMMdKHzw4O5UkWJImbZynVIo0lSGTXc7bzB1e/rrDqkgGUNysK/o4bTr+0+xKvvLoTyGqYC4Fgljy9qe1Q==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-reduce": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-reduce/-/p-reduce-3.0.0.tgz", + "integrity": "sha512-xsrIUgI0Kn6iyDYm9StOpOeK29XM1aboGji26+QEortiFST1hGZaUQOLhtEbqHErPpGW/aSz6allwK2qcptp0Q==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-try": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", + "integrity": "sha512-U1etNYuMJoIz3ZXSrrySFjsXQTWOx2/jdi86L+2pRvph/qMKL6sbcCYdH23fqsbm8TH2Gn0OybpT4eSFlCVHww==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parse-ms": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-ms/-/parse-ms-4.0.0.tgz", + "integrity": "sha512-TXfryirbmq34y8QBwgqCVLi+8oA3oWx2eAnSn62ITyEhEYaWRlVZ2DvMM9eZbMs/RfxPu/PK/aBLyGj4IrqMHw==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parse5": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-5.1.1.tgz", + "integrity": "sha512-ugq4DFI0Ptb+WWjAdOK16+u/nHfiIrcE+sh8kZMaM0WllQKLI9rOUq6c2b7cwPkXdzfQESqvoqK6ug7U/Yyzug==", + "dev": true + }, + "node_modules/parse5-htmlparser2-tree-adapter": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-6.0.1.tgz", + "integrity": "sha512-qPuWvbLgvDGilKc5BoicRovlT4MtYT6JfJyBOMDsKoiT+GiuP5qyrPCnR9HcPECIJJmZh5jRndyNThnhhb/vlA==", + "dev": true, + "dependencies": { + "parse5": "^6.0.1" + } + }, + "node_modules/parse5-htmlparser2-tree-adapter/node_modules/parse5": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", + "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==", + "dev": true + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true + }, + "node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/picocolors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", + "dev": true + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/pkg-conf": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/pkg-conf/-/pkg-conf-2.1.0.tgz", + "integrity": "sha512-C+VUP+8jis7EsQZIhDYmS5qlNtjv2yP4SNtjXK9AP1ZcTRlnSfuumaTnRfYZnYgUUYVIKqL0fRvmUGDV2fmp6g==", + "dev": true, + "dependencies": { + "find-up": "^2.0.0", + "load-json-file": "^4.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/pkg-conf/node_modules/find-up": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha512-NWzkk0jSJtTt08+FBFMvXoeZnOJD+jTtsRmBYbAIzJdX6l7dLgR7CTubCM5/eDdPUBvLCeVasP1brfVR/9/EZQ==", + "dev": true, + "dependencies": { + "locate-path": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/pkg-conf/node_modules/locate-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", + "integrity": "sha512-NCI2kiDkyR7VeEKm27Kda/iQHyKJe1Bu0FlTbYp3CqJu+9IFe9bLyAjMxf5ZDDbEg+iMPzB5zYyUTSm8wVTKmA==", + "dev": true, + "dependencies": { + "p-locate": "^2.0.0", + "path-exists": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/pkg-conf/node_modules/p-limit": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", + "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", + "dev": true, + "dependencies": { + "p-try": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/pkg-conf/node_modules/p-locate": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", + "integrity": "sha512-nQja7m7gSKuewoVRen45CtVfODR3crN3goVQ0DDZ9N3yHxgpkuBhZqsaiotSQRrADUrne346peY7kT3TSACykg==", + "dev": true, + "dependencies": { + "p-limit": "^1.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/pkg-conf/node_modules/path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/playwright": { + "version": "1.44.0", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.44.0.tgz", + "integrity": "sha512-F9b3GUCLQ3Nffrfb6dunPOkE5Mh68tR7zN32L4jCk4FjQamgesGay7/dAAe1WaMEGV04DkdJfcJzjoCKygUaRQ==", + "dev": true, + "dependencies": { + "playwright-core": "1.44.0" + }, + "bin": { + "playwright": "cli.js" + }, + "engines": { + "node": ">=16" + }, + "optionalDependencies": { + "fsevents": "2.3.2" + } + }, + "node_modules/playwright-core": { + "version": "1.44.0", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.44.0.tgz", + "integrity": "sha512-ZTbkNpFfYcGWohvTTl+xewITm7EOuqIqex0c7dNZ+aXsbrLj0qI8XlGKfPpipjm0Wny/4Lt4CJsWJk1stVS5qQ==", + "dev": true, + "bin": { + "playwright-core": "cli.js" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/portfinder": { + "version": "1.0.32", + "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.32.tgz", + "integrity": "sha512-on2ZJVVDXRADWE6jnQaX0ioEylzgBpQk8r55NE4wjXW1ZxO+BgDlY6DXwj20i0V8eB4SenDQ00WEaxfiIQPcxg==", + "dev": true, + "dependencies": { + "async": "^2.6.4", + "debug": "^3.2.7", + "mkdirp": "^0.5.6" + }, + "engines": { + "node": ">= 0.12.0" + } + }, + "node_modules/portfinder/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/possible-typed-array-names": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz", + "integrity": "sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/postcss": { + "version": "8.4.38", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.38.tgz", + "integrity": "sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "nanoid": "^3.3.7", + "picocolors": "^1.0.0", + "source-map-js": "^1.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/postcss-resolve-nested-selector": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/postcss-resolve-nested-selector/-/postcss-resolve-nested-selector-0.1.1.tgz", + "integrity": "sha512-HvExULSwLqHLgUy1rl3ANIqCsvMS0WHss2UOsXhXnQaZ9VCc2oBvIpXrl00IUFT5ZDITME0o6oiXeiHr2SAIfw==", + "dev": true + }, + "node_modules/postcss-safe-parser": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/postcss-safe-parser/-/postcss-safe-parser-6.0.0.tgz", + "integrity": "sha512-FARHN8pwH+WiS2OPCxJI8FuRJpTVnn6ZNFiqAM2aeW2LwTHWWmWgIyKC6cUo0L8aeKiF/14MNvnpls6R2PBeMQ==", + "dev": true, + "engines": { + "node": ">=12.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + "peerDependencies": { + "postcss": "^8.3.3" + } + }, + "node_modules/postcss-selector-parser": { + "version": "6.0.13", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.13.tgz", + "integrity": "sha512-EaV1Gl4mUEV4ddhDnv/xtj7sxwrwxdetHdWUGnT4VJQf+4d05v6lHYZr8N573k5Z0BViss7BDhfWtKS3+sfAqQ==", + "dev": true, + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", + "dev": true + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/pretty-ms": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/pretty-ms/-/pretty-ms-9.0.0.tgz", + "integrity": "sha512-E9e9HJ9R9NasGOgPaPE8VMeiPKAyWR5jcFpNnwIejslIhWqdqOrb2wShBsncMPUb+BcCd2OPYfh7p2W6oemTng==", + "dev": true, + "dependencies": { + "parse-ms": "^4.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "dev": true + }, + "node_modules/proto-list": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz", + "integrity": "sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==", + "dev": true + }, + "node_modules/punycode": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", + "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/qs": { + "version": "6.12.1", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.12.1.tgz", + "integrity": "sha512-zWmv4RSuB9r2mYQw3zxQuHWeU+42aKi1wWig/j4ele4ygELZ7PEO6MM7rim9oAQH2A5MWfsAVf/jPvTPgCbvUQ==", + "dev": true, + "dependencies": { + "side-channel": "^1.0.6" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/quick-lru": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", + "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "dev": true, + "dependencies": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "bin": { + "rc": "cli.js" + } + }, + "node_modules/rc/node_modules/strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/read-package-up": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/read-package-up/-/read-package-up-11.0.0.tgz", + "integrity": "sha512-MbgfoNPANMdb4oRBNg5eqLbB2t2r+o5Ua1pNt8BqGp4I0FJZhuVSOj3PaBPni4azWuSzEdNn2evevzVmEk1ohQ==", + "dev": true, + "dependencies": { + "find-up-simple": "^1.0.0", + "read-pkg": "^9.0.0", + "type-fest": "^4.6.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/read-package-up/node_modules/hosted-git-info": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-7.0.2.tgz", + "integrity": "sha512-puUZAUKT5m8Zzvs72XWy3HtvVbTWljRE66cP60bxJzAqf2DgICo7lYTY2IHUmLnNpjYvw5bvmoHvPc0QO2a62w==", + "dev": true, + "dependencies": { + "lru-cache": "^10.0.1" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/read-package-up/node_modules/lru-cache": { + "version": "10.2.2", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.2.tgz", + "integrity": "sha512-9hp3Vp2/hFQUiIwKo8XCeFVnrg8Pk3TYNPIR7tJADKi5YfcF7vEaK7avFHTlSy3kOKYaJQaalfEo6YuXdceBOQ==", + "dev": true, + "engines": { + "node": "14 || >=16.14" + } + }, + "node_modules/read-package-up/node_modules/normalize-package-data": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-6.0.1.tgz", + "integrity": "sha512-6rvCfeRW+OEZagAB4lMLSNuTNYZWLVtKccK79VSTf//yTY5VOCgcpH80O+bZK8Neps7pUnd5G+QlMg1yV/2iZQ==", + "dev": true, + "dependencies": { + "hosted-git-info": "^7.0.0", + "is-core-module": "^2.8.1", + "semver": "^7.3.5", + "validate-npm-package-license": "^3.0.4" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/read-package-up/node_modules/parse-json": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-8.1.0.tgz", + "integrity": "sha512-rum1bPifK5SSar35Z6EKZuYPJx85pkNaFrxBK3mwdfSJ1/WKbYrjoW/zTPSjRRamfmVX1ACBIdFAO0VRErW/EA==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.22.13", + "index-to-position": "^0.1.2", + "type-fest": "^4.7.1" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/read-package-up/node_modules/read-pkg": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-9.0.1.tgz", + "integrity": "sha512-9viLL4/n1BJUCT1NXVTdS1jtm80yDEgR5T4yCelII49Mbj0v1rZdKqj7zCiYdbB0CuCgdrvHcNogAKTFPBocFA==", + "dev": true, + "dependencies": { + "@types/normalize-package-data": "^2.4.3", + "normalize-package-data": "^6.0.0", + "parse-json": "^8.0.0", + "type-fest": "^4.6.0", + "unicorn-magic": "^0.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/read-package-up/node_modules/semver": { + "version": "7.6.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", + "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/read-package-up/node_modules/type-fest": { + "version": "4.18.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.18.2.tgz", + "integrity": "sha512-+suCYpfJLAe4OXS6+PPXjW3urOS4IoP9waSiLuXfLgqZODKw/aWwASvzqE886wA0kQgGy0mIWyhd87VpqIy6Xg==", + "dev": true, + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/read-pkg": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-6.0.0.tgz", + "integrity": "sha512-X1Fu3dPuk/8ZLsMhEj5f4wFAF0DWoK7qhGJvgaijocXxBmSToKfbFtqbxMO7bVjNA1dmE5huAzjXj/ey86iw9Q==", + "dev": true, + "dependencies": { + "@types/normalize-package-data": "^2.4.0", + "normalize-package-data": "^3.0.2", + "parse-json": "^5.2.0", + "type-fest": "^1.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/read-pkg-up": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-8.0.0.tgz", + "integrity": "sha512-snVCqPczksT0HS2EC+SxUndvSzn6LRCwpfSvLrIfR5BKDQQZMaI6jPRC9dYvYFDRAuFEAnkwww8kBBNE/3VvzQ==", + "dev": true, + "dependencies": { + "find-up": "^5.0.0", + "read-pkg": "^6.0.0", + "type-fest": "^1.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/read-pkg-up/node_modules/type-fest": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-1.4.0.tgz", + "integrity": "sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/read-pkg/node_modules/type-fest": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-1.4.0.tgz", + "integrity": "sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/readable-stream/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "dev": true + }, + "node_modules/redent": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/redent/-/redent-4.0.0.tgz", + "integrity": "sha512-tYkDkVVtYkSVhuQ4zBgfvciymHaeuel+zFKXShfDnFP5SyVEP7qo70Rf1jTOTCx3vGNAbnEi/xFkcfQVMIBWag==", + "dev": true, + "dependencies": { + "indent-string": "^5.0.0", + "strip-indent": "^4.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/regexp.prototype.flags": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.2.tgz", + "integrity": "sha512-NcDiDkTLuPR+++OCKB0nWafEmhg/Da8aUPLPMQbK+bxKKCm1/S5he+AqYa4PlMCVBalb4/yxIRub6qkEx5yJbw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.6", + "define-properties": "^1.2.1", + "es-errors": "^1.3.0", + "set-function-name": "^2.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/registry-auth-token": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-5.0.2.tgz", + "integrity": "sha512-o/3ikDxtXaA59BmZuZrJZDJv8NMDGSj+6j6XaeBmHw8eY1i1qd9+6H+LjVvQXx3HN6aRCGa1cUdJ9RaJZUugnQ==", + "dev": true, + "dependencies": { + "@pnpm/npm-conf": "^2.1.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/requires-port": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", + "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", + "dev": true + }, + "node_modules/resolve": { + "version": "1.22.4", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.4.tgz", + "integrity": "sha512-PXNdCiPqDqeUou+w1C2eTQbNfxKSuMxqTCuvlmmMsk1NWHL5fRrhY6Pl0qEYYc6+QqGClco1Qj8XnjPego4wfg==", + "dev": true, + "dependencies": { + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "dev": true, + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/safe-array-concat": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.2.tgz", + "integrity": "sha512-vj6RsCsWBCf19jIeHEfkRMw8DPiBb+DMXklQ/1SGDHOMlHdPUkZXFQ2YdplS23zESTijAcurb1aSgJA3AgMu1Q==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "get-intrinsic": "^1.2.4", + "has-symbols": "^1.0.3", + "isarray": "^2.0.5" + }, + "engines": { + "node": ">=0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/safe-regex-test": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.3.tgz", + "integrity": "sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "is-regex": "^1.1.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true + }, + "node_modules/secure-compare": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/secure-compare/-/secure-compare-3.0.1.tgz", + "integrity": "sha512-AckIIV90rPDcBcglUwXPF3kg0P0qmPsPXAj6BBEENQE1p5yA1xfmDJzfi1Tappj37Pv2mVbKpL3Z1T+Nn7k1Qw==", + "dev": true + }, + "node_modules/semantic-release": { + "version": "23.1.1", + "resolved": "https://registry.npmjs.org/semantic-release/-/semantic-release-23.1.1.tgz", + "integrity": "sha512-qqJDBhbtHsjUEMsojWKGuL5lQFCJuPtiXKEIlFKyTzDDGTAE/oyvznaP8GeOr5PvcqBJ6LQz4JCENWPLeehSpA==", + "dev": true, + "dependencies": { + "@semantic-release/commit-analyzer": "^12.0.0", + "@semantic-release/error": "^4.0.0", + "@semantic-release/github": "^10.0.0", + "@semantic-release/npm": "^12.0.0", + "@semantic-release/release-notes-generator": "^13.0.0", + "aggregate-error": "^5.0.0", + "cosmiconfig": "^9.0.0", + "debug": "^4.0.0", + "env-ci": "^11.0.0", + "execa": "^9.0.0", + "figures": "^6.0.0", + "find-versions": "^6.0.0", + "get-stream": "^6.0.0", + "git-log-parser": "^1.2.0", + "hook-std": "^3.0.0", + "hosted-git-info": "^7.0.0", + "import-from-esm": "^1.3.1", + "lodash-es": "^4.17.21", + "marked": "^12.0.0", + "marked-terminal": "^7.0.0", + "micromatch": "^4.0.2", + "p-each-series": "^3.0.0", + "p-reduce": "^3.0.0", + "read-package-up": "^11.0.0", + "resolve-from": "^5.0.0", + "semver": "^7.3.2", + "semver-diff": "^4.0.0", + "signale": "^1.2.1", + "yargs": "^17.5.1" + }, + "bin": { + "semantic-release": "bin/semantic-release.js" + }, + "engines": { + "node": ">=20.8.1" + } + }, + "node_modules/semantic-release/node_modules/cosmiconfig": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-9.0.0.tgz", + "integrity": "sha512-itvL5h8RETACmOTFc4UfIyB2RfEHi71Ax6E/PivVxq9NseKbOWpeyHEOIbmAw1rs8Ak0VursQNww7lf7YtUwzg==", + "dev": true, + "dependencies": { + "env-paths": "^2.2.1", + "import-fresh": "^3.3.0", + "js-yaml": "^4.1.0", + "parse-json": "^5.2.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/d-fischer" + }, + "peerDependencies": { + "typescript": ">=4.9.5" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/semantic-release/node_modules/hosted-git-info": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-7.0.2.tgz", + "integrity": "sha512-puUZAUKT5m8Zzvs72XWy3HtvVbTWljRE66cP60bxJzAqf2DgICo7lYTY2IHUmLnNpjYvw5bvmoHvPc0QO2a62w==", + "dev": true, + "dependencies": { + "lru-cache": "^10.0.1" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/semantic-release/node_modules/lru-cache": { + "version": "10.2.2", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.2.tgz", + "integrity": "sha512-9hp3Vp2/hFQUiIwKo8XCeFVnrg8Pk3TYNPIR7tJADKi5YfcF7vEaK7avFHTlSy3kOKYaJQaalfEo6YuXdceBOQ==", + "dev": true, + "engines": { + "node": "14 || >=16.14" + } + }, + "node_modules/semantic-release/node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/semantic-release/node_modules/semver": { + "version": "7.6.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", + "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/semver-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/semver-diff/-/semver-diff-4.0.0.tgz", + "integrity": "sha512-0Ju4+6A8iOnpL/Thra7dZsSlOHYAHIeMxfhWQRI1/VLcT3WDBZKKtQt/QkBOsiIN9ZpuvHE6cGZ0x4glCMmfiA==", + "dev": true, + "dependencies": { + "semver": "^7.3.5" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/semver-diff/node_modules/semver": { + "version": "7.6.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", + "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/semver-regex": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/semver-regex/-/semver-regex-4.0.5.tgz", + "integrity": "sha512-hunMQrEy1T6Jr2uEVjrAIqjwWcQTgOAcIM52C8MY1EZSD3DDNft04XzvYKPqjED65bNVVko0YI38nYeEHCX3yw==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/set-function-length": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "dev": true, + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/set-function-name": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz", + "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==", + "dev": true, + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "functions-have-names": "^1.2.3", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/side-channel": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", + "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4", + "object-inspect": "^1.13.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/signale": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/signale/-/signale-1.4.0.tgz", + "integrity": "sha512-iuh+gPf28RkltuJC7W5MRi6XAjTDCAPC/prJUpQoG4vIP3MJZ+GTydVnodXA7pwvTKb2cA0m9OFZW/cdWy/I/w==", + "dev": true, + "dependencies": { + "chalk": "^2.3.2", + "figures": "^2.0.0", + "pkg-conf": "^2.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/signale/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/signale/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/signale/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/signale/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true + }, + "node_modules/signale/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/signale/node_modules/figures": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", + "integrity": "sha512-Oa2M9atig69ZkfwiApY8F2Yy+tzMbazyvqv21R0NsSC8floSOC09BbT1ITWAdoMGQvJ/aZnR1KMwdx9tvHnTNA==", + "dev": true, + "dependencies": { + "escape-string-regexp": "^1.0.5" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/signale/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/signale/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/skin-tone": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/skin-tone/-/skin-tone-2.0.0.tgz", + "integrity": "sha512-kUMbT1oBJCpgrnKoSr0o6wPtvRWT9W9UKvGLwfJYO2WuahZRHOpEyL1ckyMGgMWh0UdpmaoFqKKD29WTomNEGA==", + "dev": true, + "dependencies": { + "unicode-emoji-modifier-base": "^1.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/slice-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", + "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" + } + }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-js": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz", + "integrity": "sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/spawn-error-forwarder": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/spawn-error-forwarder/-/spawn-error-forwarder-1.0.0.tgz", + "integrity": "sha512-gRjMgK5uFjbCvdibeGJuy3I5OYz6VLoVdsOJdA6wV0WlfQVLFueoqMxwwYD9RODdgb6oUIvlRlsyFSiQkMKu0g==", + "dev": true + }, + "node_modules/spdx-correct": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz", + "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==", + "dev": true, + "dependencies": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-exceptions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", + "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", + "dev": true + }, + "node_modules/spdx-expression-parse": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", + "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "dev": true, + "dependencies": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-license-ids": { + "version": "3.0.13", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.13.tgz", + "integrity": "sha512-XkD+zwiqXHikFZm4AX/7JSCXA98U5Db4AFd5XUg/+9UNtnH75+Z9KxtpYiJZx36mUDVOwH83pl7yvCer6ewM3w==", + "dev": true + }, + "node_modules/split2": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz", + "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==", + "dev": true, + "engines": { + "node": ">= 10.x" + } + }, + "node_modules/stream-combiner2": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/stream-combiner2/-/stream-combiner2-1.1.1.tgz", + "integrity": "sha512-3PnJbYgS56AeWgtKF5jtJRT6uFJe56Z0Hc5Ngg/6sI6rIt8iiMBTa9cvdyFfpMQjaVHr8dusbNeFGIIonxOvKw==", + "dev": true, + "dependencies": { + "duplexer2": "~0.1.0", + "readable-stream": "^2.0.2" + } + }, + "node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string.prototype.trim": { + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.9.tgz", + "integrity": "sha512-klHuCNxiMZ8MlsOihJhJEBJAiMVqU3Z2nEXWfWnIqjN0gEFS9J9+IxKozWWtQGcgoa1WUZzLjKPTr4ZHNFTFxw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.0", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimend": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.8.tgz", + "integrity": "sha512-p73uL5VCHCO2BZZ6krwwQE3kCzM7NKmis8S//xEC6fQonchbum4eP6kR4DLEjQFO3Wnj3Fuo8NM0kOSjVdHjZQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimstart": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz", + "integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/strip-final-newline": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-4.0.0.tgz", + "integrity": "sha512-aulFJcD6YK8V1G7iRB5tigAP4TsHBZZrOV8pjV++zdUwmeV8uzbY7yn6h9MswN62adStNZFuCIx4haBnRuMDaw==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/strip-indent": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-4.0.0.tgz", + "integrity": "sha512-mnVSV2l+Zv6BLpSD/8V87CW/y9EmmbYzGCIavsnsI6/nwn26DwffM/yztm30Z/I2DY9wdS3vXVCMnHDgZaVNoA==", + "dev": true, + "dependencies": { + "min-indent": "^1.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/style-search": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/style-search/-/style-search-0.1.0.tgz", + "integrity": "sha512-Dj1Okke1C3uKKwQcetra4jSuk0DqbzbYtXipzFlFMZtowbF1x7BKJwB9AayVMyFARvU8EDrZdcax4At/452cAg==", + "dev": true + }, + "node_modules/stylelint": { + "version": "15.10.3", + "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-15.10.3.tgz", + "integrity": "sha512-aBQMMxYvFzJJwkmg+BUUg3YfPyeuCuKo2f+LOw7yYbU8AZMblibwzp9OV4srHVeQldxvSFdz0/Xu8blq2AesiA==", + "dev": true, + "dependencies": { + "@csstools/css-parser-algorithms": "^2.3.1", + "@csstools/css-tokenizer": "^2.2.0", + "@csstools/media-query-list-parser": "^2.1.4", + "@csstools/selector-specificity": "^3.0.0", + "balanced-match": "^2.0.0", + "colord": "^2.9.3", + "cosmiconfig": "^8.2.0", + "css-functions-list": "^3.2.0", + "css-tree": "^2.3.1", + "debug": "^4.3.4", + "fast-glob": "^3.3.1", + "fastest-levenshtein": "^1.0.16", + "file-entry-cache": "^6.0.1", + "global-modules": "^2.0.0", + "globby": "^11.1.0", + "globjoin": "^0.1.4", + "html-tags": "^3.3.1", + "ignore": "^5.2.4", + "import-lazy": "^4.0.0", + "imurmurhash": "^0.1.4", + "is-plain-object": "^5.0.0", + "known-css-properties": "^0.28.0", + "mathml-tag-names": "^2.1.3", + "meow": "^10.1.5", + "micromatch": "^4.0.5", + "normalize-path": "^3.0.0", + "picocolors": "^1.0.0", + "postcss": "^8.4.27", + "postcss-resolve-nested-selector": "^0.1.1", + "postcss-safe-parser": "^6.0.0", + "postcss-selector-parser": "^6.0.13", + "postcss-value-parser": "^4.2.0", + "resolve-from": "^5.0.0", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "style-search": "^0.1.0", + "supports-hyperlinks": "^3.0.0", + "svg-tags": "^1.0.0", + "table": "^6.8.1", + "write-file-atomic": "^5.0.1" + }, + "bin": { + "stylelint": "bin/stylelint.mjs" + }, + "engines": { + "node": "^14.13.1 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/stylelint" + } + }, + "node_modules/stylelint-config-recommended": { + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/stylelint-config-recommended/-/stylelint-config-recommended-13.0.0.tgz", + "integrity": "sha512-EH+yRj6h3GAe/fRiyaoO2F9l9Tgg50AOFhaszyfov9v6ayXJ1IkSHwTxd7lB48FmOeSGDPLjatjO11fJpmarkQ==", + "dev": true, + "engines": { + "node": "^14.13.1 || >=16.0.0" + }, + "peerDependencies": { + "stylelint": "^15.10.0" + } + }, + "node_modules/stylelint-config-standard": { + "version": "34.0.0", + "resolved": "https://registry.npmjs.org/stylelint-config-standard/-/stylelint-config-standard-34.0.0.tgz", + "integrity": "sha512-u0VSZnVyW9VSryBG2LSO+OQTjN7zF9XJaAJRX/4EwkmU0R2jYwmBSN10acqZisDitS0CLiEiGjX7+Hrq8TAhfQ==", + "dev": true, + "dependencies": { + "stylelint-config-recommended": "^13.0.0" + }, + "engines": { + "node": "^14.13.1 || >=16.0.0" + }, + "peerDependencies": { + "stylelint": "^15.10.0" + } + }, + "node_modules/stylelint/node_modules/balanced-match": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-2.0.0.tgz", + "integrity": "sha512-1ugUSr8BHXRnK23KfuYS+gVMC3LB8QGH9W1iGtDPsNWoQbgtXSExkBu2aDR4epiGWZOjZsj6lDl/N/AqqTC3UA==", + "dev": true + }, + "node_modules/stylelint/node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/super-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/super-regex/-/super-regex-1.0.0.tgz", + "integrity": "sha512-CY8u7DtbvucKuquCmOFEKhr9Besln7n9uN8eFbwcoGYWXOMW07u2o8njWaiXt11ylS3qoGF55pILjRmPlbodyg==", + "dev": true, + "dependencies": { + "function-timeout": "^1.0.1", + "time-span": "^5.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-hyperlinks": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-3.0.0.tgz", + "integrity": "sha512-QBDPHyPQDRTy9ku4URNGY5Lah8PAaXs6tAAwp55sL5WCsSW7GIfdf6W5ixfziW+t7wh3GVvHyHHyQ1ESsoRvaA==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0", + "supports-color": "^7.0.0" + }, + "engines": { + "node": ">=14.18" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/svg-tags": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/svg-tags/-/svg-tags-1.0.0.tgz", + "integrity": "sha512-ovssysQTa+luh7A5Weu3Rta6FJlFBBbInjOh722LIt6klpU2/HtdUbszju/G4devcvk8PGt7FCLv5wftu3THUA==", + "dev": true + }, + "node_modules/table": { + "version": "6.8.1", + "resolved": "https://registry.npmjs.org/table/-/table-6.8.1.tgz", + "integrity": "sha512-Y4X9zqrCftUhMeH2EptSSERdVKt/nEdijTOacGD/97EKjhQ/Qs8RTlEGABSJNNN8lac9kheH+af7yAkEWlgneA==", + "dev": true, + "dependencies": { + "ajv": "^8.0.1", + "lodash.truncate": "^4.4.2", + "slice-ansi": "^4.0.0", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/table/node_modules/ajv": { + "version": "8.12.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", + "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/table/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true + }, + "node_modules/temp-dir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/temp-dir/-/temp-dir-3.0.0.tgz", + "integrity": "sha512-nHc6S/bwIilKHNRgK/3jlhDoIHcp45YgyiwcAk46Tr0LfEqGBVpmiAyuiuxeVE44m3mXnEeVhaipLOEWmH+Njw==", + "dev": true, + "engines": { + "node": ">=14.16" + } + }, + "node_modules/tempy": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/tempy/-/tempy-3.1.0.tgz", + "integrity": "sha512-7jDLIdD2Zp0bDe5r3D2qtkd1QOCacylBuL7oa4udvN6v2pqr4+LcCr67C8DR1zkpaZ8XosF5m1yQSabKAW6f2g==", + "dev": true, + "dependencies": { + "is-stream": "^3.0.0", + "temp-dir": "^3.0.0", + "type-fest": "^2.12.2", + "unique-string": "^3.0.0" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/tempy/node_modules/is-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", + "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", + "dev": true, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/tempy/node_modules/type-fest": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", + "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==", + "dev": true, + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/text-extensions": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/text-extensions/-/text-extensions-2.4.0.tgz", + "integrity": "sha512-te/NtwBwfiNRLf9Ijqx3T0nlqZiQ2XrrtBvu+cLL8ZRrGkO0NHTug8MYFKyoSrv/sHTaSKfilUkizV6XhxMJ3g==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", + "dev": true + }, + "node_modules/thenify": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", + "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", + "dev": true, + "dependencies": { + "any-promise": "^1.0.0" + } + }, + "node_modules/thenify-all": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", + "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==", + "dev": true, + "dependencies": { + "thenify": ">= 3.1.0 < 4" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", + "dev": true + }, + "node_modules/through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "dev": true, + "dependencies": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + }, + "node_modules/time-span": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/time-span/-/time-span-5.1.0.tgz", + "integrity": "sha512-75voc/9G4rDIJleOo4jPvN4/YC4GRZrY8yy1uU4lwrB3XEQbWve8zXoO5No4eFrGcTAMYyoY67p8jRQdtA1HbA==", + "dev": true, + "dependencies": { + "convert-hrtime": "^5.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", + "dev": true, + "peer": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/traverse": { + "version": "0.6.9", + "resolved": "https://registry.npmjs.org/traverse/-/traverse-0.6.9.tgz", + "integrity": "sha512-7bBrcF+/LQzSgFmT0X5YclVqQxtv7TDJ1f8Wj7ibBu/U6BMLeOpUxuZjV7rMc44UtKxlnMFigdhFAIszSX1DMg==", + "dev": true, + "dependencies": { + "gopd": "^1.0.1", + "typedarray.prototype.slice": "^1.0.3", + "which-typed-array": "^1.1.15" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/trim-newlines": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-4.1.1.tgz", + "integrity": "sha512-jRKj0n0jXWo6kh62nA5TEh3+4igKDXLvzBJcPpiizP7oOolUrYIxmVBG9TOtHYFHoddUk6YvAkGeGoSVTXfQXQ==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/tsconfig-paths": { + "version": "3.14.2", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.14.2.tgz", + "integrity": "sha512-o/9iXgCYc5L/JxCHPe3Hvh8Q/2xm5Z+p18PESBU6Ff33695QnCHBEjcytY2q19ua7Mbl/DavtBOLq+oG0RCL+g==", + "dev": true, + "dependencies": { + "@types/json5": "^0.0.29", + "json5": "^1.0.2", + "minimist": "^1.2.6", + "strip-bom": "^3.0.0" + } + }, + "node_modules/turbogrid": { + "version": "3.0.13", + "resolved": "https://registry.npmjs.org/turbogrid/-/turbogrid-3.0.13.tgz", + "integrity": "sha512-8owt3hf29VDyW9excRMGccq/cmqspmvg8Zt6JgXw2uuq65drl50KXtGQpGevIbqQMnvltyfyLLJjzNnWK7tCVA==", + "dev": true + }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/typed-array-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.2.tgz", + "integrity": "sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/typed-array-byte-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.1.tgz", + "integrity": "sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-byte-offset": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.2.tgz", + "integrity": "sha512-Ous0vodHa56FviZucS2E63zkgtgrACj7omjwd/8lTEMEPFFyjfixMZ1ZXenpgCFBBt4EC1J2XsyVS2gkG0eTFA==", + "dev": true, + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-length": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.6.tgz", + "integrity": "sha512-/OxDN6OtAk5KBpGb28T+HZc2M+ADtvRxXrKKbUwtsLgdoxgX13hyy7ek6bFRl5+aBs2yZzB0c4CnQfAtVypW/g==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13", + "possible-typed-array-names": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typedarray.prototype.slice": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/typedarray.prototype.slice/-/typedarray.prototype.slice-1.0.3.tgz", + "integrity": "sha512-8WbVAQAUlENo1q3c3zZYuy5k9VzBQvp8AX9WOtbvyWlLM1v5JaSRmjubLjzHF4JFtptjH/5c/i95yaElvcjC0A==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.0", + "es-errors": "^1.3.0", + "typed-array-buffer": "^1.0.2", + "typed-array-byte-offset": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/uglify-js": { + "version": "3.17.4", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.17.4.tgz", + "integrity": "sha512-T9q82TJI9e/C1TAxYvfb16xO120tMVFZrGA3f9/P4424DNu6ypK103y0GPFVa17yotwSyZW5iYXgjYHkGrJW/g==", + "dev": true, + "optional": true, + "bin": { + "uglifyjs": "bin/uglifyjs" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/unbox-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", + "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-bigints": "^1.0.2", + "has-symbols": "^1.0.3", + "which-boxed-primitive": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/unicode-emoji-modifier-base": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unicode-emoji-modifier-base/-/unicode-emoji-modifier-base-1.0.0.tgz", + "integrity": "sha512-yLSH4py7oFH3oG/9K+XWrz1pSi3dfUrWEnInbxMfArOfc1+33BlGPQtLsOYwvdMy11AwUBetYuaRxSPqgkq+8g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/unicorn-magic": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.1.0.tgz", + "integrity": "sha512-lRfVq8fE8gz6QMBuDM6a+LO3IAzTi05H6gCVaUpir2E1Rwpo4ZUog45KpNXKC/Mn3Yb9UDuHumeFTo9iV/D9FQ==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/union": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/union/-/union-0.5.0.tgz", + "integrity": "sha512-N6uOhuW6zO95P3Mel2I2zMsbsanvvtgn6jVqJv4vbVcz/JN0OkL9suomjQGmWtxJQXOCqUJvquc1sMeNz/IwlA==", + "dev": true, + "dependencies": { + "qs": "^6.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/unique-string": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-3.0.0.tgz", + "integrity": "sha512-VGXBUVwxKMBUznyffQweQABPRRW1vHZAbadFZud4pLFAqRGvv/96vafgjWFqzourzr8YonlQiPgH0YCJfawoGQ==", + "dev": true, + "dependencies": { + "crypto-random-string": "^4.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/universal-user-agent": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-7.0.2.tgz", + "integrity": "sha512-0JCqzSKnStlRRQfCdowvqy3cy0Dvtlb8xecj/H8JFZuCze4rwjPZQOgvFvn0Ws/usCHQFGpyr+pB9adaGwXn4Q==", + "dev": true + }, + "node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.0.13", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz", + "integrity": "sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "peer": true, + "dependencies": { + "escalade": "^3.1.1", + "picocolors": "^1.0.0" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/url-join": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/url-join/-/url-join-5.0.0.tgz", + "integrity": "sha512-n2huDr9h9yzd6exQVnH/jU5mr+Pfx08LRXXZhkLLetAMESRj+anQsTAh940iMrIetKAmry9coFuZQ2jY8/p3WA==", + "dev": true, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "dev": true + }, + "node_modules/validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "dev": true, + "dependencies": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "node_modules/whatwg-encoding": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-2.0.0.tgz", + "integrity": "sha512-p41ogyeMUrw3jWclHWTQg1k05DSVXPLcVxRTYsXUk+ZooOCZLcoYgPZ/HL/D/N+uQPOtcp1me1WhBEaX02mhWg==", + "dev": true, + "dependencies": { + "iconv-lite": "0.6.3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/which-boxed-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", + "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", + "dev": true, + "dependencies": { + "is-bigint": "^1.0.1", + "is-boolean-object": "^1.1.0", + "is-number-object": "^1.0.4", + "is-string": "^1.0.5", + "is-symbol": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-typed-array": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.15.tgz", + "integrity": "sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==", + "dev": true, + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==", + "dev": true + }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true + }, + "node_modules/write-file-atomic": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-5.0.1.tgz", + "integrity": "sha512-+QU2zd6OTD8XWIJCbffaiQeH9U73qIqafo1x6V1snCWYGJf6cVE0cDR4D8xRzcEnfI21IFrUPzPGtcPf8AC+Rw==", + "dev": true, + "dependencies": { + "imurmurhash": "^0.1.4", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "dev": true, + "engines": { + "node": ">=0.4" + } + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "dev": true, + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-parser": { + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/yargs/node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/yoctocolors": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/yoctocolors/-/yoctocolors-2.0.2.tgz", + "integrity": "sha512-Ct97huExsu7cWeEjmrXlofevF8CvzUglJ4iGUet5B8xn1oumtAZBpHU4GzYuoE6PVqcZ5hghtBrSlhwHuR1Jmw==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 00000000..2c2741cc --- /dev/null +++ b/package.json @@ -0,0 +1,47 @@ +{ + "name": "@adobe/aem-experimentation", + "version": "1.0.1", + "main": "src/index.js", + "scripts": { + "lint:js": "eslint src", + "lint:css": "stylelint src/**/*.css", + "lint": "npm run lint:js && npm run lint:css", + "start": "http-server . -p 3000", + "test": "playwright test" + }, + "repository": { + "type": "git", + "url": "git+ssh://git@github.com/adobe/aem-experimentation.git" + }, + "author": "Adobe Inc.", + "license": "Apache-2.0", + "keywords": [ + "aem", + "experimentation", + "experience", + "decisioning", + "plugin", + "campaigns", + "audiences" + ], + "bugs": { + "url": "https://github.com/adobe/aem-experimentation/issues" + }, + "homepage": "https://github.com/adobe/aem-experimentation#readme", + "devDependencies": { + "@babel/eslint-parser": "7.22.15", + "@playwright/test": "1.44.0", + "@semantic-release/changelog": "6.0.3", + "@semantic-release/git": "10.0.1", + "@semantic-release/npm": "12.0.1", + "eslint": "8.48.0", + "eslint-config-airbnb-base": "15.0.0", + "eslint-plugin-import": "2.28.1", + "http-server": "14.1.1", + "monocart-coverage-reports": "2.8.2", + "semantic-release": "23.1.1", + "stylelint": "15.10.3", + "stylelint-config-standard": "34.0.0" + }, + "private": true +} diff --git a/playwright.config.js b/playwright.config.js new file mode 100644 index 00000000..b3a6d4a2 --- /dev/null +++ b/playwright.config.js @@ -0,0 +1,54 @@ +/* eslint-disable import/no-extraneous-dependencies */ +import { defineConfig, devices } from '@playwright/test'; + +/** + * Read environment variables from file. + * https://github.com/motdotla/dotenv + */ +// require('dotenv').config(); + +/** + * @see https://playwright.dev/docs/test-configuration + */ +export default defineConfig({ + testDir: './tests', + /* Run tests in files in parallel */ + fullyParallel: true, + /* Fail the build on CI if you accidentally left test.only in the source code. */ + forbidOnly: !!process.env.CI, + /* Retry on CI only */ + retries: process.env.CI ? 2 : 0, + /* Opt out of parallel tests on CI. */ + workers: process.env.CI ? 1 : undefined, + /* Reporter to use. See https://playwright.dev/docs/test-reporters */ + reporter: process.env.CI ? 'line' : 'html', + use: { + /* Base URL to use in actions like `await page.goto('/')`. */ + baseURL: 'http://127.0.0.1:3000/', + + /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ + trace: 'on-first-retry', + }, + + globalSetup: './tests/setup.js', + globalTeardown: './tests/teardown.js', + + /* Configure the tests for the top 3 browsers that access the site */ + projects: [ + { + name: 'Desktop Chrome', + use: { ...devices['Desktop Chrome'] }, + }, + ], + + timeout: 10000, + + // Run your local dev server before starting the tests + webServer: { + command: 'npm run start', + url: 'http://127.0.0.1:3000', + reuseExistingServer: !process.env.CI, + stdout: 'ignore', + stderr: 'pipe', + }, +}); diff --git a/src/index.js b/src/index.js new file mode 100644 index 00000000..b8ce4fb9 --- /dev/null +++ b/src/index.js @@ -0,0 +1,888 @@ +/* + * Copyright 2024 Adobe. All rights reserved. + * This file is licensed to you under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under + * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS + * OF ANY KIND, either express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ + +let isDebugEnabled; +export function setDebugMode(url, pluginOptions) { + const { host, hostname, origin } = url; + const { isProd, prodHost } = pluginOptions; + isDebugEnabled = (url.hostname === 'localhost' + || url.hostname.endsWith('.page') + || (typeof isProd === 'function' && !isProd()) + || (prodHost && ![host, hostname, origin].includes(prodHost)) + || false); + return isDebugEnabled; +} + +export function debug(...args) { + if (isDebugEnabled) { + // eslint-disable-next-line no-console + console.debug.call(this, '[aem-experimentation]', ...args); + } +} + +export const DEFAULT_OPTIONS = { + + // Audiences related properties + audiences: {}, + audiencesMetaTagPrefix: 'audience', + audiencesQueryParameter: 'audience', + + // Campaigns related properties + campaignsMetaTagPrefix: 'campaign', + campaignsQueryParameter: 'campaign', + + // Experimentation related properties + experimentsMetaTagPrefix: 'experiment', + experimentsQueryParameter: 'experiment', +}; + +/** + * Converts a given comma-seperate string to an array. + * @param {String|String[]} str The string to convert + * @returns an array representing the converted string + */ +export function stringToArray(str) { + if (Array.isArray(str)) { + return str; + } + return str ? str.split(/[,\n]/).filter((s) => s.trim()) : []; +} + +/** + * Sanitizes a name for use as class name. + * @param {String} name The unsanitized name + * @returns {String} The class name + */ +export function toClassName(name) { + return typeof name === 'string' + ? name.toLowerCase().replace(/[^0-9a-z]/gi, '-').replace(/-+/g, '-').replace(/^-|-$/g, '') + : ''; +} + +/** + * Sanitizes a name for use as a js property name. + * @param {String} name The unsanitized name + * @returns {String} The camelCased name + */ +export function toCamelCase(name) { + return toClassName(name).replace(/-([a-z])/g, (g) => g[1].toUpperCase()); +} + +/** + * Retrieves the content of metadata tags. + * @param {String} name The metadata name (or property) + * @returns {String} The metadata value(s) + */ +export function getMetadata(name) { + const meta = [...document.head.querySelectorAll(`meta[name="${name}"]`)].map((m) => m.content).join(', '); + return meta || ''; +} + +/** + * Gets all the metadata elements that are in the given scope. + * @param {String} scope The scope/prefix for the metadata + * @returns a map of key/value pairs for the given scope + */ +export function getAllMetadata(scope) { + const value = getMetadata(scope); + return [...document.head.querySelectorAll(`meta[name^="${scope}-"]`)] + .reduce((res, meta) => { + const key = toCamelCase(meta.name.substring(scope.length + 1)); + res[key] = meta.getAttribute('content'); + return res; + }, value ? { value } : {}); +} + +/** + * Gets all the data attributes that are in the given scope. + * @param {String} scope The scope/prefix for the metadata + * @returns a map of key/value pairs for the given scope + */ +// eslint-disable-next-line no-unused-vars +function getAllDataAttributes(el, scope) { + return el.getAttributeNames() + .filter((attr) => attr === `data-${scope}` || attr.startsWith(`data-${scope}-`)) + .reduce((res, attr) => { + const key = attr === `data-${scope}` ? 'value' : attr.replace(`data-${scope}-`, ''); + res[key] = el.getAttribute(attr); + return res; + }, {}); +} + +/** + * Gets all the query parameters that are in the given scope. + * @param {String} scope The scope/prefix for the metadata + * @returns a map of key/value pairs for the given scope + */ +function getAllQueryParameters(scope) { + const usp = new URLSearchParams(window.location.search); + return [...usp.entries()] + .filter(([param]) => param === scope || param.startsWith(`${scope}-`)) + .reduce((res, [param, value]) => { + const key = param === scope ? 'value' : param.replace(`${scope}-`, ''); + if (res[key]) { + res[key] = [].concat(res[key], value); + } else { + res[key] = value; + } + return res; + }, {}); +} + +/** + * Extracts the config from a block that is in the given scope. + * @param {HTMLElement} block The block element + * @returns a map of key/value pairs for the given scope + */ +// eslint-disable-next-line import/prefer-default-export +function getAllSectionMeta(block, scope) { + const config = {}; + block.querySelectorAll(':scope > div').forEach((row) => { + if (row.children) { + const cols = [...row.children]; + if (cols[1]) { + const col = cols[1]; + let key = toClassName(cols[0].textContent); + if (key !== scope && !key.startsWith(`${scope}-`)) { + return; + } + key = key === scope ? 'value' : key.replace(`${scope}-`, ''); + let value = ''; + if (col.querySelector('a')) { + const as = [...col.querySelectorAll('a')]; + if (as.length === 1) { + value = as[0].href; + } else { + value = as.map((a) => a.href); + } + } else if (col.querySelector('p')) { + const ps = [...col.querySelectorAll('p')]; + if (ps.length === 1) { + value = ps[0].textContent; + } else { + value = ps.map((p) => p.textContent); + } + } else value = row.children[1].textContent; + config[key] = value; + } + } + }); + return config; +} + +/** + * Replaces element with content from path + * @param {String} path + * @param {HTMLElement} el + * @return Returns the path that was loaded or null if the loading failed + */ +async function replaceInner(path, el) { + try { + const resp = await fetch(path); + if (!resp.ok) { + // eslint-disable-next-line no-console + console.log('error loading content:', resp); + return null; + } + const html = await resp.text(); + // parse with DOMParser to guarantee valid HTML, and no script execution(s) + const dom = new DOMParser().parseFromString(html, 'text/html'); + // eslint-disable-next-line no-param-reassign + const newEl = dom.querySelector(el.tagName === 'MAIN' ? 'main' : 'main > div'); + el.innerHTML = newEl.innerHTML; + return path; + } catch (e) { + // eslint-disable-next-line no-console + console.log(`error loading content: ${path}`, e); + } + return null; +} + +/** + * Checks if any of the configured audiences on the page can be resolved. + * @param {String[]} pageAudiences a list of configured audiences for the page + * @param {Object} options the plugin options + * @returns Returns the names of the resolved audiences, or `null` if no audience is configured + */ +export async function getResolvedAudiences(pageAudiences, options) { + if (!pageAudiences.length || !Object.keys(options.audiences).length) { + return null; + } + // If we have a forced audience set in the query parameters (typically for simulation purposes) + // we check if it is applicable + const usp = new URLSearchParams(window.location.search); + const forcedAudience = usp.has(options.audiencesQueryParameter) + ? toClassName(usp.get(options.audiencesQueryParameter)) + : null; + if (forcedAudience) { + return pageAudiences.includes(forcedAudience) ? [forcedAudience] : []; + } + + // Otherwise, return the list of audiences that are resolved on the page + const results = await Promise.all( + pageAudiences + .map((key) => { + if (options.audiences[key] && typeof options.audiences[key] === 'function') { + return options.audiences[key](); + } + return false; + }), + ); + return pageAudiences.filter((_, i) => results[i]); +} + +/** + * Calculates percentage split for variants where the percentage split is not + * explicitly configured. + * Substracts from 100 the explicitly configured percentage splits, + * and divides the remaining percentage, among the variants without explicit + * percentage split configured + * @param {Array} variant objects + */ +function inferEmptyPercentageSplits(variants) { + const variantsWithoutPercentage = []; + + const remainingPercentage = variants.reduce((result, variant) => { + if (!variant.percentageSplit) { + variantsWithoutPercentage.push(variant); + } + const newResult = result - parseFloat(variant.percentageSplit || 0); + return newResult; + }, 1); + if (variantsWithoutPercentage.length) { + const missingPercentage = remainingPercentage / variantsWithoutPercentage.length; + variantsWithoutPercentage.forEach((v) => { + v.percentageSplit = missingPercentage.toFixed(4); + }); + } +} + +/** + * Converts the experiment config to a decision policy + * @param {Object} config The experiment config + * @returns a decision policy for the experiment config + */ +function toDecisionPolicy(config) { + const decisionPolicy = { + id: 'content-experimentation-policy', + rootDecisionNodeId: 'n1', + decisionNodes: [{ + id: 'n1', + type: 'EXPERIMENTATION', + experiment: { + id: config.id, + identityNamespace: 'ECID', + randomizationUnit: 'DEVICE', + treatments: Object.entries(config.variants).map(([key, props]) => ({ + id: key, + allocationPercentage: Number(props.percentageSplit) * 100, + })), + }, + }], + }; + return decisionPolicy; +} + +/** + * Creates an instance of a modification handler that will be responsible for applying the desired + * personalized experience. + * + * @param {Object} overrides The config overrides + * @param {Function} metadataToConfig a function that will handle the parsing of the metadata + * @param {Function} getExperienceUrl a function that returns the URL to the experience + * @param {Object} pluginOptions the plugin options + * @param {Function} cb the callback to handle the final steps + * @returns the modification handler + */ +function createModificationsHandler( + overrides, + metadataToConfig, + getExperienceUrl, + pluginOptions, + cb, +) { + return async (el, metadata) => { + const config = await metadataToConfig(pluginOptions, metadata, overrides); + if (!config) { + return null; + } + const ns = { config, el }; + const url = await getExperienceUrl(ns.config); + let res; + if (url && new URL(url, window.location.origin).pathname !== window.location.pathname) { + res = await replaceInner(url, el); + } else { + res = url; + } + cb(el.tagName === 'MAIN' ? document.body : ns.el, ns.config, res ? url : null); + if (res) { + ns.servedExperience = url; + } + return ns; + }; +} + +/** + * Rename plural properties on the object to singular. + * @param {Object} obj The object + * @param {String[]} props The properties to rename. + * @returns the object with plural properties renamed. + */ +function depluralizeProps(obj, props = []) { + props.forEach((prop) => { + if (obj[`${prop}s`]) { + obj[prop] = obj[`${prop}s`]; + delete obj[`${prop}s`]; + } + }); + return obj; +} + +/** + * Fetch the configuration entries from a JSON manifest. + * @param {String} urlString the URL to load + * @returns the list of entries that apply to the current page + */ +async function getManifestEntriesForCurrentPage(urlString) { + try { + const url = new URL(urlString, window.location.origin); + const response = await fetch(url); + const json = await response.json(); + return json.data + .map((entry) => Object.keys(entry).reduce((res, k) => { + res[k.toLowerCase()] = entry[k]; + return res; + }, {})) + .filter((entry) => (!entry.page && !entry.pages) + || entry.page === window.location.pathname + || entry.pages === window.location.pathname) + .filter((entry) => entry.selector || entry.selectors) + .filter((entry) => entry.url || entry.urls) + .map((entry) => depluralizeProps(entry, ['page', 'selector', 'url'])); + } catch (err) { + // eslint-disable-next-line no-console + console.warn('Cannot apply manifest: ', urlString, err); + } + return null; +} + +/** + * Watches the page for injected DOM elements and automatically applies the fragment customizations + */ +function watchMutationsAndApplyFragments( + ns, + scope, + entries, + aggregator, + getExperienceUrl, + pluginOptions, + metadataToConfig, + overrides, + cb, +) { + if (!entries.length) { + return; + } + + new MutationObserver(async (_, observer) => { + // eslint-disable-next-line no-restricted-syntax + for (const entry of entries) { + // eslint-disable-next-line no-await-in-loop + const config = await metadataToConfig(pluginOptions, entry, overrides); + if (!config || entry.isApplied) { + return; + } + const el = scope.querySelector(entry.selector); + if (!el) { + return; + } + entry.isApplied = true; + const fragmentNS = { config, el, type: 'fragment' }; + // eslint-disable-next-line no-await-in-loop + const url = await getExperienceUrl(fragmentNS.config); + let res; + if (url && new URL(url, window.location.origin).pathname !== window.location.pathname) { + // eslint-disable-next-line no-await-in-loop + res = await replaceInner(url, el); + } else { + res = url; + } + cb(el.tagName === 'MAIN' ? document.body : fragmentNS.el, fragmentNS.config, res ? url : null); + if (res) { + fragmentNS.servedExperience = url; + } + debug('fragment', ns, fragmentNS); + aggregator.push(fragmentNS); + } + if (entries.every((entry) => entry.isApplied)) { + observer.disconnect(); + } + }).observe(scope, { childList: true, subtree: true }); +} + +/** + * Apply the page modifications for the specified type. + * + * @param {String} ns the type of modifications to do + * @param {String} paramNS the query parameter namespace + * @param {Object} pluginOptions the plugin options + * @param {Function} metadataToConfig a function that will handle the parsing of the metadata + * @param {Function} manifestToConfig a function that will handle the parsing of the manifest + * @param {Function} getExperienceUrl a function that returns the URL to the experience + * @param {Function} cb the callback to handle the final steps + * @returns an object containing the details of the page modifications that where applied + */ +async function applyAllModifications( + type, + paramNS, + pluginOptions, + metadataToConfig, + manifestToConfig, + getExperienceUrl, + cb, +) { + const modificationsHandler = createModificationsHandler( + getAllQueryParameters(paramNS), + metadataToConfig, + getExperienceUrl, + pluginOptions, + cb, + ); + + const configs = []; + + // Full-page modifications + const pageMetadata = getAllMetadata(type); + const pageNS = await modificationsHandler( + document.querySelector('main'), + pageMetadata, + ); + if (pageNS) { + pageNS.type = 'page'; + configs.push(pageNS); + debug('page', type, pageNS); + } + + // Section-level modifications + let sectionMetadata; + await Promise.all([...document.querySelectorAll('.section-metadata')] + .map(async (sm) => { + sectionMetadata = getAllSectionMeta(sm, type); + const sectionNS = await modificationsHandler( + sm.parentElement, + sectionMetadata, + ); + if (sectionNS) { + sectionNS.type = 'section'; + debug('section', type, sectionNS); + configs.push(sectionNS); + } + })); + + if (pageMetadata.manifest) { + let entries = await getManifestEntriesForCurrentPage(pageMetadata.manifest); + if (entries) { + entries = manifestToConfig(entries); + watchMutationsAndApplyFragments( + type, + document.body, + entries, + configs, + getExperienceUrl, + pluginOptions, + metadataToConfig, + getAllQueryParameters(paramNS), + cb, + ); + } + } + + return configs; +} + +function aggregateEntries(type, allowedMultiValuesProperties) { + return (entries) => entries.reduce((aggregator, entry) => { + Object.entries(entry).forEach(([key, value]) => { + if (!aggregator[key]) { + aggregator[key] = value; + } else if (aggregator[key] !== value) { + if (allowedMultiValuesProperties.includes(key)) { + aggregator[key] = [].concat(aggregator[key], value); + } else { + // eslint-disable-next-line no-console + console.warn(`Key "${key}" in the ${type} manifest must be the same for every variant on the page.`); + } + } + }); + return aggregator; + }, {}); +} + +/** + * Parses the experiment configuration from the metadata + */ +async function getExperimentConfig(pluginOptions, metadata, overrides) { + const id = toClassName(metadata.value || metadata.experiment); + if (!id) { + return null; + } + + let pages = metadata.variants || metadata.url; + + // Backward compatibility + if (!pages) { + pages = getMetadata('instant-experiment'); + } + if (metadata.audience) { + metadata.audiences = metadata.audience; + } + + const nbOfVariants = Number(pages); + pages = Number.isNaN(nbOfVariants) + ? stringToArray(pages).map((p) => new URL(p.trim(), window.location).pathname) + : new Array(nbOfVariants).fill(window.location.pathname); + if (!pages.length) { + return null; + } + + const audiences = stringToArray(metadata.audiences).map(toClassName); + + const splits = metadata.split + // custom split + ? stringToArray(metadata.split).map((i) => parseFloat(i) / 100) + // even split + : [...new Array(pages.length)].map(() => 1 / (pages.length + 1)); + + const variantNames = []; + variantNames.push('control'); + + const variants = {}; + variants.control = { + percentageSplit: '', + pages: [window.location.pathname], + label: 'Control', + }; + + pages.forEach((page, i) => { + const vname = `challenger-${i + 1}`; + variantNames.push(vname); + variants[vname] = { + percentageSplit: `${splits[i].toFixed(4)}`, + pages: [page], + blocks: [], + label: `Challenger ${i + 1}`, + }; + }); + inferEmptyPercentageSplits(Object.values(variants)); + + const resolvedAudiences = await getResolvedAudiences( + audiences, + pluginOptions, + ); + + const startDate = metadata.startDate ? new Date(metadata.startDate) : null; + const endDate = metadata.endDate ? new Date(metadata.endDate) : null; + + const config = { + id, + label: metadata.name || `Experiment ${metadata.value || metadata.experiment}`, + status: metadata.status || 'active', + audiences, + endDate, + resolvedAudiences, + startDate, + variants, + variantNames, + }; + + config.run = ( + // experiment is active or forced + (['active', 'on', 'true'].includes(toClassName(config.status)) || overrides.value) + // experiment has resolved audiences if configured + && (!resolvedAudiences || resolvedAudiences.length) + // forced audience resolves if defined + && (!overrides.audience || audiences.includes(overrides.audience)) + && (!startDate || startDate <= Date.now()) + && (!endDate || endDate > Date.now()) + ); + + if (!config.run) { + return config; + } + + const [, forcedVariant] = (Array.isArray(overrides.value) + ? overrides.value + : stringToArray(overrides.value)) + .map((value) => value?.split('/')) + .find(([experiment]) => toClassName(experiment) === config.id) || []; + if (variantNames.includes(toClassName(forcedVariant))) { + config.selectedVariant = toClassName(forcedVariant); + } else if (overrides.variant && variantNames.includes(overrides.variant)) { + config.selectedVariant = toClassName(overrides.variant); + } else { + // eslint-disable-next-line import/extensions + const { ued } = await import('./ued.js'); + const decision = ued.evaluateDecisionPolicy(toDecisionPolicy(config), {}); + config.selectedVariant = decision.items[0].id; + } + + return config; +} +/** + * Parses the campaign manifest. + */ +function parseExperimentManifest(entries) { + return Object.values(Object.groupBy( + entries.map((e) => depluralizeProps(e, ['experiment', 'variant', 'split'])), + ({ experiment }) => experiment, + )).map(aggregateEntries('experiment', ['split', 'url', 'variant'])); +} + +function getUrlFromExperimentConfig(config) { + return config.run + ? config.variants[config.selectedVariant].pages[0] + : null; +} + +async function runExperiment(document, pluginOptions) { + return applyAllModifications( + pluginOptions.experimentsMetaTagPrefix, + pluginOptions.experimentsQueryParameter, + pluginOptions, + getExperimentConfig, + parseExperimentManifest, + getUrlFromExperimentConfig, + (el, config, result) => { + const { id, selectedVariant, variantNames } = config; + const variant = result ? selectedVariant : variantNames[0]; + el.classList.add(`experiment-${toClassName(id)}`); + el.classList.add(`variant-${toClassName(variant)}`); + window.hlx?.rum?.sampleRUM('experiment', { + source: id, + target: variant, + }); + document.dispatchEvent(new CustomEvent('aem:experimentation', { + detail: { + element: el, + type: 'experiment', + experiment: id, + variant, + }, + })); + }, + ); +} + +/** + * Parses the campaign configuration from the metadata + */ +async function getCampaignConfig(pluginOptions, metadata, overrides) { + if (!Object.keys(metadata).length || (Object.keys(metadata).length === 1 && metadata.manifest)) { + return null; + } + + // Check UTM parameters + let campaign = overrides.value; + if (!campaign) { + const usp = new URLSearchParams(window.location.search); + if (usp.has('utm_campaign')) { + campaign = toClassName(usp.get('utm_campaign')); + } + } else { + campaign = toClassName(campaign); + } + + if (metadata.audience) { + metadata.audiences = metadata.audience; + } + + const audiences = stringToArray(metadata.audiences).map(toClassName); + const resolvedAudiences = await getResolvedAudiences( + audiences, + pluginOptions, + ); + if (resolvedAudiences && !resolvedAudiences.length) { + return null; + } + + const configuredCampaigns = Object.fromEntries(Object.entries(metadata.campaigns || metadata) + .filter(([key]) => !['audience', 'audiences'].includes(key))); + + return { + audiences, + configuredCampaigns, + resolvedAudiences, + selectedCampaign: campaign && (metadata.campaigns || metadata)[campaign] + ? campaign + : null, + }; +} + +/** + * Parses the campaign manifest. + */ +function parseCampaignManifest(entries) { + return Object.values(Object.groupBy( + entries.map((e) => depluralizeProps(e, ['campaign'])), + ({ selector }) => selector, + )) + .map(aggregateEntries('campaign', ['campaign', 'url'])) + .map((e) => { + const campaigns = e.campaign; + delete e.campaign; + e.campaigns = {}; + campaigns.forEach((a, i) => { + e.campaigns[toClassName(a)] = e.url[i]; + }); + delete e.url; + return e; + }); +} + +function getUrlFromCampaignConfig(config) { + return config.selectedCampaign + ? config.configuredCampaigns[config.selectedCampaign] + : null; +} + +async function runCampaign(document, pluginOptions) { + return applyAllModifications( + pluginOptions.campaignsMetaTagPrefix, + pluginOptions.campaignsQueryParameter, + pluginOptions, + getCampaignConfig, + parseCampaignManifest, + getUrlFromCampaignConfig, + (el, config, result) => { + const { selectedCampaign = 'default' } = config; + const campaign = result ? toClassName(selectedCampaign) : 'default'; + el.classList.add(`campaign-${campaign}`); + window.hlx?.rum?.sampleRUM('campaign', { + source: el.className, + target: campaign, + }); + document.dispatchEvent(new CustomEvent('aem:experimentation', { + detail: { + element: el, + type: 'campaign', + campaign, + }, + })); + }, + ); +} + +/** + * Parses the audience configuration from the metadata + */ +async function getAudienceConfig(pluginOptions, metadata, overrides) { + if (!Object.keys(metadata).length || (Object.keys(metadata).length === 1 && metadata.manifest)) { + return null; + } + + const configuredAudiencesName = Object.keys(metadata.audiences || metadata).map(toClassName); + const resolvedAudiences = await getResolvedAudiences( + configuredAudiencesName, + pluginOptions, + ); + if (resolvedAudiences && !resolvedAudiences.length) { + return false; + } + + const selectedAudience = overrides.audience || resolvedAudiences[0]; + + return { + configuredAudiences: metadata.audiences || metadata, + resolvedAudiences, + selectedAudience, + }; +} + +/** + * Parses the audience manifest. + */ +function parseAudienceManifest(entries) { + return Object.values(Object.groupBy( + entries.map((e) => depluralizeProps(e, ['audience'])), + ({ selector }) => selector, + )) + .map(aggregateEntries('audience', ['audience', 'url'])) + .map((e) => { + const audiences = e.audience; + delete e.audience; + e.audiences = {}; + audiences.forEach((a, i) => { + e.audiences[toClassName(a)] = e.url[i]; + }); + delete e.url; + return e; + }); +} + +function getUrlFromAudienceConfig(config) { + return config.selectedAudience + ? config.configuredAudiences[config.selectedAudience] + : null; +} + +async function serveAudience(document, pluginOptions) { + return applyAllModifications( + pluginOptions.audiencesMetaTagPrefix, + pluginOptions.audiencesQueryParameter, + pluginOptions, + getAudienceConfig, + parseAudienceManifest, + getUrlFromAudienceConfig, + (el, config, result) => { + const { selectedAudience = 'default' } = config; + const audience = result ? toClassName(selectedAudience) : 'default'; + el.classList.add(`audience-${audience}`); + window.hlx?.rum?.sampleRUM('audience', { + source: el.className, + target: audience, + }); + document.dispatchEvent(new CustomEvent('aem:experimentation', { + detail: { + element: el, + type: 'audience', + audience, + }, + })); + }, + ); +} + +export async function loadEager(document, options = {}) { + const pluginOptions = { ...DEFAULT_OPTIONS, ...options }; + setDebugMode(window.location, pluginOptions); + + const ns = window.aem || window.hlx || {}; + ns.audiences = await serveAudience(document, pluginOptions); + ns.experiments = await runExperiment(document, pluginOptions); + ns.campaigns = await runCampaign(document, pluginOptions); + + // Backward compatibility + ns.experiment = ns.experiments.find((e) => e.type === 'page'); + ns.audience = ns.audiences.find((e) => e.type === 'page'); + ns.campaign = ns.campaigns.find((e) => e.type === 'page'); +} + +export async function loadLazy(document, options = {}) { + const pluginOptions = { ...DEFAULT_OPTIONS, ...options }; + // do not show the experimentation pill on prod domains + if (!isDebugEnabled) { + return; + } + // eslint-disable-next-line import/no-cycle + const preview = await import('./preview.js'); + preview.default(document, pluginOptions); +} diff --git a/src/preview.css b/src/preview.css new file mode 100644 index 00000000..3257e95b --- /dev/null +++ b/src/preview.css @@ -0,0 +1,289 @@ +/* + * Copyright 2022 Adobe. All rights reserved. + * This file is licensed to you under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under + * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS + * OF ANY KIND, either express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ +[hidden] { + display: none !important; +} + +.hlx-highlight { + --highlight-size: .5rem; + + outline-color: #888; + outline-offset: calc(-1 * var(--highlight-size)); + outline-style: dashed; + outline-width: var(--highlight-size); + background-color: #8882; +} + +.hlx-preview-overlay { + z-index: 99999; + position: fixed; + color: #eee; + font-size: 1rem; + font-weight: 600; + display: flex; + flex-direction: column; + gap: .5rem; + inset: auto auto 1em; + align-items: center; + justify-content: flex-end; + width: 100%; +} + +.hlx-badge { + --color: #888; + + border-radius: 2em; + background-color: var(--color); + border-style: solid; + border-color: #fff; + color: #eee; + padding: 1em 1.5em; + cursor: pointer; + display: flex; + align-items: center; + position: relative; + font-size: inherit; + overflow: initial; + margin: 0; + justify-content: space-between; + text-transform: none; +} + +.hlx-badge:focus, +.hlx-badge:hover { + --color: #888; +} + +.hlx-badge:focus-visible { + outline-style: solid; + outline-width: .25em; +} + +.hlx-badge > span { + user-select: none; +} + +.hlx-badge .hlx-open { + box-sizing: border-box; + position: relative; + display: block; + width: 22px; + height: 22px; + border: 2px solid; + border-radius: 100px; + margin-left: 16px; +} + +.hlx-badge .hlx-open::after { + content: ""; + display: block; + box-sizing: border-box; + position: absolute; + width: 6px; + height: 6px; + border-top: 2px solid; + border-right: 2px solid; + transform: rotate(-45deg); + left: 6px; + bottom: 5px; +} + +.hlx-badge.hlx-testing { + background-color: #fa0f00; + color: #fff; +} + +.hlx-popup { + position: absolute; + display: grid; + grid-template: + "header" min-content + "content" 1fr; + bottom: 6.5em; + left: 50%; + transform: translateX(-50%); + max-height: calc(100vh - 100px - var(--nav-height, 100px)); + max-width: calc(100vw - 2em); + min-width: calc(300px - 2em); + background-color: #444; + border-radius: 16px; + box-shadow: 0 0 10px #000; + font-size: 12px; + text-align: initial; + white-space: initial; +} + +.hlx-popup a:any-link { + color: #eee; + border: 2px solid; + padding: 5px 12px; + display: inline-block; + border-radius: 20px; + text-decoration: none; +} + +.hlx-popup-header { + display: grid; + grid-area: header; + grid-template: + "label actions" + "description actions" + / 1fr min-content; + background-color: #222; + border-radius: 16px 16px 0 0; + padding: 24px 16px; +} + +.hlx-popup-items { + overflow-y: auto; + grid-area: content; + scrollbar-gutter: stable; + scrollbar-width: thin; +} + +.hlx-popup-header-label { + grid-area: label; +} + +.hlx-popup-header-description { + grid-area: description; +} + +.hlx-popup-header-actions { + grid-area: actions; + display: flex; + flex-direction: column; +} + +.hlx-popup h4, .hlx-popup h5 { + margin: 0; +} + +.hlx-popup h4 { + font-size: 16px; +} + +.hlx-popup h5 { + font-size: 14px; +} + + +.hlx-popup p { + margin: 0; +} + +.hlx-popup::before { + content: ''; + width: 0; + height: 0; + position: absolute; + border-left: 15px solid transparent; + border-right: 15px solid transparent; + border-top: 15px solid #444; + bottom: -15px; + right: 50%; + transform: translateX(50%); +} + +.hlx-hidden { + display: none; +} + +.hlx-badge.is-active, +.hlx-badge[aria-pressed="true"] { + --color: #280; +} + +.hlx-badge.is-inactive, +.hlx-badge[aria-pressed="false"] { + --color: #fa0f00; +} + +.hlx-popup-item { + display: grid; + grid-template: + "label actions" + "description actions" + / 1fr min-content; + margin: 1em; + padding: 1em; + border-radius: 1em; + gap: .5em 1em; +} + +.hlx-popup-item-label { + grid-area: label; + white-space: nowrap; +} + +.hlx-popup-item-description { + grid-area: description; +} + +.hlx-popup-item-actions { + grid-area: actions; + display: flex; + flex-direction: column; +} + +.hlx-popup-item.is-selected { + background-color: #666; +} + +.hlx-popup-item .hlx-button { + flex: 0 0 auto; +} + +@media (width >= 600px) { + .hlx-highlight { + --highlight-size: .75rem; + } + + .hlx-preview-overlay { + right: 1em; + align-items: end; + font-size: 1.25rem; + } + + .hlx-popup { + right: 0; + left: auto; + transform: none; + min-width: 300px; + bottom: 8em; + } + + .hlx-popup::before { + right: 26px; + transform: none; + } +} + +@media (width >= 900px) { + .hlx-highlight { + --highlight-size: 1rem; + } + + .hlx-preview-overlay { + flex-flow: row wrap-reverse; + justify-content: flex-end; + font-size: 1.5rem; + } + + .hlx-popup { + bottom: 9em; + } + + .hlx-popup::before { + right: 32px; + } +} diff --git a/src/preview.js b/src/preview.js new file mode 100644 index 00000000..e253325a --- /dev/null +++ b/src/preview.js @@ -0,0 +1,612 @@ +/* + * Copyright 2022 Adobe. All rights reserved. + * This file is licensed to you under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under + * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS + * OF ANY KIND, either express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ +// eslint-disable-next-line import/no-cycle +import { + debug, + getMetadata, + toClassName, +} from './index.js'; + +const DOMAIN_KEY_NAME = 'aem-domainkey'; + +class AemExperimentationBar extends HTMLElement { + connectedCallback() { + // Create a shadow root + const shadow = this.attachShadow({ mode: 'open' }); + + const cssPath = new URL(new Error().stack.split('\n')[2].match(/[a-z]+:[^:]+/)[0]).pathname.replace('preview.js', 'preview.css'); + const link = document.createElement('link'); + link.rel = 'stylesheet'; + link.href = cssPath; + link.onload = () => { + shadow.querySelector('.hlx-preview-overlay').removeAttribute('hidden'); + }; + shadow.append(link); + shadow.append(link); + + const el = document.createElement('div'); + el.className = 'hlx-preview-overlay'; + shadow.append(el); + } +} +customElements.define('aem-experimentation-bar', AemExperimentationBar); + +function watchForAddedExperiences(ns, cb) { + let { length } = ns; + window.setInterval(() => { + if (length !== ns.length) { + const diff = length - ns.length; + length = ns.length; + ns.slice(diff).map((c) => cb(c)); + } + }, 1000); +} + +function createPreviewOverlay() { + const overlay = document.createElement('aem-experimentation-bar'); + return overlay; +} + +function getOverlay() { + let overlay = document.querySelector('aem-experimentation-bar')?.shadowRoot.children[1]; + if (!overlay) { + const el = createPreviewOverlay(); + const style = document.createElement('style'); + style.textContent = ` + .hlx-highlight { + --highlight-size: .5rem; + + outline-color: #888; + outline-offset: calc(-1 * var(--highlight-size)); + outline-style: dashed; + outline-width: var(--highlight-size); + background-color: #8882; + }`; + el.prepend(style); + document.body.prepend(el); + [, overlay] = el.shadowRoot.children; + } + return overlay; +} + +function createButton(label) { + const button = document.createElement('button'); + button.className = 'hlx-badge'; + const text = document.createElement('span'); + text.innerHTML = label; + button.append(text); + return button; +} + +function createPopupItem(item) { + const actions = typeof item === 'object' + ? item.actions.map((action) => (action.href + ? `` + : ``)) + : []; + const div = document.createElement('div'); + div.className = `hlx-popup-item${item.isSelected ? ' is-selected' : ''}`; + div.innerHTML = ` +
${typeof item === 'object' ? item.label : item}
+ ${item.description ? `
${item.description}
` : ''} + ${actions.length ? `
${actions}
` : ''}`; + const buttons = [...div.querySelectorAll('.hlx-button a')]; + item.actions?.forEach((action, index) => { + if (action.onclick) { + buttons[index].addEventListener('click', action.onclick); + } + }); + return div; +} + +function createPopupDialog(header, items = []) { + const actions = typeof header === 'object' + ? (header.actions || []).map((action) => (action.href + ? `` + : ``)) + : []; + const popup = document.createElement('div'); + popup.className = 'hlx-popup hlx-hidden'; + popup.innerHTML = ` +
+
${typeof header === 'object' ? header.label : header}
+ ${header.description ? `
${header.description}
` : ''} + ${actions.length ? `
${actions}
` : ''} +
+
`; + const list = popup.querySelector('.hlx-popup-items'); + items.forEach((item) => { + list.append(createPopupItem(item)); + }); + const buttons = [...popup.querySelectorAll('.hlx-popup-header-actions .hlx-button a')]; + header.actions?.forEach((action, index) => { + if (action.onclick) { + buttons[index].addEventListener('click', action.onclick); + } + }); + return popup; +} + +function createPopupButton(label, header, items, eventListeners = {}) { + const button = createButton(label); + const popup = createPopupDialog(header, items); + button.innerHTML += ''; + button.append(popup); + button.addEventListener('click', (ev) => { + if (ev.target.closest('.hlx-popup')) { + return; + } + getOverlay().querySelectorAll('.hlx-badge .hlx-popup:not(.hlx-hidden)').forEach((el) => { + if (el !== popup) { + el.classList.toggle('hlx-hidden', true); + } + }); + popup.classList.toggle('hlx-hidden'); + }); + Object.entries(eventListeners).forEach(([evt, listener]) => { + button.addEventListener(evt, listener); + }); + return button; +} + +// eslint-disable-next-line no-unused-vars +function createToggleButton(label) { + const button = document.createElement('div'); + button.className = 'hlx-badge'; + button.role = 'button'; + button.setAttribute('aria-pressed', false); + button.setAttribute('tabindex', 0); + const text = document.createElement('span'); + text.innerHTML = label; + button.append(text); + button.addEventListener('click', () => { + button.setAttribute('aria-pressed', button.getAttribute('aria-pressed') === 'false'); + }); + return button; +} + +const percentformat = new Intl.NumberFormat('en-US', { style: 'percent', maximumSignificantDigits: 3 }); +const countformat = new Intl.NumberFormat('en-US', { maximumSignificantDigits: 2 }); +const significanceformat = { + format: (value) => { + if (value < 0.005) { + return 'highly significant'; + } + if (value < 0.05) { + return 'significant'; + } + if (value < 0.1) { + return 'marginally significant'; + } + return 'not significant'; + }, +}; +const bigcountformat = { + format: (value) => { + if (value > 1000000) { + return `${countformat.format(value / 1000000)}M`; + } + if (value > 1000) { + return `${countformat.format(value / 1000)}K`; + } + return countformat.format(value); + }, +}; + +function createVariant(experiment, variantName, config, options) { + const selectedVariant = config?.selectedVariant || config?.variantNames[0]; + const variant = config.variants[variantName]; + const split = variant.percentageSplit; + const percentage = percentformat.format(split); + + const experimentURL = new URL(window.location.href); + // this will retain other query params such as ?rum=on + experimentURL.searchParams.set(options.experimentsQueryParameter, `${experiment}/${variantName}`); + + return { + label: `${variantName}`, + description: ` +

${variant.label}

+

(${percentage} split)

+

`, + actions: [{ label: 'Simulate', href: experimentURL.href }], + isSelected: selectedVariant === variantName, + }; +} + +async function fetchRumData(experiment, options) { + if (!options.domainKey) { + // eslint-disable-next-line no-console + console.warn('Cannot show RUM data. No `domainKey` configured.'); + return null; + } + if (!options.prodHost && (typeof options.isProd !== 'function' || !options.isProd())) { + // eslint-disable-next-line no-console + console.warn('Cannot show RUM data. No `prodHost` configured or custom `isProd` method provided.'); + return null; + } + + // the query is a bit slow, so I'm only fetching the results when the popup is opened + const resultsURL = new URL('https://helix-pages.anywhere.run/helix-services/run-query@v3/rum-experiments'); + // restrict results to the production host, this also reduces query cost + if (typeof options.isProd === 'function' && options.isProd()) { + resultsURL.searchParams.set('url', window.location.host); + } else if (options.prodHost) { + resultsURL.searchParams.set('url', options.prodHost); + } + resultsURL.searchParams.set('domainkey', options.domainKey); + resultsURL.searchParams.set('experiment', experiment); + resultsURL.searchParams.set('conversioncheckpoint', options.conversionName); + + const response = await fetch(resultsURL.href); + if (!response.ok) { + return null; + } + + const { results } = await response.json(); + const { data } = results; + if (!data.length) { + return null; + } + + const numberify = (obj) => Object.entries(obj).reduce((o, [k, v]) => { + o[k] = Number.parseFloat(v); + o[k] = Number.isNaN(o[k]) ? v : o[k]; + return o; + }, {}); + + const variantsAsNums = data.map(numberify); + const totals = Object.entries( + variantsAsNums.reduce((o, v) => { + Object.entries(v).forEach(([k, val]) => { + if (typeof val === 'number' && Number.isInteger(val) && k.startsWith('variant_')) { + o[k] = (o[k] || 0) + val; + } else if (typeof val === 'number' && Number.isInteger(val) && k.startsWith('control_')) { + o[k] = val; + } + }); + return o; + }, {}), + ).reduce((o, [k, v]) => { + o[k] = v; + const vkey = k.replace(/^(variant|control)_/, 'variant_'); + const ckey = k.replace(/^(variant|control)_/, 'control_'); + const tkey = k.replace(/^(variant|control)_/, 'total_'); + if (!Number.isNaN(o[ckey]) && !Number.isNaN(o[vkey])) { + o[tkey] = o[ckey] + o[vkey]; + } + return o; + }, {}); + const richVariants = variantsAsNums + .map((v) => ({ + ...v, + allocation_rate: v.variant_experimentations / totals.total_experimentations, + })) + .reduce((o, v) => { + const variantName = v.variant; + o[variantName] = v; + return o; + }, { + control: { + variant: 'control', + ...Object.entries(variantsAsNums[0]).reduce((k, v) => { + const [key, val] = v; + if (key.startsWith('control_')) { + k[key.replace(/^control_/, 'variant_')] = val; + } + return k; + }, {}), + }, + }); + const winner = variantsAsNums.reduce((w, v) => { + if (v.variant_conversion_rate > w.conversion_rate && v.p_value < 0.05) { + w.conversion_rate = v.variant_conversion_rate; + w.p_value = v.p_value; + w.variant = v.variant; + } + return w; + }, { variant: 'control', p_value: 1, conversion_rate: 0 }); + + return { + richVariants, + totals, + variantsAsNums, + winner, + }; +} + +function populatePerformanceMetrics(div, config, { + richVariants, totals, variantsAsNums, winner, +}, conversionName) { + // add summary + const summary = div.querySelector('.hlx-info'); + summary.innerHTML = `Showing results for ${bigcountformat.format(totals.total_experimentations)} visits and ${bigcountformat.format(totals.total_conversions)} conversions: `; + if (totals.total_conversion_events < 500 && winner.p_value > 0.05) { + summary.innerHTML += ` not yet enough data to determine a winner. Keep going until you get ${bigcountformat.format((500 * totals.total_experimentations) / totals.total_conversion_events)} visits.`; + } else if (winner.p_value > 0.05) { + summary.innerHTML += ' no significant difference between variants. In doubt, stick with control.'; + } else if (winner.variant === 'control') { + summary.innerHTML += ' Stick with control. No variant is better than the control.'; + } else { + summary.innerHTML += ` ${winner.variant} is the winner.`; + } + + // add traffic allocation to control and each variant + config.variantNames.forEach((variantName, index) => { + const variantDiv = getOverlay().querySelectorAll('.hlx-popup-item')[index]; + const percentage = variantDiv.querySelector('.percentage'); + percentage.innerHTML = ` + ${bigcountformat.format(richVariants[variantName].variant_conversions)} ${conversionName} events / + ${bigcountformat.format(richVariants[variantName].variant_experimentations)} visits + (${percentformat.format(richVariants[variantName].variant_experimentations / totals.total_experimentations)} split) + `; + }); + + // add click rate and significance to each variant + variantsAsNums.forEach((result) => { + const variant = getOverlay().querySelectorAll('.hlx-popup-item')[config.variantNames.indexOf(result.variant)]; + if (variant) { + const performance = variant.querySelector('.performance'); + performance.innerHTML = ` + ${conversionName} conversion rate: ${percentformat.format(result.variant_conversion_rate)} + vs. ${percentformat.format(result.control_conversion_rate)} + ${significanceformat.format(result.p_value)} + `; + } + }); +} + +/** + * Create Badge if a Page is enlisted in a AEM Experiment + * @return {Object} returns a badge or empty string + */ +async function decorateExperimentPill({ el, config }, container, options) { + if (!config) { + return; + } + // eslint-disable-next-line no-console + debug('preview experiment', config.id); + + const domainKey = window.localStorage.getItem(DOMAIN_KEY_NAME); + const conversionName = (el.tagName === 'MAIN' + ? toClassName(getMetadata('conversion-name')) + : el.dataset.conversionName + ) || 'click'; + const pill = createPopupButton( + `Experiment: ${config.id}`, + { + label: config.label, + description: ` +
+ ${config.status} + ${config.resolvedAudiences ? ', ' : ''} + ${config.resolvedAudiences && config.resolvedAudiences.length ? config.resolvedAudiences[0] : ''} + ${config.resolvedAudiences && !config.resolvedAudiences.length ? 'No audience resolved' : ''} + ${config.variants[config.variantNames[0]].blocks?.length ? ', Blocks: ' : ''} + ${config.variants[config.variantNames[0]].blocks?.join(',') || ''} +
+
How is it going?
`, + actions: [ + ...config.manifest ? [{ label: 'Manifest', href: config.manifest }] : [], + { + label: '', + onclick: async () => { + // eslint-disable-next-line no-alert + const key = window.prompt( + 'Please enter your domain key:', + window.localStorage.getItem(DOMAIN_KEY_NAME) || '', + ); + if (key && key.match(/[a-f0-9-]+/)) { + window.localStorage.setItem(DOMAIN_KEY_NAME, key); + const performanceMetrics = await fetchRumData(config.id, { + ...options, + domainKey: key, + }); + if (performanceMetrics === null) { + return; + } + populatePerformanceMetrics(pill, config, performanceMetrics, conversionName); + } else if (key === '') { + window.localStorage.removeItem(DOMAIN_KEY_NAME); + } + }, + }, + ], + }, + config.variantNames.map((vname) => createVariant(config.id, vname, config, options)), + { + click: (ev) => { + if (!ev.target.querySelector('.hlx-hidden')) { + el.scrollIntoView({ behavior: 'smooth', block: 'nearest' }); + } + }, + mouseenter: () => { el.classList.add('hlx-highlight'); }, + mouseleave: () => { + document.querySelectorAll('.hlx-highlight') + .forEach((e) => e.classList.remove('hlx-highlight')); + }, + }, + ); + if (config.run) { + pill.classList.add(`is-${toClassName(config.status)}`); + } + container.append(pill); + const performanceMetrics = await fetchRumData(config.id, { + ...options, conversionName, domainKey, + }); + if (performanceMetrics === null) { + return; + } + populatePerformanceMetrics(pill, config, performanceMetrics, conversionName); +} + +async function decorateExperimentPills(container, options) { + const ns = window.aem || window.hlx; + if (!ns?.experiments) { + return null; + } + + watchForAddedExperiences(ns.experiments, (c) => decorateExperimentPill(c, container, options)); + return Promise.all(ns.experiments.map((c) => decorateExperimentPill(c, container, options))); +} + +function createCampaign(campaign, isSelected, options) { + const url = new URL(window.location.href); + if (campaign !== 'default') { + url.searchParams.set(options.campaignsQueryParameter, campaign); + } else { + url.searchParams.delete(options.campaignsQueryParameter); + } + + return { + label: `${campaign}`, + actions: [{ label: 'Simulate', href: url.href }], + isSelected, + }; +} + +/** + * Create Badge if a Page is enlisted in a AEM Campaign + * @return {Object} returns a badge or empty string + */ +async function decorateCampaignPill({ el, config }, container, options) { + if (!config) { + return; + } + const pill = createPopupButton( + `Campaign: ${config.selectedCampaign || 'default'}`, + { + label: 'Campaigns on this page:', + description: ` +
+ ${config.audiences.length && config.resolvedAudiences?.length ? `Audience: ${config.resolvedAudiences[0]}` : ''} + ${config.audiences.length && !config.resolvedAudiences?.length ? 'No audience resolved' : ''} + ${!config.audiences.length || !config.resolvedAudiences ? 'No audience configured' : ''} +
`, + }, + [ + createCampaign('default', !config.selectedCampaign || config.selectedCampaign === 'default', options), + ...Object.keys(config.configuredCampaigns) + .filter((c) => c !== 'audience') + .map((c) => createCampaign(c, config.selectedCampaign === c, options)), + ], + { + click: (ev) => { + if (!ev.target.querySelector('.hlx-hidden')) { + el.scrollIntoView({ behavior: 'smooth', block: 'nearest' }); + } + }, + mouseenter: () => { el.classList.add('hlx-highlight'); }, + mouseleave: () => { + document.querySelectorAll('.hlx-highlight') + .forEach((e) => e.classList.remove('hlx-highlight')); + }, + }, + ); + + if (config.selectedCampaign) { + pill.classList.add('is-active'); + } + container.append(pill); +} + +async function decorateCampaignPills(container, options) { + const ns = window.aem || window.hlx; + if (!ns?.campaigns) { + return null; + } + + watchForAddedExperiences(ns.campaigns, (c) => decorateCampaignPill(c, container, options)); + return Promise.all(ns.campaigns.map((c) => decorateCampaignPill(c, container, options))); +} + +function createAudience(audience, isSelected, options) { + const url = new URL(window.location.href); + url.searchParams.set(options.audiencesQueryParameter, audience); + + return { + label: `${audience}`, + actions: [{ label: 'Simulate', href: url.href }], + isSelected, + }; +} + +/** + * Create Badge if a Page is enlisted in a AEM Audiences + * @return {Object} returns a badge or empty string + */ +async function decorateAudiencesPill({ el, config }, container, options) { + if (!config) { + return; + } + const configuredAudienceNames = Object.keys(config.configuredAudiences); + if (!Object.keys(config.configuredAudiences).length || !Object.keys(options.audiences).length) { + return; + } + + const pill = createPopupButton( + `Audience: ${config.selectedAudience || 'default'}`, + { + label: 'Audiences for this page:', + }, + [ + createAudience('default', !config.selectedAudience || config.selectedAudience === 'default', options), + ...configuredAudienceNames + .filter((a) => a !== 'audience') + .map((a) => createAudience(a, config.selectedAudience === a, options)), + ], + { + click: (ev) => { + if (!ev.target.querySelector('.hlx-hidden')) { + el.scrollIntoView({ behavior: 'smooth', block: 'nearest' }); + } + }, + mouseenter: () => { el.classList.add('hlx-highlight'); }, + mouseleave: () => { + document.querySelectorAll('.hlx-highlight') + .forEach((e) => e.classList.remove('hlx-highlight')); + }, + }, + ); + + if (config.selectedAudience) { + pill.classList.add('is-active'); + } + container.append(pill); +} + +async function decorateAudiencesPills(container, options) { + const ns = window.aem || window.hlx; + if (!ns?.audiences) { + return null; + } + + watchForAddedExperiences(ns.audiences, (c) => decorateAudiencesPill(c, container, options)); + return Promise.all(ns.audiences.map((c) => decorateAudiencesPill(c, container, options))); +} + +/** + * Decorates Preview mode badges and overlays + * @return {Object} returns a badge or empty string + */ +export default async function decoratePreviewMode(document, options) { + try { + const overlay = getOverlay(); + + await decorateAudiencesPills(overlay, options); + await decorateCampaignPills(overlay, options); + await decorateExperimentPills(overlay, options); + } catch (e) { + // eslint-disable-next-line no-console + console.log(e); + } +} diff --git a/src/ued.js b/src/ued.js new file mode 100644 index 00000000..4d4e3a39 --- /dev/null +++ b/src/ued.js @@ -0,0 +1,193 @@ +/* + * Copyright 2022 Adobe. All rights reserved. + * This file is licensed to you under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under + * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS + * OF ANY KIND, either express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ +/* eslint-disable */ + +var storage = window.sessionStorage; + +function murmurhash3_32_gc(key, seed) { + var remainder = key.length & 3; + var bytes = key.length - remainder; + var c1 = 0xcc9e2d51; + var c2 = 0x1b873593; + var h1 = seed; + var k1; + var h1b; + var i = 0; + while (i < bytes) { + k1 = + ((key.charCodeAt(i) & 0xff)) | + ((key.charCodeAt(++i) & 0xff) << 8) | + ((key.charCodeAt(++i) & 0xff) << 16) | + ((key.charCodeAt(++i) & 0xff) << 24); + ++i; + k1 = ((((k1 & 0xffff) * c1) + ((((k1 >>> 16) * c1) & 0xffff) << 16))) & 0xffffffff; + k1 = (k1 << 15) | (k1 >>> 17); + k1 = ((((k1 & 0xffff) * c2) + ((((k1 >>> 16) * c2) & 0xffff) << 16))) & 0xffffffff; + h1 ^= k1; + h1 = (h1 << 13) | (h1 >>> 19); + h1b = ((((h1 & 0xffff) * 5) + ((((h1 >>> 16) * 5) & 0xffff) << 16))) & 0xffffffff; + h1 = (((h1b & 0xffff) + 0x6b64) + ((((h1b >>> 16) + 0xe654) & 0xffff) << 16)); + } + k1 = 0; + switch (remainder) { + case 3: k1 ^= (key.charCodeAt(i + 2) & 0xff) << 16; + case 2: k1 ^= (key.charCodeAt(i + 1) & 0xff) << 8; + case 1: + k1 ^= (key.charCodeAt(i) & 0xff); + k1 = (((k1 & 0xffff) * c1) + ((((k1 >>> 16) * c1) & 0xffff) << 16)) & 0xffffffff; + k1 = (k1 << 15) | (k1 >>> 17); + k1 = (((k1 & 0xffff) * c2) + ((((k1 >>> 16) * c2) & 0xffff) << 16)) & 0xffffffff; + h1 ^= k1; + } + h1 ^= key.length; + h1 ^= h1 >>> 16; + h1 = (((h1 & 0xffff) * 0x85ebca6b) + ((((h1 >>> 16) * 0x85ebca6b) & 0xffff) << 16)) & 0xffffffff; + h1 ^= h1 >>> 13; + h1 = ((((h1 & 0xffff) * 0xc2b2ae35) + ((((h1 >>> 16) * 0xc2b2ae35) & 0xffff) << 16))) & 0xffffffff; + h1 ^= h1 >>> 16; + return h1 >>> 0; +} + +var TOTAL_BUCKETS = 10000; +function getBucket(saltedId) { + var hash = murmurhash3_32_gc(saltedId, 0); + var hashFixedBucket = Math.abs(hash) % TOTAL_BUCKETS; + var bucket = hashFixedBucket / TOTAL_BUCKETS; + return bucket; +} +function pickWithWeightsBucket(allocationPercentages, treatments, bucket) { + var sum = allocationPercentages.reduce(function (partialSum, a) { return partialSum + a; }, 0); + var partialSum = 0.0; + for (var i = 0; i < treatments.length; i++) { + partialSum += Number(allocationPercentages[i].toFixed(2)) / sum; + if (bucket > partialSum) { + continue; + } + return treatments[i]; + } +} +function assignTreatmentByVisitor(experimentid, identityId, allocationPercentages, treatments) { + var saltedId = experimentid + '.' + identityId; + var bucketId = getBucket(saltedId); + var treatmentId = pickWithWeightsBucket(allocationPercentages, treatments, bucketId); + return { + treatmentId: treatmentId, + bucketId: bucketId + }; +} + +var LOCAL_STORAGE_KEY = 'unified-decisioning-experiments'; +function assignTreatment(allocationPercentages, treatments) { + var random = Math.random() * 100; + var i = treatments.length; + while (random > 0 && i > 0) { + i -= 1; + random -= +allocationPercentages[i]; + } + return treatments[i]; +} +function getLastExperimentTreatment(experimentId) { + var experimentsStr = storage.getItem(LOCAL_STORAGE_KEY); + if (experimentsStr) { + var experiments = JSON.parse(experimentsStr); + if (experiments[experimentId]) { + return experiments[experimentId].treatment; + } + } + return null; +} +function setLastExperimentTreatment(experimentId, treatment) { + var experimentsStr = storage.getItem(LOCAL_STORAGE_KEY); + var experiments = experimentsStr ? JSON.parse(experimentsStr) : {}; + var now = new Date(); + var expKeys = Object.keys(experiments); + expKeys.forEach(function (key) { + var date = new Date(experiments[key].date); + if ((now.getTime() - date.getTime()) > (1000 * 86400 * 30)) { + delete experiments[key]; + } + }); + var date = now.toISOString().split('T')[0]; + experiments[experimentId] = { treatment: treatment, date: date }; + storage.setItem(LOCAL_STORAGE_KEY, JSON.stringify(experiments)); +} +function assignTreatmentByDevice(experimentId, allocationPercentages, treatments) { + var cachedTreatmentId = getLastExperimentTreatment(experimentId); + var treatmentIdResponse; + if (!cachedTreatmentId || !treatments.includes(cachedTreatmentId)) { + var assignedTreatmentId = assignTreatment(allocationPercentages, treatments); + setLastExperimentTreatment(experimentId, assignedTreatmentId); + treatmentIdResponse = assignedTreatmentId; + } + else { + treatmentIdResponse = cachedTreatmentId; + } + return { + treatmentId: treatmentIdResponse + }; +} + +var RandomizationUnit = { + VISITOR: 'VISITOR', + DEVICE: 'DEVICE' +}; +function evaluateExperiment(context, experiment) { + var experimentId = experiment.id, identityNamespace = experiment.identityNamespace, _a = experiment.randomizationUnit, randomizationUnit = _a === void 0 ? RandomizationUnit.VISITOR : _a; + var identityMap = context.identityMap; + var treatments = experiment.treatments.map(function (item) { return item.id; }); + var allocationPercentages = experiment.treatments.map(function (item) { return item.allocationPercentage; }); + var treatmentAssignment = null; + switch (randomizationUnit) { + case RandomizationUnit.VISITOR: { + var identityId = identityMap[identityNamespace][0].id; + treatmentAssignment = assignTreatmentByVisitor(experimentId, identityId, allocationPercentages, treatments); + break; + } + case RandomizationUnit.DEVICE: { + treatmentAssignment = assignTreatmentByDevice(experimentId, allocationPercentages, treatments); + break; + } + default: + throw new Error("Unknow randomization unit"); + } + var evaluationResponse = { + experimentId: experimentId, + hashedBucket: treatmentAssignment.bucketId, + treatment: { + id: treatmentAssignment.treatmentId + } + }; + return evaluationResponse; +} + +function traverseDecisionTree(decisionNodesMap, context, currentNodeId) { + var _a = decisionNodesMap[currentNodeId], experiment = _a.experiment, type = _a.type; + if (type === 'EXPERIMENTATION') { + var treatment = evaluateExperiment(context, experiment).treatment; + return [treatment]; + } +} +function evaluateDecisionPolicy(decisionPolicy, context) { + if (context.storage && context.storage instanceof Storage) { + storage = context.storage; + } + var decisionNodesMap = {}; + decisionPolicy.decisionNodes.forEach(function (item) { + decisionNodesMap[item['id']] = item; + }); + var items = traverseDecisionTree(decisionNodesMap, context, decisionPolicy.rootDecisionNodeId); + return { + items: items + }; +} + +export const ued = { evaluateDecisionPolicy }; diff --git a/tests/audiences.test.js b/tests/audiences.test.js new file mode 100644 index 00000000..08e4b436 --- /dev/null +++ b/tests/audiences.test.js @@ -0,0 +1,194 @@ +/* eslint-disable import/no-extraneous-dependencies */ +import { test, expect } from '@playwright/test'; +import { track } from './coverage.js'; +import { goToAndRunAudience, waitForDomEvent } from './utils.js'; + +track(test); + +test.describe('Page-level audiences', () => { + test('Replaces the page content with the variant.', async ({ page }) => { + await goToAndRunAudience(page, '/tests/fixtures/audiences/page-level'); + expect(await page.locator('main').textContent()).toContain('Hello v1!'); + await goToAndRunAudience(page, '/tests/fixtures/audiences/page-level--async'); + expect(await page.locator('main').textContent()).toContain('Hello v2!'); + }); + + test('Sets a class on the body for the main resolved audience.', async ({ page }) => { + await goToAndRunAudience(page, '/tests/fixtures/audiences/page-level'); + expect(await page.locator('body').getAttribute('class')).not.toContain('audience-default'); + expect(await page.locator('body').getAttribute('class')).toContain('audience-foo'); + expect(await page.locator('body').getAttribute('class')).not.toContain('audience-bar'); + }); + + test('Ignores empty audiences.', async ({ page }) => { + await goToAndRunAudience(page, '/tests/fixtures/audiences/page-level--empty'); + expect(await page.locator('main').textContent()).toContain('Hello World!'); + expect(await page.locator('body').getAttribute('class')).toContain('audience-default'); + expect(await page.locator('body').getAttribute('class')).not.toContain('audience-foo'); + expect(await page.locator('body').getAttribute('class')).not.toContain('audience-bar'); + }); + + test('Controls the audience shown via query parameters.', async ({ page }) => { + await goToAndRunAudience(page, '/tests/fixtures/audiences/page-level?audience=foo'); + expect(await page.locator('main').textContent()).toContain('Hello v1!'); + await goToAndRunAudience(page, '/tests/fixtures/audiences/page-level?audience=bar'); + expect(await page.locator('main').textContent()).toContain('Hello v2!'); + }); + + test('Ignores invalid audiences.', async ({ page }) => { + await goToAndRunAudience(page, '/tests/fixtures/audiences/page-level--invalid'); + expect(await page.locator('main').textContent()).toContain('Hello v2!'); + }); + + test('Ignores invalid audience references in the query parameters.', async ({ page }) => { + await goToAndRunAudience(page, '/tests/fixtures/audiences/page-level?audience=baz'); + expect(await page.locator('main').textContent()).toContain('Hello World!'); + }); + + test('Ignores invalid variant urls.', async ({ page }) => { + await goToAndRunAudience(page, '/tests/fixtures/audiences/page-level--invalid-url'); + expect(await page.locator('main').textContent()).toContain('Hello World!'); + }); + + test('Tracks the audience in RUM.', async ({ page }) => { + await page.addInitScript(() => { + window.rumCalls = []; + window.hlx = { rum: { sampleRUM: (...args) => window.rumCalls.push(args) } }; + }); + await goToAndRunAudience(page, '/tests/fixtures/audiences/page-level'); + expect(await page.evaluate(() => window.rumCalls)).toContainEqual([ + 'audience', + expect.objectContaining({ + source: 'audience-foo', + target: 'foo', + }), + ]); + }); + + test('Exposes the audiences in a JS API.', async ({ page }) => { + await goToAndRunAudience(page, '/tests/fixtures/audiences/page-level'); + expect(await page.evaluate(() => window.hlx.audiences)).toContainEqual( + expect.objectContaining({ + type: 'page', + config: expect.objectContaining({ + configuredAudiences: { + foo: '/tests/fixtures/audiences/variant-1', + bar: '/tests/fixtures/audiences/variant-2', + }, + resolvedAudiences: ['foo', 'bar'], + selectedAudience: 'foo', + }), + servedExperience: '/tests/fixtures/audiences/variant-1', + }), + ); + }); + + test('triggers a DOM event with the audience detail', async ({ page }) => { + const fn = await waitForDomEvent(page, 'aem:experimentation'); + await page.goto('/tests/fixtures/audiences/page-level'); + expect(await page.evaluate(fn)).toEqual({ + type: 'audience', + element: await page.evaluate(() => document.body), + audience: 'foo', + }); + }); +}); + +test.describe('Section-level audiences', () => { + test('Replaces the section content with the variant.', async ({ page }) => { + await goToAndRunAudience(page, '/tests/fixtures/audiences/section-level'); + expect(await page.locator('main>div').textContent()).toContain('Hello v2!'); + }); + + test('Sets classes on the section for the audience.', async ({ page }) => { + await goToAndRunAudience(page, '/tests/fixtures/audiences/section-level'); + expect(await page.locator('main>div').getAttribute('class')).toContain('audience-bar'); + await goToAndRunAudience(page, '/tests/fixtures/audiences/section-level?audience=foo'); + expect(await page.locator('main>div').getAttribute('class')).toContain('audience-foo'); + }); + + test('Exposes the audiences in a JS API.', async ({ page }) => { + await goToAndRunAudience(page, '/tests/fixtures/audiences/section-level'); + expect(await page.evaluate(() => window.hlx.audiences)).toContainEqual( + expect.objectContaining({ + type: 'section', + config: expect.objectContaining({ + configuredAudiences: { + foo: `${await page.evaluate(() => window.location.origin)}/tests/fixtures/audiences/variant-1`, + bar: '/tests/fixtures/audiences/variant-2', + }, + resolvedAudiences: ['bar'], + selectedAudience: 'bar', + }), + servedExperience: '/tests/fixtures/audiences/variant-2', + }), + ); + }); + + test('triggers a DOM event with the audience detail', async ({ page }) => { + const fn = await waitForDomEvent(page, 'aem:experimentation'); + await page.goto('/tests/fixtures/audiences/section-level'); + expect(await page.evaluate(fn)).toEqual({ + type: 'audience', + element: await page.evaluate(() => document.querySelector('.section')), + audience: 'bar', + }); + }); +}); + +test.describe('Fragment-level audiences', () => { + test('Replaces the fragment content with the variant.', async ({ page }) => { + await goToAndRunAudience(page, '/tests/fixtures/audiences/fragment-level'); + expect(await page.locator('.fragment').textContent()).toContain('Hello v1!'); + }); + + test('Supports plural format for manifest keys.', async ({ page }) => { + await goToAndRunAudience(page, '/tests/fixtures/audiences/fragment-level--alt'); + expect(await page.locator('.fragment').textContent()).toContain('Hello v1!'); + }); + + test('Ignores invalid manifest url.', async ({ page }) => { + await goToAndRunAudience(page, '/tests/fixtures/audiences/fragment-level--invalid-url'); + expect(await page.locator('.fragment').textContent()).toContain('Hello World!'); + }); + + test('Replaces the async fragment content with the variant.', async ({ page }) => { + await goToAndRunAudience(page, '/tests/fixtures/audiences/fragment-level--async'); + expect(await page.locator('.fragment').textContent()).toContain('Hello v2!'); + }); + + test('Sets classes on the section for the audience.', async ({ page }) => { + await goToAndRunAudience(page, '/tests/fixtures/audiences/fragment-level'); + expect(await page.locator('.fragment').getAttribute('class')).toContain('audience-foo'); + await goToAndRunAudience(page, '/tests/fixtures/audiences/fragment-level?audience=bar'); + expect(await page.locator('.fragment').getAttribute('class')).toContain('audience-bar'); + }); + + test('Exposes the audiences in a JS API.', async ({ page }) => { + await goToAndRunAudience(page, '/tests/fixtures/audiences/fragment-level'); + expect(await page.evaluate(() => window.hlx.audiences)).toContainEqual( + expect.objectContaining({ + type: 'fragment', + config: expect.objectContaining({ + configuredAudiences: { + foo: '/tests/fixtures/audiences/variant-1', + bar: '/tests/fixtures/audiences/variant-2', + }, + resolvedAudiences: ['foo'], + selectedAudience: 'foo', + }), + servedExperience: '/tests/fixtures/audiences/variant-1', + }), + ); + }); + + test('triggers a DOM event with the audience detail', async ({ page }) => { + const fn = await waitForDomEvent(page, 'aem:experimentation'); + await page.goto('/tests/fixtures/audiences/fragment-level'); + expect(await page.evaluate(fn)).toEqual({ + type: 'audience', + element: await page.evaluate(() => document.querySelector('.fragment')), + audience: 'foo', + }); + }); +}); diff --git a/tests/campaigns.test.js b/tests/campaigns.test.js new file mode 100644 index 00000000..2218febf --- /dev/null +++ b/tests/campaigns.test.js @@ -0,0 +1,206 @@ +/* eslint-disable import/no-extraneous-dependencies */ +import { test, expect } from '@playwright/test'; +import { track } from './coverage.js'; +import { goToAndRunCampaign, waitForDomEvent } from './utils.js'; + +track(test); + +test.describe('Page-level campaigns', () => { + test('Replaces the page content with the variant.', async ({ page }) => { + await goToAndRunCampaign(page, '/tests/fixtures/campaigns/page-level'); + expect(await page.locator('main').textContent()).toContain('Hello World!'); + await goToAndRunCampaign(page, '/tests/fixtures/campaigns/page-level?campaign=foo'); + expect(await page.locator('main').textContent()).toContain('Hello v1!'); + await goToAndRunCampaign(page, '/tests/fixtures/campaigns/page-level?campaign=bar'); + expect(await page.locator('main').textContent()).toContain('Hello v2!'); + }); + + test('Serves the campaign if the configured audience is resolved.', async ({ page }) => { + await page.addInitScript(() => { + window.AUDIENCES = { baz: () => false }; + }); + await goToAndRunCampaign(page, '/tests/fixtures/campaigns/page-level--audiences?campaign=foo'); + expect(await page.locator('main').textContent()).toContain('Hello World!'); + await page.addInitScript(() => { + window.AUDIENCES = { baz: () => true }; + }); + await goToAndRunCampaign(page, '/tests/fixtures/campaigns/page-level--audiences?campaign=foo'); + expect(await page.locator('main').textContent()).toContain('Hello v1!'); + }); + + test('Sets a class on the body for the active campaign.', async ({ page }) => { + await goToAndRunCampaign(page, '/tests/fixtures/campaigns/page-level'); + expect(await page.locator('body').getAttribute('class')).toContain('campaign-default'); + await goToAndRunCampaign(page, '/tests/fixtures/campaigns/page-level?campaign=foo'); + expect(await page.locator('body').getAttribute('class')).toContain('campaign-foo'); + await goToAndRunCampaign(page, '/tests/fixtures/campaigns/page-level?campaign=bar'); + expect(await page.locator('body').getAttribute('class')).toContain('campaign-bar'); + }); + + test('Ignores empty campaigns.', async ({ page }) => { + await goToAndRunCampaign(page, '/tests/fixtures/campaigns/page-level--empty?campaign=foo'); + expect(await page.locator('main').textContent()).toContain('Hello World!'); + expect(await page.locator('body').getAttribute('class')).toContain('campaign-default'); + }); + + test('Controls the campaign shown via UTM query parameters.', async ({ page }) => { + await goToAndRunCampaign(page, '/tests/fixtures/campaigns/page-level?utm_campaign=foo'); + expect(await page.locator('main').textContent()).toContain('Hello v1!'); + await goToAndRunCampaign(page, '/tests/fixtures/campaigns/page-level?utm_campaign=bar'); + expect(await page.locator('main').textContent()).toContain('Hello v2!'); + }); + + test('Ignores invalid campaigns references in the query parameters.', async ({ page }) => { + await goToAndRunCampaign(page, '/tests/fixtures/campaigns/page-level?campaign=baz'); + expect(await page.locator('main').textContent()).toContain('Hello World!'); + }); + + test('Ignores invalid variant urls.', async ({ page }) => { + await goToAndRunCampaign(page, '/tests/fixtures/campaigns/page-level--invalid-url?campaign=foo'); + expect(await page.locator('main').textContent()).toContain('Hello World!'); + }); + + test('Tracks the campaign in RUM.', async ({ page }) => { + await page.addInitScript(() => { + window.rumCalls = []; + window.hlx = { rum: { sampleRUM: (...args) => window.rumCalls.push(args) } }; + }); + await goToAndRunCampaign(page, '/tests/fixtures/campaigns/page-level?campaign=foo'); + expect(await page.evaluate(() => window.rumCalls)).toContainEqual([ + 'campaign', + expect.objectContaining({ + source: 'campaign-foo', + target: 'foo', + }), + ]); + }); + + test('Exposes the campaign in a JS API.', async ({ page }) => { + await goToAndRunCampaign(page, '/tests/fixtures/campaigns/page-level?campaign=bar'); + expect(await page.evaluate(() => window.hlx.campaigns)).toContainEqual( + expect.objectContaining({ + type: 'page', + config: expect.objectContaining({ + configuredCampaigns: { + foo: '/tests/fixtures/campaigns/variant-1', + bar: '/tests/fixtures/campaigns/variant-2', + }, + selectedCampaign: 'bar', + }), + servedExperience: '/tests/fixtures/campaigns/variant-2', + }), + ); + }); + + test('triggers a DOM event with the campaign detail', async ({ page }) => { + const fn = await waitForDomEvent(page, 'aem:experimentation'); + await page.goto('/tests/fixtures/campaigns/page-level?campaign=bar'); + expect(await page.evaluate(fn)).toEqual({ + type: 'campaign', + element: await page.evaluate(() => document.body), + campaign: 'bar', + }); + }); +}); + +test.describe('Section-level campaigns', () => { + test('Replaces the section content with the variant.', async ({ page }) => { + await goToAndRunCampaign(page, '/tests/fixtures/campaigns/section-level?campaign=bar'); + expect(await page.locator('main>div').textContent()).toContain('Hello v2!'); + }); + + test('Sets classes on the section for the campaign.', async ({ page }) => { + await goToAndRunCampaign(page, '/tests/fixtures/campaigns/section-level?campaign=foo'); + expect(await page.locator('main>div').getAttribute('class')).toContain('campaign-foo'); + await goToAndRunCampaign(page, '/tests/fixtures/campaigns/section-level?campaign=bar'); + expect(await page.locator('main>div').getAttribute('class')).toContain('campaign-bar'); + }); + + test('Exposes the campaigns in a JS API.', async ({ page }) => { + await goToAndRunCampaign(page, '/tests/fixtures/campaigns/section-level?campaign=bar'); + expect(await page.evaluate(() => window.hlx.campaigns)).toContainEqual( + expect.objectContaining({ + type: 'section', + config: expect.objectContaining({ + configuredCampaigns: { + foo: '/tests/fixtures/campaigns/variant-1', + bar: '/tests/fixtures/campaigns/variant-2', + }, + selectedCampaign: 'bar', + }), + servedExperience: '/tests/fixtures/campaigns/variant-2', + }), + ); + }); + + test('triggers a DOM event with the campaign detail', async ({ page }) => { + const fn = await waitForDomEvent(page, 'aem:experimentation'); + await page.goto('/tests/fixtures/campaigns/section-level?campaign=bar'); + expect(await page.evaluate(fn)).toEqual({ + type: 'campaign', + element: await page.evaluate(() => document.querySelector('.section')), + campaign: 'bar', + }); + }); +}); + +test.describe('Fragment-level campaigns', () => { + test('Replaces the fragment content with the variant.', async ({ page }) => { + await goToAndRunCampaign(page, '/tests/fixtures/campaigns/fragment-level?campaign=foo'); + expect(await page.locator('.fragment').textContent()).toContain('Hello v1!'); + }); + + test('Supports plural format for manifest keys.', async ({ page }) => { + await goToAndRunCampaign(page, '/tests/fixtures/campaigns/fragment-level--alt?campaign=foo'); + expect(await page.locator('.fragment').textContent()).toContain('Hello v1!'); + }); + + test('Ignores invalid manifest url.', async ({ page }) => { + await goToAndRunCampaign(page, '/tests/fixtures/campaigns/fragment-level--invalid-url?campaign=foo'); + expect(await page.locator('.fragment').textContent()).toContain('Hello World!'); + }); + + test('Sets classes on the section for the campaign.', async ({ page }) => { + await goToAndRunCampaign(page, '/tests/fixtures/campaigns/fragment-level?campaign=foo'); + expect(await page.locator('.fragment').getAttribute('class')).toContain('campaign-foo'); + await goToAndRunCampaign(page, '/tests/fixtures/campaigns/fragment-level?campaign=bar'); + expect(await page.locator('.fragment').getAttribute('class')).toContain('campaign-bar'); + }); + + test('Exposes the campaigns in a JS API.', async ({ page }) => { + await goToAndRunCampaign(page, '/tests/fixtures/campaigns/fragment-level?campaign=foo'); + expect(await page.evaluate(() => window.hlx.campaigns)).toContainEqual( + expect.objectContaining({ + type: 'fragment', + config: expect.objectContaining({ + configuredCampaigns: { + foo: '/tests/fixtures/campaigns/variant-1', + bar: '/tests/fixtures/campaigns/variant-2', + }, + selectedCampaign: 'foo', + }), + servedExperience: '/tests/fixtures/campaigns/variant-1', + }), + ); + }); + + test('triggers a DOM event with the campaign detail', async ({ page }) => { + const fn = await waitForDomEvent(page, 'aem:experimentation'); + await page.goto('/tests/fixtures/campaigns/fragment-level?campaign=foo'); + expect(await page.evaluate(fn)).toEqual({ + type: 'campaign', + element: await page.evaluate(() => document.querySelector('.fragment')), + campaign: 'foo', + }); + }); +}); + +test.describe('Backward Compatibility with v1', () => { + test('Support the old "audience" metadata.', async ({ page }) => { + await page.addInitScript(() => { + window.AUDIENCES = { baz: () => true }; + }); + await goToAndRunCampaign(page, '/tests/fixtures/campaigns/page-level--backward-compatibility--audience?campaign=foo'); + expect(await page.locator('main').textContent()).toContain('Hello v1!'); + }); +}); diff --git a/tests/coverage.js b/tests/coverage.js new file mode 100644 index 00000000..939df135 --- /dev/null +++ b/tests/coverage.js @@ -0,0 +1,37 @@ +// eslint-disable-next-line import/no-extraneous-dependencies +import MCR from 'monocart-coverage-reports'; + +const coverageReport = MCR({ + name: 'AEM Experimentation Plugin Coverage Report', + outputDir: './coverage', + reports: ['v8', 'console-details', 'codecov'], + entryFilter: { + '**/src/ued.js': false, + '**/src/**': true, + }, +}); + +export async function start() { + // Nothing to do here +} + +export async function end() { + await coverageReport.generate(); +} + +export function track(test) { + test.beforeEach(async ({ page }) => { + await Promise.all([ + page.coverage.startJSCoverage({ resetOnNavigation: false }), + page.coverage.startCSSCoverage({ resetOnNavigation: false }), + ]); + }); + + test.afterEach(async ({ page }) => { + const [jsCoverage, cssCoverage] = await Promise.all([ + page.coverage.stopJSCoverage(), + page.coverage.stopCSSCoverage(), + ]); + await coverageReport.add([...jsCoverage, ...cssCoverage]); + }); +} diff --git a/tests/experiments.test.js b/tests/experiments.test.js new file mode 100644 index 00000000..883ce274 --- /dev/null +++ b/tests/experiments.test.js @@ -0,0 +1,321 @@ +/* eslint-disable import/no-extraneous-dependencies */ +import { test, expect } from '@playwright/test'; +import { track } from './coverage.js'; +import { goToAndRunExperiment, waitForDomEvent } from './utils.js'; + +track(test); + +test.describe('Page-level experiments', () => { + test('Replaces the page content with the variant.', async ({ page }) => { + await goToAndRunExperiment(page, '/tests/fixtures/experiments/page-level'); + expect(await page.locator('main').textContent()).toMatch(/Hello (World|v1|v2)!/); + }); + + test('Visiting the page multiple times yields the same variant', async ({ page }) => { + await goToAndRunExperiment(page, '/tests/fixtures/experiments/page-level'); + const text = await page.locator('main').textContent(); + await goToAndRunExperiment(page, '/tests/fixtures/experiments/page-level'); + expect(await page.locator('main').textContent()).toEqual(text); + await goToAndRunExperiment(page, '/tests/fixtures/experiments/page-level'); + expect(await page.locator('main').textContent()).toEqual(text); + }); + + test('does not run inactive experiments.', async ({ page }) => { + await goToAndRunExperiment(page, '/tests/fixtures/experiments/page-level--inactive'); + expect(await page.locator('main').textContent()).toEqual('Hello World!'); + await goToAndRunExperiment(page, '/tests/fixtures/experiments/page-level--inactive?experiment=foo/challenger-1'); + expect(await page.locator('main').textContent()).toEqual('Hello v1!'); + }); + + test('Serves the variant if the configured audience is resolved.', async ({ page }) => { + await page.addInitScript(() => { + window.AUDIENCES = { bar: () => false }; + }); + await goToAndRunExperiment(page, '/tests/fixtures/experiments/page-level--audiences?experiment=foo/challenger-1'); + expect(await page.locator('main').textContent()).toEqual('Hello World!'); + await page.addInitScript(() => { + window.AUDIENCES = { bar: () => true }; + }); + await goToAndRunExperiment(page, '/tests/fixtures/experiments/page-level--audiences?experiment=foo/challenger-1'); + expect(await page.locator('main').textContent()).toEqual('Hello v1!'); + await page.addInitScript(() => { + window.AUDIENCES = { bar: async () => Promise.resolve(true) }; + }); + await goToAndRunExperiment(page, '/tests/fixtures/experiments/page-level--audiences?experiment=foo/challenger-2'); + expect(await page.locator('main').textContent()).toEqual('Hello v2!'); + }); + + test('Supports the "stard-date" and "end-date" metadata.', async ({ page }) => { + await goToAndRunExperiment(page, '/tests/fixtures/experiments/page-level--time-bound'); + expect(await page.locator('main').textContent()).toMatch(/Hello (World|v1|v2)!/); + await goToAndRunExperiment(page, '/tests/fixtures/experiments/page-level--time-bound-start'); + expect(await page.locator('main').textContent()).toEqual('Hello World!'); + await goToAndRunExperiment(page, '/tests/fixtures/experiments/page-level--time-bound-end'); + expect(await page.locator('main').textContent()).toEqual('Hello World!'); + }); + + test('Supports the "split" metadata.', async ({ page }) => { + await goToAndRunExperiment(page, '/tests/fixtures/experiments/page-level--split'); + expect(await page.locator('main').textContent()).toEqual('Hello v2!'); + }); + + test('Sets classes on the body for the experiment.', async ({ page }) => { + await goToAndRunExperiment(page, '/tests/fixtures/experiments/page-level?experiment=foo/control'); + expect(await page.locator('body').getAttribute('class')).toContain('experiment-foo'); + expect(await page.locator('body').getAttribute('class')).toContain('variant-control'); + await goToAndRunExperiment(page, '/tests/fixtures/experiments/page-level?experiment=foo/challenger-1'); + expect(await page.locator('body').getAttribute('class')).toContain('experiment-foo'); + expect(await page.locator('body').getAttribute('class')).toContain('variant-challenger-1'); + await goToAndRunExperiment(page, '/tests/fixtures/experiments/page-level?experiment=foo/challenger-2'); + expect(await page.locator('body').getAttribute('class')).toContain('experiment-foo'); + expect(await page.locator('body').getAttribute('class')).toContain('variant-challenger-2'); + }); + + test('Ignores empty experiments.', async ({ page }) => { + await goToAndRunExperiment(page, '/tests/fixtures/experiments/page-level--empty?experiment=foo/challenger-1'); + expect(await page.locator('main').textContent()).toEqual('Hello World!'); + expect(await page.locator('body').getAttribute('class')).not.toContain('experiment-foo'); + expect(await page.locator('body').getAttribute('class')).not.toContain('variant-control'); + + await goToAndRunExperiment(page, '/tests/fixtures/experiments/page-level--empty2?experiment=foo/challenger-1'); + expect(await page.locator('main').textContent()).toEqual('Hello World!'); + expect(await page.locator('body').getAttribute('class')).not.toContain('experiment-foo'); + expect(await page.locator('body').getAttribute('class')).not.toContain('variant-control'); + }); + + test('Ignores invalid experiment references in the query parameters.', async ({ page }) => { + await goToAndRunExperiment(page, '/tests/fixtures/experiments/page-level?experiment=foo/invalid'); + expect(await page.locator('main').textContent()).toMatch(/Hello (World|v1|v2)!/); + }); + + test('Ignores invalid variant urls.', async ({ page }) => { + await goToAndRunExperiment(page, '/tests/fixtures/experiments/page-level--invalid-url?experiment=foo/challenger-1'); + expect(await page.locator('main').textContent()).toEqual('Hello World!'); + expect(await page.locator('body').getAttribute('class')).toContain('experiment-foo'); + expect(await page.locator('body').getAttribute('class')).toContain('variant-control'); + }); + + test('Supports code experiments.', async ({ page }) => { + await goToAndRunExperiment(page, '/tests/fixtures/experiments/page-level--code?experiment=foo/challenger-1'); + expect(await page.locator('main').textContent()).toEqual('Hello World!'); + expect(await page.locator('body').getAttribute('class')).toContain('experiment-foo'); + expect(await page.locator('body').getAttribute('class')).toContain('variant-challenger-1'); + }); + + test('Tracks the experiment in RUM.', async ({ page }) => { + await page.addInitScript(() => { + window.rumCalls = []; + window.hlx = { rum: { sampleRUM: (...args) => window.rumCalls.push(args) } }; + }); + await goToAndRunExperiment(page, '/tests/fixtures/experiments/page-level'); + expect(await page.evaluate(() => window.rumCalls)).toContainEqual([ + 'experiment', + expect.objectContaining({ + source: 'foo', + target: expect.stringMatching(/control|challenger-1|challenger-2/), + }), + ]); + }); + + test('Exposes the experiment in a JS API.', async ({ page }) => { + await goToAndRunExperiment(page, '/tests/fixtures/experiments/page-level'); + expect(await page.evaluate(() => window.hlx.experiments)).toContainEqual( + expect.objectContaining({ + type: 'page', + config: expect.objectContaining({ + id: 'foo', + run: true, + selectedVariant: expect.stringMatching(/control|challenger-1|challenger-2/), + status: 'active', + variants: { + control: expect.objectContaining({ percentageSplit: '0.3334' }), + 'challenger-1': expect.objectContaining({ percentageSplit: '0.3333' }), + 'challenger-2': expect.objectContaining({ percentageSplit: '0.3333' }), + }, + }), + servedExperience: expect.stringContaining('/tests/fixtures/experiments/page-level'), + }), + ); + }); + + test('Controls the variant shown via query parameters.', async ({ page }) => { + await goToAndRunExperiment(page, '/tests/fixtures/experiments/page-level?experiment=foo/control'); + expect(await page.locator('main').textContent()).toEqual('Hello World!'); + await goToAndRunExperiment(page, '/tests/fixtures/experiments/page-level?experiment=foo/challenger-1'); + expect(await page.locator('main').textContent()).toEqual('Hello v1!'); + }); + + test('supports overriding the shown experiment and variant via query parameters.', async ({ page }) => { + await goToAndRunExperiment(page, '/tests/fixtures/experiments/page-level?experiment=foo/challenger-2&experiment=bar/challenger-1'); + expect(await page.locator('main').textContent()).toEqual('Hello v2!'); + await goToAndRunExperiment(page, '/tests/fixtures/experiments/page-level?experiment=foo&experiment-variant=challenger-1'); + expect(await page.locator('main').textContent()).toEqual('Hello v1!'); + await goToAndRunExperiment(page, '/tests/fixtures/experiments/page-level--audiences?experiment=foo&experiment-variant=challenger-2&audience=bar'); + expect(await page.locator('main').textContent()).toEqual('Hello v2!'); + }); + + test('triggers a DOM event with the experiment detail', async ({ page }) => { + const fn = await waitForDomEvent(page, 'aem:experimentation'); + await page.goto('/tests/fixtures/experiments/page-level?experiment=foo&experiment-variant=challenger-1'); + expect(await page.evaluate(fn)).toEqual({ + type: 'experiment', + element: await page.evaluate(() => document.body), + experiment: 'foo', + variant: 'challenger-1', + }); + }); +}); + +test.describe('Section-level experiments', () => { + test('Replaces the section content with the variant.', async ({ page }) => { + await goToAndRunExperiment(page, '/tests/fixtures/experiments/section-level'); + expect(await page.locator('main>div').textContent()).toMatch(/Hello (World|v1|v2)!/); + await goToAndRunExperiment(page, '/tests/fixtures/experiments/section-level?experiment=bar/control'); + expect(await page.locator('main>div').textContent()).toContain('Hello World!'); + await goToAndRunExperiment(page, '/tests/fixtures/experiments/section-level?experiment=bar/challenger-1'); + expect(await page.locator('main>div').textContent()).toContain('Hello v1!'); + await goToAndRunExperiment(page, '/tests/fixtures/experiments/section-level?experiment=bar/challenger-2'); + expect(await page.locator('main>div').textContent()).toContain('Hello v2!'); + }); + + test('Sets classes on the section for the experiment.', async ({ page }) => { + await goToAndRunExperiment(page, '/tests/fixtures/experiments/section-level?experiment=bar/control'); + expect(await page.locator('main>div').getAttribute('class')).toContain('experiment-bar'); + expect(await page.locator('main>div').getAttribute('class')).toContain('variant-control'); + await goToAndRunExperiment(page, '/tests/fixtures/experiments/section-level?experiment=bar/challenger-1'); + expect(await page.locator('main>div').getAttribute('class')).toContain('experiment-bar'); + expect(await page.locator('main>div').getAttribute('class')).toContain('variant-challenger-1'); + await goToAndRunExperiment(page, '/tests/fixtures/experiments/section-level?experiment=bar/challenger-2'); + expect(await page.locator('main>div').getAttribute('class')).toContain('experiment-bar'); + expect(await page.locator('main>div').getAttribute('class')).toContain('variant-challenger-2'); + }); + + test('Exposes the experiment in a JS API.', async ({ page }) => { + await goToAndRunExperiment(page, '/tests/fixtures/experiments/section-level'); + expect(await page.evaluate(() => window.hlx.experiments)).toContainEqual( + expect.objectContaining({ + type: 'section', + config: expect.objectContaining({ + id: 'bar', + run: true, + selectedVariant: expect.stringMatching(/control|challenger-1|challenger-2/), + status: 'active', + variants: { + control: expect.objectContaining({ percentageSplit: '0.3334' }), + 'challenger-1': expect.objectContaining({ percentageSplit: '0.3333' }), + 'challenger-2': expect.objectContaining({ percentageSplit: '0.3333' }), + }, + }), + servedExperience: expect.stringMatching(/\/tests\/fixtures\/experiments\/(page|section)-level/), + }), + ); + }); + + test('triggers a DOM event with the experiment detail', async ({ page }) => { + const fn = await waitForDomEvent(page, 'aem:experimentation'); + await page.goto('/tests/fixtures/experiments/section-level?experiment=bar/challenger-2'); + expect(await page.evaluate(fn)).toEqual({ + type: 'experiment', + element: await page.evaluate(() => document.querySelector('.section')), + experiment: 'bar', + variant: 'challenger-2', + }); + }); +}); + +test.describe('Fragment-level experiments', () => { + test('Replaces the fragment content with the variant.', async ({ page }) => { + await goToAndRunExperiment(page, '/tests/fixtures/experiments/fragment-level'); + expect(await page.locator('.fragment').first().textContent()).toMatch(/Hello (World|v1|v2)!/); + await goToAndRunExperiment(page, '/tests/fixtures/experiments/fragment-level?experiment=baz/control'); + expect(await page.locator('.fragment').first().textContent()).toContain('Hello World!'); + await goToAndRunExperiment(page, '/tests/fixtures/experiments/fragment-level?experiment=baz/challenger-1'); + expect(await page.locator('.fragment').first().textContent()).toContain('Hello v1!'); + await goToAndRunExperiment(page, '/tests/fixtures/experiments/fragment-level?experiment=baz/challenger-2'); + expect(await page.locator('.fragment').first().textContent()).toContain('Hello v2!'); + }); + + test('Supports plural format for manifest keys.', async ({ page }) => { + await goToAndRunExperiment(page, '/tests/fixtures/experiments/fragment-level--alt?experiment=baz/control'); + expect(await page.locator('.fragment').first().textContent()).toContain('Hello World!'); + await goToAndRunExperiment(page, '/tests/fixtures/experiments/fragment-level--alt?experiment=baz/challenger-1'); + expect(await page.locator('.fragment').first().textContent()).toContain('Hello v1!'); + await goToAndRunExperiment(page, '/tests/fixtures/experiments/fragment-level--alt?experiment=baz/challenger-2'); + expect(await page.locator('.fragment').first().textContent()).toContain('Hello v2!'); + }); + + test('Ignores invalid manifest url.', async ({ page }) => { + await goToAndRunExperiment(page, '/tests/fixtures/experiments/fragment-level--invalid-url'); + expect(await page.locator('.fragment').first().textContent()).toContain('Hello World!'); + }); + + test('Replaces the async fragment content with the variant.', async ({ page }) => { + await goToAndRunExperiment(page, '/tests/fixtures/experiments/fragment-level--async'); + expect(await page.locator('.fragment').first().textContent()).toMatch(/Hello (World|v1|v2)!/); + await goToAndRunExperiment(page, '/tests/fixtures/experiments/fragment-level--async?experiment=baz/control'); + expect(await page.locator('.fragment').first().textContent()).toContain('Hello World!'); + await goToAndRunExperiment(page, '/tests/fixtures/experiments/fragment-level--async?experiment=baz/challenger-1'); + expect(await page.locator('.fragment').first().textContent()).toContain('Hello v1!'); + await goToAndRunExperiment(page, '/tests/fixtures/experiments/fragment-level--async?experiment=baz/challenger-2'); + expect(await page.locator('.fragment').first().textContent()).toContain('Hello v2!'); + }); + + test('Sets classes on the section for the experiment.', async ({ page }) => { + await goToAndRunExperiment(page, '/tests/fixtures/experiments/fragment-level?experiment=baz/control'); + expect(await page.locator('.fragment').first().getAttribute('class')).toContain('experiment-baz'); + expect(await page.locator('.fragment').first().getAttribute('class')).toContain('variant-control'); + await goToAndRunExperiment(page, '/tests/fixtures/experiments/fragment-level?experiment=baz/challenger-1'); + expect(await page.locator('.fragment').first().getAttribute('class')).toContain('experiment-baz'); + expect(await page.locator('.fragment').first().getAttribute('class')).toContain('variant-challenger-1'); + await goToAndRunExperiment(page, '/tests/fixtures/experiments/fragment-level?experiment=baz/challenger-2'); + expect(await page.locator('.fragment').first().getAttribute('class')).toContain('experiment-baz'); + expect(await page.locator('.fragment').first().getAttribute('class')).toContain('variant-challenger-2'); + }); + + test('Exposes the experiment in a JS API.', async ({ page }) => { + await goToAndRunExperiment(page, '/tests/fixtures/experiments/fragment-level'); + expect(await page.evaluate(() => window.hlx.experiments)).toContainEqual( + expect.objectContaining({ + type: 'fragment', + config: expect.objectContaining({ + id: 'baz', + run: true, + selectedVariant: expect.stringMatching(/control|challenger-1|challenger-2/), + status: 'active', + variants: { + control: expect.objectContaining({ percentageSplit: '0.3334' }), + 'challenger-1': expect.objectContaining({ percentageSplit: '0.3333' }), + 'challenger-2': expect.objectContaining({ percentageSplit: '0.3333' }), + }, + }), + servedExperience: expect.stringMatching(/\/tests\/fixtures\/experiments\/(fragment|section)-level/), + }), + ); + }); + + test('triggers a DOM event with the experiment detail', async ({ page }) => { + const fn = await waitForDomEvent(page, 'aem:experimentation'); + await page.goto('/tests/fixtures/experiments/fragment-level?experiment=baz/challenger-1'); + expect(await page.evaluate(fn)).toEqual({ + type: 'experiment', + element: await page.evaluate(() => document.querySelector('.fragment')), + experiment: 'baz', + variant: 'challenger-1', + }); + }); +}); + +test.describe('Backward Compatibility with v1', () => { + test('Support the old "instant-experiment" metadata.', async ({ page }) => { + await goToAndRunExperiment(page, '/tests/fixtures/experiments/page-level--backward-compatibility--instant-experiment?experiment=foo/challenger-1'); + expect(await page.locator('main').textContent()).toEqual('Hello v1!'); + }); + + test('Support the old "audience" metadata.', async ({ page }) => { + await page.addInitScript(() => { + window.AUDIENCES = { bar: () => true }; + }); + await goToAndRunExperiment(page, '/tests/fixtures/experiments/page-level--backward-compatibility--audience?experiment=foo/challenger-1'); + expect(await page.locator('main').textContent()).toEqual('Hello v1!'); + }); +}); diff --git a/tests/fixtures/aem.js b/tests/fixtures/aem.js new file mode 100644 index 00000000..61527b42 --- /dev/null +++ b/tests/fixtures/aem.js @@ -0,0 +1,759 @@ +/* + * Copyright 2024 Adobe. All rights reserved. + * This file is licensed to you under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under + * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS + * OF ANY KIND, either express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ + +/* eslint-env browser */ + +/** + * log RUM if part of the sample. + * @param {string} checkpoint identifies the checkpoint in funnel + * @param {Object} data additional data for RUM sample + * @param {string} data.source DOM node that is the source of a checkpoint event, + * identified by #id or .classname + * @param {string} data.target subject of the checkpoint event, + * for instance the href of a link, or a search term + */ +function sampleRUM(checkpoint, data = {}) { + const SESSION_STORAGE_KEY = 'aem-rum'; + sampleRUM.baseURL = sampleRUM.baseURL + || new URL(window.RUM_BASE == null ? 'https://rum.hlx.page' : window.RUM_BASE, window.location); + sampleRUM.defer = sampleRUM.defer || []; + const defer = (fnname) => { + sampleRUM[fnname] = sampleRUM[fnname] || ((...args) => sampleRUM.defer.push({ fnname, args })); + }; + sampleRUM.drain = sampleRUM.drain + || ((dfnname, fn) => { + sampleRUM[dfnname] = fn; + sampleRUM.defer + .filter(({ fnname }) => dfnname === fnname) + .forEach(({ fnname, args }) => sampleRUM[fnname](...args)); + }); + sampleRUM.always = sampleRUM.always || []; + sampleRUM.always.on = (chkpnt, fn) => { + sampleRUM.always[chkpnt] = fn; + }; + sampleRUM.on = (chkpnt, fn) => { + sampleRUM.cases[chkpnt] = fn; + }; + defer('observe'); + defer('cwv'); + try { + window.hlx = window.hlx || {}; + if (!window.hlx.rum) { + const usp = new URLSearchParams(window.location.search); + const weight = usp.get('rum') === 'on' ? 1 : 100; // with parameter, weight is 1. Defaults to 100. + const id = Array.from({ length: 75 }, (_, i) => String.fromCharCode(48 + i)) + .filter((a) => /\d|[A-Z]/i.test(a)) + .filter(() => Math.random() * 75 > 70) + .join(''); + const random = Math.random(); + const isSelected = random * weight < 1; + const firstReadTime = window.performance ? window.performance.timeOrigin : Date.now(); + const urlSanitizers = { + full: () => window.location.href, + origin: () => window.location.origin, + path: () => window.location.href.replace(/\?.*$/, ''), + }; + // eslint-disable-next-line max-len + const rumSessionStorage = sessionStorage.getItem(SESSION_STORAGE_KEY) + ? JSON.parse(sessionStorage.getItem(SESSION_STORAGE_KEY)) + : {}; + // eslint-disable-next-line max-len + rumSessionStorage.pages = (rumSessionStorage.pages ? rumSessionStorage.pages : 0) + + 1 + /* noise */ + (Math.floor(Math.random() * 20) - 10); + sessionStorage.setItem(SESSION_STORAGE_KEY, JSON.stringify(rumSessionStorage)); + // eslint-disable-next-line object-curly-newline, max-len + window.hlx.rum = { + weight, + id, + random, + isSelected, + firstReadTime, + sampleRUM, + sanitizeURL: urlSanitizers[window.hlx.RUM_MASK_URL || 'path'], + rumSessionStorage, + }; + } + + const { weight, id, firstReadTime } = window.hlx.rum; + if (window.hlx && window.hlx.rum && window.hlx.rum.isSelected) { + const knownProperties = [ + 'weight', + 'id', + 'referer', + 'checkpoint', + 't', + 'source', + 'target', + 'cwv', + 'CLS', + 'FID', + 'LCP', + 'INP', + 'TTFB', + ]; + const sendPing = (pdata = data) => { + // eslint-disable-next-line max-len + const t = Math.round( + window.performance ? window.performance.now() : Date.now() - firstReadTime, + ); + // eslint-disable-next-line object-curly-newline, max-len, no-use-before-define + const body = JSON.stringify( + { + weight, id, referer: window.hlx.rum.sanitizeURL(), checkpoint, t, ...data, + }, + knownProperties, + ); + const url = new URL(`.rum/${weight}`, sampleRUM.baseURL).href; + navigator.sendBeacon(url, body); + // eslint-disable-next-line no-console + console.debug(`ping:${checkpoint}`, pdata); + }; + sampleRUM.cases = sampleRUM.cases || { + load: () => sampleRUM('pagesviewed', { source: window.hlx.rum.rumSessionStorage.pages }) || true, + cwv: () => sampleRUM.cwv(data) || true, + lazy: () => { + // use classic script to avoid CORS issues + const script = document.createElement('script'); + script.src = new URL( + '.rum/@adobe/helix-rum-enhancer@^1/src/index.js', + sampleRUM.baseURL, + ).href; + document.head.appendChild(script); + return true; + }, + }; + sendPing(data); + if (sampleRUM.cases[checkpoint]) { + sampleRUM.cases[checkpoint](); + } + } + if (sampleRUM.always[checkpoint]) { + sampleRUM.always[checkpoint](data); + } + } catch (error) { + // something went wrong + } +} + +/** + * Setup block utils. + */ +function setup() { + window.hlx = window.hlx || {}; + window.hlx.RUM_MASK_URL = 'full'; + window.hlx.codeBasePath = ''; + window.hlx.lighthouse = new URLSearchParams(window.location.search).get('lighthouse') === 'on'; + + const scriptEl = document.querySelector('script[src$="/scripts/scripts.js"]'); + if (scriptEl) { + try { + [window.hlx.codeBasePath] = new URL(scriptEl.src).pathname.split('/scripts/scripts.js'); + } catch (error) { + // eslint-disable-next-line no-console + console.log(error); + } + } +} + +/** + * Auto initializiation. + */ + +function init() { + setup(); +} + +/** + * Sanitizes a string for use as class name. + * @param {string} name The unsanitized string + * @returns {string} The class name + */ +function toClassName(name) { + return typeof name === 'string' + ? name + .toLowerCase() + .replace(/[^0-9a-z]/gi, '-') + .replace(/-+/g, '-') + .replace(/^-|-$/g, '') + : ''; +} + +/** + * Sanitizes a string for use as a js property name. + * @param {string} name The unsanitized string + * @returns {string} The camelCased name + */ +function toCamelCase(name) { + return toClassName(name).replace(/-([a-z])/g, (g) => g[1].toUpperCase()); +} + +/** + * Extracts the config from a block. + * @param {Element} block The block element + * @returns {object} The block config + */ +// eslint-disable-next-line import/prefer-default-export +function readBlockConfig(block) { + const config = {}; + block.querySelectorAll(':scope > div').forEach((row) => { + if (row.children) { + const cols = [...row.children]; + if (cols[1]) { + const col = cols[1]; + const name = toClassName(cols[0].textContent); + let value = ''; + if (col.querySelector('a')) { + const as = [...col.querySelectorAll('a')]; + if (as.length === 1) { + value = as[0].href; + } else { + value = as.map((a) => a.href); + } + } else if (col.querySelector('img')) { + const imgs = [...col.querySelectorAll('img')]; + if (imgs.length === 1) { + value = imgs[0].src; + } else { + value = imgs.map((img) => img.src); + } + } else if (col.querySelector('p')) { + const ps = [...col.querySelectorAll('p')]; + if (ps.length === 1) { + value = ps[0].textContent; + } else { + value = ps.map((p) => p.textContent); + } + } else value = row.children[1].textContent; + config[name] = value; + } + } + }); + return config; +} + +/** + * Loads a CSS file. + * @param {string} href URL to the CSS file + */ +async function loadCSS(href) { + return new Promise((resolve, reject) => { + if (!document.querySelector(`head > link[href="${href}"]`)) { + const link = document.createElement('link'); + link.rel = 'stylesheet'; + link.href = href; + link.onload = resolve; + link.onerror = reject; + document.head.append(link); + } else { + resolve(); + } + }); +} + +/** + * Loads a non module JS file. + * @param {string} src URL to the JS file + * @param {Object} attrs additional optional attributes + */ +async function loadScript(src, attrs) { + return new Promise((resolve, reject) => { + if (!document.querySelector(`head > script[src="${src}"]`)) { + const script = document.createElement('script'); + script.src = src; + if (attrs) { + // eslint-disable-next-line no-restricted-syntax, guard-for-in + for (const attr in attrs) { + script.setAttribute(attr, attrs[attr]); + } + } + script.onload = resolve; + script.onerror = reject; + document.head.append(script); + } else { + resolve(); + } + }); +} + +/** + * Retrieves the content of metadata tags. + * @param {string} name The metadata name (or property) + * @param {Document} doc Document object to query for metadata. Defaults to the window's document + * @returns {string} The metadata value(s) + */ +function getMetadata(name, doc = document) { + const attr = name && name.includes(':') ? 'property' : 'name'; + const meta = [...doc.head.querySelectorAll(`meta[${attr}="${name}"]`)] + .map((m) => m.content) + .join(', '); + return meta || ''; +} + +/** + * Returns a picture element with webp and fallbacks + * @param {string} src The image URL + * @param {string} [alt] The image alternative text + * @param {boolean} [eager] Set loading attribute to eager + * @param {Array} [breakpoints] Breakpoints and corresponding params (eg. width) + * @returns {Element} The picture element + */ +function createOptimizedPicture( + src, + alt = '', + eager = false, + breakpoints = [{ media: '(min-width: 600px)', width: '2000' }, { width: '750' }], +) { + const url = new URL(src, window.location.href); + const picture = document.createElement('picture'); + const { pathname } = url; + const ext = pathname.substring(pathname.lastIndexOf('.') + 1); + + // webp + breakpoints.forEach((br) => { + const source = document.createElement('source'); + if (br.media) source.setAttribute('media', br.media); + source.setAttribute('type', 'image/webp'); + source.setAttribute('srcset', `${pathname}?width=${br.width}&format=webply&optimize=medium`); + picture.appendChild(source); + }); + + // fallback + breakpoints.forEach((br, i) => { + if (i < breakpoints.length - 1) { + const source = document.createElement('source'); + if (br.media) source.setAttribute('media', br.media); + source.setAttribute('srcset', `${pathname}?width=${br.width}&format=${ext}&optimize=medium`); + picture.appendChild(source); + } else { + const img = document.createElement('img'); + img.setAttribute('loading', eager ? 'eager' : 'lazy'); + img.setAttribute('alt', alt); + picture.appendChild(img); + img.setAttribute('src', `${pathname}?width=${br.width}&format=${ext}&optimize=medium`); + } + }); + + return picture; +} + +/** + * Set template (page structure) and theme (page styles). + */ +function decorateTemplateAndTheme() { + const addClasses = (element, classes) => { + classes.split(',').forEach((c) => { + element.classList.add(toClassName(c.trim())); + }); + }; + const template = getMetadata('template'); + if (template) addClasses(document.body, template); + const theme = getMetadata('theme'); + if (theme) addClasses(document.body, theme); +} + +/** + * Wrap inline text content of block cells within a

tag. + * @param {Element} block the block element + */ +function wrapTextNodes(block) { + const validWrappers = [ + 'P', + 'PRE', + 'UL', + 'OL', + 'PICTURE', + 'TABLE', + 'H1', + 'H2', + 'H3', + 'H4', + 'H5', + 'H6', + ]; + + const wrap = (el) => { + const wrapper = document.createElement('p'); + wrapper.append(...el.childNodes); + el.append(wrapper); + }; + + block.querySelectorAll(':scope > div > div').forEach((blockColumn) => { + if (blockColumn.hasChildNodes()) { + const hasWrapper = !!blockColumn.firstElementChild + && validWrappers.some((tagName) => blockColumn.firstElementChild.tagName === tagName); + if (!hasWrapper) { + wrap(blockColumn); + } else if ( + blockColumn.firstElementChild.tagName === 'PICTURE' + && (blockColumn.children.length > 1 || !!blockColumn.textContent.trim()) + ) { + wrap(blockColumn); + } + } + }); +} + +/** + * Decorates paragraphs containing a single link as buttons. + * @param {Element} element container element + */ +function decorateButtons(element) { + element.querySelectorAll('a').forEach((a) => { + a.title = a.title || a.textContent; + if (a.href !== a.textContent) { + const up = a.parentElement; + const twoup = a.parentElement.parentElement; + if (!a.querySelector('img')) { + if (up.childNodes.length === 1 && (up.tagName === 'P' || up.tagName === 'DIV')) { + a.className = 'button'; // default + up.classList.add('button-container'); + } + if ( + up.childNodes.length === 1 + && up.tagName === 'STRONG' + && twoup.childNodes.length === 1 + && twoup.tagName === 'P' + ) { + a.className = 'button primary'; + twoup.classList.add('button-container'); + } + if ( + up.childNodes.length === 1 + && up.tagName === 'EM' + && twoup.childNodes.length === 1 + && twoup.tagName === 'P' + ) { + a.className = 'button secondary'; + twoup.classList.add('button-container'); + } + } + } + }); +} + +/** + * Add for icon, prefixed with codeBasePath and optional prefix. + * @param {Element} [span] span element with icon classes + * @param {string} [prefix] prefix to be added to icon src + * @param {string} [alt] alt text to be added to icon + */ +function decorateIcon(span, prefix = '', alt = '') { + const iconName = Array.from(span.classList) + .find((c) => c.startsWith('icon-')) + .substring(5); + const img = document.createElement('img'); + img.dataset.iconName = iconName; + img.src = `${window.hlx.codeBasePath}${prefix}/icons/${iconName}.svg`; + img.alt = alt; + img.loading = 'lazy'; + span.append(img); +} + +/** + * Add for icons, prefixed with codeBasePath and optional prefix. + * @param {Element} [element] Element containing icons + * @param {string} [prefix] prefix to be added to icon the src + */ +function decorateIcons(element, prefix = '') { + const icons = [...element.querySelectorAll('span.icon')]; + icons.forEach((span) => { + decorateIcon(span, prefix); + }); +} + +/** + * Decorates all sections in a container element. + * @param {Element} main The container element + */ +function decorateSections(main) { + main.querySelectorAll(':scope > div').forEach((section) => { + const wrappers = []; + let defaultContent = false; + [...section.children].forEach((e) => { + if (e.tagName === 'DIV' || !defaultContent) { + const wrapper = document.createElement('div'); + wrappers.push(wrapper); + defaultContent = e.tagName !== 'DIV'; + if (defaultContent) wrapper.classList.add('default-content-wrapper'); + } + wrappers[wrappers.length - 1].append(e); + }); + wrappers.forEach((wrapper) => section.append(wrapper)); + section.classList.add('section'); + section.dataset.sectionStatus = 'initialized'; + section.style.display = 'none'; + + // Process section metadata + const sectionMeta = section.querySelector('div.section-metadata'); + if (sectionMeta) { + const meta = readBlockConfig(sectionMeta); + Object.keys(meta).forEach((key) => { + if (key === 'style') { + const styles = meta.style + .split(',') + .filter((style) => style) + .map((style) => toClassName(style.trim())); + styles.forEach((style) => section.classList.add(style)); + } else { + section.dataset[toCamelCase(key)] = meta[key]; + } + }); + sectionMeta.parentNode.remove(); + } + }); +} + +/** + * Gets placeholders object. + * @param {string} [prefix] Location of placeholders + * @returns {object} Window placeholders object + */ +// eslint-disable-next-line import/prefer-default-export +async function fetchPlaceholders(prefix = 'default') { + window.placeholders = window.placeholders || {}; + if (!window.placeholders[prefix]) { + window.placeholders[prefix] = new Promise((resolve) => { + fetch(`${prefix === 'default' ? '' : prefix}/placeholders.json`) + .then((resp) => { + if (resp.ok) { + return resp.json(); + } + return {}; + }) + .then((json) => { + const placeholders = {}; + json.data + .filter((placeholder) => placeholder.Key) + .forEach((placeholder) => { + placeholders[toCamelCase(placeholder.Key)] = placeholder.Text; + }); + window.placeholders[prefix] = placeholders; + resolve(window.placeholders[prefix]); + }) + .catch(() => { + // error loading placeholders + window.placeholders[prefix] = {}; + resolve(window.placeholders[prefix]); + }); + }); + } + return window.placeholders[`${prefix}`]; +} + +/** + * Updates all section status in a container element. + * @param {Element} main The container element + */ +function updateSectionsStatus(main) { + const sections = [...main.querySelectorAll(':scope > div.section')]; + for (let i = 0; i < sections.length; i += 1) { + const section = sections[i]; + const status = section.dataset.sectionStatus; + if (status !== 'loaded') { + const loadingBlock = section.querySelector( + '.block[data-block-status="initialized"], .block[data-block-status="loading"]', + ); + if (loadingBlock) { + section.dataset.sectionStatus = 'loading'; + break; + } else { + section.dataset.sectionStatus = 'loaded'; + section.style.display = null; + } + } + } +} + +/** + * Builds a block DOM Element from a two dimensional array, string, or object + * @param {string} blockName name of the block + * @param {*} content two dimensional array or string or object of content + */ +function buildBlock(blockName, content) { + const table = Array.isArray(content) ? content : [[content]]; + const blockEl = document.createElement('div'); + // build image block nested div structure + blockEl.classList.add(blockName); + table.forEach((row) => { + const rowEl = document.createElement('div'); + row.forEach((col) => { + const colEl = document.createElement('div'); + const vals = col.elems ? col.elems : [col]; + vals.forEach((val) => { + if (val) { + if (typeof val === 'string') { + colEl.innerHTML += val; + } else { + colEl.appendChild(val); + } + } + }); + rowEl.appendChild(colEl); + }); + blockEl.appendChild(rowEl); + }); + return blockEl; +} + +/** + * Loads JS and CSS for a block. + * @param {Element} block The block element + */ +async function loadBlock(block) { + const status = block.dataset.blockStatus; + if (status !== 'loading' && status !== 'loaded') { + block.dataset.blockStatus = 'loading'; + const { blockName } = block.dataset; + try { + const cssLoaded = loadCSS(`${window.hlx.codeBasePath}/blocks/${blockName}/${blockName}.css`); + const decorationComplete = new Promise((resolve) => { + (async () => { + try { + const mod = await import( + `${window.hlx.codeBasePath}/blocks/${blockName}/${blockName}.js` + ); + if (mod.default) { + await mod.default(block); + } + } catch (error) { + // eslint-disable-next-line no-console + console.log(`failed to load module for ${blockName}`, error); + } + resolve(); + })(); + }); + await Promise.all([cssLoaded, decorationComplete]); + } catch (error) { + // eslint-disable-next-line no-console + console.log(`failed to load block ${blockName}`, error); + } + block.dataset.blockStatus = 'loaded'; + } + return block; +} + +/** + * Loads JS and CSS for all blocks in a container element. + * @param {Element} main The container element + */ +async function loadBlocks(main) { + updateSectionsStatus(main); + const blocks = [...main.querySelectorAll('div.block')]; + for (let i = 0; i < blocks.length; i += 1) { + // eslint-disable-next-line no-await-in-loop + await loadBlock(blocks[i]); + updateSectionsStatus(main); + } +} + +/** + * Decorates a block. + * @param {Element} block The block element + */ +function decorateBlock(block) { + const shortBlockName = block.classList[0]; + if (shortBlockName) { + block.classList.add('block'); + block.dataset.blockName = shortBlockName; + block.dataset.blockStatus = 'initialized'; + wrapTextNodes(block); + const blockWrapper = block.parentElement; + blockWrapper.classList.add(`${shortBlockName}-wrapper`); + const section = block.closest('.section'); + if (section) section.classList.add(`${shortBlockName}-container`); + } +} + +/** + * Decorates all blocks in a container element. + * @param {Element} main The container element + */ +function decorateBlocks(main) { + main.querySelectorAll('div.section > div > div').forEach(decorateBlock); +} + +/** + * Loads a block named 'header' into header + * @param {Element} header header element + * @returns {Promise} + */ +async function loadHeader(header) { + const headerBlock = buildBlock('header', ''); + header.append(headerBlock); + decorateBlock(headerBlock); + return loadBlock(headerBlock); +} + +/** + * Loads a block named 'footer' into footer + * @param footer footer element + * @returns {Promise} + */ +async function loadFooter(footer) { + const footerBlock = buildBlock('footer', ''); + footer.append(footerBlock); + decorateBlock(footerBlock); + return loadBlock(footerBlock); +} + +/** + * Load LCP block and/or wait for LCP in default content. + * @param {Array} lcpBlocks Array of blocks + */ +async function waitForLCP(lcpBlocks) { + const block = document.querySelector('.block'); + const hasLCPBlock = block && lcpBlocks.includes(block.dataset.blockName); + if (hasLCPBlock) await loadBlock(block); + + document.body.style.display = null; + const lcpCandidate = document.querySelector('main img'); + + await new Promise((resolve) => { + if (lcpCandidate && !lcpCandidate.complete) { + lcpCandidate.setAttribute('loading', 'eager'); + lcpCandidate.addEventListener('load', resolve); + lcpCandidate.addEventListener('error', resolve); + } else { + resolve(); + } + }); +} + +init(); + +export { + buildBlock, + createOptimizedPicture, + decorateBlock, + decorateBlocks, + decorateButtons, + decorateIcons, + decorateSections, + decorateTemplateAndTheme, + fetchPlaceholders, + getMetadata, + loadBlock, + loadBlocks, + loadCSS, + loadFooter, + loadHeader, + loadScript, + readBlockConfig, + sampleRUM, + setup, + toCamelCase, + toClassName, + updateSectionsStatus, + waitForLCP, + wrapTextNodes, +}; diff --git a/tests/fixtures/audiences/fragment-level--alt.html b/tests/fixtures/audiences/fragment-level--alt.html new file mode 100644 index 00000000..0dffb768 --- /dev/null +++ b/tests/fixtures/audiences/fragment-level--alt.html @@ -0,0 +1,23 @@ + + + + + + + +

+
+
+
+
Hello World!
+
+
+
+
+ + \ No newline at end of file diff --git a/tests/fixtures/audiences/fragment-level--async.html b/tests/fixtures/audiences/fragment-level--async.html new file mode 100644 index 00000000..64b9e1dd --- /dev/null +++ b/tests/fixtures/audiences/fragment-level--async.html @@ -0,0 +1,25 @@ + + + + + + + +
+
+
+ + + \ No newline at end of file diff --git a/tests/fixtures/audiences/fragment-level--invalid-url.html b/tests/fixtures/audiences/fragment-level--invalid-url.html new file mode 100644 index 00000000..19cd8305 --- /dev/null +++ b/tests/fixtures/audiences/fragment-level--invalid-url.html @@ -0,0 +1,23 @@ + + + + + + + +
+
+
+
+
Hello World!
+
+
+
+
+ + \ No newline at end of file diff --git a/tests/fixtures/audiences/fragment-level.html b/tests/fixtures/audiences/fragment-level.html new file mode 100644 index 00000000..af5b73b2 --- /dev/null +++ b/tests/fixtures/audiences/fragment-level.html @@ -0,0 +1,23 @@ + + + + + + + +
+
+
+
+
Hello World!
+
+
+
+
+ + \ No newline at end of file diff --git a/tests/fixtures/audiences/fragments--alt.json b/tests/fixtures/audiences/fragments--alt.json new file mode 100644 index 00000000..322072e5 --- /dev/null +++ b/tests/fixtures/audiences/fragments--alt.json @@ -0,0 +1,17 @@ +{ + "data": [ + { + "Pages": "/tests/fixtures/audiences/fragment-level--alt", + "Audiences": "Foo", + "Selectors": ".fragment", + "Urls": "/tests/fixtures/audiences/variant-1" + }, + { + "Pages": "/tests/fixtures/audiences/fragment-level--alt", + "Audiences": "Bar", + "Selectors": ".fragment", + "Urls": "/tests/fixtures/audiences/variant-2" + } + ], + ":type": "sheet" +} \ No newline at end of file diff --git a/tests/fixtures/audiences/fragments.json b/tests/fixtures/audiences/fragments.json new file mode 100644 index 00000000..104f1575 --- /dev/null +++ b/tests/fixtures/audiences/fragments.json @@ -0,0 +1,29 @@ +{ + "data": [ + { + "Page": "/tests/fixtures/audiences/fragment-level", + "Audience": "Foo", + "Selector": ".fragment", + "Url": "/tests/fixtures/audiences/variant-1" + }, + { + "Page": "/tests/fixtures/audiences/fragment-level", + "Audience": "Bar", + "Selector": ".fragment", + "Url": "/tests/fixtures/audiences/variant-2" + }, + { + "Page": "/tests/fixtures/audiences/fragment-level--async", + "Audience": "Foo", + "Selector": ".fragment", + "Url": "/tests/fixtures/audiences/variant-1" + }, + { + "Page": "/tests/fixtures/audiences/fragment-level--async", + "Audience": "Bar", + "Selector": ".fragment", + "Url": "/tests/fixtures/audiences/variant-2" + } + ], + ":type": "sheet" +} \ No newline at end of file diff --git a/tests/fixtures/audiences/page-level--async.html b/tests/fixtures/audiences/page-level--async.html new file mode 100644 index 00000000..267d52b6 --- /dev/null +++ b/tests/fixtures/audiences/page-level--async.html @@ -0,0 +1,18 @@ + + + + + + + + +
+
Hello World!
+
+ + \ No newline at end of file diff --git a/tests/fixtures/audiences/page-level--empty.html b/tests/fixtures/audiences/page-level--empty.html new file mode 100644 index 00000000..1f050dd5 --- /dev/null +++ b/tests/fixtures/audiences/page-level--empty.html @@ -0,0 +1,18 @@ + + + + + + + + +
+
Hello World!
+
+ + \ No newline at end of file diff --git a/tests/fixtures/audiences/page-level--invalid-url.html b/tests/fixtures/audiences/page-level--invalid-url.html new file mode 100644 index 00000000..6fec3c0c --- /dev/null +++ b/tests/fixtures/audiences/page-level--invalid-url.html @@ -0,0 +1,18 @@ + + + + + + + + +
+
Hello World!
+
+ + \ No newline at end of file diff --git a/tests/fixtures/audiences/page-level--invalid.html b/tests/fixtures/audiences/page-level--invalid.html new file mode 100644 index 00000000..2ebf689a --- /dev/null +++ b/tests/fixtures/audiences/page-level--invalid.html @@ -0,0 +1,18 @@ + + + + + + + + +
+
Hello World!
+
+ + \ No newline at end of file diff --git a/tests/fixtures/audiences/page-level.html b/tests/fixtures/audiences/page-level.html new file mode 100644 index 00000000..c4227ed4 --- /dev/null +++ b/tests/fixtures/audiences/page-level.html @@ -0,0 +1,18 @@ + + + + + + + + +
+
Hello World!
+
+ + \ No newline at end of file diff --git a/tests/fixtures/audiences/section-level.html b/tests/fixtures/audiences/section-level.html new file mode 100644 index 00000000..e064b2c7 --- /dev/null +++ b/tests/fixtures/audiences/section-level.html @@ -0,0 +1,22 @@ + + + + + + +
+
+
Hello World!
+ +
+
+ + \ No newline at end of file diff --git a/tests/fixtures/audiences/variant-1.html b/tests/fixtures/audiences/variant-1.html new file mode 100644 index 00000000..17dc08dc --- /dev/null +++ b/tests/fixtures/audiences/variant-1.html @@ -0,0 +1,9 @@ + + + + +
+
Hello v1!
+
+ + \ No newline at end of file diff --git a/tests/fixtures/audiences/variant-2.html b/tests/fixtures/audiences/variant-2.html new file mode 100644 index 00000000..d057125e --- /dev/null +++ b/tests/fixtures/audiences/variant-2.html @@ -0,0 +1,9 @@ + + + + +
+
Hello v2!
+
+ + \ No newline at end of file diff --git a/tests/fixtures/campaigns/fragment-level--alt.html b/tests/fixtures/campaigns/fragment-level--alt.html new file mode 100644 index 00000000..98e88fa7 --- /dev/null +++ b/tests/fixtures/campaigns/fragment-level--alt.html @@ -0,0 +1,17 @@ + + + + + + +
+
+
+
+
Hello World!
+
+
+
+
+ + \ No newline at end of file diff --git a/tests/fixtures/campaigns/fragment-level--async.html b/tests/fixtures/campaigns/fragment-level--async.html new file mode 100644 index 00000000..cbb28471 --- /dev/null +++ b/tests/fixtures/campaigns/fragment-level--async.html @@ -0,0 +1,19 @@ + + + + + + +
+
+
+ + + \ No newline at end of file diff --git a/tests/fixtures/campaigns/fragment-level--invalid-url.html b/tests/fixtures/campaigns/fragment-level--invalid-url.html new file mode 100644 index 00000000..32a782ee --- /dev/null +++ b/tests/fixtures/campaigns/fragment-level--invalid-url.html @@ -0,0 +1,17 @@ + + + + + + +
+
+
+
+
Hello World!
+
+
+
+
+ + \ No newline at end of file diff --git a/tests/fixtures/campaigns/fragment-level.html b/tests/fixtures/campaigns/fragment-level.html new file mode 100644 index 00000000..5cbd580c --- /dev/null +++ b/tests/fixtures/campaigns/fragment-level.html @@ -0,0 +1,17 @@ + + + + + + +
+
+
+
+
Hello World!
+
+
+
+
+ + \ No newline at end of file diff --git a/tests/fixtures/campaigns/fragments--alt.json b/tests/fixtures/campaigns/fragments--alt.json new file mode 100644 index 00000000..b684ee64 --- /dev/null +++ b/tests/fixtures/campaigns/fragments--alt.json @@ -0,0 +1,17 @@ +{ + "data": [ + { + "Pages": "/tests/fixtures/campaigns/fragment-level--alt", + "Campaigns": "Foo", + "Selectors": ".fragment", + "Urls": "/tests/fixtures/campaigns/variant-1" + }, + { + "Pages": "/tests/fixtures/campaigns/fragment-level--alt", + "Campaigns": "Bar", + "Selectors": ".fragment", + "Urls": "/tests/fixtures/campaigns/variant-2" + } + ], + ":type": "sheet" +} \ No newline at end of file diff --git a/tests/fixtures/campaigns/fragments.json b/tests/fixtures/campaigns/fragments.json new file mode 100644 index 00000000..c3de752d --- /dev/null +++ b/tests/fixtures/campaigns/fragments.json @@ -0,0 +1,17 @@ +{ + "data": [ + { + "Page": "/tests/fixtures/campaigns/fragment-level", + "Campaign": "Foo", + "Selector": ".fragment", + "Url": "/tests/fixtures/campaigns/variant-1" + }, + { + "Page": "/tests/fixtures/campaigns/fragment-level", + "Campaign": "Bar", + "Selector": ".fragment", + "Url": "/tests/fixtures/campaigns/variant-2" + } + ], + ":type": "sheet" +} \ No newline at end of file diff --git a/tests/fixtures/campaigns/page-level--audiences.html b/tests/fixtures/campaigns/page-level--audiences.html new file mode 100644 index 00000000..5475ed8b --- /dev/null +++ b/tests/fixtures/campaigns/page-level--audiences.html @@ -0,0 +1,11 @@ + + + + + + + + +
Hello World!
+ + \ No newline at end of file diff --git a/tests/fixtures/campaigns/page-level--backward-compatibility--audience.html b/tests/fixtures/campaigns/page-level--backward-compatibility--audience.html new file mode 100644 index 00000000..e3ed2386 --- /dev/null +++ b/tests/fixtures/campaigns/page-level--backward-compatibility--audience.html @@ -0,0 +1,11 @@ + + + + + + + + +
Hello World!
+ + \ No newline at end of file diff --git a/tests/fixtures/campaigns/page-level--empty.html b/tests/fixtures/campaigns/page-level--empty.html new file mode 100644 index 00000000..e6aac97e --- /dev/null +++ b/tests/fixtures/campaigns/page-level--empty.html @@ -0,0 +1,12 @@ + + + + + + + +
+
Hello World!
+
+ + \ No newline at end of file diff --git a/tests/fixtures/campaigns/page-level--invalid-url.html b/tests/fixtures/campaigns/page-level--invalid-url.html new file mode 100644 index 00000000..101a8b9c --- /dev/null +++ b/tests/fixtures/campaigns/page-level--invalid-url.html @@ -0,0 +1,12 @@ + + + + + + + +
+
Hello World!
+
+ + \ No newline at end of file diff --git a/tests/fixtures/campaigns/page-level.html b/tests/fixtures/campaigns/page-level.html new file mode 100644 index 00000000..df3ea0d9 --- /dev/null +++ b/tests/fixtures/campaigns/page-level.html @@ -0,0 +1,12 @@ + + + + + + + +
+
Hello World!
+
+ + \ No newline at end of file diff --git a/tests/fixtures/campaigns/section-level.html b/tests/fixtures/campaigns/section-level.html new file mode 100644 index 00000000..e0b99176 --- /dev/null +++ b/tests/fixtures/campaigns/section-level.html @@ -0,0 +1,16 @@ + + + + + +
+
+
Hello World!
+ +
+
+ + \ No newline at end of file diff --git a/tests/fixtures/campaigns/variant-1.html b/tests/fixtures/campaigns/variant-1.html new file mode 100644 index 00000000..17dc08dc --- /dev/null +++ b/tests/fixtures/campaigns/variant-1.html @@ -0,0 +1,9 @@ + + + + +
+
Hello v1!
+
+ + \ No newline at end of file diff --git a/tests/fixtures/campaigns/variant-2.html b/tests/fixtures/campaigns/variant-2.html new file mode 100644 index 00000000..d057125e --- /dev/null +++ b/tests/fixtures/campaigns/variant-2.html @@ -0,0 +1,9 @@ + + + + +
+
Hello v2!
+
+ + \ No newline at end of file diff --git a/tests/fixtures/experiments/fragment-level--alt.html b/tests/fixtures/experiments/fragment-level--alt.html new file mode 100644 index 00000000..8d3307ad --- /dev/null +++ b/tests/fixtures/experiments/fragment-level--alt.html @@ -0,0 +1,17 @@ + + + + + + +
+
+
+
+
Hello World!
+
+
+
+
+ + \ No newline at end of file diff --git a/tests/fixtures/experiments/fragment-level--async.html b/tests/fixtures/experiments/fragment-level--async.html new file mode 100644 index 00000000..bab83092 --- /dev/null +++ b/tests/fixtures/experiments/fragment-level--async.html @@ -0,0 +1,19 @@ + + + + + + +
+
+
+ + + \ No newline at end of file diff --git a/tests/fixtures/experiments/fragment-level--invalid-url.html b/tests/fixtures/experiments/fragment-level--invalid-url.html new file mode 100644 index 00000000..fc9a675b --- /dev/null +++ b/tests/fixtures/experiments/fragment-level--invalid-url.html @@ -0,0 +1,17 @@ + + + + + + +
+
+
+
+
Hello World!
+
+
+
+
+ + \ No newline at end of file diff --git a/tests/fixtures/experiments/fragment-level.html b/tests/fixtures/experiments/fragment-level.html new file mode 100644 index 00000000..75f2a820 --- /dev/null +++ b/tests/fixtures/experiments/fragment-level.html @@ -0,0 +1,17 @@ + + + + + + +
+
+
+
+
Hello World!
+
+
+
+
+ + \ No newline at end of file diff --git a/tests/fixtures/experiments/fragments--alt.json b/tests/fixtures/experiments/fragments--alt.json new file mode 100644 index 00000000..749999aa --- /dev/null +++ b/tests/fixtures/experiments/fragments--alt.json @@ -0,0 +1,19 @@ +{ + "data": [ + { + "Pages": "/tests/fixtures/experiments/fragment-level--alt", + "Experiments": "Baz", + "Variants": "challenger-1", + "Selectors": ".fragment", + "Urls": "/tests/fixtures/experiments/section-level-v1" + }, + { + "Pages": "/tests/fixtures/experiments/fragment-level--alt", + "Experiments": "Baz", + "Variants": "challenger-2", + "Selectors": ".fragment", + "Urls": "/tests/fixtures/experiments/section-level-v2" + } + ], + ":type": "sheet" +} \ No newline at end of file diff --git a/tests/fixtures/experiments/fragments.json b/tests/fixtures/experiments/fragments.json new file mode 100644 index 00000000..7fb3c722 --- /dev/null +++ b/tests/fixtures/experiments/fragments.json @@ -0,0 +1,33 @@ +{ + "data": [ + { + "Page": "/tests/fixtures/experiments/fragment-level", + "Experiment": "Baz", + "Variant": "challenger-1", + "Selector": ".fragment", + "Url": "/tests/fixtures/experiments/section-level-v1" + }, + { + "Page": "/tests/fixtures/experiments/fragment-level", + "Experiment": "Baz", + "Variant": "challenger-2", + "Selector": ".fragment", + "Url": "/tests/fixtures/experiments/section-level-v2" + }, + { + "Page": "/tests/fixtures/experiments/fragment-level--async", + "Experiment": "Baz", + "Variant": "challenger-1", + "Selector": ".fragment", + "Url": "/tests/fixtures/experiments/section-level-v1" + }, + { + "Page": "/tests/fixtures/experiments/fragment-level--async", + "Experiment": "Baz", + "Variant": "challenger-2", + "Selector": ".fragment", + "Url": "/tests/fixtures/experiments/section-level-v2" + } + ], + ":type": "sheet" +} \ No newline at end of file diff --git a/tests/fixtures/experiments/page-level--audiences.html b/tests/fixtures/experiments/page-level--audiences.html new file mode 100644 index 00000000..1fab348e --- /dev/null +++ b/tests/fixtures/experiments/page-level--audiences.html @@ -0,0 +1,11 @@ + + + + + + + + +
Hello World!
+ + \ No newline at end of file diff --git a/tests/fixtures/experiments/page-level--backward-compatibility--audience.html b/tests/fixtures/experiments/page-level--backward-compatibility--audience.html new file mode 100644 index 00000000..99f19ad0 --- /dev/null +++ b/tests/fixtures/experiments/page-level--backward-compatibility--audience.html @@ -0,0 +1,11 @@ + + + + + + + + +
Hello World!
+ + \ No newline at end of file diff --git a/tests/fixtures/experiments/page-level--backward-compatibility--instant-experiment.html b/tests/fixtures/experiments/page-level--backward-compatibility--instant-experiment.html new file mode 100644 index 00000000..50301eee --- /dev/null +++ b/tests/fixtures/experiments/page-level--backward-compatibility--instant-experiment.html @@ -0,0 +1,10 @@ + + + + + + + +
Hello World!
+ + \ No newline at end of file diff --git a/tests/fixtures/experiments/page-level--code.html b/tests/fixtures/experiments/page-level--code.html new file mode 100644 index 00000000..de01d6e9 --- /dev/null +++ b/tests/fixtures/experiments/page-level--code.html @@ -0,0 +1,10 @@ + + + + + + + +
Hello World!
+ + \ No newline at end of file diff --git a/tests/fixtures/experiments/page-level--empty.html b/tests/fixtures/experiments/page-level--empty.html new file mode 100644 index 00000000..f37b132c --- /dev/null +++ b/tests/fixtures/experiments/page-level--empty.html @@ -0,0 +1,10 @@ + + + + + + + +
Hello World!
+ + \ No newline at end of file diff --git a/tests/fixtures/experiments/page-level--empty2.html b/tests/fixtures/experiments/page-level--empty2.html new file mode 100644 index 00000000..c8f6e1fa --- /dev/null +++ b/tests/fixtures/experiments/page-level--empty2.html @@ -0,0 +1,10 @@ + + + + + + + +
Hello World!
+ + \ No newline at end of file diff --git a/tests/fixtures/experiments/page-level--inactive.html b/tests/fixtures/experiments/page-level--inactive.html new file mode 100644 index 00000000..782081be --- /dev/null +++ b/tests/fixtures/experiments/page-level--inactive.html @@ -0,0 +1,11 @@ + + + + + + + + +
Hello World!
+ + \ No newline at end of file diff --git a/tests/fixtures/experiments/page-level--invalid-url.html b/tests/fixtures/experiments/page-level--invalid-url.html new file mode 100644 index 00000000..87cb1d45 --- /dev/null +++ b/tests/fixtures/experiments/page-level--invalid-url.html @@ -0,0 +1,10 @@ + + + + + + + +
Hello World!
+ + \ No newline at end of file diff --git a/tests/fixtures/experiments/page-level--split.html b/tests/fixtures/experiments/page-level--split.html new file mode 100644 index 00000000..17fb7462 --- /dev/null +++ b/tests/fixtures/experiments/page-level--split.html @@ -0,0 +1,11 @@ + + + + + + + + +
Hello World!
+ + \ No newline at end of file diff --git a/tests/fixtures/experiments/page-level--time-bound-end.html b/tests/fixtures/experiments/page-level--time-bound-end.html new file mode 100644 index 00000000..dc3407b8 --- /dev/null +++ b/tests/fixtures/experiments/page-level--time-bound-end.html @@ -0,0 +1,11 @@ + + + + + + + + +
Hello World!
+ + \ No newline at end of file diff --git a/tests/fixtures/experiments/page-level--time-bound-start.html b/tests/fixtures/experiments/page-level--time-bound-start.html new file mode 100644 index 00000000..72e12c4e --- /dev/null +++ b/tests/fixtures/experiments/page-level--time-bound-start.html @@ -0,0 +1,11 @@ + + + + + + + + +
Hello World!
+ + \ No newline at end of file diff --git a/tests/fixtures/experiments/page-level--time-bound.html b/tests/fixtures/experiments/page-level--time-bound.html new file mode 100644 index 00000000..fde3028b --- /dev/null +++ b/tests/fixtures/experiments/page-level--time-bound.html @@ -0,0 +1,12 @@ + + + + + + + + + +
Hello World!
+ + \ No newline at end of file diff --git a/tests/fixtures/experiments/page-level-v1.html b/tests/fixtures/experiments/page-level-v1.html new file mode 100644 index 00000000..4771e208 --- /dev/null +++ b/tests/fixtures/experiments/page-level-v1.html @@ -0,0 +1,7 @@ + + + + +
Hello v1!
+ + \ No newline at end of file diff --git a/tests/fixtures/experiments/page-level-v2.html b/tests/fixtures/experiments/page-level-v2.html new file mode 100644 index 00000000..9ff94a12 --- /dev/null +++ b/tests/fixtures/experiments/page-level-v2.html @@ -0,0 +1,7 @@ + + + + +
Hello v2!
+ + \ No newline at end of file diff --git a/tests/fixtures/experiments/page-level.html b/tests/fixtures/experiments/page-level.html new file mode 100644 index 00000000..03467640 --- /dev/null +++ b/tests/fixtures/experiments/page-level.html @@ -0,0 +1,10 @@ + + + + + + + +
Hello World!
+ + \ No newline at end of file diff --git a/tests/fixtures/experiments/section-level-v1.html b/tests/fixtures/experiments/section-level-v1.html new file mode 100644 index 00000000..17dc08dc --- /dev/null +++ b/tests/fixtures/experiments/section-level-v1.html @@ -0,0 +1,9 @@ + + + + +
+
Hello v1!
+
+ + \ No newline at end of file diff --git a/tests/fixtures/experiments/section-level-v2.html b/tests/fixtures/experiments/section-level-v2.html new file mode 100644 index 00000000..d057125e --- /dev/null +++ b/tests/fixtures/experiments/section-level-v2.html @@ -0,0 +1,9 @@ + + + + +
+
Hello v2!
+
+ + \ No newline at end of file diff --git a/tests/fixtures/experiments/section-level.html b/tests/fixtures/experiments/section-level.html new file mode 100644 index 00000000..bf66e92b --- /dev/null +++ b/tests/fixtures/experiments/section-level.html @@ -0,0 +1,22 @@ + + + + + +
+
+
Hello World!
+ +
+
+ + \ No newline at end of file diff --git a/tests/fixtures/global.html b/tests/fixtures/global.html new file mode 100644 index 00000000..70f2c9ff --- /dev/null +++ b/tests/fixtures/global.html @@ -0,0 +1,8 @@ + + + + + +
Hello World!
+ + \ No newline at end of file diff --git a/tests/fixtures/scripts.js b/tests/fixtures/scripts.js new file mode 100644 index 00000000..e763cb30 --- /dev/null +++ b/tests/fixtures/scripts.js @@ -0,0 +1,103 @@ +import { + buildBlock, + decorateButtons, + decorateIcons, + decorateSections, + decorateBlocks, + decorateTemplateAndTheme, + waitForLCP, + loadBlocks, +} from './aem.js'; + +const LCP_BLOCKS = []; // add your LCP blocks to the list + +/** + * Builds hero block and prepends to main in a new section. + * @param {Element} main The container element + */ +function buildHeroBlock(main) { + const h1 = main.querySelector('h1'); + const picture = main.querySelector('picture'); + // eslint-disable-next-line no-bitwise + if (h1 && picture && (h1.compareDocumentPosition(picture) & Node.DOCUMENT_POSITION_PRECEDING)) { + const section = document.createElement('div'); + section.append(buildBlock('hero', { elems: [picture, h1] })); + main.prepend(section); + } +} + +/** + * Builds all synthetic blocks in a container element. + * @param {Element} main The container element + */ +function buildAutoBlocks(main) { + try { + buildHeroBlock(main); + } catch (error) { + // eslint-disable-next-line no-console + console.error('Auto Blocking failed', error); + } +} + +/** + * Decorates the main element. + * @param {Element} main The main element + */ +// eslint-disable-next-line import/prefer-default-export +export function decorateMain(main) { + // hopefully forward compatible button decoration + decorateButtons(main); + decorateIcons(main); + buildAutoBlocks(main); + decorateSections(main); + decorateBlocks(main); +} + +/** + * Loads everything needed to get to LCP. + * @param {Element} doc The container element + */ +async function loadEager(doc) { + document.documentElement.lang = 'en'; + decorateTemplateAndTheme(); + + // Add below snippet early in the eager phase + if (document.head.querySelector('[name^="experiment"],[name^="campaign-"],[name^="audience-"]') + || [...document.querySelectorAll('.section-metadata div')].some((d) => d.textContent.match(/Experiment|Campaign|Audience/i))) { + // eslint-disable-next-line import/no-absolute-path, import/no-unresolved + const { loadEager: runEager } = await import('/src/index.js'); + await runEager(document, { audiences: window.AUDIENCES || {} }); + } + + const main = doc.querySelector('main'); + if (main) { + decorateMain(main); + document.body.classList.add('appear'); + await waitForLCP(LCP_BLOCKS); + } +} + +/** + * Loads everything that doesn't need to be delayed. + * @param {Element} doc The container element + */ +async function loadLazy(doc) { + const main = doc.querySelector('main'); + await loadBlocks(main); +} + +/** + * Loads everything that happens a lot later, + * without impacting the user experience. + */ +function loadDelayed() { + // load anything that can be postponed to the latest here +} + +async function loadPage() { + await loadEager(document); + await loadLazy(document); + loadDelayed(); +} + +loadPage(); diff --git a/tests/global.test.js b/tests/global.test.js new file mode 100644 index 00000000..5f38d617 --- /dev/null +++ b/tests/global.test.js @@ -0,0 +1,20 @@ +/* eslint-disable import/no-extraneous-dependencies */ +import { test, expect } from '@playwright/test'; +import { track } from './coverage.js'; + +track(test); + +test.describe('Plugin config', () => { + test('debug statements are shown in dev/stage', async ({ page }) => { + await page.goto('/tests/fixtures/global'); + await page.addScriptTag({ content: 'import { setDebugMode } from "/src/index.js"; window.setDebugMode = setDebugMode;', type: 'module' }); + expect(await page.evaluate(async () => window.setDebugMode(new URL('http://localhost:3000'), {}))).toEqual(true); + expect(await page.evaluate(async () => window.setDebugMode(new URL('https://ref--repo--org.hlx.page/'), {}))).toEqual(true); + expect(await page.evaluate(async () => window.setDebugMode(new URL('https://ref--repo--org.hlx.live/'), {}))).toEqual(false); + expect(await page.evaluate(async () => window.setDebugMode(new URL('https://ref--repo--org.hlx.live/'), { isProd: () => false }))).toEqual(true); + expect(await page.evaluate(async () => window.setDebugMode(new URL('https://stage.foo.com'), { prodHost: 'www.foo.com' }))).toEqual(true); + }); + + // test.skip('debug statements are not shown on prod'); + // test.skip('sends event with details when experiment/audience/campaign is run'); +}); diff --git a/tests/setup.js b/tests/setup.js new file mode 100644 index 00000000..72408938 --- /dev/null +++ b/tests/setup.js @@ -0,0 +1,5 @@ +import { start } from './coverage.js'; + +export default async function setup() { + await start(); +} diff --git a/tests/teardown.js b/tests/teardown.js new file mode 100644 index 00000000..553211fc --- /dev/null +++ b/tests/teardown.js @@ -0,0 +1,5 @@ +import { end } from './coverage.js'; + +export default async function teardown() { + await end(); +} diff --git a/tests/utils.js b/tests/utils.js new file mode 100644 index 00000000..1df0890e --- /dev/null +++ b/tests/utils.js @@ -0,0 +1,34 @@ +import { expect } from '@playwright/test'; + +async function waitForNamespace(page, namespace) { + await expect(async () => { + expect(await page.evaluate((ns) => window.hlx[ns], namespace)).toBeDefined(); + }).toPass(); + // Wait for the fragments to decorate + await new Promise((res) => { setTimeout(res); }); +} + +export async function goToAndRunAudience(page, url) { + await page.goto(url); + await waitForNamespace(page, 'audiences'); +} + +export async function goToAndRunCampaign(page, url) { + await page.goto(url); + await waitForNamespace(page, 'campaigns'); +} + +export async function goToAndRunExperiment(page, url) { + await page.goto(url); + await waitForNamespace(page, 'experiments'); +} + +export async function waitForDomEvent(page, eventName) { + await page.addInitScript((name) => { + // Override the prototype + window.eventPromise = new Promise((resolve) => { + document.addEventListener(name, (ev) => resolve(ev.detail)); + }); + }, eventName); + return async () => await window.eventPromise; +} From 2b6a7d289e60c0689a0823dcf8f83b6bdf09b3e1 Mon Sep 17 00:00:00 2001 From: Xinyi Feng Date: Tue, 11 Jun 2024 16:34:15 -0700 Subject: [PATCH 03/10] Squashed 'plugins/experimentation/' changes from 33c3263..09f8a72 09f8a72 fix: pill css loading on localhost git-subtree-dir: plugins/experimentation git-subtree-split: 09f8a72796f1ca9daeb91e68c62ef4952f5c4254 --- src/preview.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/preview.js b/src/preview.js index e253325a..628461e5 100644 --- a/src/preview.js +++ b/src/preview.js @@ -23,7 +23,7 @@ class AemExperimentationBar extends HTMLElement { // Create a shadow root const shadow = this.attachShadow({ mode: 'open' }); - const cssPath = new URL(new Error().stack.split('\n')[2].match(/[a-z]+:[^:]+/)[0]).pathname.replace('preview.js', 'preview.css'); + const cssPath = new URL(new Error().stack.split('\n')[2].match(/[a-z]+?:\/\/.*?\/[^:]+/)[0]).pathname.replace('preview.js', 'preview.css'); const link = document.createElement('link'); link.rel = 'stylesheet'; link.href = cssPath; From b04889d9126e31ec609ec8883519a1587a3b0f26 Mon Sep 17 00:00:00 2001 From: Xinyi Feng Date: Mon, 17 Jun 2024 08:24:53 -0700 Subject: [PATCH 04/10] fix the conditon of adding experiment plugin --- scripts/scripts.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/scripts/scripts.js b/scripts/scripts.js index 3ed722bb..24cd2ca2 100644 --- a/scripts/scripts.js +++ b/scripts/scripts.js @@ -40,9 +40,10 @@ window.hlx.plugins.add('rum-conversion', { }); window.hlx.plugins.add('experimentation', { - condition: () => getMetadata('experiment') - || Object.keys(getAllMetadata('campaign')).length - || Object.keys(getAllMetadata('audience')).length, + condition: () => document.head.querySelector('[name^="experiment"],[name^="campaign-"],[name^="audience-"]') + || document.querySelector('.section[class*="experiment-"],.section[class*="audience-"],.section[class*="campaign-"]') + || [...document.querySelectorAll('.section-metadata div')].some((d) => d.textContent.match(/Experiment|Campaign|Audience/i)) + , options: { audiences: AUDIENCES }, load: 'eager', url: '/plugins/experimentation/src/index.js', @@ -182,7 +183,6 @@ export function decorateMain(main) { async function loadEager(doc) { document.documentElement.lang = 'en'; decorateTemplateAndTheme(); - await window.hlx.plugins.run('loadEager'); // load demo config From efa27f2bc90a0a346b9dadc1b4e7ec6e1e90eb19 Mon Sep 17 00:00:00 2001 From: Xinyi Feng Date: Thu, 20 Jun 2024 21:55:19 -0700 Subject: [PATCH 05/10] Squashed 'plugins/experimentation/' changes from 09f8a72..638e0db 638e0db fix: fragment content replacement c61fdaf doc: update instrumentation details for plugin approach git-subtree-dir: plugins/experimentation git-subtree-split: 638e0db53a4fa7886ef9713acc853fc7b02c76be --- README.md | 7 ++++++- src/index.js | 12 +++++++++--- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index c75967c0..3a997ab6 100644 --- a/README.md +++ b/README.md @@ -97,7 +97,12 @@ const experimentationConfig = { }; window.aem.plugins.add('experimentation', { // use window.hlx instead of your project has this - condition: () => document.head.querySelector('[name^="experiment"],[name^="campaign-"],[name^="audience-"]') + condition: () => + // page level metadata + document.head.querySelector('[name^="experiment"],[name^="campaign-"],[name^="audience-"]') + // decorated section metadata + || document.querySelector('.section[class*=experiment],.section[class*=audience],.section[class*=campaign]') + // undecorated section metadata || [...document.querySelectorAll('.section-metadata div')].some((d) => d.textContent.match(/Experiment|Campaign|Audience/i)), options: experimentationConfig, url: '/plugins/experimentation/src/index.js', diff --git a/src/index.js b/src/index.js index b8ce4fb9..fce95a61 100644 --- a/src/index.js +++ b/src/index.js @@ -185,7 +185,7 @@ function getAllSectionMeta(block, scope) { * @param {HTMLElement} el * @return Returns the path that was loaded or null if the loading failed */ -async function replaceInner(path, el) { +async function replaceInner(path, el, selector) { try { const resp = await fetch(path); if (!resp.ok) { @@ -197,7 +197,13 @@ async function replaceInner(path, el) { // parse with DOMParser to guarantee valid HTML, and no script execution(s) const dom = new DOMParser().parseFromString(html, 'text/html'); // eslint-disable-next-line no-param-reassign - const newEl = dom.querySelector(el.tagName === 'MAIN' ? 'main' : 'main > div'); + let newEl; + if (selector) { + newEl = dom.querySelector(selector); + } + if (!newEl) { + newEl = dom.querySelector(el.tagName === 'MAIN' ? 'main' : 'main > div'); + } el.innerHTML = newEl.innerHTML; return path; } catch (e) { @@ -412,7 +418,7 @@ function watchMutationsAndApplyFragments( let res; if (url && new URL(url, window.location.origin).pathname !== window.location.pathname) { // eslint-disable-next-line no-await-in-loop - res = await replaceInner(url, el); + res = await replaceInner(url, el, entry.selector); } else { res = url; } From 30f172d2b8a4c0748ea33a05a48d52c03d3d14ca Mon Sep 17 00:00:00 2001 From: Xinyi Feng Date: Fri, 21 Jun 2024 08:12:21 -0700 Subject: [PATCH 06/10] fix fragment experiment issue on auto-blocking block and regular blocks --- scripts/scripts.js | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/scripts/scripts.js b/scripts/scripts.js index 24cd2ca2..93b6972a 100644 --- a/scripts/scripts.js +++ b/scripts/scripts.js @@ -8,9 +8,11 @@ import { decorateButtons, decorateIcons, decorateSections, + decorateBlock, decorateBlocks, decorateTemplateAndTheme, waitForLCP, + loadBlock, loadBlocks, loadCSS, } from './lib-franklin.js'; @@ -275,6 +277,28 @@ async function loadPage() { await setupAnalytics; } +// Properly decorate fragments that were pulled in +document.addEventListener('aem:experimentation', (ev) => { + // Do not redecorate the default content + if (ev.detail.variant === 'control') { + return; + } + // Rebuild the autoblock as needed + if (ev.detail.element.classList.contains('hero')) { + const parent = ev.detail.element.parentElement.parentElement; + [...ev.detail.element.children].reverse().forEach((el) => parent.prepend(el)); + ev.detail.element.remove(); + // Rebuild and redecorate the hero block + buildHeroBlock(parent); + decorateBlocks(parent); + loadBlocks(parent); + } else if (ev.detail.element.classList.contains('block')) { + // Otherwise, just reset the replaced blocks and redecorate them + decorateBlock(ev.detail.element); + loadBlock(ev.detail.element); + } +}); + const cwv = {}; // Forward the RUM CWV cached measurements to edge using WebSDK before the page unloads From cdecca463280e70d951e474fb4e628ada472c220 Mon Sep 17 00:00:00 2001 From: Xinyi Feng Date: Sat, 22 Jun 2024 20:11:35 -0700 Subject: [PATCH 07/10] fix: fetch campigns and audiences in metadata property for page-level experiment --- plugins/experimentation/src/index.js | 18 ++++++++++++------ scripts/scripts.js | 2 +- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/plugins/experimentation/src/index.js b/plugins/experimentation/src/index.js index fce95a61..bc1fcb96 100644 --- a/plugins/experimentation/src/index.js +++ b/plugins/experimentation/src/index.js @@ -94,12 +94,18 @@ export function getMetadata(name) { */ export function getAllMetadata(scope) { const value = getMetadata(scope); - return [...document.head.querySelectorAll(`meta[name^="${scope}-"]`)] - .reduce((res, meta) => { - const key = toCamelCase(meta.name.substring(scope.length + 1)); - res[key] = meta.getAttribute('content'); - return res; - }, value ? { value } : {}); + const metaTags = document.head.querySelectorAll(`meta[name^="${scope}-"], meta[property^="${scope}:-"]`); + + return [...metaTags].reduce((res, meta) => { + const key = meta.getAttribute('name') + ? meta.getAttribute('name').substring(scope.length + 1) + : meta.getAttribute('property').substring(scope.length + 2); + + const camelCaseKey = toCamelCase(key); + res[camelCaseKey] = meta.getAttribute('content'); + + return res; + }, value ? { value } : {}); } /** diff --git a/scripts/scripts.js b/scripts/scripts.js index 93b6972a..c9f03c3b 100644 --- a/scripts/scripts.js +++ b/scripts/scripts.js @@ -42,7 +42,7 @@ window.hlx.plugins.add('rum-conversion', { }); window.hlx.plugins.add('experimentation', { - condition: () => document.head.querySelector('[name^="experiment"],[name^="campaign-"],[name^="audience-"]') + condition: () => document.head.querySelector('[name^="experiment"],[property^="campaign:-"],[property^="audience:-"]') || document.querySelector('.section[class*="experiment-"],.section[class*="audience-"],.section[class*="campaign-"]') || [...document.querySelectorAll('.section-metadata div')].some((d) => d.textContent.match(/Experiment|Campaign|Audience/i)) , From d284d3d3ddfa3af4538da40a1fbe0a136cd23209 Mon Sep 17 00:00:00 2001 From: Xinyi Feng Date: Sun, 23 Jun 2024 21:45:18 -0700 Subject: [PATCH 08/10] fix: switch to default page in campaigns has issue on decoration, and audiences wrongly redirected. --- plugins/experimentation/src/index.js | 1 + plugins/experimentation/src/preview.js | 6 +++++- scripts/scripts.js | 5 +++-- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/plugins/experimentation/src/index.js b/plugins/experimentation/src/index.js index bc1fcb96..8e9e273d 100644 --- a/plugins/experimentation/src/index.js +++ b/plugins/experimentation/src/index.js @@ -500,6 +500,7 @@ async function applyAllModifications( } })); + // Fragment-level modifications if (pageMetadata.manifest) { let entries = await getManifestEntriesForCurrentPage(pageMetadata.manifest); if (entries) { diff --git a/plugins/experimentation/src/preview.js b/plugins/experimentation/src/preview.js index 628461e5..e69ca6c5 100644 --- a/plugins/experimentation/src/preview.js +++ b/plugins/experimentation/src/preview.js @@ -531,7 +531,11 @@ async function decorateCampaignPills(container, options) { function createAudience(audience, isSelected, options) { const url = new URL(window.location.href); - url.searchParams.set(options.audiencesQueryParameter, audience); + if (audience !== 'default') { + url.searchParams.set(options.audiencesQueryParameter, audience); + } else { + url.searchParams.delete(options.audiencesQueryParameter); + } return { label: `${audience}`, diff --git a/scripts/scripts.js b/scripts/scripts.js index c9f03c3b..0cd7851e 100644 --- a/scripts/scripts.js +++ b/scripts/scripts.js @@ -42,7 +42,8 @@ window.hlx.plugins.add('rum-conversion', { }); window.hlx.plugins.add('experimentation', { - condition: () => document.head.querySelector('[name^="experiment"],[property^="campaign:-"],[property^="audience:-"]') + condition: () => document.head.querySelector('[name^="experiment"],[name^="campaign-"],[name^="audience-"]') + || document.head.querySelector('[property^="campaign:-"],[property^="audience:-"]') || document.querySelector('.section[class*="experiment-"],.section[class*="audience-"],.section[class*="campaign-"]') || [...document.querySelectorAll('.section-metadata div')].some((d) => d.textContent.match(/Experiment|Campaign|Audience/i)) , @@ -280,7 +281,7 @@ async function loadPage() { // Properly decorate fragments that were pulled in document.addEventListener('aem:experimentation', (ev) => { // Do not redecorate the default content - if (ev.detail.variant === 'control') { + if (ev.detail.variant === 'control' || ev.detail?.campaign === 'default' || ev.detail?.audience === 'default') { return; } // Rebuild the autoblock as needed From 5739b000e2769accfdcc79dbd5e519d78ea9f912 Mon Sep 17 00:00:00 2001 From: Xinyi Feng Date: Mon, 24 Jun 2024 08:08:13 -0700 Subject: [PATCH 09/10] fix lint --- package-lock.json | 3 ++- package.json | 6 +++--- scripts/scripts.js | 5 +---- 3 files changed, 6 insertions(+), 8 deletions(-) diff --git a/package-lock.json b/package-lock.json index 617865eb..daf386d9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,7 +15,7 @@ "@web/test-runner": "0.14.0", "@web/test-runner-commands": "0.6.4", "chai": "4.3.6", - "eslint": "8.22.0", + "eslint": "^8.22.0", "eslint-config-airbnb-base": "15.0.0", "eslint-plugin-import": "2.26.0", "puppeteer": "^21.2.1", @@ -2490,6 +2490,7 @@ "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.22.0.tgz", "integrity": "sha512-ci4t0sz6vSRKdmkOGmprBo6fmI4PrphDFMy5JEq/fNS0gQkJM3rLmrqcp8ipMcdobH3KtUP40KniAE9W19S4wA==", "dev": true, + "license": "MIT", "dependencies": { "@eslint/eslintrc": "^1.3.0", "@humanwhocodes/config-array": "^0.10.4", diff --git a/package.json b/package.json index c2cf80b1..1cf94a39 100644 --- a/package.json +++ b/package.json @@ -28,13 +28,13 @@ "@web/test-runner": "0.14.0", "@web/test-runner-commands": "0.6.4", "chai": "4.3.6", - "eslint": "8.22.0", + "eslint": "^8.22.0", "eslint-config-airbnb-base": "15.0.0", "eslint-plugin-import": "2.26.0", + "puppeteer": "^21.2.1", "sinon": "14.0.0", "stylelint": "14.10.0", "stylelint-config-prettier": "9.0.3", - "stylelint-config-standard": "25.0.0", - "puppeteer": "^21.2.1" + "stylelint-config-standard": "25.0.0" } } diff --git a/scripts/scripts.js b/scripts/scripts.js index 0cd7851e..d2637df3 100644 --- a/scripts/scripts.js +++ b/scripts/scripts.js @@ -1,8 +1,6 @@ import { sampleRUM, buildBlock, - getAllMetadata, - getMetadata, loadHeader, loadFooter, decorateButtons, @@ -45,8 +43,7 @@ window.hlx.plugins.add('experimentation', { condition: () => document.head.querySelector('[name^="experiment"],[name^="campaign-"],[name^="audience-"]') || document.head.querySelector('[property^="campaign:-"],[property^="audience:-"]') || document.querySelector('.section[class*="experiment-"],.section[class*="audience-"],.section[class*="campaign-"]') - || [...document.querySelectorAll('.section-metadata div')].some((d) => d.textContent.match(/Experiment|Campaign|Audience/i)) - , + || [...document.querySelectorAll('.section-metadata div')].some((d) => d.textContent.match(/Experiment|Campaign|Audience/i)), options: { audiences: AUDIENCES }, load: 'eager', url: '/plugins/experimentation/src/index.js', From 0812b7a89142d404ca23c33f33f0c1b62fef920b Mon Sep 17 00:00:00 2001 From: Xinyi Feng Date: Tue, 25 Jun 2024 09:54:42 -0700 Subject: [PATCH 10/10] revert history commits on this branch --- plugins/experimentation/src/index.js | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/plugins/experimentation/src/index.js b/plugins/experimentation/src/index.js index 8e9e273d..fc456ebe 100644 --- a/plugins/experimentation/src/index.js +++ b/plugins/experimentation/src/index.js @@ -577,6 +577,13 @@ async function getExperimentConfig(pluginOptions, metadata, overrides) { const variantNames = []; variantNames.push('control'); + stringToArray(getMetadata("variants-name")).forEach((v) => { + if (variantNames.length <= pages.length) { + variantNames.push(v); + } else{ + console.log(`Variant name "${v}" is ignored: Number of variants names is more than the number of variants`); + } + }); const variants = {}; variants.control = { @@ -586,8 +593,13 @@ async function getExperimentConfig(pluginOptions, metadata, overrides) { }; pages.forEach((page, i) => { - const vname = `challenger-${i + 1}`; - variantNames.push(vname); + const vname = + variantNames.length > i + 1 + ? variantNames[i + 1] + : `challenger-${i + 1}`; + if (variantNames.length <= i + 1) { + variantNames.push(vname); + } variants[vname] = { percentageSplit: `${splits[i].toFixed(4)}`, pages: [page],