diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..32b59c5 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,10 @@ +root = true + +[*] +charset = utf-8 +end_of_line = lf +indent_style = tab +indent_size = 4 +insert_final_newline = true +tab_width = 4 +trim_trailing_whitespace = true diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..1f49262 --- /dev/null +++ b/.gitignore @@ -0,0 +1,9 @@ +.idea/ +.vscode/ +docs/ +tmp/ +node_modules/ + +.brackets.json +*.log +*.env diff --git a/.npmignore b/.npmignore new file mode 100644 index 0000000..a7feb76 --- /dev/null +++ b/.npmignore @@ -0,0 +1,10 @@ +**/tsconfig.json +**/nodemon.json +**/tslint.json +**/*.config.js +.editorconfig +src +demo +example +docs +*.png diff --git a/.nvmrc b/.nvmrc new file mode 100644 index 0000000..4044f90 --- /dev/null +++ b/.nvmrc @@ -0,0 +1 @@ +12.0.0 diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..42e0b81 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2022 Voltra + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md index 464457d..85d59b5 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,242 @@ # html-gdpr-guard -Vanilla JavaScript binding to gdpr-guard as efficiently and easily as possible, based on data provided in the DOM + +> Vanilla JavaScript binding to gdpr-guard as efficiently and easily as possible, based on data provided in the DOM + +
html-gdpr-guard logo
+ +You can have a look at the [demo](https://voltra.github.io/html-gdpr-guard) to see it in action and inspect the DOM. + +## Install + +Via NPM: `npm i -S html-gdpr-guard` + +Via Yarn: `yarn add html-gdpr-guard` + +As a 3rd-party script tag: +```html + +``` + +## Use + +Using modules: +```javascript +import { + restoreHtmlGdprManager, + // + HtmlGdprGuardError, + NoManagerDefinitionError, + NoNameError, + NoCheckboxError, +} from "html-gdpr-guard" +``` + +Using commonjs: +```javascript +const { + restoreHtmlGdprManager, + // + HtmlGdprGuardError, + NoManagerDefinitionError, + NoNameError, + NoCheckboxError, +} = require("html-gdpr-guard"); +``` + +In the browser: +```javascript +const { + restoreHtmlGdprManager, + // + HtmlGdprGuardError, + NoManagerDefinitionError, + NoNameError, + NoCheckboxError, +} = htmlGdprGuard; +``` + +## Restore your manager instance + +To restore your manager instance, you will need an instance of [`GdprSavior`](https://www.ludwig-guerin.fr/gdpr-guard/interfaces/serde_GdprSavior.GdprSavior.html). +The simplest one is [gdpr-guard-local](https://www.npmjs.com/package/gdpr-guard-local) which relies on local storage. + +The simplest way to restore your manager is to let the library do everything: +```javascript +const gdprSavior = getMyGdprSavior(); +const manager = await restoreHtmlGdprManager(gdprSavior); +``` + +If it fails, it will throw an instance of `HtmlGdprGuardError` which can be one of the following: +* `NoManagerDefinitionError` +* `NoNameError` +* `NoCheckboxError` + +## Create your DOM structure + +### A guard's data + +#### Guard name (mandatory) + +A guard's data is scoped within the root element that is marked using the `data-gdpr-guard` attribute. +That attribute can contain the name of your guard, otherwise the first element that has a `data-gdpr-guard-name` +will be used to retrieve the guard's name. **It is mandatory** + +#### Guard description (optional) + +The guard's description can be added via a `data-gdpr-guard-description` with a value on the root element, or +you can tag an element with `data-gdpr-guard-description` whose `textContent` will be treated as its description. +**It is optional** + +It will default to an empty string. Note that if the description is the attribute's value it won't be shown to the user. + +#### Guard storage (optional) + +The guard's storage can be added via a `data-gdpr-guard-storage` attribute whose value should be the key in the [`GdprStorage`](https://www.ludwig-guerin.fr/gdpr-guard/enums/GdprStorage.GdprStorage-1.html) enum. **It is optional** + +#### Guard checkbox (mandatory) + +The checkbox that controls the guard is resolved (among the guard's children) in the following order based on the guard's name: +* checkbox whose ID is the guard's name +* checkbox whose `name` attribute is the guard's name +* first checkbox marked with the `data-gdpr-checkbox` attribute + +#### Guard's required status (optional) + +To mark the guard as required you can: +* Add the `gdpr-guard-required` attribute on the guard's root element +* Add the `required` attribute on the guard's checkbox + +Note that, just like the way `gdpr-guard` handles required guards, if a parent is required +then all of its children will be as well. + +You don't *have* to make your checkbox required and disabled, it will be all synced up as the guard is parsed. + +## A group's data + +A group behaves exactly like a guard, except that its root is marked using `data-gdpr-group` instead of `data-gdpr-guard`. + +### The manager's data + +The manager behaves a little bit like a guard, but has specific attributes: + +* `data-gdpr` is used to find the root of your manager, unless you provide it in `restoreHtmlGdprManager`'s options. Its value is treated as the manager's name. You don't have to give it a value. You can skip it altogether. +* `data-gdpr-manager` that can be used to store the name of the manager if you didn't provide a value to the `data-gdpr` attribute (or the attribute itself) + +## Customize the restoration process + +You can pass a set of options as the second argument of `restoreHtmlGdprManager`. Let's inspect them one by one. + +### `gdprEl` HTMLElement + +The html element that will serve as root of the manager's definitions. By default, it will use `document.querySelector("[data-gdpr]")`. + +If the manager can't be found, it'll throw a `NoManagerDefinitionError`. + +### `autoCloseBanner` bool + +Whether the banner should be automatically closed once the manager has been restored if the consent banner has already been shown. + +### `bindEventHandlersHook` function + +A callback that can be used to attach event listeners to the manager's [`GdprManagerEventHub`](https://www.ludwig-guerin.fr/gdpr-guard/classes/GdprManagerEventHub.GdprManagerEventHub-1.html). + +The callback's signature is the following: +```typescript +type BindEventsCallback = (eventsHub: GdprManagerEventHub) => void; +``` + +For instance: +```javascript +await restoreHtmlGdprManager(gdprSavior, { + bindEventHandlersHook(eventsHub) { + eventsHub.onEnable("myGuard", () => { + connectToWsApi(); + }); + + eventsHub.onDisable("myGuard", () => { + disconnectFromWsApi(); + }); + }, +}); +``` + +### `addGuardsBeforeHook` function + +A callback that can be used to add guards' definitions to the [`GdprManagerBuilder`](https://www.ludwig-guerin.fr/gdpr-guard/classes/builders_GdprManagerBuilder.GdprManagerBuilder.html) instance before the library parses data from the DOM. + +The callback's signature is the following: +```typescript +type AddGuardsCallback = (managerBuilder: GdprManagerBuilder) => void; +``` + +### `addGuardsAfterHook` function + +A callback that can be used to add guards' definitions to the [`GdprManagerBuilder`](https://www.ludwig-guerin.fr/gdpr-guard/classes/builders_GdprManagerBuilder.GdprManagerBuilder.html) instance after the library parsed data from the DOM. + +The callback's signature is the following: +```typescript +type AddGuardsCallback = (managerBuilder: GdprManagerBuilder) => void; +``` + +### `onDeclineAllErrorHook` function + +A callback that can be used to hande/capture errors when the user click on a "decline all" button. + +The callback's signature is the following: +```typescript +type StoreErrorHandler = (didStore: boolean, error?: Error) => void; +``` + +### `onSaveErrorHook` function + +A callback that can be used to hande/capture errors when the user saves their preferences. + +The callback's signature is the following: +```typescript +type StoreErrorHandler = (didStore: boolean, error?: Error) => void; +``` + +### `onCancelErrorHook` function + +A callback that can be used to hande/capture errors when the user click on a "cancel" button. + +The callback's signature is the following: +```typescript +type StoreErrorHandler = (didStore: boolean, error?: Error) => void; +``` + +### `onBannerClose` function + +A callback that can be used to execute code when the GDPR banner is closed. + +The callback's signature is the following: +```typescript +type BannerCallback = () => void; +``` + +For instance: +```javascript +await restoreHtmlGdprManager(gdprSavior, { + onBannerClose() { + hideMyGdprBanner(); + }, +}); +``` + +### `onBannerOpen` function + +A callback that can be used to execute code when the GDPR banner is closed. + +The callback's signature is the following: +```typescript +type BannerCallback = () => void; +``` + +For instance: +```javascript +await restoreHtmlGdprManager(gdprSavior, { + onBannerOpen() { + showMyGdprBanner(); + }, +}); +``` diff --git a/dist/index.js b/dist/index.js new file mode 100644 index 0000000..a089f6c --- /dev/null +++ b/dist/index.js @@ -0,0 +1,2 @@ +!function(r,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.htmlGdprGuard=t():r.htmlGdprGuard=t()}(self,(function(){return(()=>{var r={845:r=>{self,r.exports=(()=>{"use strict";var r={315:(r,t,e)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.makeGuard=void 0;var n=e(670);t.makeGuard=function(r,t,e,o,i){return void 0===e&&(e=n.GdprStorage.Cookie),void 0===o&&(o=!1),void 0===i&&(i=null),{name:r,description:t,storage:e,required:o,enabled:null===i?o:i,enable:function(){return this.enabled||this.toggle(),this},disable:function(){return this.enabled&&this.toggle(),this},toggle:function(){return this.required||(this.enabled=!this.enabled),this},makeRequired:function(){return this.required=!0,this.enabled=!0,this},isEnabled:function(r){return this.name===r&&this.enabled},enableForStorage:function(r){return this.enabled||this.toggleForStorage(r),this},disableForStorage:function(r){return this.enabled&&this.toggleForStorage(r),this},toggleForStorage:function(r){return this.storage!=r||this.required||this.toggle(),this},raw:function(){return JSON.parse(JSON.stringify(this))}}}},822:function(r,t,e){var n=this&&this.__values||function(r){var t="function"==typeof Symbol&&Symbol.iterator,e=t&&r[t],n=0;if(e)return e.call(r);if(r&&"number"==typeof r.length)return{next:function(){return r&&n>=r.length&&(r=void 0),{value:r&&r[n++],done:!r}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},o=this&&this.__read||function(r,t){var e="function"==typeof Symbol&&r[Symbol.iterator];if(!e)return r;var n,o,i=e.call(r),u=[];try{for(;(void 0===t||t-- >0)&&!(n=i.next()).done;)u.push(n.value)}catch(r){o={error:r}}finally{try{n&&!n.done&&(e=i.return)&&e.call(i)}finally{if(o)throw o.error}}return u},i=this&&this.__spreadArray||function(r,t,e){if(e||2===arguments.length)for(var n,o=0,i=t.length;o=r.length&&(r=void 0),{value:r&&r[n++],done:!r}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},o=this&&this.__read||function(r,t){var e="function"==typeof Symbol&&r[Symbol.iterator];if(!e)return r;var n,o,i=e.call(r),u=[];try{for(;(void 0===t||t-- >0)&&!(n=i.next()).done;)u.push(n.value)}catch(r){o={error:r}}finally{try{n&&!n.done&&(e=i.return)&&e.call(i)}finally{if(o)throw o.error}}return u},i=this&&this.__spreadArray||function(r,t,e){if(e||2===arguments.length)for(var n,o=0,i=t.length;o{Object.defineProperty(t,"__esModule",{value:!0}),t.GdprManagerEventHub=void 0;var e=function(){function r(){this.eventMap={}}return r.prototype.onEnable=function(r,t){return this.addListener("enable",r,t),this},r.prototype.onDisable=function(r,t){return this.addListener("disable",r,t),this},r.prototype.enable=function(r){return this.executeListeners("enable",r),this},r.prototype.disable=function(r){return this.executeListeners("disable",r),this},r.prototype.tagFor=function(r,t){return"".concat(r,"--").concat(t)},r.prototype.addListener=function(r,t,e){var n=this.tagFor(r,t);n in this.eventMap||(this.eventMap[n]=[]),this.eventMap[n].push(e)},r.prototype.executeListeners=function(r,t){var e,n=this.tagFor(r,t);null===(e=this.eventMap[n])||void 0===e||e.forEach((function(r){return r()}))},r}();t.GdprManagerEventHub=e},670:(r,t)=>{var e;Object.defineProperty(t,"__esModule",{value:!0}),t.GdprStorage=void 0,function(r){r[r.None=1]="None",r[r.Cookie=2]="Cookie",r[r.LocalStorage=4]="LocalStorage",r[r.SessionStorage=8]="SessionStorage",r[r.IndexedDb=16]="IndexedDb",r[r.FileSystem=16]="FileSystem",r[r.ServerStorage=16]="ServerStorage",r[r.All=30]="All"}(e||(e={})),t.GdprStorage=e},860:function(r,t,e){var n,o=this&&this.__extends||(n=function(r,t){return n=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(r,t){r.__proto__=t}||function(r,t){for(var e in t)Object.prototype.hasOwnProperty.call(t,e)&&(r[e]=t[e])},n(r,t)},function(r,t){if("function"!=typeof t&&null!==t)throw new TypeError("Class extends value "+String(t)+" is not a constructor or null");function e(){this.constructor=r}n(r,t),r.prototype=null===t?Object.create(t):(e.prototype=t.prototype,new e)}),i=this&&this.__read||function(r,t){var e="function"==typeof Symbol&&r[Symbol.iterator];if(!e)return r;var n,o,i=e.call(r),u=[];try{for(;(void 0===t||t-- >0)&&!(n=i.next()).done;)u.push(n.value)}catch(r){o={error:r}}finally{try{n&&!n.done&&(e=i.return)&&e.call(i)}finally{if(o)throw o.error}}return u},u=this&&this.__spreadArray||function(r,t,e){if(e||2===arguments.length)for(var n,o=0,i=t.length;o{Object.defineProperty(t,"__esModule",{value:!0}),t.GdprGuardBuilder=void 0;var n=e(670),o=e(315),i=function(){function r(r,t,e,n){this.parent=r,this.storage=t,this.enable=e,this.require=n,this.name="",this.description="",n&&(this.enable=!0)}return r.create=function(t,e,o,i){return void 0===e&&(e=n.GdprStorage.Cookie),void 0===o&&(o=!1),void 0===i&&(i=!1),new r(t,e,o,i)},r.prototype.endGuard=function(){var r=this.require||this.enable,t=(0,o.makeGuard)(this.name,this.description,this.storage,this.require,r);return this.require&&t.makeRequired(),this.parent.guards.push(t),this.parent},r.prototype.withName=function(r){return this.edit((function(t){return t.name=r}))},r.prototype.withDescription=function(r){return this.edit((function(t){return t.description=r}))},r.prototype.enabled=function(){return this.edit((function(r){return r.enable=!0}))},r.prototype.disabled=function(){return this.edit((function(r){return r.enable=!1}))},r.prototype.storedIn=function(r){return this.edit((function(t){return t.storage=r}))},r.prototype.required=function(){return this.edit((function(r){return r.require=!0}))},r.prototype.edit=function(r){return r(this),this},r}();t.GdprGuardBuilder=i},237:(r,t,e)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.GdprManagerBuilder=void 0;var n=e(670),o=e(777),i=e(171),u=function(){function r(){this.storage=n.GdprStorage.Cookie,this.groups=[],this.bannerWasShown=!1}return r.make=function(){return new r},r.prototype.withBannerShown=function(r){void 0===r&&(r=!0),this.bannerWasShown=r},r.prototype.startGroup=function(r,t,e,n){return void 0===r&&(r=null),void 0===t&&(t=""),void 0===e&&(e=""),void 0===n&&(n=!0),i.GdprGroupBuilder.create(this,t,e,r,n,!1)},r.prototype.startRequiredGroup=function(r,t,e){return void 0===r&&(r=null),void 0===t&&(t=""),void 0===e&&(e=""),this.startEnabledGroup(r,t,e).required()},r.prototype.startEnabledGroup=function(r,t,e){return void 0===r&&(r=null),void 0===t&&(t=""),void 0===e&&(e=""),this.startGroup(r,t,e,!0).enabled()},r.prototype.startDisabledGroup=function(r,t,e){return void 0===r&&(r=null),void 0===t&&(t=""),void 0===e&&(e=""),this.startGroup(r,t,e,!1).disabled()},r.prototype.build=function(){var r=o.GdprManager.create(this.groups);return r.bannerWasShown=this.bannerWasShown,r},r.prototype.endGroup=function(){return this},r}();t.GdprManagerBuilder=u},171:function(r,t,e){var n=this&&this.__createBinding||(Object.create?function(r,t,e,n){void 0===n&&(n=e);var o=Object.getOwnPropertyDescriptor(t,e);o&&!("get"in o?!t.__esModule:o.writable||o.configurable)||(o={enumerable:!0,get:function(){return t[e]}}),Object.defineProperty(r,n,o)}:function(r,t,e,n){void 0===n&&(n=e),r[n]=t[e]}),o=this&&this.__exportStar||function(r,t){for(var e in r)"default"===e||Object.prototype.hasOwnProperty.call(t,e)||n(t,r,e)};Object.defineProperty(t,"__esModule",{value:!0}),o(e(890),t),o(e(237),t),o(e(860),t)},93:function(r,t,e){var n=this&&this.__createBinding||(Object.create?function(r,t,e,n){void 0===n&&(n=e);var o=Object.getOwnPropertyDescriptor(t,e);o&&!("get"in o?!t.__esModule:o.writable||o.configurable)||(o={enumerable:!0,get:function(){return t[e]}}),Object.defineProperty(r,n,o)}:function(r,t,e,n){void 0===n&&(n=e),r[n]=t[e]}),o=this&&this.__exportStar||function(r,t){for(var e in r)"default"===e||Object.prototype.hasOwnProperty.call(t,e)||n(t,r,e)};Object.defineProperty(t,"__esModule",{value:!0}),o(e(315),t),o(e(822),t),o(e(777),t),o(e(670),t),o(e(779),t),o(e(171),t),o(e(562),t),o(e(344),t)},562:(r,t,e)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.GdprDeserializer=void 0;var n=e(777),o=e(670),i=e(822),u=e(315),a=function(){function r(){}return r.manager=function(r){var t=this;if(!["enabled","groups"].every((function(t){return t in r}))||"boolean"!=typeof r.enabled||!Array.isArray(r.groups))return null;var e=r.groups.map((function(r){return t.group(r)})).filter((function(r){return null!==r})),o=n.GdprManager.create([]);return o.enabled=!!r.enabled,o.bannerWasShown=!!r.bannerWasShown,e.length?(e.forEach((function(r){return o.addGroup(r)})),o):null},r.group=function(r){var t=this,e=this.guard(r);if(null===e)return null;var n=["guards"];if(!n.every((function(t){return t in r}))||!Array.isArray(r.guards))return null;var o=i.GdprGuardGroup.for(e.name,e.description,e.enabled,e.required),u=r.guards.map((function(r){return n.every((function(t){return t in r}))?t.group(r):t.guard(r)})).filter((function(r){return null!==r}));return u.length?(u.forEach((function(r){return o.addGuard(r)})),o):null},r.guard=function(r){return["name","enabled","required","description","storage"].every((function(t){return t in r}))&&"string"==typeof r.name&&"boolean"==typeof r.enabled&&"boolean"==typeof r.required&&"string"==typeof r.description&&"number"==typeof r.storage&&r.storage in o.GdprStorage?(0,u.makeGuard)(r.name,r.description,r.storage,!!r.required,!!r.enabled):null},r}();t.GdprDeserializer=a},344:function(r,t){var e=this&&this.__awaiter||function(r,t,e,n){return new(e||(e=Promise))((function(o,i){function u(r){try{c(n.next(r))}catch(r){i(r)}}function a(r){try{c(n.throw(r))}catch(r){i(r)}}function c(r){var t;r.done?o(r.value):(t=r.value,t instanceof e?t:new e((function(r){r(t)}))).then(u,a)}c((n=n.apply(r,t||[])).next())}))},n=this&&this.__generator||function(r,t){var e,n,o,i,u={label:0,sent:function(){if(1&o[0])throw o[1];return o[1]},trys:[],ops:[]};return i={next:a(0),throw:a(1),return:a(2)},"function"==typeof Symbol&&(i[Symbol.iterator]=function(){return this}),i;function a(i){return function(a){return function(i){if(e)throw new TypeError("Generator is already executing.");for(;u;)try{if(e=1,n&&(o=2&i[0]?n.return:i[0]?n.throw||((o=n.return)&&o.call(n),0):n.next)&&!(o=o.call(n,i[1])).done)return o;switch(n=0,o&&(i=[2&i[0],o.value]),i[0]){case 0:case 1:o=i;break;case 4:return u.label++,{value:i[1],done:!1};case 5:u.label++,n=i[1],i=[0];continue;case 7:i=u.ops.pop(),u.trys.pop();continue;default:if(!((o=(o=u.trys).length>0&&o[o.length-1])||6!==i[0]&&2!==i[0])){u=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]{Object.defineProperty(t,"__esModule",{value:!0}),t.visitGdpr=void 0;var n=e(777),o=e(822);t.visitGdpr=function(r,e){var i=void 0===e?{}:e,u=i.onManager,a=void 0===u?function(){}:u,c=i.onGroup,s=void 0===c?function(){}:c,l=i.onGuard,d=void 0===l?function(){}:l,f=i.onEach,p=void 0===f?function(){}:f,h={onManager:a,onGroup:s,onGuard:d,onEach:p};r instanceof n.GdprManager?(a(r),p(r),r.getGroups().forEach((function(r){return(0,t.visitGdpr)(r,h)}))):r instanceof o.GdprGuardGroup?(s(r),p(r),r.getGuards().forEach((function(r){return(0,t.visitGdpr)(r,h)}))):(d(r),p(r))}}},t={};return function e(n){var o=t[n];if(void 0!==o)return o.exports;var i=t[n]={exports:{}};return r[n].call(i.exports,i,i.exports,e),i.exports}(93)})()}},t={};function e(n){var o=t[n];if(void 0!==o)return o.exports;var i=t[n]={exports:{}};return r[n](i,i.exports,e),i.exports}e.d=(r,t)=>{for(var n in t)e.o(t,n)&&!e.o(r,n)&&Object.defineProperty(r,n,{enumerable:!0,get:t[n]})},e.o=(r,t)=>Object.prototype.hasOwnProperty.call(r,t),e.r=r=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(r,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(r,"__esModule",{value:!0})};var n={};return(()=>{"use strict";e.r(n),e.d(n,{HtmlGdprGuardError:()=>o,NoCheckboxError:()=>d,NoManagerDefinitionError:()=>u,NoNameError:()=>s,restoreHtmlGdprManager:()=>O});var r,t=(r=function(t,e){return r=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(r,t){r.__proto__=t}||function(r,t){for(var e in t)Object.prototype.hasOwnProperty.call(t,e)&&(r[e]=t[e])},r(t,e)},function(t,e){if("function"!=typeof e&&null!==e)throw new TypeError("Class extends value "+String(e)+" is not a constructor or null");function n(){this.constructor=t}r(t,e),t.prototype=null===e?Object.create(e):(n.prototype=e.prototype,new n)}),o=function(r){function e(t){return r.call(this,t)||this}return t(e,r),e}(Error),i=function(){var r=function(t,e){return r=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(r,t){r.__proto__=t}||function(r,t){for(var e in t)Object.prototype.hasOwnProperty.call(t,e)&&(r[e]=t[e])},r(t,e)};return function(t,e){if("function"!=typeof e&&null!==e)throw new TypeError("Class extends value "+String(e)+" is not a constructor or null");function n(){this.constructor=t}r(t,e),t.prototype=null===e?Object.create(e):(n.prototype=e.prototype,new n)}}(),u=function(r){function t(e){return void 0===e&&(e=t.defaultMessage),r.call(this,e)||this}return i(t,r),t.defaultMessage="No definition found for the GDPR manager",t}(o),a=e(845),c=function(){var r=function(t,e){return r=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(r,t){r.__proto__=t}||function(r,t){for(var e in t)Object.prototype.hasOwnProperty.call(t,e)&&(r[e]=t[e])},r(t,e)};return function(t,e){if("function"!=typeof e&&null!==e)throw new TypeError("Class extends value "+String(e)+" is not a constructor or null");function n(){this.constructor=t}r(t,e),t.prototype=null===e?Object.create(e):(n.prototype=e.prototype,new n)}}(),s=function(r){function t(e){return void 0===e&&(e=t.defaultMessage),r.call(this,e)||this}return c(t,r),t.defaultMessage="Guard definition is missing the guard's name",t}(o),l=function(){var r=function(t,e){return r=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(r,t){r.__proto__=t}||function(r,t){for(var e in t)Object.prototype.hasOwnProperty.call(t,e)&&(r[e]=t[e])},r(t,e)};return function(t,e){if("function"!=typeof e&&null!==e)throw new TypeError("Class extends value "+String(e)+" is not a constructor or null");function n(){this.constructor=t}r(t,e),t.prototype=null===e?Object.create(e):(n.prototype=e.prototype,new n)}}(),d=function(r){function t(e){return void 0===e&&(e=t.defaultMessage),r.call(this,e)||this}return l(t,r),t.defaultMessage="No checkbox found for that guard",t}(o),f=function(r){return!!r&&!/^\s*$/.test(r)},p=function(r,t,e){void 0===e&&(e="gdpr-guard-name");var n=r.dataset[function(r){return r.replace(/-(\w)/g,(function(r,t){return t.toUpperCase()}))}(t)];if(f(n))return n.trim();var o,i,u=(o=r,i="[data-".concat(e,"]"),function(r,t){for(var e=0;e=r.length&&(r=void 0),{value:r&&r[n++],done:!r}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")}(i),a=u.next();!a.done;a=u.next()){var c=(0,a.value)();if(null===(o=null==c?void 0:c.matches)||void 0===o?void 0:o.call(c,"input[type='checkbox']"))return c}}catch(r){e={error:r}}finally{try{a&&!a.done&&(n=u.return)&&n.call(u)}finally{if(e)throw e.error}}throw new d},v=function(r){var t;if(r.hasAttribute("data-gdpr-guard-description"))return r.dataset.gdprGuardDescription;var e=r.querySelector("[data-gdpr-guard-description]");return null!==(t=null==e?void 0:e.textContent)&&void 0!==t?t:null},y=function(r){if(r.hasAttribute("data-gdpr-guard-storage")){var t=r.dataset.gdprGuardStorage;if(t&&t in a.GdprStorage)return a.GdprStorage[t]}return null},b=function(r,t){return t.required||r.hasAttribute("data-gdpr-guard-required")},g=function(r,t,e){void 0===e&&(e=!1);var n=function(){t.setAttribute("checked","checked"),t.setAttribute("disabled","disabled")},o=function(){t.setAttribute("required","required")},i=function(){r.setAttribute("data-gdpr-guard-required","")};e?(i(),n(),o()):t.required?(i(),n()):r.hasAttribute("data-gdpr-guard-required")&&(n(),o())},G=function(r,t){var e="function"==typeof Symbol&&r[Symbol.iterator];if(!e)return r;var n,o,i=e.call(r),u=[];try{for(;(void 0===t||t-- >0)&&!(n=i.next()).done;)u.push(n.value)}catch(r){o={error:r}}finally{try{n&&!n.done&&(e=i.return)&&e.call(i)}finally{if(o)throw o.error}}return u},w=function(r,t,e){if(e||2===arguments.length)for(var n,o=0,i=t.length;o0)&&!(n=i.next()).done;)u.push(n.value)}catch(r){o={error:r}}finally{try{n&&!n.done&&(e=i.return)&&e.call(i)}finally{if(o)throw o.error}}return u}(r,2),o=n[0],i=n[1],u=t.target;(null===(e=null==u?void 0:u.matches)||void 0===e?void 0:e.call(u,o))&&i.forEach((function(r){return r(t)}))}))}))}},E=function(r,t,e){document.querySelectorAll(t).forEach((function(t){var n=t.dataset.gdprOnEnable;r.hasGuard(n)?r.events.onEnable(n,(function(){var r=t.matches("script"),n=r?document.createElement("script"):t.cloneNode(!0);r&&t.getAttributeNames().forEach((function(r){var e=t.getAttribute(r);n.setAttribute(r,e)})),e(n),n.removeAttribute("data-gdpr-on-enable"),t.remove(),document.head.appendChild(n)})):t.remove()}))},x=function(r,t,e,n){return new(e||(e=Promise))((function(o,i){function u(r){try{c(n.next(r))}catch(r){i(r)}}function a(r){try{c(n.throw(r))}catch(r){i(r)}}function c(r){var t;r.done?o(r.value):(t=r.value,t instanceof e?t:new e((function(r){r(t)}))).then(u,a)}c((n=n.apply(r,t||[])).next())}))},k=function(r,t){var e,n,o,i,u={label:0,sent:function(){if(1&o[0])throw o[1];return o[1]},trys:[],ops:[]};return i={next:a(0),throw:a(1),return:a(2)},"function"==typeof Symbol&&(i[Symbol.iterator]=function(){return this}),i;function a(i){return function(a){return function(i){if(e)throw new TypeError("Generator is already executing.");for(;u;)try{if(e=1,n&&(o=2&i[0]?n.return:i[0]?n.throw||((o=n.return)&&o.call(n),0):n.next)&&!(o=o.call(n,i[1])).done)return o;switch(n=0,o&&(i=[2&i[0],o.value]),i[0]){case 0:case 1:o=i;break;case 4:return u.label++,{value:i[1],done:!1};case 5:u.label++,n=i[1],i=[0];continue;case 7:i=u.ops.pop(),u.trys.pop();continue;default:if(!((o=(o=u.trys).length>0&&o[o.length-1])||6!==i[0]&&2!==i[0])){u=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]0&&o[o.length-1])||6!==i[0]&&2!==i[0])){u=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]{\"use strict\";var t={315:(t,r,e)=>{Object.defineProperty(r,\"__esModule\",{value:!0}),r.makeGuard=void 0;var n=e(670);r.makeGuard=function(t,r,e,o,i){return void 0===e&&(e=n.GdprStorage.Cookie),void 0===o&&(o=!1),void 0===i&&(i=null),{name:t,description:r,storage:e,required:o,enabled:null===i?o:i,enable:function(){return this.enabled||this.toggle(),this},disable:function(){return this.enabled&&this.toggle(),this},toggle:function(){return this.required||(this.enabled=!this.enabled),this},makeRequired:function(){return this.required=!0,this.enabled=!0,this},isEnabled:function(t){return this.name===t&&this.enabled},enableForStorage:function(t){return this.enabled||this.toggleForStorage(t),this},disableForStorage:function(t){return this.enabled&&this.toggleForStorage(t),this},toggleForStorage:function(t){return this.storage!=t||this.required||this.toggle(),this},raw:function(){return JSON.parse(JSON.stringify(this))}}}},822:function(t,r,e){var n=this&&this.__values||function(t){var r=\"function\"==typeof Symbol&&Symbol.iterator,e=r&&t[r],n=0;if(e)return e.call(t);if(t&&\"number\"==typeof t.length)return{next:function(){return t&&n>=t.length&&(t=void 0),{value:t&&t[n++],done:!t}}};throw new TypeError(r?\"Object is not iterable.\":\"Symbol.iterator is not defined.\")},o=this&&this.__read||function(t,r){var e=\"function\"==typeof Symbol&&t[Symbol.iterator];if(!e)return t;var n,o,i=e.call(t),u=[];try{for(;(void 0===r||r-- >0)&&!(n=i.next()).done;)u.push(n.value)}catch(t){o={error:t}}finally{try{n&&!n.done&&(e=i.return)&&e.call(i)}finally{if(o)throw o.error}}return u},i=this&&this.__spreadArray||function(t,r,e){if(e||2===arguments.length)for(var n,o=0,i=r.length;o=t.length&&(t=void 0),{value:t&&t[n++],done:!t}}};throw new TypeError(r?\"Object is not iterable.\":\"Symbol.iterator is not defined.\")},o=this&&this.__read||function(t,r){var e=\"function\"==typeof Symbol&&t[Symbol.iterator];if(!e)return t;var n,o,i=e.call(t),u=[];try{for(;(void 0===r||r-- >0)&&!(n=i.next()).done;)u.push(n.value)}catch(t){o={error:t}}finally{try{n&&!n.done&&(e=i.return)&&e.call(i)}finally{if(o)throw o.error}}return u},i=this&&this.__spreadArray||function(t,r,e){if(e||2===arguments.length)for(var n,o=0,i=r.length;o{Object.defineProperty(r,\"__esModule\",{value:!0}),r.GdprManagerEventHub=void 0;var e=function(){function t(){this.eventMap={}}return t.prototype.onEnable=function(t,r){return this.addListener(\"enable\",t,r),this},t.prototype.onDisable=function(t,r){return this.addListener(\"disable\",t,r),this},t.prototype.enable=function(t){return this.executeListeners(\"enable\",t),this},t.prototype.disable=function(t){return this.executeListeners(\"disable\",t),this},t.prototype.tagFor=function(t,r){return\"\".concat(t,\"--\").concat(r)},t.prototype.addListener=function(t,r,e){var n=this.tagFor(t,r);n in this.eventMap||(this.eventMap[n]=[]),this.eventMap[n].push(e)},t.prototype.executeListeners=function(t,r){var e,n=this.tagFor(t,r);null===(e=this.eventMap[n])||void 0===e||e.forEach((function(t){return t()}))},t}();r.GdprManagerEventHub=e},670:(t,r)=>{var e;Object.defineProperty(r,\"__esModule\",{value:!0}),r.GdprStorage=void 0,function(t){t[t.None=1]=\"None\",t[t.Cookie=2]=\"Cookie\",t[t.LocalStorage=4]=\"LocalStorage\",t[t.SessionStorage=8]=\"SessionStorage\",t[t.IndexedDb=16]=\"IndexedDb\",t[t.FileSystem=16]=\"FileSystem\",t[t.ServerStorage=16]=\"ServerStorage\",t[t.All=30]=\"All\"}(e||(e={})),r.GdprStorage=e},860:function(t,r,e){var n,o=this&&this.__extends||(n=function(t,r){return n=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(t,r){t.__proto__=r}||function(t,r){for(var e in r)Object.prototype.hasOwnProperty.call(r,e)&&(t[e]=r[e])},n(t,r)},function(t,r){if(\"function\"!=typeof r&&null!==r)throw new TypeError(\"Class extends value \"+String(r)+\" is not a constructor or null\");function e(){this.constructor=t}n(t,r),t.prototype=null===r?Object.create(r):(e.prototype=r.prototype,new e)}),i=this&&this.__read||function(t,r){var e=\"function\"==typeof Symbol&&t[Symbol.iterator];if(!e)return t;var n,o,i=e.call(t),u=[];try{for(;(void 0===r||r-- >0)&&!(n=i.next()).done;)u.push(n.value)}catch(t){o={error:t}}finally{try{n&&!n.done&&(e=i.return)&&e.call(i)}finally{if(o)throw o.error}}return u},u=this&&this.__spreadArray||function(t,r,e){if(e||2===arguments.length)for(var n,o=0,i=r.length;o{Object.defineProperty(r,\"__esModule\",{value:!0}),r.GdprGuardBuilder=void 0;var n=e(670),o=e(315),i=function(){function t(t,r,e,n){this.parent=t,this.storage=r,this.enable=e,this.require=n,this.name=\"\",this.description=\"\",n&&(this.enable=!0)}return t.create=function(r,e,o,i){return void 0===e&&(e=n.GdprStorage.Cookie),void 0===o&&(o=!1),void 0===i&&(i=!1),new t(r,e,o,i)},t.prototype.endGuard=function(){var t=this.require||this.enable,r=(0,o.makeGuard)(this.name,this.description,this.storage,this.require,t);return this.require&&r.makeRequired(),this.parent.guards.push(r),this.parent},t.prototype.withName=function(t){return this.edit((function(r){return r.name=t}))},t.prototype.withDescription=function(t){return this.edit((function(r){return r.description=t}))},t.prototype.enabled=function(){return this.edit((function(t){return t.enable=!0}))},t.prototype.disabled=function(){return this.edit((function(t){return t.enable=!1}))},t.prototype.storedIn=function(t){return this.edit((function(r){return r.storage=t}))},t.prototype.required=function(){return this.edit((function(t){return t.require=!0}))},t.prototype.edit=function(t){return t(this),this},t}();r.GdprGuardBuilder=i},237:(t,r,e)=>{Object.defineProperty(r,\"__esModule\",{value:!0}),r.GdprManagerBuilder=void 0;var n=e(670),o=e(777),i=e(171),u=function(){function t(){this.storage=n.GdprStorage.Cookie,this.groups=[],this.bannerWasShown=!1}return t.make=function(){return new t},t.prototype.withBannerShown=function(t){void 0===t&&(t=!0),this.bannerWasShown=t},t.prototype.startGroup=function(t,r,e,n){return void 0===t&&(t=null),void 0===r&&(r=\"\"),void 0===e&&(e=\"\"),void 0===n&&(n=!0),i.GdprGroupBuilder.create(this,r,e,t,n,!1)},t.prototype.startRequiredGroup=function(t,r,e){return void 0===t&&(t=null),void 0===r&&(r=\"\"),void 0===e&&(e=\"\"),this.startEnabledGroup(t,r,e).required()},t.prototype.startEnabledGroup=function(t,r,e){return void 0===t&&(t=null),void 0===r&&(r=\"\"),void 0===e&&(e=\"\"),this.startGroup(t,r,e,!0).enabled()},t.prototype.startDisabledGroup=function(t,r,e){return void 0===t&&(t=null),void 0===r&&(r=\"\"),void 0===e&&(e=\"\"),this.startGroup(t,r,e,!1).disabled()},t.prototype.build=function(){var t=o.GdprManager.create(this.groups);return t.bannerWasShown=this.bannerWasShown,t},t.prototype.endGroup=function(){return this},t}();r.GdprManagerBuilder=u},171:function(t,r,e){var n=this&&this.__createBinding||(Object.create?function(t,r,e,n){void 0===n&&(n=e);var o=Object.getOwnPropertyDescriptor(r,e);o&&!(\"get\"in o?!r.__esModule:o.writable||o.configurable)||(o={enumerable:!0,get:function(){return r[e]}}),Object.defineProperty(t,n,o)}:function(t,r,e,n){void 0===n&&(n=e),t[n]=r[e]}),o=this&&this.__exportStar||function(t,r){for(var e in t)\"default\"===e||Object.prototype.hasOwnProperty.call(r,e)||n(r,t,e)};Object.defineProperty(r,\"__esModule\",{value:!0}),o(e(890),r),o(e(237),r),o(e(860),r)},93:function(t,r,e){var n=this&&this.__createBinding||(Object.create?function(t,r,e,n){void 0===n&&(n=e);var o=Object.getOwnPropertyDescriptor(r,e);o&&!(\"get\"in o?!r.__esModule:o.writable||o.configurable)||(o={enumerable:!0,get:function(){return r[e]}}),Object.defineProperty(t,n,o)}:function(t,r,e,n){void 0===n&&(n=e),t[n]=r[e]}),o=this&&this.__exportStar||function(t,r){for(var e in t)\"default\"===e||Object.prototype.hasOwnProperty.call(r,e)||n(r,t,e)};Object.defineProperty(r,\"__esModule\",{value:!0}),o(e(315),r),o(e(822),r),o(e(777),r),o(e(670),r),o(e(779),r),o(e(171),r),o(e(562),r),o(e(344),r)},562:(t,r,e)=>{Object.defineProperty(r,\"__esModule\",{value:!0}),r.GdprDeserializer=void 0;var n=e(777),o=e(670),i=e(822),u=e(315),a=function(){function t(){}return t.manager=function(t){var r=this;if(![\"enabled\",\"groups\"].every((function(r){return r in t}))||\"boolean\"!=typeof t.enabled||!Array.isArray(t.groups))return null;var e=t.groups.map((function(t){return r.group(t)})).filter((function(t){return null!==t})),o=n.GdprManager.create([]);return o.enabled=!!t.enabled,o.bannerWasShown=!!t.bannerWasShown,e.length?(e.forEach((function(t){return o.addGroup(t)})),o):null},t.group=function(t){var r=this,e=this.guard(t);if(null===e)return null;var n=[\"guards\"];if(!n.every((function(r){return r in t}))||!Array.isArray(t.guards))return null;var o=i.GdprGuardGroup.for(e.name,e.description,e.enabled,e.required),u=t.guards.map((function(t){return n.every((function(r){return r in t}))?r.group(t):r.guard(t)})).filter((function(t){return null!==t}));return u.length?(u.forEach((function(t){return o.addGuard(t)})),o):null},t.guard=function(t){return[\"name\",\"enabled\",\"required\",\"description\",\"storage\"].every((function(r){return r in t}))&&\"string\"==typeof t.name&&\"boolean\"==typeof t.enabled&&\"boolean\"==typeof t.required&&\"string\"==typeof t.description&&\"number\"==typeof t.storage&&t.storage in o.GdprStorage?(0,u.makeGuard)(t.name,t.description,t.storage,!!t.required,!!t.enabled):null},t}();r.GdprDeserializer=a},344:function(t,r){var e=this&&this.__awaiter||function(t,r,e,n){return new(e||(e=Promise))((function(o,i){function u(t){try{s(n.next(t))}catch(t){i(t)}}function a(t){try{s(n.throw(t))}catch(t){i(t)}}function s(t){var r;t.done?o(t.value):(r=t.value,r instanceof e?r:new e((function(t){t(r)}))).then(u,a)}s((n=n.apply(t,r||[])).next())}))},n=this&&this.__generator||function(t,r){var e,n,o,i,u={label:0,sent:function(){if(1&o[0])throw o[1];return o[1]},trys:[],ops:[]};return i={next:a(0),throw:a(1),return:a(2)},\"function\"==typeof Symbol&&(i[Symbol.iterator]=function(){return this}),i;function a(i){return function(a){return function(i){if(e)throw new TypeError(\"Generator is already executing.\");for(;u;)try{if(e=1,n&&(o=2&i[0]?n.return:i[0]?n.throw||((o=n.return)&&o.call(n),0):n.next)&&!(o=o.call(n,i[1])).done)return o;switch(n=0,o&&(i=[2&i[0],o.value]),i[0]){case 0:case 1:o=i;break;case 4:return u.label++,{value:i[1],done:!1};case 5:u.label++,n=i[1],i=[0];continue;case 7:i=u.ops.pop(),u.trys.pop();continue;default:if(!((o=(o=u.trys).length>0&&o[o.length-1])||6!==i[0]&&2!==i[0])){u=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]{Object.defineProperty(r,\"__esModule\",{value:!0}),r.visitGdpr=void 0;var n=e(777),o=e(822);r.visitGdpr=function(t,e){var i=void 0===e?{}:e,u=i.onManager,a=void 0===u?function(){}:u,s=i.onGroup,d=void 0===s?function(){}:s,c=i.onGuard,p=void 0===c?function(){}:c,l=i.onEach,f=void 0===l?function(){}:l,h={onManager:a,onGroup:d,onGuard:p,onEach:f};t instanceof n.GdprManager?(a(t),f(t),t.getGroups().forEach((function(t){return(0,r.visitGdpr)(t,h)}))):t instanceof o.GdprGuardGroup?(d(t),f(t),t.getGuards().forEach((function(t){return(0,r.visitGdpr)(t,h)}))):(p(t),f(t))}}},r={};return function e(n){var o=r[n];if(void 0!==o)return o.exports;var i=r[n]={exports:{}};return t[n].call(i.exports,i,i.exports,e),i.exports}(93)})()}));","// The module cache\nvar __webpack_module_cache__ = {};\n\n// The require function\nfunction __webpack_require__(moduleId) {\n\t// Check if module is in cache\n\tvar cachedModule = __webpack_module_cache__[moduleId];\n\tif (cachedModule !== undefined) {\n\t\treturn cachedModule.exports;\n\t}\n\t// Create a new module (and put it into the cache)\n\tvar module = __webpack_module_cache__[moduleId] = {\n\t\t// no module.id needed\n\t\t// no module.loaded needed\n\t\texports: {}\n\t};\n\n\t// Execute the module function\n\t__webpack_modules__[moduleId](module, module.exports, __webpack_require__);\n\n\t// Return the exports of the module\n\treturn module.exports;\n}\n\n","// define getter functions for harmony exports\n__webpack_require__.d = (exports, definition) => {\n\tfor(var key in definition) {\n\t\tif(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n\t\t\tObject.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n\t\t}\n\t}\n};","__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))","// define __esModule on exports\n__webpack_require__.r = (exports) => {\n\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n\t}\n\tObject.defineProperty(exports, '__esModule', { value: true });\n};","export class HtmlGdprGuardError extends Error {\n\tconstructor(message: string) {\n\t\tsuper(message);\n\t}\n}\n","import { HtmlGdprGuardError } from \"@/errors/HtmlGdprGuardError\";\n\n/**\n * Error thrown when the library does not find\n * a root {@link HTMLElement} to get the manager's\n * data from\n */\nexport class NoManagerDefinitionError extends HtmlGdprGuardError {\n\tstatic defaultMessage: string = \"No definition found for the GDPR manager\";\n\n\tconstructor(message = NoManagerDefinitionError.defaultMessage) {\n\t\tsuper(message);\n\t}\n}\n","import { HtmlGdprGuardError } from \"@/errors/HtmlGdprGuardError\";\n\nexport class NoNameError extends HtmlGdprGuardError {\n\tstatic defaultMessage: string = \"Guard definition is missing the guard's name\";\n\n\tconstructor(message: string = NoNameError.defaultMessage) {\n\t\tsuper(message);\n\t}\n}\n","import { HtmlGdprGuardError } from \"@/errors/HtmlGdprGuardError\";\n\nexport class NoCheckboxError extends HtmlGdprGuardError {\n\tstatic defaultMessage: string = \"No checkbox found for that guard\";\n\n\tconstructor(message: string = NoCheckboxError.defaultMessage) {\n\t\tsuper(message);\n\t}\n}\n","export const isMeaningfulStr = (str?: string|null): str is string => {\n\treturn !!str && !/^\\s*$/.test(str);\n};\n\nexport const toCamelCase = (str: string): string => {\n\treturn str.replace(/-(\\w)/g, (_, letter: string) => letter.toUpperCase());\n};\n","import { childSelector } from \"@/utils/dom\";\nimport { NoNameError } from \"@/errors/NoNameError\";\nimport { NoCheckboxError } from \"@/errors/NoCheckboxError\";\nimport { GdprStorage } from \"gdpr-guard\";\nimport { isMeaningfulStr, toCamelCase } from \"@/utils/misc\";\nimport { NoManagerDefinitionError } from \"@/errors/NoManagerDefinitionError\";\n\n/**\n * Get the guard's name from the DOM\n * @param guardEl - The guard element to query\n * @param guardDataKey - The key in the dataset of {@link guardEl} where the name could be\n * @param nameDataKey - The name of the data attribute that can be found in child nodes to parse the name\n * @throws {NoNameError} - If it can't find the guard's name\n */\nexport const nameFromDOM = (guardEl: HTMLElement, guardDataKey: string, nameDataKey: string = \"gdpr-guard-name\"): string => {\n\tconst str = guardEl.dataset[toCamelCase(guardDataKey)];\n\n\tif (isMeaningfulStr(str)) {\n\t\treturn str.trim();\n\t}\n\n\t// const nameHolder: HTMLElement|null = guardEl.querySelector(`[data-${nameDataKey}]`);\n\tconst nameHolder: HTMLElement|null = childSelector(guardEl, `[data-${nameDataKey}]`);\n\n\tconst name = nameHolder?.dataset[nameDataKey];\n\tif (!isMeaningfulStr(name)) {\n\t\tconst textName = nameHolder?.textContent;\n\n\t\tif (isMeaningfulStr(textName)) {\n\t\t\treturn textName.trim();\n\t\t}\n\n\t\tthrow new NoNameError();\n\t}\n\n\treturn name.trim();\n};\n\n/**\n * Get the guard's checkbox from the DOM\n * @param guardEl - The root of the guard's tree\n * @param guardName - The guard's name\n */\nexport const checkboxFromDOM = (guardEl: HTMLElement, guardName: string) => {\n\tconst strategies = [\n\t\t() => document.getElementById(guardName), // by ID\n\t\t() => guardEl.querySelector(`[type=\"checkbox\"][name=\"${guardName}\"]`), // by name\n\t\t() => guardEl.querySelector(`[type=\"checkbox\"][data-gdpr-checkbox]`), // by specific attribute\n\t];\n\n\tfor (const strategy of strategies) {\n\t\tconst checkbox = strategy();\n\n\t\tif (checkbox?.matches?.(\"input[type='checkbox']\")) {\n\t\t\treturn checkbox as HTMLInputElement;\n\t\t}\n\t}\n\n\tthrow new NoCheckboxError();\n};\n\n/**\n * Retrieve the guard's description from the DOM\n * @param guardEl - The root of the guard's state tree\n */\nexport const descriptionFromDOM = (guardEl: HTMLElement) => {\n\tif (guardEl.hasAttribute(\"data-gdpr-guard-description\")) {\n\t\treturn guardEl.dataset.gdprGuardDescription;\n\t}\n\n\tconst descriptionEl = guardEl.querySelector(\"[data-gdpr-guard-description]\");\n\n\treturn descriptionEl?.textContent ?? null;\n};\n\n/**\n * Get the {@link GdprStorage} from the DOM\n * @param guardEl - The root the guard's state tree\n */\nexport const storageFromDOM = (guardEl: HTMLElement): GdprStorage|null => {\n\tif (guardEl.hasAttribute(\"data-gdpr-guard-storage\")) {\n\t\tconst rawStorage = guardEl.dataset.gdprGuardStorage;\n\n\t\tif (rawStorage && rawStorage in GdprStorage) {\n\t\t\treturn GdprStorage[rawStorage];\n\t\t}\n\t}\n\n\treturn null;\n};\n\n/**\n * Check whether the guard is marked as required in the DOM\n * @param guardEl - The root of the guard's state tree\n * @param checkbox - The guard's checkbox\n */\nexport const guardIsRequiredInDOM = (guardEl: HTMLElement, checkbox: HTMLInputElement) => {\n\treturn checkbox.required || guardEl.hasAttribute(\"data-gdpr-guard-required\");\n};\n\n/**\n * Sync the required status across all attributes in the DOM\n * @param guardEl - The root of the guard's state tree\n * @param checkbox - The guard's checkbox\n * @param isRequired - Whether the guard is already marked as required\n */\nexport const syncRequiredInDOM = (guardEl: HTMLElement, checkbox: HTMLInputElement, isRequired: boolean = false) => {\n\tconst makeCheckedDisabled = () => {\n\t\tcheckbox.setAttribute(\"checked\", \"checked\");\n\t\tcheckbox.setAttribute(\"disabled\", \"disabled\");\n\t};\n\n\tconst makeRequired = () => {\n\t\tcheckbox.setAttribute(\"required\", \"required\");\n\t};\n\n\tconst addGdprRequiredAttr = () => {\n\t\tguardEl.setAttribute(\"data-gdpr-guard-required\", \"\");\n\t};\n\n\tif(isRequired) {\n\t\taddGdprRequiredAttr();\n\t\tmakeCheckedDisabled();\n\t\tmakeRequired();\n\t} else if (checkbox.required) {\n\t\taddGdprRequiredAttr();\n\t\tmakeCheckedDisabled();\n\t} else if (guardEl.hasAttribute(\"data-gdpr-guard-required\")) {\n\t\tmakeCheckedDisabled();\n\t\tmakeRequired();\n\t}\n}\n\n/**\n * Extract the manager's own details from the DOM\n * @param gdprEl - The root of the GDPR state tree\n */\nexport const parseManagerDetails = (gdprEl: HTMLElement) => {\n\tlet managerEl = gdprEl;\n\tconst { gdpr } = gdprEl.dataset;\n\tlet managerName: string = \"\";\n\n\tif (isMeaningfulStr(gdpr)) {\n\t\tmanagerName = gdpr;\n\t} else {\n\t\tconst el = gdprEl.querySelector(\"[data-gdpr-manager]\");\n\n\t\tif (!el) {\n\t\t\tthrow new NoManagerDefinitionError();\n\t\t}\n\n\t\tmanagerEl = el as HTMLElement;\n\t\tmanagerName = nameFromDOM(managerEl, \"gdpr-manager\");\n\t}\n\n\tconst managerCheckbox = checkboxFromDOM(managerEl, managerName);\n\n\treturn {\n\t\tmanagerEl,\n\t\tmanagerCheckbox,\n\t\tmanagerName,\n\t};\n};\n","/**\n * Execute an action/callback on each child\n * @param rootEl - The parent element\n * @param action - The action/callback to execute on each child\n */\nexport const forEachChild = (rootEl: HTMLElement, action: (el: HTMLElement) => void) => {\n\tfor (let i = 0; i < rootEl.childElementCount; i += 1) {\n\t\tconst el = rootEl.children.item(i);\n\n\t\tif (el) {\n\t\t\taction(el as HTMLElement);\n\t\t}\n\t}\n}\n\nexport const findChild = (rootEl: HTMLElement, predicate: (el: HTMLElement) => boolean) => {\n\tfor (let i = 0; i < rootEl.childElementCount; i += 1) {\n\t\tconst el = rootEl.children.item(i);\n\n\t\tif (el && predicate(el as HTMLElement)) {\n\t\t\treturn el as HTMLElement;\n\t\t}\n\t}\n\n\treturn null;\n}\n\n/**\n * Find all the children that satisfy the given predicate\n * @param rootEl - The parent element\n * @param predicate - The predicate to satisfy\n */\nexport const findAllChildren = (rootEl: HTMLElement, predicate: (el: HTMLElement) => boolean) => {\n\tconst ret = [] as HTMLElement[];\n\n\tfor (let i = 0; i < rootEl.childElementCount; i += 1) {\n\t\tconst el = rootEl.children.item(i);\n\n\t\tif (el && predicate(el as HTMLElement)) {\n\t\t\tret.push(el as HTMLElement);\n\t\t}\n\t}\n\n\treturn ret;\n};\n\n/**\n * Get the first child that matches the given selector\n * @param rootEl - The parent element\n * @param selector - The children selector\n */\nexport const childSelector = (rootEl: HTMLElement, selector: string) => {\n\treturn findChild(rootEl, el => el.matches(selector));\n}\n\n/**\n * Get all the children of the given root that match the given selector\n * @param rootEl - The parent element\n * @param selector - The children selector\n */\nexport const childSelectorAll = (rootEl: HTMLElement, selector: string) => {\n\treturn findAllChildren(rootEl, el => el.matches(selector));\n};\n","import { GdprGroupBuilder, GdprManagerBuilder } from \"gdpr-guard\";\nimport {\n\tcheckboxFromDOM,\n\tdescriptionFromDOM,\n\tguardIsRequiredInDOM,\n\tnameFromDOM,\n\tstorageFromDOM, syncRequiredInDOM\n} from \"@/domainLogic/dataExtractors\";\nimport { childSelectorAll, forEachChild } from \"@/utils/dom\";\n\nexport interface GuardParseResult {\n\tname: string;\n\tcheckbox: HTMLInputElement;\n}\n\n/**\n * Parse a guard's data and add it to the manager\n * @param guardEl - The root element of the gaurd's data\n * @param groupBuilder - The current group builder's state\n * @param parentRequired - Whether the group is required\n */\nconst addGuard = (guardEl: HTMLElement, groupBuilder: GdprGroupBuilder, parentRequired: boolean): GuardParseResult => {\n\tconst guardBuilder = groupBuilder.startGuard();\n\n\tconst name = nameFromDOM(guardEl, \"gdpr-guard\");\n\tguardBuilder.withName(name);\n\n\tconst checkbox = checkboxFromDOM(guardEl, name);\n\n\tconst isRequired = parentRequired || guardIsRequiredInDOM(guardEl, checkbox);\n\tsyncRequiredInDOM(guardEl, checkbox, isRequired);\n\n\tif (isRequired) {\n\t\tguardBuilder.required().enabled();\n\t} else if (checkbox.checked) {\n\t\tguardBuilder.enabled();\n\t} else {\n\t\tguardBuilder.disabled();\n\t}\n\n\tconst description = descriptionFromDOM(guardEl);\n\n\tif (description) {\n\t\tguardBuilder.withDescription(description);\n\t}\n\n\tconst storage = storageFromDOM(guardEl);\n\n\tif (storage !== null) {\n\t\tguardBuilder.storedIn(storage);\n\t}\n\n\tguardBuilder.endGuard();\n\n\treturn {\n\t\tname,\n\t\tcheckbox,\n\t};\n};\n\n/**\n * Get the data for a group and add it to the manager\n * @param groupEl - The root of the group's data\n * @param managerBuilder - The current manager (or group) builder's state\n * @param parentRequired - Whether the manager (or parent group) is required\n * @throws {NoNameError} - If the group's name or a guard's name cannot be parsed\n */\nconst addGroup = (groupEl: HTMLElement, managerBuilder: GdprManagerBuilder, parentRequired: boolean): GuardParseResult[] => {\n\tconst groupBuilder = managerBuilder.startGroup();\n\n\t// The name is mandatory, if it can't parse it then it'll throw\n\tconst name = nameFromDOM(groupEl, \"gdpr-group\");\n\tgroupBuilder.withName(name);\n\n\tconst checkbox = checkboxFromDOM(groupEl, name);\n\n\tconst parsedGuards = [{\n\t\tname,\n\t\tcheckbox,\n\t}];\n\n\tconst isRequired = parentRequired || guardIsRequiredInDOM(groupEl, checkbox);\n\tsyncRequiredInDOM(groupEl, checkbox, isRequired);\n\n\tif (isRequired) {\n\t\tgroupBuilder.required().enabled();\n\t} else if (checkbox.checked) {\n\t\tgroupBuilder.enabled();\n\t} else {\n\t\tgroupBuilder.disabled();\n\t}\n\n\tconst description = descriptionFromDOM(groupEl);\n\n\tif (description) {\n\t\tgroupBuilder.withDescription(description);\n\t}\n\n\tconst storage = storageFromDOM(groupEl);\n\n\tif (storage !== null) {\n\t\tgroupBuilder.storedIn(storage);\n\t}\n\n\t// Recursively parse child guards from there\n\tconst guards = addChildGuards(groupEl, groupBuilder, isRequired);\n\tgroupBuilder.endGroup();\n\n\n\tparsedGuards.push(...guards);\n\treturn parsedGuards;\n};\n\n/**\n * Recursively add the child guards of a group to the manager\n * @param rootEl - The root element for that group\n * @param groupBuilder - The current group builder's state\n * @param required - Whether the group is required\n */\nconst addChildGuards = (rootEl: HTMLElement, groupBuilder: GdprGroupBuilder, required: boolean = false): GuardParseResult[] => {\n\tconst parsedGuards = [] as GuardParseResult[];\n\n\tforEachChild(rootEl, el => {\n\t\tif (el?.matches(\"[data-gdpr-group]\")) {\n\t\t\tconst guards = addGroup(el as HTMLElement, groupBuilder, required);\n\t\t\tparsedGuards.push(...guards);\n\t\t} else if (el?.matches(\"[data-gdpr-guard]\")) {\n\t\t\tconst guard = addGuard(el as HTMLElement, groupBuilder, required);\n\t\t\tparsedGuards.push(guard);\n\t\t}\n\t});\n\n\treturn parsedGuards;\n};\n\n/**\n * Get the guards from the DOM and add them all to the manager\n * @param managerEl - The root element of the manager's definition\n * @param managerBuilder - The current manager builder's state\n */\nexport const addGuardsFromDOM = (managerEl: HTMLElement, managerBuilder: GdprManagerBuilder): GuardParseResult[] => {\n\treturn childSelectorAll(managerEl, \"[data-gdpr-group]\")\n\t\t.flatMap(el => {\n\t\t\treturn addGroup(el as HTMLElement, managerBuilder, false);\n\t\t});\n};\n","/**\n * Type for event listeners used in the {@link GlobalEventBus}\n */\ntype Listener = (e: Event) => void;\ntype EventName = string;\ntype Selector = string;\n\nexport const GlobalEventBus = {\n\t/**\n\t * Store the event managers and their listeners\n\t */\n\tevents: {} as Record>,\n\n\t/**\n\t * Add an event listener on the given selector as a live listener (i.e. is not limited to the current matching set of {@link HTMLElement})\n\t * @param event - The name of the event\n\t * @param selector - The selector to match against\n\t * @param listener - The listener to call when the event is triggered on an element that matches the given selector\n\t */\n\ton(event: EventName, selector: Selector, listener: Listener) {\n\t\tif (!(event in this.events)) { // This event had no selectors or listeners attached yet\n\t\t\tthis.events[event] = {\n\t\t\t\t[selector]: [listener],\n\t\t\t};\n\n\t\t\twindow.addEventListener(event, e => {\n\t\t\t\tObject.entries(this.events[event])\n\t\t\t\t\t.forEach(([selector, listeners]: [Selector, Listener[]]) => {\n\t\t\t\t\t\tconst target = e.target as HTMLElement|null;\n\n\t\t\t\t\t\tif (target?.matches?.(selector)) {\n\t\t\t\t\t\t\tlisteners.forEach(listener => listener(e));\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t});\n\t\t} else {\n\t\t\tconst eventManager = this.events[event];\n\n\t\t\tif (!(selector in eventManager)) { // This event didn't have the selector registered yet\n\t\t\t\teventManager[selector] = [];\n\t\t\t}\n\n\t\t\teventManager[selector].push(listener);\n\t\t}\n\n\t}\n};\n","import { GdprGuard, GdprManager, GdprManagerFactory, GdprSavior } from \"gdpr-guard\";\nimport { GdprManagerEventHub } from \"gdpr-guard/dist/GdprManagerEventHub\";\nimport { GlobalEventBus } from \"@/utils/eventBus\";\nimport { GuardParseResult } from \"@/domainLogic/guardsParsing\";\n\n/**\n * Add listeners to the change event of the manager's and guards' checkboxes\n * @param manager - The manager to handle state changes for\n * @param managerCheckbox - The global manager toggle checkbox\n * @param parsedGuards - The guards that have been parsed from the DOM\n * @param hadManager - Whether the manager came from the savior instead of the factory\n */\nexport const setupCheckboxListeners = (manager: GdprManager, managerCheckbox: HTMLInputElement, parsedGuards: GuardParseResult[], hadManager: boolean) => {\n\tconst handleInitialSync = (checkbox: HTMLInputElement, guard: GdprGuard) => {\n\t\tif (hadManager) {\n\t\t\tif ((checkbox.checked && !guard.enabled) || (!checkbox.checked && guard.enabled)) {\n\t\t\t\tcheckbox.click();\n\t\t\t}\n\t\t}\n\t};\n\n\thandleInitialSync(managerCheckbox, manager);\n\n\tmanagerCheckbox.addEventListener(\"click\", () => {\n\t\tmanager.toggle();\n\t});\n\n\tparsedGuards.forEach(({ name, checkbox }) => {\n\t\tconst guard = manager.getGuard(name)!;\n\n\t\thandleInitialSync(checkbox, guard);\n\n\t\tcheckbox.addEventListener(\"click\", () => {\n\t\t\tguard.toggle();\n\t\t});\n\t});\n};\n\n/**\n * Setup item activation in the `` tag (i.e. to execute code when the corresponding guard is enabled)\n * @param manager - The manager to attach the activation logic to\n * @param itemSelector - The selector to query all the related items (must include `[data-gdpr-on-enable]`)\n * @param setupItemHook - The function to call to set up the item before putting it in the DOM\n */\nexport const setupInHeadActivation = (\n\tmanager: GdprManager,\n\titemSelector: string,\n\tsetupItemHook: (item: ItemType) => void\n) => {\n\tdocument.querySelectorAll(itemSelector)\n\t\t.forEach(item => {\n\t\t\tconst guardName = item.dataset.gdprOnEnable!;\n\n\t\t\tif (manager.hasGuard(guardName)) {\n\t\t\t\tmanager.events.onEnable(guardName, () => {\n\t\t\t\t\t/*\n\t\t\t\t\t\tScript tags have an internal attribute checking whether\n\t\t\t\t\t\tthey have already been loaded. Cloning a script will\n\t\t\t\t\t\talways clone that flag as well (which is unwanted).\n\t\t\t\t\t */\n\n\t\t\t\t\tconst isScript = item.matches(\"script\");\n\n\t\t\t\t\tconst clonedItem = (\n\t\t\t\t\t\tisScript\n\t\t\t\t\t\t\t? document.createElement(\"script\")\n\t\t\t\t\t\t\t: item.cloneNode(true)\n\t\t\t\t\t) as ItemType;\n\n\t\t\t\t\tif (isScript) {\n\t\t\t\t\t\t// Copy attributes over\n\t\t\t\t\t\titem.getAttributeNames().forEach(attrName => {\n\t\t\t\t\t\t\tconst attrValue = item.getAttribute(attrName)!;\n\t\t\t\t\t\t\tclonedItem.setAttribute(attrName, attrValue);\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\n\t\t\t\t\tsetupItemHook(clonedItem);\n\t\t\t\t\tclonedItem.removeAttribute(\"data-gdpr-on-enable\");\n\t\t\t\t\titem.remove();\n\t\t\t\t\tdocument.head.appendChild(clonedItem);\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\titem.remove();\n\t\t\t}\n\t\t});\n};\n\n\n/**\n * Setup scripts activation logic to load them when the corresponding guard is enabled (type must initially be text and the src attribute mst be present)\n * @param manager - The manager to attach the activation logic to\n */\nexport const setupScriptActivation = (manager: GdprManager) => {\n\tsetupInHeadActivation(\n\t\tmanager,\n\t\t\"script[type='text'][src][data-gdpr-on-enable]\",\n\t\tactualScript => {\n\t\t\tactualScript.setAttribute(\"type\", \"text/javascript\");\n\t\t}\n\t);\n};\n\n/**\n * Setup stylesheets activation logic to load them when the corresponding guard is enabled (rel attribute must be different from stylesheet and the href attribute must be present)\n * @param manager - The manager to attach the activation logic to\n */\nexport const setupStyleSheetsActivation = (manager: GdprManager) => {\n\tsetupInHeadActivation(\n\t\tmanager,\n\t\t\"link[href][data-gdpr-on-enable]\",\n\t\tactualStyleSheet => {\n\t\t\tactualStyleSheet.setAttribute(\"rel\", \"stylesheet\");\n\t\t}\n\t);\n};\n\nexport type BindEventsCallback = (eventsHub: GdprManagerEventHub) => void;\n\nexport type StoreErrorHandler = (didStore: boolean, error?: Error) => void;\n\nexport interface SetupButtonListenersHooks {\n\tonDeclineAllErrorHook: StoreErrorHandler;\n\tonAllowAllErrorHook: StoreErrorHandler;\n\tonCancelErrorHook: StoreErrorHandler;\n\tonSaveErrorHook: StoreErrorHandler;\n\tonBannerClose: () => void;\n\tonBannerOpen: () => void;\n}\n\n/**\n * Bind event listeners to the general buttons\n * @param manager\n * @param gdprSavior\n * @param hooks\n * @param restoreFactory\n */\nexport const setupButtonsListeners = (\n\tmanager: GdprManager,\n\tgdprSavior: GdprSavior,\n\thooks: SetupButtonListenersHooks,\n\trestoreFactory: GdprManagerFactory\n) => {\n\tconst doClose = () => {\n\t\tmanager.closeBanner();\n\t\thooks.onBannerClose();\n\t};\n\n\tGlobalEventBus.on(\"click\", \"[data-gdpr-open]\", e => {\n\t\te.preventDefault();\n\n\t\tmanager.resetAndShowBanner();\n\t\thooks.onBannerOpen();\n\t});\n\n\tGlobalEventBus.on(\"click\", \"[data-gdpr-decline-all]\", e => {\n\t\te.preventDefault();\n\n\t\tmanager.disable();\n\n\t\tgdprSavior.store(manager.raw())\n\t\t\t.then(didStore => {\n\t\t\t\tif (!didStore) {\n\t\t\t\t\thooks.onDeclineAllErrorHook(didStore);\n\t\t\t\t} else {\n\t\t\t\t\tdoClose();\n\t\t\t\t}\n\t\t\t}).catch(e => hooks.onDeclineAllErrorHook(false, e));\n\t});\n\n\tGlobalEventBus.on(\"click\", \"[data-gdpr-allow-all]\", e => {\n\t\te.preventDefault();\n\n\t\tmanager.enable();\n\n\t\tgdprSavior.store(manager.raw())\n\t\t\t.then(didStore => {\n\t\t\t\tif (!didStore) {\n\t\t\t\t\thooks.onAllowAllErrorHook(didStore);\n\t\t\t\t} else {\n\t\t\t\t\tdoClose();\n\t\t\t\t}\n\t\t\t}).catch(e => hooks.onAllowAllErrorHook(false, e));\n\t});\n\n\tGlobalEventBus.on(\"click\", \"[data-gdpr-cancel]\", e => {\n\t\te.preventDefault();\n\n\t\t(async () => {\n\t\t\ttry {\n\t\t\t\tconst hadManager = await gdprSavior.exists(false);\n\n\t\t\t\tif (hadManager) {\n\t\t\t\t\tawait gdprSavior.restore(true);\n\t\t\t\t} else {\n\t\t\t\t\tawait gdprSavior.restoreOrCreate(restoreFactory);\n\t\t\t\t\t//TODO: Use save/restore new API (when it's out, for now the savior API has to suffice)\n\t\t\t\t}\n\t\t\t} catch(e) {\n\t\t\t\thooks.onCancelErrorHook(true, e as Error);\n\t\t\t}\n\t\t})();\n\t});\n\n\tGlobalEventBus.on(\"click\", \"[data-gdpr-save]\", e => {\n\t\te.preventDefault();\n\n\t\tgdprSavior.store(manager.raw())\n\t\t\t.then(didStore => {\n\t\t\t\tif (!didStore) {\n\t\t\t\t\thooks.onSaveErrorHook(didStore);\n\t\t\t\t} else {\n\t\t\t\t\tdoClose();\n\t\t\t\t}\n\t\t\t}).catch(e => hooks.onSaveErrorHook(e));\n\t});\n};\n","import { NoManagerDefinitionError } from \"@/errors/NoManagerDefinitionError\";\nimport { GdprManager, GdprManagerBuilder, GdprSavior } from \"gdpr-guard\";\nimport { parseManagerDetails } from \"@/domainLogic/dataExtractors\";\nimport { GdprManagerEventHub } from \"gdpr-guard/dist/GdprManagerEventHub\";\nimport { addGuardsFromDOM } from \"@/domainLogic/guardsParsing\";\nimport {\n\tBindEventsCallback,\n\tsetupButtonsListeners,\n\tsetupCheckboxListeners,\n\tsetupScriptActivation,\n\tsetupStyleSheetsActivation,\n\tStoreErrorHandler,\n} from \"@/domainLogic/listeners\";\n\nexport type AddGuardsCallback = (managerBuilder: GdprManagerBuilder) => void;\n\nexport interface GdprHtmlManagerOptions {\n\t/**\n\t * The element that serves as the root of the GDPR manager's definition in the DOM\n\t * @default document.querySelector(\"[data-gdpr]\")\n\t */\n\tgdprEl?: HTMLElement;\n\n\t/**\n\t * Whether to auto close the banner (only if it has already been displayed to the user)\n\t * @default true\n\t */\n\tautoCloseBanner?: boolean;\n\n\t/**\n\t * A callback to attach event listeners to the {@link GdprManagerEventHub} before finalizing the setup\n\t * @default () => {}\n\t */\n\tbindEventHandlersHook?: BindEventsCallback;\n\n\t/**\n\t * Add guards before the ones parsed from the DOM\n\t * @param managerBuilder\n\t * @default () => {}\n\t */\n\taddGuardsBeforeHook?: AddGuardsCallback;\n\n\t/**\n\t * Add guards after the ones parsed from the DOM\n\t * @param managerBuilder\n\t * @default () => {}\n\t */\n\taddGuardsAfterHook?: AddGuardsCallback;\n\n\t/**\n\t * Handle failure of declining all\n\t */\n\tonDeclineAllErrorHook?: StoreErrorHandler;\n\n\t/**\n\t * Handle failure of allowing all\n\t */\n\tonAllowAllErrorHook?: StoreErrorHandler;\n\n\t/**\n\t * Handle failure of saving\n\t */\n\tonSaveErrorHook?: StoreErrorHandler;\n\n\t/**\n\t * Handle failure of cancelling\n\t */\n\tonCancelErrorHook?: StoreErrorHandler;\n\n\t/**\n\t * Execute code when closing the banner\n\t */\n\tonBannerClose?: () => void;\n\n\t/**\n\t * Execute code when opening the banner\n\t */\n\tonBannerOpen?: () => void;\n}\n\n// TODO: Reset API in gdpr-guard?\n\n/**\n * Initialize the gdpr-guard logic from the DOM or the provided {@link GdprSavior}\n * @param gdprSavior - The savior to use to restore and save the {@link GdprManager} data\n * @param {GdprHtmlManagerOptions} [options] - The setup's options\n * @returns {Promise} The restored GDPR manager\n * @throws {NoManagerDefinitionError} - If no manager definition can be found\n * (either {@link gdprEl} is `undefined` or `document.querySelector(\"[data-gdpr]\")` returned `null`)\n */\nexport const restoreHtmlGdprManager = async (gdprSavior: GdprSavior, {\n\tgdprEl = undefined,\n\tautoCloseBanner = true,\n\n\tbindEventHandlersHook = () => {},\n\taddGuardsBeforeHook = () => {},\n\taddGuardsAfterHook = () => {},\n\n\tonDeclineAllErrorHook = (didStore, err) => console.error(\"[HtmlGdprGuard @ onDeclineAllErrorHook]\", {didStore, err}),\n\tonAllowAllErrorHook = (didStore, err) => console.error(\"[HtmlGdprGuard @ onAllowAllErrorHook]\", {didStore, err}),\n\tonSaveErrorHook = (didStore, err) => console.error(\"[HtmlGdprGuard @ onSaveErrorHook]\", {didStore, err}),\n\tonCancelErrorHook = (didStore, err) => console.error(\"[HtmlGdprGuard @ onCancelErrorHook]\", {didStore, err}),\n\n\tonBannerClose = () => {},\n\tonBannerOpen = () => {},\n}: GdprHtmlManagerOptions = {}): Promise => {\n\tif (typeof gdprEl === \"undefined\") {\n\t\tgdprEl = document.querySelector(\"[data-gdpr]\") ?? undefined;\n\n\t\tif (typeof gdprEl === \"undefined\") {\n\t\t\tthrow new NoManagerDefinitionError();\n\t\t}\n\t}\n\n\tconst { managerEl, managerCheckbox } = parseManagerDetails(gdprEl);\n\n\tconst managerBuilder = GdprManagerBuilder.make();\n\n\taddGuardsBeforeHook(managerBuilder);\n\tconst parsedGuards = addGuardsFromDOM(managerEl, managerBuilder);\n\taddGuardsAfterHook(managerBuilder);\n\n\tconst managerFactory = async () => managerBuilder.build();\n\tconst hadManager = await gdprSavior.exists(false);\n\tconst manager = await gdprSavior.restoreOrCreate(managerFactory);\n\n\tsetupScriptActivation(manager);\n\tsetupStyleSheetsActivation(manager);\n\tsetupCheckboxListeners(manager, managerCheckbox, parsedGuards, hadManager);\n\tsetupButtonsListeners(manager, gdprSavior, {\n\t\tonDeclineAllErrorHook,\n\t\tonAllowAllErrorHook,\n\t\tonSaveErrorHook,\n\t\tonCancelErrorHook,\n\t\tonBannerClose,\n\t\tonBannerOpen,\n\t}, managerFactory);\n\n\tbindEventHandlersHook(manager.events);\n\n\tif (autoCloseBanner && manager.bannerWasShown) {\n\t\tmanager.closeBanner();\n\t\tonBannerClose();\n\t} else { // Allows banner to be in closed state by default and open it when JS is ready\n\t\tmanager.resetAndShowBanner();\n\t\tonBannerOpen();\n\t}\n\n\treturn manager;\n};\n\nexport * from \"./errors\";\n"],"names":["root","factory","exports","module","define","amd","self","t","r","e","Object","defineProperty","value","makeGuard","n","o","i","GdprStorage","Cookie","name","description","storage","required","enabled","enable","this","toggle","disable","makeRequired","isEnabled","enableForStorage","toggleForStorage","disableForStorage","raw","JSON","parse","stringify","__values","Symbol","iterator","call","length","next","done","TypeError","__read","u","push","error","return","__spreadArray","arguments","Array","prototype","slice","concat","GdprGuardGroup","a","None","bindings","Map","for","addGuard","set","hasGuard","has","getGuard","get","s","doForEachGuard","guards","map","forEach","getGuards","values","GdprManager","d","c","bannerWasShown","events","GdprManagerEventHub","groups","create","addGroup","closeBanner","visitGdpr","onEach","resetAndShowBanner","createGroup","reduceGroupsPred","hasGroup","getGroup","forEachGroup","getGroups","eventMap","onEnable","addListener","onDisable","executeListeners","tagFor","LocalStorage","SessionStorage","IndexedDb","FileSystem","ServerStorage","All","__extends","setPrototypeOf","__proto__","hasOwnProperty","String","constructor","GdprGroupBuilder","p","parent","require","startGroup","startRequiredGroup","endGroup","withName","edit","withDescription","storedIn","disabled","startGuard","GdprGuardBuilder","startRequiredGuard","withEnabledGuard","endGuard","withDisabledGuard","GdprManagerBuilder","make","withBannerShown","startEnabledGroup","startDisabledGroup","build","__createBinding","getOwnPropertyDescriptor","__esModule","writable","configurable","enumerable","__exportStar","GdprDeserializer","manager","every","isArray","group","filter","guard","__awaiter","Promise","throw","then","apply","__generator","label","sent","trys","ops","pop","GdprSaviorAdapter","exists","restore","storeIfNotExists","store","restoreOrCreate","updateSharedManager","check","resolve","setTimeout","onManager","onGroup","onGuard","l","f","h","__webpack_module_cache__","__webpack_require__","moduleId","cachedModule","undefined","__webpack_modules__","definition","key","obj","prop","toStringTag","message","Error","NoManagerDefinitionError","defaultMessage","HtmlGdprGuardError","NoNameError","NoCheckboxError","isMeaningfulStr","str","test","nameFromDOM","guardEl","guardDataKey","nameDataKey","dataset","replace","_","letter","toUpperCase","toCamelCase","trim","rootEl","selector","nameHolder","predicate","childElementCount","el","children","item","findChild","matches","textName","textContent","checkboxFromDOM","guardName","strategies","document","getElementById","querySelector","checkbox","strategy","descriptionFromDOM","hasAttribute","gdprGuardDescription","descriptionEl","storageFromDOM","rawStorage","gdprGuardStorage","guardIsRequiredInDOM","syncRequiredInDOM","isRequired","makeCheckedDisabled","setAttribute","addGdprRequiredAttr","groupEl","managerBuilder","parentRequired","groupBuilder","parsedGuards","checked","addChildGuards","action","forEachChild","guardBuilder","GlobalEventBus","on","event","listener","eventManager","window","addEventListener","entries","listeners","target","setupInHeadActivation","itemSelector","setupItemHook","querySelectorAll","gdprOnEnable","isScript","clonedItem","createElement","cloneNode","getAttributeNames","attrName","attrValue","getAttribute","removeAttribute","remove","head","appendChild","restoreHtmlGdprManager","gdprSavior","gdprEl","autoCloseBanner","bindEventHandlersHook","addGuardsBeforeHook","addGuardsAfterHook","onDeclineAllErrorHook","didStore","err","console","onAllowAllErrorHook","onSaveErrorHook","onCancelErrorHook","onBannerClose","onBannerOpen","managerEl","gdpr","managerName","managerCheckbox","parseManagerDetails","ret","findAllChildren","flatMap","addGuardsFromDOM","managerFactory","hadManager","actualScript","setupScriptActivation","actualStyleSheet","setupStyleSheetsActivation","handleInitialSync","click","setupCheckboxListeners","hooks","restoreFactory","doClose","preventDefault","catch","setupButtonsListeners"],"sourceRoot":""} \ No newline at end of file diff --git a/example/3rd-party.css b/example/3rd-party.css new file mode 100644 index 0000000..c3ebd4c --- /dev/null +++ b/example/3rd-party.css @@ -0,0 +1,3 @@ +body { + background-color: lightcoral; +} diff --git a/example/3rd-party.js b/example/3rd-party.js new file mode 100644 index 0000000..d6e5aea --- /dev/null +++ b/example/3rd-party.js @@ -0,0 +1 @@ +alert("3rd-party script loaded"); diff --git a/example/index.html b/example/index.html new file mode 100644 index 0000000..0d44a22 --- /dev/null +++ b/example/index.html @@ -0,0 +1,179 @@ + + + + + html-gdpr-guard DEMO + + + + + + + + + + + +
+ Some random nav and stuff +
+ +
+
+ lorem ipsum +
+ + + + +
+ +
+ +
+ + diff --git a/example/index.js b/example/index.js new file mode 100644 index 0000000..7d81844 --- /dev/null +++ b/example/index.js @@ -0,0 +1,48 @@ +const { + defaults, + LocalStorageSavior, +} = gdprGuardLocal; + +const { restoreHtmlGdprManager } = htmlGdprGuard; + +MicroModal.init({ + debugMode: true, +}); + +document.querySelectorAll("[data-gdpr-open]") + .forEach(el => { + el.addEventListener("click", () => { + MicroModal.show("gdpr-modal"); + }, { passive: true }); + }); + +document.querySelectorAll("[data-gdpr-allow-all], [data-gdpr-decline-all], [data-gdpr-save], [data-gdpr-cancel]") + .forEach(el => { + el.addEventListener("click", () => { + window.gdprManager.closeBanner(); + MicroModal.close("gdpr-modal"); + }, { passive: true }) + }); + +const banner = document.querySelector("[data-gdpr-banner]"); + +(async () => { + try { + const savior = new LocalStorageSavior( + defaults.makeConfig({ + version: "v1.0.0", + }) + ); + + window.gdprManager = await restoreHtmlGdprManager(savior, { + onBannerOpen() { + banner.style.display = "block"; + }, + onBannerClose() { + banner.style.display = "none"; + }, + }); + } catch(e) { + console.error(e); + } +})(); diff --git a/example/main.css b/example/main.css new file mode 100644 index 0000000..3409acb --- /dev/null +++ b/example/main.css @@ -0,0 +1,102 @@ +* { + margin: 0; + padding: 0; + box-sizing: border-box; +} + +html { + width: 100vw; + height: 100vh; +} + +body { + overflow: hidden auto; + width: 100%; + height: 100%; +} + +button { + cursor: pointer; +} + + +.btn { + padding: 5px 10px; + background-color: lightcyan; + color: black; + border: 2px solid currentColor; + border-radius: 8px; + margin: 5px; +} + +.btn.-success { + background-color: darkgreen; + color: white; + border: 2px solid darkgreen; +} + +.btn.-failure { + background-color: darkred; + color: white; + border: 2px solid darkred; +} + +#gdpr-modal { + display: none; + position: fixed; + inset: 0; + z-index: 100; +} + +#gdpr-modal.is-open { + display: block; +} + +#gdpr-banner { + position: fixed; + bottom: 2rem; + left: 2rem; + right: 2rem; + background-color: beige; + box-shadow: 0 1px 2px rgba(0,0,0, 0.3); + padding: 1rem; + border-radius: 4px; + z-index: 10; +} + +.backdrop { + width: 100vw; + height: 100vh; + position: absolute; + inset: 0; + + background-color: rgba(0,0,0, 0.5); + backdrop-filter: blur(10px); + cursor: pointer; +} + +.backdrop > * { + cursor: auto; +} + +.modal { + width: 95vw; + height: 90vh; + overflow: auto; + background-color: white; + border-radius: 30px; + padding: 20px; + margin: 5vh 2.5vw; +} + +.gdpr-guard { + margin: 20px 5px; + padding: 5px; + border: 1px solid black; +} + +:required, +:disabled { + opacity: 0.5; + cursor: not-allowed; +} diff --git a/html-gdpr-guard.png b/html-gdpr-guard.png new file mode 100644 index 0000000..e6d7a7b Binary files /dev/null and b/html-gdpr-guard.png differ diff --git a/lib/domainLogic/dataExtractors.d.ts b/lib/domainLogic/dataExtractors.d.ts new file mode 100644 index 0000000..e56464c --- /dev/null +++ b/lib/domainLogic/dataExtractors.d.ts @@ -0,0 +1,47 @@ +import { GdprStorage } from "gdpr-guard"; +/** + * Get the guard's name from the DOM + * @param guardEl - The guard element to query + * @param guardDataKey - The key in the dataset of {@link guardEl} where the name could be + * @param nameDataKey - The name of the data attribute that can be found in child nodes to parse the name + * @throws {NoNameError} - If it can't find the guard's name + */ +export declare const nameFromDOM: (guardEl: HTMLElement, guardDataKey: string, nameDataKey?: string) => string; +/** + * Get the guard's checkbox from the DOM + * @param guardEl - The root of the guard's tree + * @param guardName - The guard's name + */ +export declare const checkboxFromDOM: (guardEl: HTMLElement, guardName: string) => HTMLInputElement; +/** + * Retrieve the guard's description from the DOM + * @param guardEl - The root of the guard's state tree + */ +export declare const descriptionFromDOM: (guardEl: HTMLElement) => string | null | undefined; +/** + * Get the {@link GdprStorage} from the DOM + * @param guardEl - The root the guard's state tree + */ +export declare const storageFromDOM: (guardEl: HTMLElement) => GdprStorage | null; +/** + * Check whether the guard is marked as required in the DOM + * @param guardEl - The root of the guard's state tree + * @param checkbox - The guard's checkbox + */ +export declare const guardIsRequiredInDOM: (guardEl: HTMLElement, checkbox: HTMLInputElement) => boolean; +/** + * Sync the required status across all attributes in the DOM + * @param guardEl - The root of the guard's state tree + * @param checkbox - The guard's checkbox + * @param isRequired - Whether the guard is already marked as required + */ +export declare const syncRequiredInDOM: (guardEl: HTMLElement, checkbox: HTMLInputElement, isRequired?: boolean) => void; +/** + * Extract the manager's own details from the DOM + * @param gdprEl - The root of the GDPR state tree + */ +export declare const parseManagerDetails: (gdprEl: HTMLElement) => { + managerEl: HTMLElement; + managerCheckbox: HTMLInputElement; + managerName: string; +}; diff --git a/lib/domainLogic/guardsParsing.d.ts b/lib/domainLogic/guardsParsing.d.ts new file mode 100644 index 0000000..0c9c8b9 --- /dev/null +++ b/lib/domainLogic/guardsParsing.d.ts @@ -0,0 +1,11 @@ +import { GdprManagerBuilder } from "gdpr-guard"; +export interface GuardParseResult { + name: string; + checkbox: HTMLInputElement; +} +/** + * Get the guards from the DOM and add them all to the manager + * @param managerEl - The root element of the manager's definition + * @param managerBuilder - The current manager builder's state + */ +export declare const addGuardsFromDOM: (managerEl: HTMLElement, managerBuilder: GdprManagerBuilder) => GuardParseResult[]; diff --git a/lib/domainLogic/listeners.d.ts b/lib/domainLogic/listeners.d.ts new file mode 100644 index 0000000..5c8647e --- /dev/null +++ b/lib/domainLogic/listeners.d.ts @@ -0,0 +1,46 @@ +import { GdprManager, GdprManagerFactory, GdprSavior } from "gdpr-guard"; +import { GdprManagerEventHub } from "gdpr-guard/dist/GdprManagerEventHub"; +import { GuardParseResult } from "@/domainLogic/guardsParsing"; +/** + * Add listeners to the change event of the manager's and guards' checkboxes + * @param manager - The manager to handle state changes for + * @param managerCheckbox - The global manager toggle checkbox + * @param parsedGuards - The guards that have been parsed from the DOM + * @param hadManager - Whether the manager came from the savior instead of the factory + */ +export declare const setupCheckboxListeners: (manager: GdprManager, managerCheckbox: HTMLInputElement, parsedGuards: GuardParseResult[], hadManager: boolean) => void; +/** + * Setup item activation in the `` tag (i.e. to execute code when the corresponding guard is enabled) + * @param manager - The manager to attach the activation logic to + * @param itemSelector - The selector to query all the related items (must include `[data-gdpr-on-enable]`) + * @param setupItemHook - The function to call to set up the item before putting it in the DOM + */ +export declare const setupInHeadActivation: (manager: GdprManager, itemSelector: string, setupItemHook: (item: ItemType) => void) => void; +/** + * Setup scripts activation logic to load them when the corresponding guard is enabled (type must initially be text and the src attribute mst be present) + * @param manager - The manager to attach the activation logic to + */ +export declare const setupScriptActivation: (manager: GdprManager) => void; +/** + * Setup stylesheets activation logic to load them when the corresponding guard is enabled (rel attribute must be different from stylesheet and the href attribute must be present) + * @param manager - The manager to attach the activation logic to + */ +export declare const setupStyleSheetsActivation: (manager: GdprManager) => void; +export declare type BindEventsCallback = (eventsHub: GdprManagerEventHub) => void; +export declare type StoreErrorHandler = (didStore: boolean, error?: Error) => void; +export interface SetupButtonListenersHooks { + onDeclineAllErrorHook: StoreErrorHandler; + onAllowAllErrorHook: StoreErrorHandler; + onCancelErrorHook: StoreErrorHandler; + onSaveErrorHook: StoreErrorHandler; + onBannerClose: () => void; + onBannerOpen: () => void; +} +/** + * Bind event listeners to the general buttons + * @param manager + * @param gdprSavior + * @param hooks + * @param restoreFactory + */ +export declare const setupButtonsListeners: (manager: GdprManager, gdprSavior: GdprSavior, hooks: SetupButtonListenersHooks, restoreFactory: GdprManagerFactory) => void; diff --git a/lib/errors/HtmlGdprGuardError.d.ts b/lib/errors/HtmlGdprGuardError.d.ts new file mode 100644 index 0000000..1fb0371 --- /dev/null +++ b/lib/errors/HtmlGdprGuardError.d.ts @@ -0,0 +1,3 @@ +export declare class HtmlGdprGuardError extends Error { + constructor(message: string); +} diff --git a/lib/errors/NoCheckboxError.d.ts b/lib/errors/NoCheckboxError.d.ts new file mode 100644 index 0000000..ae64933 --- /dev/null +++ b/lib/errors/NoCheckboxError.d.ts @@ -0,0 +1,5 @@ +import { HtmlGdprGuardError } from "@/errors/HtmlGdprGuardError"; +export declare class NoCheckboxError extends HtmlGdprGuardError { + static defaultMessage: string; + constructor(message?: string); +} diff --git a/lib/errors/NoManagerDefinitionError.d.ts b/lib/errors/NoManagerDefinitionError.d.ts new file mode 100644 index 0000000..5e82125 --- /dev/null +++ b/lib/errors/NoManagerDefinitionError.d.ts @@ -0,0 +1,10 @@ +import { HtmlGdprGuardError } from "@/errors/HtmlGdprGuardError"; +/** + * Error thrown when the library does not find + * a root {@link HTMLElement} to get the manager's + * data from + */ +export declare class NoManagerDefinitionError extends HtmlGdprGuardError { + static defaultMessage: string; + constructor(message?: string); +} diff --git a/lib/errors/NoNameError.d.ts b/lib/errors/NoNameError.d.ts new file mode 100644 index 0000000..06dea60 --- /dev/null +++ b/lib/errors/NoNameError.d.ts @@ -0,0 +1,5 @@ +import { HtmlGdprGuardError } from "@/errors/HtmlGdprGuardError"; +export declare class NoNameError extends HtmlGdprGuardError { + static defaultMessage: string; + constructor(message?: string); +} diff --git a/lib/errors/index.d.ts b/lib/errors/index.d.ts new file mode 100644 index 0000000..242ed89 --- /dev/null +++ b/lib/errors/index.d.ts @@ -0,0 +1,4 @@ +export * from "./HtmlGdprGuardError"; +export * from "./NoCheckboxError"; +export * from "./NoManagerDefinitionError"; +export * from "./NoNameError"; diff --git a/lib/index.d.ts b/lib/index.d.ts new file mode 100644 index 0000000..cfea655 --- /dev/null +++ b/lib/index.d.ts @@ -0,0 +1,66 @@ +import { GdprManager, GdprManagerBuilder, GdprSavior } from "gdpr-guard"; +import { BindEventsCallback, StoreErrorHandler } from "@/domainLogic/listeners"; +export declare type AddGuardsCallback = (managerBuilder: GdprManagerBuilder) => void; +export interface GdprHtmlManagerOptions { + /** + * The element that serves as the root of the GDPR manager's definition in the DOM + * @default document.querySelector("[data-gdpr]") + */ + gdprEl?: HTMLElement; + /** + * Whether to auto close the banner (only if it has already been displayed to the user) + * @default true + */ + autoCloseBanner?: boolean; + /** + * A callback to attach event listeners to the {@link GdprManagerEventHub} before finalizing the setup + * @default () => {} + */ + bindEventHandlersHook?: BindEventsCallback; + /** + * Add guards before the ones parsed from the DOM + * @param managerBuilder + * @default () => {} + */ + addGuardsBeforeHook?: AddGuardsCallback; + /** + * Add guards after the ones parsed from the DOM + * @param managerBuilder + * @default () => {} + */ + addGuardsAfterHook?: AddGuardsCallback; + /** + * Handle failure of declining all + */ + onDeclineAllErrorHook?: StoreErrorHandler; + /** + * Handle failure of allowing all + */ + onAllowAllErrorHook?: StoreErrorHandler; + /** + * Handle failure of saving + */ + onSaveErrorHook?: StoreErrorHandler; + /** + * Handle failure of cancelling + */ + onCancelErrorHook?: StoreErrorHandler; + /** + * Execute code when closing the banner + */ + onBannerClose?: () => void; + /** + * Execute code when opening the banner + */ + onBannerOpen?: () => void; +} +/** + * Initialize the gdpr-guard logic from the DOM or the provided {@link GdprSavior} + * @param gdprSavior - The savior to use to restore and save the {@link GdprManager} data + * @param {GdprHtmlManagerOptions} [options] - The setup's options + * @returns {Promise} The restored GDPR manager + * @throws {NoManagerDefinitionError} - If no manager definition can be found + * (either {@link gdprEl} is `undefined` or `document.querySelector("[data-gdpr]")` returned `null`) + */ +export declare const restoreHtmlGdprManager: (gdprSavior: GdprSavior, { gdprEl, autoCloseBanner, bindEventHandlersHook, addGuardsBeforeHook, addGuardsAfterHook, onDeclineAllErrorHook, onAllowAllErrorHook, onSaveErrorHook, onCancelErrorHook, onBannerClose, onBannerOpen, }?: GdprHtmlManagerOptions) => Promise; +export * from "./errors"; diff --git a/lib/utils/dom.d.ts b/lib/utils/dom.d.ts new file mode 100644 index 0000000..76d0afe --- /dev/null +++ b/lib/utils/dom.d.ts @@ -0,0 +1,25 @@ +/** + * Execute an action/callback on each child + * @param rootEl - The parent element + * @param action - The action/callback to execute on each child + */ +export declare const forEachChild: (rootEl: HTMLElement, action: (el: HTMLElement) => void) => void; +export declare const findChild: (rootEl: HTMLElement, predicate: (el: HTMLElement) => boolean) => HTMLElement | null; +/** + * Find all the children that satisfy the given predicate + * @param rootEl - The parent element + * @param predicate - The predicate to satisfy + */ +export declare const findAllChildren: (rootEl: HTMLElement, predicate: (el: HTMLElement) => boolean) => HTMLElement[]; +/** + * Get the first child that matches the given selector + * @param rootEl - The parent element + * @param selector - The children selector + */ +export declare const childSelector: (rootEl: HTMLElement, selector: string) => HTMLElement | null; +/** + * Get all the children of the given root that match the given selector + * @param rootEl - The parent element + * @param selector - The children selector + */ +export declare const childSelectorAll: (rootEl: HTMLElement, selector: string) => HTMLElement[]; diff --git a/lib/utils/eventBus.d.ts b/lib/utils/eventBus.d.ts new file mode 100644 index 0000000..2a66554 --- /dev/null +++ b/lib/utils/eventBus.d.ts @@ -0,0 +1,20 @@ +/** + * Type for event listeners used in the {@link GlobalEventBus} + */ +declare type Listener = (e: Event) => void; +declare type EventName = string; +declare type Selector = string; +export declare const GlobalEventBus: { + /** + * Store the event managers and their listeners + */ + events: Record>; + /** + * Add an event listener on the given selector as a live listener (i.e. is not limited to the current matching set of {@link HTMLElement}) + * @param event - The name of the event + * @param selector - The selector to match against + * @param listener - The listener to call when the event is triggered on an element that matches the given selector + */ + on(event: EventName, selector: Selector, listener: Listener): void; +}; +export {}; diff --git a/lib/utils/misc.d.ts b/lib/utils/misc.d.ts new file mode 100644 index 0000000..8a23f72 --- /dev/null +++ b/lib/utils/misc.d.ts @@ -0,0 +1,2 @@ +export declare const isMeaningfulStr: (str?: string | null | undefined) => str is string; +export declare const toCamelCase: (str: string) => string; diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..50e36a0 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,3417 @@ +{ + "name": "html-gdpr-guard", + "version": "0.0.1", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "html-gdpr-guard", + "version": "0.0.1", + "license": "MIT", + "dependencies": { + "gdpr-guard": "^2.2.1", + "gh-pages": "^3.2.3" + }, + "devDependencies": { + "ts-loader": "^9.2.6", + "typedoc": "^0.22.7", + "typedoc-plugin-as-member-of": "^1.0.2", + "typescript": "^4.6.0", + "webpack": "^5.60.0", + "webpack-cli": "^4.9.1" + } + }, + "node_modules/@discoveryjs/json-ext": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz", + "integrity": "sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==", + "dev": true, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/@types/eslint": { + "version": "8.4.1", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.4.1.tgz", + "integrity": "sha512-GE44+DNEyxxh2Kc6ro/VkIj+9ma0pO0bwv9+uHSyBrikYOHr8zYcdPvnBOp1aw8s+CjRvuSx7CyWqRrNFQ59mA==", + "dev": true, + "dependencies": { + "@types/estree": "*", + "@types/json-schema": "*" + } + }, + "node_modules/@types/eslint-scope": { + "version": "3.7.3", + "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.3.tgz", + "integrity": "sha512-PB3ldyrcnAicT35TWPs5IcwKD8S333HMaa2VVv4+wdvebJkjWuW/xESoB8IwRcog8HYVYamb1g/R31Qv5Bx03g==", + "dev": true, + "dependencies": { + "@types/eslint": "*", + "@types/estree": "*" + } + }, + "node_modules/@types/estree": { + "version": "0.0.51", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.51.tgz", + "integrity": "sha512-CuPgU6f3eT/XgKKPqKd/gLZV1Xmvf1a2R5POBOGQa6uv82xpls89HU5zKeVoyR8XzHd1RGNOlQlvUe3CFkjWNQ==", + "dev": true + }, + "node_modules/@types/json-schema": { + "version": "7.0.11", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz", + "integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==", + "dev": true + }, + "node_modules/@types/node": { + "version": "17.0.23", + "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.23.tgz", + "integrity": "sha512-UxDxWn7dl97rKVeVS61vErvw086aCYhDLyvRQZ5Rk65rZKepaFdm53GeqXaKBuOhED4e9uWq34IC3TdSdJJ2Gw==", + "dev": true + }, + "node_modules/@webassemblyjs/ast": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.1.tgz", + "integrity": "sha512-ukBh14qFLjxTQNTXocdyksN5QdM28S1CxHt2rdskFyL+xFV7VremuBLVbmCePj+URalXBENx/9Lm7lnhihtCSw==", + "dev": true, + "dependencies": { + "@webassemblyjs/helper-numbers": "1.11.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.1" + } + }, + "node_modules/@webassemblyjs/floating-point-hex-parser": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.1.tgz", + "integrity": "sha512-iGRfyc5Bq+NnNuX8b5hwBrRjzf0ocrJPI6GWFodBFzmFnyvrQ83SHKhmilCU/8Jv67i4GJZBMhEzltxzcNagtQ==", + "dev": true + }, + "node_modules/@webassemblyjs/helper-api-error": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.1.tgz", + "integrity": "sha512-RlhS8CBCXfRUR/cwo2ho9bkheSXG0+NwooXcc3PAILALf2QLdFyj7KGsKRbVc95hZnhnERon4kW/D3SZpp6Tcg==", + "dev": true + }, + "node_modules/@webassemblyjs/helper-buffer": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.1.tgz", + "integrity": "sha512-gwikF65aDNeeXa8JxXa2BAk+REjSyhrNC9ZwdT0f8jc4dQQeDQ7G4m0f2QCLPJiMTTO6wfDmRmj/pW0PsUvIcA==", + "dev": true + }, + "node_modules/@webassemblyjs/helper-numbers": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.1.tgz", + "integrity": "sha512-vDkbxiB8zfnPdNK9Rajcey5C0w+QJugEglN0of+kmO8l7lDb77AnlKYQF7aarZuCrv+l0UvqL+68gSDr3k9LPQ==", + "dev": true, + "dependencies": { + "@webassemblyjs/floating-point-hex-parser": "1.11.1", + "@webassemblyjs/helper-api-error": "1.11.1", + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webassemblyjs/helper-wasm-bytecode": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.1.tgz", + "integrity": "sha512-PvpoOGiJwXeTrSf/qfudJhwlvDQxFgelbMqtq52WWiXC6Xgg1IREdngmPN3bs4RoO83PnL/nFrxucXj1+BX62Q==", + "dev": true + }, + "node_modules/@webassemblyjs/helper-wasm-section": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.1.tgz", + "integrity": "sha512-10P9No29rYX1j7F3EVPX3JvGPQPae+AomuSTPiF9eBQeChHI6iqjMIwR9JmOJXwpnn/oVGDk7I5IlskuMwU/pg==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/helper-buffer": "1.11.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.1", + "@webassemblyjs/wasm-gen": "1.11.1" + } + }, + "node_modules/@webassemblyjs/ieee754": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.1.tgz", + "integrity": "sha512-hJ87QIPtAMKbFq6CGTkZYJivEwZDbQUgYd3qKSadTNOhVY7p+gfP6Sr0lLRVTaG1JjFj+r3YchoqRYxNH3M0GQ==", + "dev": true, + "dependencies": { + "@xtuc/ieee754": "^1.2.0" + } + }, + "node_modules/@webassemblyjs/leb128": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.1.tgz", + "integrity": "sha512-BJ2P0hNZ0u+Th1YZXJpzW6miwqQUGcIHT1G/sf72gLVD9DZ5AdYTqPNbHZh6K1M5VmKvFXwGSWZADz+qBWxeRw==", + "dev": true, + "dependencies": { + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webassemblyjs/utf8": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.1.tgz", + "integrity": "sha512-9kqcxAEdMhiwQkHpkNiorZzqpGrodQQ2IGrHHxCy+Ozng0ofyMA0lTqiLkVs1uzTRejX+/O0EOT7KxqVPuXosQ==", + "dev": true + }, + "node_modules/@webassemblyjs/wasm-edit": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.1.tgz", + "integrity": "sha512-g+RsupUC1aTHfR8CDgnsVRVZFJqdkFHpsHMfJuWQzWU3tvnLC07UqHICfP+4XyL2tnr1amvl1Sdp06TnYCmVkA==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/helper-buffer": "1.11.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.1", + "@webassemblyjs/helper-wasm-section": "1.11.1", + "@webassemblyjs/wasm-gen": "1.11.1", + "@webassemblyjs/wasm-opt": "1.11.1", + "@webassemblyjs/wasm-parser": "1.11.1", + "@webassemblyjs/wast-printer": "1.11.1" + } + }, + "node_modules/@webassemblyjs/wasm-gen": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.1.tgz", + "integrity": "sha512-F7QqKXwwNlMmsulj6+O7r4mmtAlCWfO/0HdgOxSklZfQcDu0TpLiD1mRt/zF25Bk59FIjEuGAIyn5ei4yMfLhA==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.1", + "@webassemblyjs/ieee754": "1.11.1", + "@webassemblyjs/leb128": "1.11.1", + "@webassemblyjs/utf8": "1.11.1" + } + }, + "node_modules/@webassemblyjs/wasm-opt": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.1.tgz", + "integrity": "sha512-VqnkNqnZlU5EB64pp1l7hdm3hmQw7Vgqa0KF/KCNO9sIpI6Fk6brDEiX+iCOYrvMuBWDws0NkTOxYEb85XQHHw==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/helper-buffer": "1.11.1", + "@webassemblyjs/wasm-gen": "1.11.1", + "@webassemblyjs/wasm-parser": "1.11.1" + } + }, + "node_modules/@webassemblyjs/wasm-parser": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.1.tgz", + "integrity": "sha512-rrBujw+dJu32gYB7/Lup6UhdkPx9S9SnobZzRVL7VcBH9Bt9bCBLEuX/YXOOtBsOZ4NQrRykKhffRWHvigQvOA==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/helper-api-error": "1.11.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.1", + "@webassemblyjs/ieee754": "1.11.1", + "@webassemblyjs/leb128": "1.11.1", + "@webassemblyjs/utf8": "1.11.1" + } + }, + "node_modules/@webassemblyjs/wast-printer": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.1.tgz", + "integrity": "sha512-IQboUWM4eKzWW+N/jij2sRatKMh99QEelo3Eb2q0qXkvPRISAj8Qxtmw5itwqK+TTkBuUIE45AxYPToqPtL5gg==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.11.1", + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webpack-cli/configtest": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@webpack-cli/configtest/-/configtest-1.1.1.tgz", + "integrity": "sha512-1FBc1f9G4P/AxMqIgfZgeOTuRnwZMten8E7zap5zgpPInnCrP8D4Q81+4CWIch8i/Nf7nXjP0v6CjjbHOrXhKg==", + "dev": true, + "peerDependencies": { + "webpack": "4.x.x || 5.x.x", + "webpack-cli": "4.x.x" + } + }, + "node_modules/@webpack-cli/info": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/@webpack-cli/info/-/info-1.4.1.tgz", + "integrity": "sha512-PKVGmazEq3oAo46Q63tpMr4HipI3OPfP7LiNOEJg963RMgT0rqheag28NCML0o3GIzA3DmxP1ZIAv9oTX1CUIA==", + "dev": true, + "dependencies": { + "envinfo": "^7.7.3" + }, + "peerDependencies": { + "webpack-cli": "4.x.x" + } + }, + "node_modules/@webpack-cli/serve": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/@webpack-cli/serve/-/serve-1.6.1.tgz", + "integrity": "sha512-gNGTiTrjEVQ0OcVnzsRSqTxaBSr+dmTfm+qJsCDluky8uhdLWep7Gcr62QsAKHTMxjCS/8nEITsmFAhfIx+QSw==", + "dev": true, + "peerDependencies": { + "webpack-cli": "4.x.x" + }, + "peerDependenciesMeta": { + "webpack-dev-server": { + "optional": true + } + } + }, + "node_modules/@xtuc/ieee754": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", + "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", + "dev": true + }, + "node_modules/@xtuc/long": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", + "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", + "dev": true + }, + "node_modules/acorn": { + "version": "8.7.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.0.tgz", + "integrity": "sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-import-assertions": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.8.0.tgz", + "integrity": "sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw==", + "dev": true, + "peerDependencies": { + "acorn": "^8" + } + }, + "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/ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "dev": true, + "peerDependencies": { + "ajv": "^6.9.1" + } + }, + "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/array-union": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", + "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", + "dependencies": { + "array-uniq": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/array-uniq": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", + "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/async": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz", + "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==", + "dependencies": { + "lodash": "^4.17.14" + } + }, + "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==" + }, + "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==", + "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.20.2", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.20.2.tgz", + "integrity": "sha512-CQOBCqp/9pDvDbx3xfMi+86pr4KXIf2FDkTTdeuYw8OxS9t898LA1Khq57gtufFILXpfgsSx5woNgsBgvGjpsA==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + } + ], + "dependencies": { + "caniuse-lite": "^1.0.30001317", + "electron-to-chromium": "^1.4.84", + "escalade": "^3.1.1", + "node-releases": "^2.0.2", + "picocolors": "^1.0.0" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "dev": true + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001320", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001320.tgz", + "integrity": "sha512-MWPzG54AGdo3nWx7zHZTefseM5Y1ccM7hlQKHRqJkPozUaw3hNbBTMmLn16GG2FUzjR13Cr3NPfhIieX5PzXDA==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + } + ] + }, + "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/chrome-trace-event": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz", + "integrity": "sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==", + "dev": true, + "engines": { + "node": ">=6.0" + } + }, + "node_modules/clone-deep": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", + "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", + "dev": true, + "dependencies": { + "is-plain-object": "^2.0.4", + "kind-of": "^6.0.2", + "shallow-clone": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "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/colorette": { + "version": "2.0.16", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.16.tgz", + "integrity": "sha512-hUewv7oMjCp+wkBv5Rm0v87eJhq4woh5rSR+42YSQJKecCqgIqNkZ6lAlQms/BwHPJA5NKMRlpxPRv0n8HQW6g==", + "dev": true + }, + "node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" + }, + "node_modules/commondir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", + "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=" + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + }, + "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/electron-to-chromium": { + "version": "1.4.96", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.96.tgz", + "integrity": "sha512-DPNjvNGPabv6FcyjzLAN4C0psN/GgD9rSGvMTuv81SeXG/EX3mCz0wiw9N1tUEnfQXYCJi3H8M0oFPRziZh7rw==", + "dev": true + }, + "node_modules/email-addresses": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/email-addresses/-/email-addresses-3.1.0.tgz", + "integrity": "sha512-k0/r7GrWVL32kZlGwfPNgB2Y/mMXVTq/decgLczm/j34whdaspNrZO8CnXPf1laaHxI6ptUlsnAxN+UAPw+fzg==" + }, + "node_modules/enhanced-resolve": { + "version": "5.9.2", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.9.2.tgz", + "integrity": "sha512-GIm3fQfwLJ8YZx2smuHpBKkXC1yOk+OBEmKckVyL0i/ea8mqDEykK3ld5dgH1QYPNyT/lIllxV2LULnxCHaHkA==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.4", + "tapable": "^2.2.0" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/envinfo": { + "version": "7.8.1", + "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.8.1.tgz", + "integrity": "sha512-/o+BXHmB7ocbHEAs6F2EnG0ogybVVUdkRunTT2glZU9XAaGmhqskrvKwqXuDfNjEO0LZKWdejEEpnq8aM0tOaw==", + "dev": true, + "bin": { + "envinfo": "dist/cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/es-module-lexer": { + "version": "0.9.3", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-0.9.3.tgz", + "integrity": "sha512-1HQ2M2sPtxwnvOvT1ZClHyQDiggdNjURWpY2we6aMKCQiUVxTmVs2UYPLIrD84sS+kMdUwfBSylbJPwNnBrnHQ==", + "dev": true + }, + "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": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "engines": { + "node": ">=0.8.0" + } + }, + "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/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/esrecurse/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/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/events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "dev": true, + "engines": { + "node": ">=0.8.x" + } + }, + "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/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-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/fastest-levenshtein": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.12.tgz", + "integrity": "sha512-On2N+BpYJ15xIC974QNVuYGMOlEVt4s0EOI3wwMqOmK1fdDY+FN/zltPV8vosq4ad4c/gJ1KHScUn/6AWIgiow==", + "dev": true + }, + "node_modules/filename-reserved-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/filename-reserved-regex/-/filename-reserved-regex-2.0.0.tgz", + "integrity": "sha1-q/c9+rc10EVECr/qLZHzieu/oik=", + "engines": { + "node": ">=4" + } + }, + "node_modules/filenamify": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/filenamify/-/filenamify-4.3.0.tgz", + "integrity": "sha512-hcFKyUG57yWGAzu1CMt/dPzYZuv+jAJUT85bL8mrXvNe6hWj6yEHEc4EdcgiA6Z3oi1/9wXJdZPXF2dZNgwgOg==", + "dependencies": { + "filename-reserved-regex": "^2.0.0", + "strip-outer": "^1.0.1", + "trim-repeated": "^1.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "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-cache-dir": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.2.tgz", + "integrity": "sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==", + "dependencies": { + "commondir": "^1.0.1", + "make-dir": "^3.0.2", + "pkg-dir": "^4.1.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/avajs/find-cache-dir?sponsor=1" + } + }, + "node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/fs-extra": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + }, + "engines": { + "node": ">=6 <7 || >=8" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" + }, + "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/gdpr-guard": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/gdpr-guard/-/gdpr-guard-2.2.2.tgz", + "integrity": "sha512-FMju5E1s+BcKHlnwnoOJOn10UaG0F6OTJ2NMWqPukuLdJEuIfcHCnfbOzEYZCCMQuuH/mmPeciCVtL25rS+3hA==" + }, + "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/gh-pages": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/gh-pages/-/gh-pages-3.2.3.tgz", + "integrity": "sha512-jA1PbapQ1jqzacECfjUaO9gV8uBgU6XNMV0oXLtfCX3haGLe5Atq8BxlrADhbD6/UdG9j6tZLWAkAybndOXTJg==", + "dependencies": { + "async": "^2.6.1", + "commander": "^2.18.0", + "email-addresses": "^3.0.1", + "filenamify": "^4.3.0", + "find-cache-dir": "^3.3.1", + "fs-extra": "^8.1.0", + "globby": "^6.1.0" + }, + "bin": { + "gh-pages": "bin/gh-pages.js", + "gh-pages-clean": "bin/gh-pages-clean.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/glob": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", + "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-to-regexp": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", + "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", + "dev": true + }, + "node_modules/globby": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz", + "integrity": "sha1-9abXDoOV4hyFj7BInWTfAkJNUGw=", + "dependencies": { + "array-union": "^1.0.1", + "glob": "^7.0.3", + "object-assign": "^4.0.1", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.9", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz", + "integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==" + }, + "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-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/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/import-local": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz", + "integrity": "sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==", + "dev": true, + "dependencies": { + "pkg-dir": "^4.2.0", + "resolve-cwd": "^3.0.0" + }, + "bin": { + "import-local-fixture": "fixtures/cli.js" + }, + "engines": { + "node": ">=8" + }, + "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": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "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==" + }, + "node_modules/interpret": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-2.2.0.tgz", + "integrity": "sha512-Ju0Bz/cEia55xDwUWEa8+olFpCiQoypjnQySseKtmjNrnps3P+xfpUmGr90T7yjlVJmOtybRvPXhKMbHr+fWnw==", + "dev": true, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/is-core-module": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.8.1.tgz", + "integrity": "sha512-SdNCUs284hr40hFTFP6l0IfZ/RSrMXF3qgoRHd3/79unUTvrFO/JoXwkGm+5J/Oe3E/b5GsnG330uUNgRpu1PA==", + "dev": true, + "dependencies": { + "has": "^1.0.3" + }, + "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-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dev": true, + "dependencies": { + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "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/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true + }, + "node_modules/isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/jest-worker": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", + "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", + "dev": true, + "dependencies": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "engines": { + "node": ">= 10.13.0" + } + }, + "node_modules/jest-worker/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "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-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/jsonc-parser": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.0.0.tgz", + "integrity": "sha512-fQzRfAbIBnR0IQvftw9FJveWiHp72Fg20giDrHz6TdfB12UH/uue0D3hm57UB5KgAVuniLMCaS8P1IMj9NR7cA==", + "dev": true + }, + "node_modules/jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "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/loader-runner": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.2.0.tgz", + "integrity": "sha512-92+huvxMvYlMzMt0iIOukcwYBFpkYJdpl2xsZ7LrlayO7E8SOv+JJUEK17B/dJIHAOLMfh2dZZ/Y18WgmGtYNw==", + "dev": true, + "engines": { + "node": ">=6.11.5" + } + }, + "node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + }, + "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/lunr": { + "version": "2.3.9", + "resolved": "https://registry.npmjs.org/lunr/-/lunr-2.3.9.tgz", + "integrity": "sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow==", + "dev": true + }, + "node_modules/make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "dependencies": { + "semver": "^6.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/marked": { + "version": "4.0.12", + "resolved": "https://registry.npmjs.org/marked/-/marked-4.0.12.tgz", + "integrity": "sha512-hgibXWrEDNBWgGiK18j/4lkS6ihTe9sxtV4Q1OQppb/0zzyPSzoFANBa5MfsG/zgsWklmNnhm0XACZOH/0HBiQ==", + "dev": true, + "bin": { + "marked": "bin/marked.js" + }, + "engines": { + "node": ">= 12" + } + }, + "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/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-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dev": true, + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "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/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "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/node-releases": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.2.tgz", + "integrity": "sha512-XxYDdcQ6eKqp/YjI+tb2C5WM2LgjnZrfYg4vgQt49EK268b6gYCHsBLrK2qvJo4FmCtqmKezb0WZFK4fkrZNsg==", + "dev": true + }, + "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/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dependencies": { + "wrappy": "1" + } + }, + "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/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "engines": { + "node": ">=6" + } + }, + "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==", + "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": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "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/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": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/pinkie": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/pinkie-promise": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", + "dependencies": { + "pinkie": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "dependencies": { + "find-up": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, + "dependencies": { + "safe-buffer": "^5.1.0" + } + }, + "node_modules/rechoir": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.7.1.tgz", + "integrity": "sha512-/njmZ8s1wVeR6pjTZ+0nCnv8SpZNRMT2D1RLOJQESlYFDBvwpTA4KWJpZ+sBJ4+vhjILRcK7JIFdGCdxEAAitg==", + "dev": true, + "dependencies": { + "resolve": "^1.9.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/resolve": { + "version": "1.22.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.0.tgz", + "integrity": "sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw==", + "dev": true, + "dependencies": { + "is-core-module": "^2.8.1", + "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-cwd": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", + "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", + "dev": true, + "dependencies": { + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "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/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "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/schema-utils": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", + "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==", + "dev": true, + "dependencies": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/serialize-javascript": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", + "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", + "dev": true, + "dependencies": { + "randombytes": "^2.1.0" + } + }, + "node_modules/shallow-clone": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", + "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", + "dev": true, + "dependencies": { + "kind-of": "^6.0.2" + }, + "engines": { + "node": ">=8" + } + }, + "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/shiki": { + "version": "0.10.1", + "resolved": "https://registry.npmjs.org/shiki/-/shiki-0.10.1.tgz", + "integrity": "sha512-VsY7QJVzU51j5o1+DguUd+6vmCmZ5v/6gYu4vyYAhzjuNQU6P/vmSy4uQaOhvje031qQMiW0d2BwgMH52vqMng==", + "dev": true, + "dependencies": { + "jsonc-parser": "^3.0.0", + "vscode-oniguruma": "^1.6.1", + "vscode-textmate": "5.2.0" + } + }, + "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/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-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "dev": true, + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "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/strip-outer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/strip-outer/-/strip-outer-1.0.1.tgz", + "integrity": "sha512-k55yxKHwaXnpYGsOzg4Vl8+tDrWylxDEpknGjhTiZB8dFRU5rTo9CAzeycivxV3s+zlTKwrs6WxMxR95n26kwg==", + "dependencies": { + "escape-string-regexp": "^1.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "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-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/tapable": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", + "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/terser": { + "version": "5.12.1", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.12.1.tgz", + "integrity": "sha512-NXbs+7nisos5E+yXwAD+y7zrcTkMqb0dEJxIGtSKPdCBzopf7ni4odPul2aechpV7EXNvOudYOX2bb5tln1jbQ==", + "dev": true, + "dependencies": { + "acorn": "^8.5.0", + "commander": "^2.20.0", + "source-map": "~0.7.2", + "source-map-support": "~0.5.20" + }, + "bin": { + "terser": "bin/terser" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/terser-webpack-plugin": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.1.tgz", + "integrity": "sha512-GvlZdT6wPQKbDNW/GDQzZFg/j4vKU96yl2q6mcUkzKOgW4gwf1Z8cZToUCrz31XHlPWH8MVb1r2tFtdDtTGJ7g==", + "dev": true, + "dependencies": { + "jest-worker": "^27.4.5", + "schema-utils": "^3.1.1", + "serialize-javascript": "^6.0.0", + "source-map": "^0.6.1", + "terser": "^5.7.2" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.1.0" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "esbuild": { + "optional": true + }, + "uglify-js": { + "optional": true + } + } + }, + "node_modules/terser/node_modules/source-map": { + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", + "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "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-repeated": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/trim-repeated/-/trim-repeated-1.0.0.tgz", + "integrity": "sha1-42RqLqTokTEr9+rObPsFOAvAHCE=", + "dependencies": { + "escape-string-regexp": "^1.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ts-loader": { + "version": "9.2.8", + "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-9.2.8.tgz", + "integrity": "sha512-gxSak7IHUuRtwKf3FIPSW1VpZcqF9+MBrHOvBp9cjHh+525SjtCIJKVGjRKIAfxBwDGDGCFF00rTfzB1quxdSw==", + "dev": true, + "dependencies": { + "chalk": "^4.1.0", + "enhanced-resolve": "^5.0.0", + "micromatch": "^4.0.0", + "semver": "^7.3.4" + }, + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "typescript": "*", + "webpack": "^5.0.0" + } + }, + "node_modules/ts-loader/node_modules/semver": { + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/typedoc": { + "version": "0.22.13", + "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.22.13.tgz", + "integrity": "sha512-NHNI7Dr6JHa/I3+c62gdRNXBIyX7P33O9TafGLd07ur3MqzcKgwTvpg18EtvCLHJyfeSthAtCLpM7WkStUmDuQ==", + "dev": true, + "dependencies": { + "glob": "^7.2.0", + "lunr": "^2.3.9", + "marked": "^4.0.12", + "minimatch": "^5.0.1", + "shiki": "^0.10.1" + }, + "bin": { + "typedoc": "bin/typedoc" + }, + "engines": { + "node": ">= 12.10.0" + }, + "peerDependencies": { + "typescript": "4.0.x || 4.1.x || 4.2.x || 4.3.x || 4.4.x || 4.5.x || 4.6.x" + } + }, + "node_modules/typedoc-plugin-as-member-of": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/typedoc-plugin-as-member-of/-/typedoc-plugin-as-member-of-1.0.2.tgz", + "integrity": "sha512-M7nC4i42HOGmbZValMq99Uh5gNJoaOYif5/p/CQR3kXOD3E1qaPu1Aj1MHdRwHE2V1yUeeEbILQVMMkkLJ4JuQ==", + "dev": true, + "peerDependencies": { + "typedoc": ">=0.7 <1.11.1" + } + }, + "node_modules/typedoc/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/typedoc/node_modules/minimatch": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.0.1.tgz", + "integrity": "sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/typescript": { + "version": "4.6.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.6.3.tgz", + "integrity": "sha512-yNIatDa5iaofVozS/uQJEl3JRWLKKGJKh6Yaiv0GLGSuhpFJe7P3SbHZ8/yjAHRQwKRoA6YZqlfjXWmVzoVSMw==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=4.2.0" + } + }, + "node_modules/universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "engines": { + "node": ">= 4.0.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/vscode-oniguruma": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/vscode-oniguruma/-/vscode-oniguruma-1.6.2.tgz", + "integrity": "sha512-KH8+KKov5eS/9WhofZR8M8dMHWN2gTxjMsG4jd04YhpbPR91fUj7rYQ2/XjeHCJWbg7X++ApRIU9NUwM2vTvLA==", + "dev": true + }, + "node_modules/vscode-textmate": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/vscode-textmate/-/vscode-textmate-5.2.0.tgz", + "integrity": "sha512-Uw5ooOQxRASHgu6C7GVvUxisKXfSgW4oFlO+aa+PAkgmH89O3CXxEEzNRNtHSqtXFTl0nAC1uYj0GMSH27uwtQ==", + "dev": true + }, + "node_modules/watchpack": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.3.1.tgz", + "integrity": "sha512-x0t0JuydIo8qCNctdDrn1OzH/qDzk2+rdCOC3YzumZ42fiMqmQ7T3xQurykYMhYfHaPHTp4ZxAx2NfUo1K6QaA==", + "dev": true, + "dependencies": { + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.1.2" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/webpack": { + "version": "5.70.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.70.0.tgz", + "integrity": "sha512-ZMWWy8CeuTTjCxbeaQI21xSswseF2oNOwc70QSKNePvmxE7XW36i7vpBMYZFAUHPwQiEbNGCEYIOOlyRbdGmxw==", + "dev": true, + "dependencies": { + "@types/eslint-scope": "^3.7.3", + "@types/estree": "^0.0.51", + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/wasm-edit": "1.11.1", + "@webassemblyjs/wasm-parser": "1.11.1", + "acorn": "^8.4.1", + "acorn-import-assertions": "^1.7.6", + "browserslist": "^4.14.5", + "chrome-trace-event": "^1.0.2", + "enhanced-resolve": "^5.9.2", + "es-module-lexer": "^0.9.0", + "eslint-scope": "5.1.1", + "events": "^3.2.0", + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.2.9", + "json-parse-better-errors": "^1.0.2", + "loader-runner": "^4.2.0", + "mime-types": "^2.1.27", + "neo-async": "^2.6.2", + "schema-utils": "^3.1.0", + "tapable": "^2.1.1", + "terser-webpack-plugin": "^5.1.3", + "watchpack": "^2.3.1", + "webpack-sources": "^3.2.3" + }, + "bin": { + "webpack": "bin/webpack.js" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependenciesMeta": { + "webpack-cli": { + "optional": true + } + } + }, + "node_modules/webpack-cli": { + "version": "4.9.2", + "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-4.9.2.tgz", + "integrity": "sha512-m3/AACnBBzK/kMTcxWHcZFPrw/eQuY4Df1TxvIWfWM2x7mRqBQCqKEd96oCUa9jkapLBaFfRce33eGDb4Pr7YQ==", + "dev": true, + "dependencies": { + "@discoveryjs/json-ext": "^0.5.0", + "@webpack-cli/configtest": "^1.1.1", + "@webpack-cli/info": "^1.4.1", + "@webpack-cli/serve": "^1.6.1", + "colorette": "^2.0.14", + "commander": "^7.0.0", + "execa": "^5.0.0", + "fastest-levenshtein": "^1.0.12", + "import-local": "^3.0.2", + "interpret": "^2.2.0", + "rechoir": "^0.7.0", + "webpack-merge": "^5.7.3" + }, + "bin": { + "webpack-cli": "bin/cli.js" + }, + "engines": { + "node": ">=10.13.0" + }, + "peerDependencies": { + "webpack": "4.x.x || 5.x.x" + }, + "peerDependenciesMeta": { + "@webpack-cli/generators": { + "optional": true + }, + "@webpack-cli/migrate": { + "optional": true + }, + "webpack-bundle-analyzer": { + "optional": true + }, + "webpack-dev-server": { + "optional": true + } + } + }, + "node_modules/webpack-cli/node_modules/commander": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", + "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", + "dev": true, + "engines": { + "node": ">= 10" + } + }, + "node_modules/webpack-merge": { + "version": "5.8.0", + "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.8.0.tgz", + "integrity": "sha512-/SaI7xY0831XwP6kzuwhKWVKDP9t1QY1h65lAFLbZqMPIuYcD9QAW4u9STIbU9kaJbPBB/geU/gLr1wDjOhQ+Q==", + "dev": true, + "dependencies": { + "clone-deep": "^4.0.1", + "wildcard": "^2.0.0" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/webpack-sources": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz", + "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==", + "dev": true, + "engines": { + "node": ">=10.13.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/wildcard": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.0.tgz", + "integrity": "sha512-JcKqAHLPxcdb9KM49dufGXn2x3ssnfjbcaQdLlfZsL9rH9wgDQjUtDxbo8NE0F6SFvydeu1VhZe7hZuHsB2/pw==", + "dev": true + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "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 + } + }, + "dependencies": { + "@discoveryjs/json-ext": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz", + "integrity": "sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==", + "dev": true + }, + "@types/eslint": { + "version": "8.4.1", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.4.1.tgz", + "integrity": "sha512-GE44+DNEyxxh2Kc6ro/VkIj+9ma0pO0bwv9+uHSyBrikYOHr8zYcdPvnBOp1aw8s+CjRvuSx7CyWqRrNFQ59mA==", + "dev": true, + "requires": { + "@types/estree": "*", + "@types/json-schema": "*" + } + }, + "@types/eslint-scope": { + "version": "3.7.3", + "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.3.tgz", + "integrity": "sha512-PB3ldyrcnAicT35TWPs5IcwKD8S333HMaa2VVv4+wdvebJkjWuW/xESoB8IwRcog8HYVYamb1g/R31Qv5Bx03g==", + "dev": true, + "requires": { + "@types/eslint": "*", + "@types/estree": "*" + } + }, + "@types/estree": { + "version": "0.0.51", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.51.tgz", + "integrity": "sha512-CuPgU6f3eT/XgKKPqKd/gLZV1Xmvf1a2R5POBOGQa6uv82xpls89HU5zKeVoyR8XzHd1RGNOlQlvUe3CFkjWNQ==", + "dev": true + }, + "@types/json-schema": { + "version": "7.0.11", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz", + "integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==", + "dev": true + }, + "@types/node": { + "version": "17.0.23", + "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.23.tgz", + "integrity": "sha512-UxDxWn7dl97rKVeVS61vErvw086aCYhDLyvRQZ5Rk65rZKepaFdm53GeqXaKBuOhED4e9uWq34IC3TdSdJJ2Gw==", + "dev": true + }, + "@webassemblyjs/ast": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.1.tgz", + "integrity": "sha512-ukBh14qFLjxTQNTXocdyksN5QdM28S1CxHt2rdskFyL+xFV7VremuBLVbmCePj+URalXBENx/9Lm7lnhihtCSw==", + "dev": true, + "requires": { + "@webassemblyjs/helper-numbers": "1.11.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.1" + } + }, + "@webassemblyjs/floating-point-hex-parser": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.1.tgz", + "integrity": "sha512-iGRfyc5Bq+NnNuX8b5hwBrRjzf0ocrJPI6GWFodBFzmFnyvrQ83SHKhmilCU/8Jv67i4GJZBMhEzltxzcNagtQ==", + "dev": true + }, + "@webassemblyjs/helper-api-error": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.1.tgz", + "integrity": "sha512-RlhS8CBCXfRUR/cwo2ho9bkheSXG0+NwooXcc3PAILALf2QLdFyj7KGsKRbVc95hZnhnERon4kW/D3SZpp6Tcg==", + "dev": true + }, + "@webassemblyjs/helper-buffer": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.1.tgz", + "integrity": "sha512-gwikF65aDNeeXa8JxXa2BAk+REjSyhrNC9ZwdT0f8jc4dQQeDQ7G4m0f2QCLPJiMTTO6wfDmRmj/pW0PsUvIcA==", + "dev": true + }, + "@webassemblyjs/helper-numbers": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.1.tgz", + "integrity": "sha512-vDkbxiB8zfnPdNK9Rajcey5C0w+QJugEglN0of+kmO8l7lDb77AnlKYQF7aarZuCrv+l0UvqL+68gSDr3k9LPQ==", + "dev": true, + "requires": { + "@webassemblyjs/floating-point-hex-parser": "1.11.1", + "@webassemblyjs/helper-api-error": "1.11.1", + "@xtuc/long": "4.2.2" + } + }, + "@webassemblyjs/helper-wasm-bytecode": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.1.tgz", + "integrity": "sha512-PvpoOGiJwXeTrSf/qfudJhwlvDQxFgelbMqtq52WWiXC6Xgg1IREdngmPN3bs4RoO83PnL/nFrxucXj1+BX62Q==", + "dev": true + }, + "@webassemblyjs/helper-wasm-section": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.1.tgz", + "integrity": "sha512-10P9No29rYX1j7F3EVPX3JvGPQPae+AomuSTPiF9eBQeChHI6iqjMIwR9JmOJXwpnn/oVGDk7I5IlskuMwU/pg==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/helper-buffer": "1.11.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.1", + "@webassemblyjs/wasm-gen": "1.11.1" + } + }, + "@webassemblyjs/ieee754": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.1.tgz", + "integrity": "sha512-hJ87QIPtAMKbFq6CGTkZYJivEwZDbQUgYd3qKSadTNOhVY7p+gfP6Sr0lLRVTaG1JjFj+r3YchoqRYxNH3M0GQ==", + "dev": true, + "requires": { + "@xtuc/ieee754": "^1.2.0" + } + }, + "@webassemblyjs/leb128": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.1.tgz", + "integrity": "sha512-BJ2P0hNZ0u+Th1YZXJpzW6miwqQUGcIHT1G/sf72gLVD9DZ5AdYTqPNbHZh6K1M5VmKvFXwGSWZADz+qBWxeRw==", + "dev": true, + "requires": { + "@xtuc/long": "4.2.2" + } + }, + "@webassemblyjs/utf8": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.1.tgz", + "integrity": "sha512-9kqcxAEdMhiwQkHpkNiorZzqpGrodQQ2IGrHHxCy+Ozng0ofyMA0lTqiLkVs1uzTRejX+/O0EOT7KxqVPuXosQ==", + "dev": true + }, + "@webassemblyjs/wasm-edit": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.1.tgz", + "integrity": "sha512-g+RsupUC1aTHfR8CDgnsVRVZFJqdkFHpsHMfJuWQzWU3tvnLC07UqHICfP+4XyL2tnr1amvl1Sdp06TnYCmVkA==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/helper-buffer": "1.11.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.1", + "@webassemblyjs/helper-wasm-section": "1.11.1", + "@webassemblyjs/wasm-gen": "1.11.1", + "@webassemblyjs/wasm-opt": "1.11.1", + "@webassemblyjs/wasm-parser": "1.11.1", + "@webassemblyjs/wast-printer": "1.11.1" + } + }, + "@webassemblyjs/wasm-gen": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.1.tgz", + "integrity": "sha512-F7QqKXwwNlMmsulj6+O7r4mmtAlCWfO/0HdgOxSklZfQcDu0TpLiD1mRt/zF25Bk59FIjEuGAIyn5ei4yMfLhA==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.1", + "@webassemblyjs/ieee754": "1.11.1", + "@webassemblyjs/leb128": "1.11.1", + "@webassemblyjs/utf8": "1.11.1" + } + }, + "@webassemblyjs/wasm-opt": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.1.tgz", + "integrity": "sha512-VqnkNqnZlU5EB64pp1l7hdm3hmQw7Vgqa0KF/KCNO9sIpI6Fk6brDEiX+iCOYrvMuBWDws0NkTOxYEb85XQHHw==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/helper-buffer": "1.11.1", + "@webassemblyjs/wasm-gen": "1.11.1", + "@webassemblyjs/wasm-parser": "1.11.1" + } + }, + "@webassemblyjs/wasm-parser": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.1.tgz", + "integrity": "sha512-rrBujw+dJu32gYB7/Lup6UhdkPx9S9SnobZzRVL7VcBH9Bt9bCBLEuX/YXOOtBsOZ4NQrRykKhffRWHvigQvOA==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/helper-api-error": "1.11.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.1", + "@webassemblyjs/ieee754": "1.11.1", + "@webassemblyjs/leb128": "1.11.1", + "@webassemblyjs/utf8": "1.11.1" + } + }, + "@webassemblyjs/wast-printer": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.1.tgz", + "integrity": "sha512-IQboUWM4eKzWW+N/jij2sRatKMh99QEelo3Eb2q0qXkvPRISAj8Qxtmw5itwqK+TTkBuUIE45AxYPToqPtL5gg==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.11.1", + "@xtuc/long": "4.2.2" + } + }, + "@webpack-cli/configtest": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@webpack-cli/configtest/-/configtest-1.1.1.tgz", + "integrity": "sha512-1FBc1f9G4P/AxMqIgfZgeOTuRnwZMten8E7zap5zgpPInnCrP8D4Q81+4CWIch8i/Nf7nXjP0v6CjjbHOrXhKg==", + "dev": true, + "requires": {} + }, + "@webpack-cli/info": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/@webpack-cli/info/-/info-1.4.1.tgz", + "integrity": "sha512-PKVGmazEq3oAo46Q63tpMr4HipI3OPfP7LiNOEJg963RMgT0rqheag28NCML0o3GIzA3DmxP1ZIAv9oTX1CUIA==", + "dev": true, + "requires": { + "envinfo": "^7.7.3" + } + }, + "@webpack-cli/serve": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/@webpack-cli/serve/-/serve-1.6.1.tgz", + "integrity": "sha512-gNGTiTrjEVQ0OcVnzsRSqTxaBSr+dmTfm+qJsCDluky8uhdLWep7Gcr62QsAKHTMxjCS/8nEITsmFAhfIx+QSw==", + "dev": true, + "requires": {} + }, + "@xtuc/ieee754": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", + "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", + "dev": true + }, + "@xtuc/long": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", + "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", + "dev": true + }, + "acorn": { + "version": "8.7.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.0.tgz", + "integrity": "sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ==", + "dev": true + }, + "acorn-import-assertions": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.8.0.tgz", + "integrity": "sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw==", + "dev": true, + "requires": {} + }, + "ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "dev": true, + "requires": {} + }, + "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, + "requires": { + "color-convert": "^2.0.1" + } + }, + "array-union": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", + "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", + "requires": { + "array-uniq": "^1.0.1" + } + }, + "array-uniq": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", + "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=" + }, + "async": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz", + "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==", + "requires": { + "lodash": "^4.17.14" + } + }, + "balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "requires": { + "fill-range": "^7.0.1" + } + }, + "browserslist": { + "version": "4.20.2", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.20.2.tgz", + "integrity": "sha512-CQOBCqp/9pDvDbx3xfMi+86pr4KXIf2FDkTTdeuYw8OxS9t898LA1Khq57gtufFILXpfgsSx5woNgsBgvGjpsA==", + "dev": true, + "requires": { + "caniuse-lite": "^1.0.30001317", + "electron-to-chromium": "^1.4.84", + "escalade": "^3.1.1", + "node-releases": "^2.0.2", + "picocolors": "^1.0.0" + } + }, + "buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "dev": true + }, + "caniuse-lite": { + "version": "1.0.30001320", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001320.tgz", + "integrity": "sha512-MWPzG54AGdo3nWx7zHZTefseM5Y1ccM7hlQKHRqJkPozUaw3hNbBTMmLn16GG2FUzjR13Cr3NPfhIieX5PzXDA==", + "dev": true + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "chrome-trace-event": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz", + "integrity": "sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==", + "dev": true + }, + "clone-deep": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", + "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", + "dev": true, + "requires": { + "is-plain-object": "^2.0.4", + "kind-of": "^6.0.2", + "shallow-clone": "^3.0.0" + } + }, + "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, + "requires": { + "color-name": "~1.1.4" + } + }, + "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 + }, + "colorette": { + "version": "2.0.16", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.16.tgz", + "integrity": "sha512-hUewv7oMjCp+wkBv5Rm0v87eJhq4woh5rSR+42YSQJKecCqgIqNkZ6lAlQms/BwHPJA5NKMRlpxPRv0n8HQW6g==", + "dev": true + }, + "commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" + }, + "commondir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", + "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=" + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + }, + "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, + "requires": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + } + }, + "electron-to-chromium": { + "version": "1.4.96", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.96.tgz", + "integrity": "sha512-DPNjvNGPabv6FcyjzLAN4C0psN/GgD9rSGvMTuv81SeXG/EX3mCz0wiw9N1tUEnfQXYCJi3H8M0oFPRziZh7rw==", + "dev": true + }, + "email-addresses": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/email-addresses/-/email-addresses-3.1.0.tgz", + "integrity": "sha512-k0/r7GrWVL32kZlGwfPNgB2Y/mMXVTq/decgLczm/j34whdaspNrZO8CnXPf1laaHxI6ptUlsnAxN+UAPw+fzg==" + }, + "enhanced-resolve": { + "version": "5.9.2", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.9.2.tgz", + "integrity": "sha512-GIm3fQfwLJ8YZx2smuHpBKkXC1yOk+OBEmKckVyL0i/ea8mqDEykK3ld5dgH1QYPNyT/lIllxV2LULnxCHaHkA==", + "dev": true, + "requires": { + "graceful-fs": "^4.2.4", + "tapable": "^2.2.0" + } + }, + "envinfo": { + "version": "7.8.1", + "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.8.1.tgz", + "integrity": "sha512-/o+BXHmB7ocbHEAs6F2EnG0ogybVVUdkRunTT2glZU9XAaGmhqskrvKwqXuDfNjEO0LZKWdejEEpnq8aM0tOaw==", + "dev": true + }, + "es-module-lexer": { + "version": "0.9.3", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-0.9.3.tgz", + "integrity": "sha512-1HQ2M2sPtxwnvOvT1ZClHyQDiggdNjURWpY2we6aMKCQiUVxTmVs2UYPLIrD84sS+kMdUwfBSylbJPwNnBrnHQ==", + "dev": true + }, + "escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "dev": true + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" + }, + "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, + "requires": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + } + }, + "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, + "requires": { + "estraverse": "^5.2.0" + }, + "dependencies": { + "estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true + } + } + }, + "estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true + }, + "events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "dev": true + }, + "execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "dev": true, + "requires": { + "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" + } + }, + "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 + }, + "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 + }, + "fastest-levenshtein": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.12.tgz", + "integrity": "sha512-On2N+BpYJ15xIC974QNVuYGMOlEVt4s0EOI3wwMqOmK1fdDY+FN/zltPV8vosq4ad4c/gJ1KHScUn/6AWIgiow==", + "dev": true + }, + "filename-reserved-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/filename-reserved-regex/-/filename-reserved-regex-2.0.0.tgz", + "integrity": "sha1-q/c9+rc10EVECr/qLZHzieu/oik=" + }, + "filenamify": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/filenamify/-/filenamify-4.3.0.tgz", + "integrity": "sha512-hcFKyUG57yWGAzu1CMt/dPzYZuv+jAJUT85bL8mrXvNe6hWj6yEHEc4EdcgiA6Z3oi1/9wXJdZPXF2dZNgwgOg==", + "requires": { + "filename-reserved-regex": "^2.0.0", + "strip-outer": "^1.0.1", + "trim-repeated": "^1.0.0" + } + }, + "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, + "requires": { + "to-regex-range": "^5.0.1" + } + }, + "find-cache-dir": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.2.tgz", + "integrity": "sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==", + "requires": { + "commondir": "^1.0.1", + "make-dir": "^3.0.2", + "pkg-dir": "^4.1.0" + } + }, + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + }, + "fs-extra": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "gdpr-guard": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/gdpr-guard/-/gdpr-guard-2.2.2.tgz", + "integrity": "sha512-FMju5E1s+BcKHlnwnoOJOn10UaG0F6OTJ2NMWqPukuLdJEuIfcHCnfbOzEYZCCMQuuH/mmPeciCVtL25rS+3hA==" + }, + "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 + }, + "gh-pages": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/gh-pages/-/gh-pages-3.2.3.tgz", + "integrity": "sha512-jA1PbapQ1jqzacECfjUaO9gV8uBgU6XNMV0oXLtfCX3haGLe5Atq8BxlrADhbD6/UdG9j6tZLWAkAybndOXTJg==", + "requires": { + "async": "^2.6.1", + "commander": "^2.18.0", + "email-addresses": "^3.0.1", + "filenamify": "^4.3.0", + "find-cache-dir": "^3.3.1", + "fs-extra": "^8.1.0", + "globby": "^6.1.0" + } + }, + "glob": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", + "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "glob-to-regexp": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", + "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", + "dev": true + }, + "globby": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz", + "integrity": "sha1-9abXDoOV4hyFj7BInWTfAkJNUGw=", + "requires": { + "array-union": "^1.0.1", + "glob": "^7.0.3", + "object-assign": "^4.0.1", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" + } + }, + "graceful-fs": { + "version": "4.2.9", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz", + "integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==" + }, + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "requires": { + "function-bind": "^1.1.1" + } + }, + "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 + }, + "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 + }, + "import-local": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz", + "integrity": "sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==", + "dev": true, + "requires": { + "pkg-dir": "^4.2.0", + "resolve-cwd": "^3.0.0" + } + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "interpret": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-2.2.0.tgz", + "integrity": "sha512-Ju0Bz/cEia55xDwUWEa8+olFpCiQoypjnQySseKtmjNrnps3P+xfpUmGr90T7yjlVJmOtybRvPXhKMbHr+fWnw==", + "dev": true + }, + "is-core-module": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.8.1.tgz", + "integrity": "sha512-SdNCUs284hr40hFTFP6l0IfZ/RSrMXF3qgoRHd3/79unUTvrFO/JoXwkGm+5J/Oe3E/b5GsnG330uUNgRpu1PA==", + "dev": true, + "requires": { + "has": "^1.0.3" + } + }, + "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 + }, + "is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dev": true, + "requires": { + "isobject": "^3.0.1" + } + }, + "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 + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + }, + "jest-worker": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", + "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", + "dev": true, + "requires": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "dependencies": { + "supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "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 + }, + "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 + }, + "jsonc-parser": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.0.0.tgz", + "integrity": "sha512-fQzRfAbIBnR0IQvftw9FJveWiHp72Fg20giDrHz6TdfB12UH/uue0D3hm57UB5KgAVuniLMCaS8P1IMj9NR7cA==", + "dev": true + }, + "jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", + "requires": { + "graceful-fs": "^4.1.6" + } + }, + "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 + }, + "loader-runner": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.2.0.tgz", + "integrity": "sha512-92+huvxMvYlMzMt0iIOukcwYBFpkYJdpl2xsZ7LrlayO7E8SOv+JJUEK17B/dJIHAOLMfh2dZZ/Y18WgmGtYNw==", + "dev": true + }, + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "requires": { + "p-locate": "^4.1.0" + } + }, + "lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + }, + "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, + "requires": { + "yallist": "^4.0.0" + } + }, + "lunr": { + "version": "2.3.9", + "resolved": "https://registry.npmjs.org/lunr/-/lunr-2.3.9.tgz", + "integrity": "sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow==", + "dev": true + }, + "make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "requires": { + "semver": "^6.0.0" + } + }, + "marked": { + "version": "4.0.12", + "resolved": "https://registry.npmjs.org/marked/-/marked-4.0.12.tgz", + "integrity": "sha512-hgibXWrEDNBWgGiK18j/4lkS6ihTe9sxtV4Q1OQppb/0zzyPSzoFANBa5MfsG/zgsWklmNnhm0XACZOH/0HBiQ==", + "dev": true + }, + "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 + }, + "micromatch": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", + "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "dev": true, + "requires": { + "braces": "^3.0.2", + "picomatch": "^2.3.1" + } + }, + "mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "dev": true + }, + "mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dev": true, + "requires": { + "mime-db": "1.52.0" + } + }, + "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 + }, + "minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "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-releases": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.2.tgz", + "integrity": "sha512-XxYDdcQ6eKqp/YjI+tb2C5WM2LgjnZrfYg4vgQt49EK268b6gYCHsBLrK2qvJo4FmCtqmKezb0WZFK4fkrZNsg==", + "dev": true + }, + "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, + "requires": { + "path-key": "^3.0.0" + } + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "requires": { + "wrappy": "1" + } + }, + "onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dev": true, + "requires": { + "mimic-fn": "^2.1.0" + } + }, + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "requires": { + "p-limit": "^2.2.0" + } + }, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==" + }, + "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==" + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" + }, + "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 + }, + "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 + }, + "picocolors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", + "dev": true + }, + "picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" + }, + "pinkie": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=" + }, + "pinkie-promise": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", + "requires": { + "pinkie": "^2.0.0" + } + }, + "pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "requires": { + "find-up": "^4.0.0" + } + }, + "punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "dev": true + }, + "randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, + "requires": { + "safe-buffer": "^5.1.0" + } + }, + "rechoir": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.7.1.tgz", + "integrity": "sha512-/njmZ8s1wVeR6pjTZ+0nCnv8SpZNRMT2D1RLOJQESlYFDBvwpTA4KWJpZ+sBJ4+vhjILRcK7JIFdGCdxEAAitg==", + "dev": true, + "requires": { + "resolve": "^1.9.0" + } + }, + "resolve": { + "version": "1.22.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.0.tgz", + "integrity": "sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw==", + "dev": true, + "requires": { + "is-core-module": "^2.8.1", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + } + }, + "resolve-cwd": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", + "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", + "dev": true, + "requires": { + "resolve-from": "^5.0.0" + } + }, + "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 + }, + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true + }, + "schema-utils": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", + "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==", + "dev": true, + "requires": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + } + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" + }, + "serialize-javascript": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", + "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", + "dev": true, + "requires": { + "randombytes": "^2.1.0" + } + }, + "shallow-clone": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", + "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", + "dev": true, + "requires": { + "kind-of": "^6.0.2" + } + }, + "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, + "requires": { + "shebang-regex": "^3.0.0" + } + }, + "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 + }, + "shiki": { + "version": "0.10.1", + "resolved": "https://registry.npmjs.org/shiki/-/shiki-0.10.1.tgz", + "integrity": "sha512-VsY7QJVzU51j5o1+DguUd+6vmCmZ5v/6gYu4vyYAhzjuNQU6P/vmSy4uQaOhvje031qQMiW0d2BwgMH52vqMng==", + "dev": true, + "requires": { + "jsonc-parser": "^3.0.0", + "vscode-oniguruma": "^1.6.1", + "vscode-textmate": "5.2.0" + } + }, + "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 + }, + "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 + }, + "source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "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 + }, + "strip-outer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/strip-outer/-/strip-outer-1.0.1.tgz", + "integrity": "sha512-k55yxKHwaXnpYGsOzg4Vl8+tDrWylxDEpknGjhTiZB8dFRU5rTo9CAzeycivxV3s+zlTKwrs6WxMxR95n26kwg==", + "requires": { + "escape-string-regexp": "^1.0.2" + } + }, + "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, + "requires": { + "has-flag": "^4.0.0" + } + }, + "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 + }, + "tapable": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", + "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", + "dev": true + }, + "terser": { + "version": "5.12.1", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.12.1.tgz", + "integrity": "sha512-NXbs+7nisos5E+yXwAD+y7zrcTkMqb0dEJxIGtSKPdCBzopf7ni4odPul2aechpV7EXNvOudYOX2bb5tln1jbQ==", + "dev": true, + "requires": { + "acorn": "^8.5.0", + "commander": "^2.20.0", + "source-map": "~0.7.2", + "source-map-support": "~0.5.20" + }, + "dependencies": { + "source-map": { + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", + "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", + "dev": true + } + } + }, + "terser-webpack-plugin": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.1.tgz", + "integrity": "sha512-GvlZdT6wPQKbDNW/GDQzZFg/j4vKU96yl2q6mcUkzKOgW4gwf1Z8cZToUCrz31XHlPWH8MVb1r2tFtdDtTGJ7g==", + "dev": true, + "requires": { + "jest-worker": "^27.4.5", + "schema-utils": "^3.1.1", + "serialize-javascript": "^6.0.0", + "source-map": "^0.6.1", + "terser": "^5.7.2" + } + }, + "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, + "requires": { + "is-number": "^7.0.0" + } + }, + "trim-repeated": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/trim-repeated/-/trim-repeated-1.0.0.tgz", + "integrity": "sha1-42RqLqTokTEr9+rObPsFOAvAHCE=", + "requires": { + "escape-string-regexp": "^1.0.2" + } + }, + "ts-loader": { + "version": "9.2.8", + "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-9.2.8.tgz", + "integrity": "sha512-gxSak7IHUuRtwKf3FIPSW1VpZcqF9+MBrHOvBp9cjHh+525SjtCIJKVGjRKIAfxBwDGDGCFF00rTfzB1quxdSw==", + "dev": true, + "requires": { + "chalk": "^4.1.0", + "enhanced-resolve": "^5.0.0", + "micromatch": "^4.0.0", + "semver": "^7.3.4" + }, + "dependencies": { + "semver": { + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + } + } + }, + "typedoc": { + "version": "0.22.13", + "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.22.13.tgz", + "integrity": "sha512-NHNI7Dr6JHa/I3+c62gdRNXBIyX7P33O9TafGLd07ur3MqzcKgwTvpg18EtvCLHJyfeSthAtCLpM7WkStUmDuQ==", + "dev": true, + "requires": { + "glob": "^7.2.0", + "lunr": "^2.3.9", + "marked": "^4.0.12", + "minimatch": "^5.0.1", + "shiki": "^0.10.1" + }, + "dependencies": { + "brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0" + } + }, + "minimatch": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.0.1.tgz", + "integrity": "sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g==", + "dev": true, + "requires": { + "brace-expansion": "^2.0.1" + } + } + } + }, + "typedoc-plugin-as-member-of": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/typedoc-plugin-as-member-of/-/typedoc-plugin-as-member-of-1.0.2.tgz", + "integrity": "sha512-M7nC4i42HOGmbZValMq99Uh5gNJoaOYif5/p/CQR3kXOD3E1qaPu1Aj1MHdRwHE2V1yUeeEbILQVMMkkLJ4JuQ==", + "dev": true, + "requires": {} + }, + "typescript": { + "version": "4.6.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.6.3.tgz", + "integrity": "sha512-yNIatDa5iaofVozS/uQJEl3JRWLKKGJKh6Yaiv0GLGSuhpFJe7P3SbHZ8/yjAHRQwKRoA6YZqlfjXWmVzoVSMw==", + "dev": true + }, + "universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==" + }, + "uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "requires": { + "punycode": "^2.1.0" + } + }, + "vscode-oniguruma": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/vscode-oniguruma/-/vscode-oniguruma-1.6.2.tgz", + "integrity": "sha512-KH8+KKov5eS/9WhofZR8M8dMHWN2gTxjMsG4jd04YhpbPR91fUj7rYQ2/XjeHCJWbg7X++ApRIU9NUwM2vTvLA==", + "dev": true + }, + "vscode-textmate": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/vscode-textmate/-/vscode-textmate-5.2.0.tgz", + "integrity": "sha512-Uw5ooOQxRASHgu6C7GVvUxisKXfSgW4oFlO+aa+PAkgmH89O3CXxEEzNRNtHSqtXFTl0nAC1uYj0GMSH27uwtQ==", + "dev": true + }, + "watchpack": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.3.1.tgz", + "integrity": "sha512-x0t0JuydIo8qCNctdDrn1OzH/qDzk2+rdCOC3YzumZ42fiMqmQ7T3xQurykYMhYfHaPHTp4ZxAx2NfUo1K6QaA==", + "dev": true, + "requires": { + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.1.2" + } + }, + "webpack": { + "version": "5.70.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.70.0.tgz", + "integrity": "sha512-ZMWWy8CeuTTjCxbeaQI21xSswseF2oNOwc70QSKNePvmxE7XW36i7vpBMYZFAUHPwQiEbNGCEYIOOlyRbdGmxw==", + "dev": true, + "requires": { + "@types/eslint-scope": "^3.7.3", + "@types/estree": "^0.0.51", + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/wasm-edit": "1.11.1", + "@webassemblyjs/wasm-parser": "1.11.1", + "acorn": "^8.4.1", + "acorn-import-assertions": "^1.7.6", + "browserslist": "^4.14.5", + "chrome-trace-event": "^1.0.2", + "enhanced-resolve": "^5.9.2", + "es-module-lexer": "^0.9.0", + "eslint-scope": "5.1.1", + "events": "^3.2.0", + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.2.9", + "json-parse-better-errors": "^1.0.2", + "loader-runner": "^4.2.0", + "mime-types": "^2.1.27", + "neo-async": "^2.6.2", + "schema-utils": "^3.1.0", + "tapable": "^2.1.1", + "terser-webpack-plugin": "^5.1.3", + "watchpack": "^2.3.1", + "webpack-sources": "^3.2.3" + } + }, + "webpack-cli": { + "version": "4.9.2", + "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-4.9.2.tgz", + "integrity": "sha512-m3/AACnBBzK/kMTcxWHcZFPrw/eQuY4Df1TxvIWfWM2x7mRqBQCqKEd96oCUa9jkapLBaFfRce33eGDb4Pr7YQ==", + "dev": true, + "requires": { + "@discoveryjs/json-ext": "^0.5.0", + "@webpack-cli/configtest": "^1.1.1", + "@webpack-cli/info": "^1.4.1", + "@webpack-cli/serve": "^1.6.1", + "colorette": "^2.0.14", + "commander": "^7.0.0", + "execa": "^5.0.0", + "fastest-levenshtein": "^1.0.12", + "import-local": "^3.0.2", + "interpret": "^2.2.0", + "rechoir": "^0.7.0", + "webpack-merge": "^5.7.3" + }, + "dependencies": { + "commander": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", + "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", + "dev": true + } + } + }, + "webpack-merge": { + "version": "5.8.0", + "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.8.0.tgz", + "integrity": "sha512-/SaI7xY0831XwP6kzuwhKWVKDP9t1QY1h65lAFLbZqMPIuYcD9QAW4u9STIbU9kaJbPBB/geU/gLr1wDjOhQ+Q==", + "dev": true, + "requires": { + "clone-deep": "^4.0.1", + "wildcard": "^2.0.0" + } + }, + "webpack-sources": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz", + "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==", + "dev": true + }, + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + }, + "wildcard": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.0.tgz", + "integrity": "sha512-JcKqAHLPxcdb9KM49dufGXn2x3ssnfjbcaQdLlfZsL9rH9wgDQjUtDxbo8NE0F6SFvydeu1VhZe7hZuHsB2/pw==", + "dev": true + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + } + } +} diff --git a/package.json b/package.json index a2c4673..9df62e2 100644 --- a/package.json +++ b/package.json @@ -1,19 +1,39 @@ { - "name": "html-gdpr-guard", - "version": "0.0.1", - "description": "Vanilla JavaScript binding to gdpr-guard as efficiently and easily as possible, based on data provided in the DOM", - "main": "index.js", - "scripts": { - "test": "echo \"Error: no test specified\" && exit 1" - }, - "repository": { - "type": "git", - "url": "git+https://github.com/Voltra/html-gdpr-guard.git" - }, - "author": "Voltra ", - "license": "MIT", - "bugs": { - "url": "https://github.com/Voltra/html-gdpr-guard/issues" - }, - "homepage": "https://github.com/Voltra/html-gdpr-guard#readme" + "name": "html-gdpr-guard", + "version": "1.0.0", + "description": "Vanilla JavaScript binding to use gdpr-guard as efficiently and easily as possible, based on data provided in the DOM", + "main": "dist/index.js", + "types": "lib/index.d.ts", + "scripts": { + "dev": "webpack --mode development", + "build": "webpack --mode production", + "watch": "webpack --mode development --watch", + "clean": "rm -rf dist", + "predocs": "([[ -d ./docs ]] && rm -rf ./docs) || true", + "docs": " typedoc --options typedoc.config.js", + "predeploy:docs": "npm run docs", + "deploy:docs": "gh-pages -d docs" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/Voltra/html-gdpr-guard.git" + }, + "author": "Voltra ", + "license": "MIT", + "bugs": { + "url": "https://github.com/Voltra/html-gdpr-guard/issues" + }, + "homepage": "https://voltra.github.io/html-gdpr-guard/", + "devDependencies": { + "ts-loader": "^9.2.6", + "typedoc": "^0.22.7", + "typedoc-plugin-as-member-of": "^1.0.2", + "typescript": "^4.6.0", + "webpack": "^5.60.0", + "webpack-cli": "^4.9.1" + }, + "dependencies": { + "gdpr-guard": "^2.2.1", + "gh-pages": "^3.2.3" + } } diff --git a/src/domainLogic/dataExtractors.ts b/src/domainLogic/dataExtractors.ts new file mode 100644 index 0000000..15a6649 --- /dev/null +++ b/src/domainLogic/dataExtractors.ts @@ -0,0 +1,163 @@ +import { childSelector } from "@/utils/dom"; +import { NoNameError } from "@/errors/NoNameError"; +import { NoCheckboxError } from "@/errors/NoCheckboxError"; +import { GdprStorage } from "gdpr-guard"; +import { isMeaningfulStr, toCamelCase } from "@/utils/misc"; +import { NoManagerDefinitionError } from "@/errors/NoManagerDefinitionError"; + +/** + * Get the guard's name from the DOM + * @param guardEl - The guard element to query + * @param guardDataKey - The key in the dataset of {@link guardEl} where the name could be + * @param nameDataKey - The name of the data attribute that can be found in child nodes to parse the name + * @throws {NoNameError} - If it can't find the guard's name + */ +export const nameFromDOM = (guardEl: HTMLElement, guardDataKey: string, nameDataKey: string = "gdpr-guard-name"): string => { + const str = guardEl.dataset[toCamelCase(guardDataKey)]; + + if (isMeaningfulStr(str)) { + return str.trim(); + } + + // const nameHolder: HTMLElement|null = guardEl.querySelector(`[data-${nameDataKey}]`); + const nameHolder: HTMLElement|null = childSelector(guardEl, `[data-${nameDataKey}]`); + + const name = nameHolder?.dataset[nameDataKey]; + if (!isMeaningfulStr(name)) { + const textName = nameHolder?.textContent; + + if (isMeaningfulStr(textName)) { + return textName.trim(); + } + + throw new NoNameError(); + } + + return name.trim(); +}; + +/** + * Get the guard's checkbox from the DOM + * @param guardEl - The root of the guard's tree + * @param guardName - The guard's name + */ +export const checkboxFromDOM = (guardEl: HTMLElement, guardName: string) => { + const strategies = [ + () => document.getElementById(guardName), // by ID + () => guardEl.querySelector(`[type="checkbox"][name="${guardName}"]`), // by name + () => guardEl.querySelector(`[type="checkbox"][data-gdpr-checkbox]`), // by specific attribute + ]; + + for (const strategy of strategies) { + const checkbox = strategy(); + + if (checkbox?.matches?.("input[type='checkbox']")) { + return checkbox as HTMLInputElement; + } + } + + throw new NoCheckboxError(); +}; + +/** + * Retrieve the guard's description from the DOM + * @param guardEl - The root of the guard's state tree + */ +export const descriptionFromDOM = (guardEl: HTMLElement) => { + if (guardEl.hasAttribute("data-gdpr-guard-description")) { + return guardEl.dataset.gdprGuardDescription; + } + + const descriptionEl = guardEl.querySelector("[data-gdpr-guard-description]"); + + return descriptionEl?.textContent ?? null; +}; + +/** + * Get the {@link GdprStorage} from the DOM + * @param guardEl - The root the guard's state tree + */ +export const storageFromDOM = (guardEl: HTMLElement): GdprStorage|null => { + if (guardEl.hasAttribute("data-gdpr-guard-storage")) { + const rawStorage = guardEl.dataset.gdprGuardStorage; + + if (rawStorage && rawStorage in GdprStorage) { + return GdprStorage[rawStorage]; + } + } + + return null; +}; + +/** + * Check whether the guard is marked as required in the DOM + * @param guardEl - The root of the guard's state tree + * @param checkbox - The guard's checkbox + */ +export const guardIsRequiredInDOM = (guardEl: HTMLElement, checkbox: HTMLInputElement) => { + return checkbox.required || guardEl.hasAttribute("data-gdpr-guard-required"); +}; + +/** + * Sync the required status across all attributes in the DOM + * @param guardEl - The root of the guard's state tree + * @param checkbox - The guard's checkbox + * @param isRequired - Whether the guard is already marked as required + */ +export const syncRequiredInDOM = (guardEl: HTMLElement, checkbox: HTMLInputElement, isRequired: boolean = false) => { + const makeCheckedDisabled = () => { + checkbox.setAttribute("checked", "checked"); + checkbox.setAttribute("disabled", "disabled"); + }; + + const makeRequired = () => { + checkbox.setAttribute("required", "required"); + }; + + const addGdprRequiredAttr = () => { + guardEl.setAttribute("data-gdpr-guard-required", ""); + }; + + if(isRequired) { + addGdprRequiredAttr(); + makeCheckedDisabled(); + makeRequired(); + } else if (checkbox.required) { + addGdprRequiredAttr(); + makeCheckedDisabled(); + } else if (guardEl.hasAttribute("data-gdpr-guard-required")) { + makeCheckedDisabled(); + makeRequired(); + } +} + +/** + * Extract the manager's own details from the DOM + * @param gdprEl - The root of the GDPR state tree + */ +export const parseManagerDetails = (gdprEl: HTMLElement) => { + let managerEl = gdprEl; + const { gdpr } = gdprEl.dataset; + let managerName: string = ""; + + if (isMeaningfulStr(gdpr)) { + managerName = gdpr; + } else { + const el = gdprEl.querySelector("[data-gdpr-manager]"); + + if (!el) { + throw new NoManagerDefinitionError(); + } + + managerEl = el as HTMLElement; + managerName = nameFromDOM(managerEl, "gdpr-manager"); + } + + const managerCheckbox = checkboxFromDOM(managerEl, managerName); + + return { + managerEl, + managerCheckbox, + managerName, + }; +}; diff --git a/src/domainLogic/guardsParsing.ts b/src/domainLogic/guardsParsing.ts new file mode 100644 index 0000000..8784f25 --- /dev/null +++ b/src/domainLogic/guardsParsing.ts @@ -0,0 +1,146 @@ +import { GdprGroupBuilder, GdprManagerBuilder } from "gdpr-guard"; +import { + checkboxFromDOM, + descriptionFromDOM, + guardIsRequiredInDOM, + nameFromDOM, + storageFromDOM, syncRequiredInDOM +} from "@/domainLogic/dataExtractors"; +import { childSelectorAll, forEachChild } from "@/utils/dom"; + +export interface GuardParseResult { + name: string; + checkbox: HTMLInputElement; +} + +/** + * Parse a guard's data and add it to the manager + * @param guardEl - The root element of the gaurd's data + * @param groupBuilder - The current group builder's state + * @param parentRequired - Whether the group is required + */ +const addGuard = (guardEl: HTMLElement, groupBuilder: GdprGroupBuilder, parentRequired: boolean): GuardParseResult => { + const guardBuilder = groupBuilder.startGuard(); + + const name = nameFromDOM(guardEl, "gdpr-guard"); + guardBuilder.withName(name); + + const checkbox = checkboxFromDOM(guardEl, name); + + const isRequired = parentRequired || guardIsRequiredInDOM(guardEl, checkbox); + syncRequiredInDOM(guardEl, checkbox, isRequired); + + if (isRequired) { + guardBuilder.required().enabled(); + } else if (checkbox.checked) { + guardBuilder.enabled(); + } else { + guardBuilder.disabled(); + } + + const description = descriptionFromDOM(guardEl); + + if (description) { + guardBuilder.withDescription(description); + } + + const storage = storageFromDOM(guardEl); + + if (storage !== null) { + guardBuilder.storedIn(storage); + } + + guardBuilder.endGuard(); + + return { + name, + checkbox, + }; +}; + +/** + * Get the data for a group and add it to the manager + * @param groupEl - The root of the group's data + * @param managerBuilder - The current manager (or group) builder's state + * @param parentRequired - Whether the manager (or parent group) is required + * @throws {NoNameError} - If the group's name or a guard's name cannot be parsed + */ +const addGroup = (groupEl: HTMLElement, managerBuilder: GdprManagerBuilder, parentRequired: boolean): GuardParseResult[] => { + const groupBuilder = managerBuilder.startGroup(); + + // The name is mandatory, if it can't parse it then it'll throw + const name = nameFromDOM(groupEl, "gdpr-group"); + groupBuilder.withName(name); + + const checkbox = checkboxFromDOM(groupEl, name); + + const parsedGuards = [{ + name, + checkbox, + }]; + + const isRequired = parentRequired || guardIsRequiredInDOM(groupEl, checkbox); + syncRequiredInDOM(groupEl, checkbox, isRequired); + + if (isRequired) { + groupBuilder.required().enabled(); + } else if (checkbox.checked) { + groupBuilder.enabled(); + } else { + groupBuilder.disabled(); + } + + const description = descriptionFromDOM(groupEl); + + if (description) { + groupBuilder.withDescription(description); + } + + const storage = storageFromDOM(groupEl); + + if (storage !== null) { + groupBuilder.storedIn(storage); + } + + // Recursively parse child guards from there + const guards = addChildGuards(groupEl, groupBuilder, isRequired); + groupBuilder.endGroup(); + + + parsedGuards.push(...guards); + return parsedGuards; +}; + +/** + * Recursively add the child guards of a group to the manager + * @param rootEl - The root element for that group + * @param groupBuilder - The current group builder's state + * @param required - Whether the group is required + */ +const addChildGuards = (rootEl: HTMLElement, groupBuilder: GdprGroupBuilder, required: boolean = false): GuardParseResult[] => { + const parsedGuards = [] as GuardParseResult[]; + + forEachChild(rootEl, el => { + if (el?.matches("[data-gdpr-group]")) { + const guards = addGroup(el as HTMLElement, groupBuilder, required); + parsedGuards.push(...guards); + } else if (el?.matches("[data-gdpr-guard]")) { + const guard = addGuard(el as HTMLElement, groupBuilder, required); + parsedGuards.push(guard); + } + }); + + return parsedGuards; +}; + +/** + * Get the guards from the DOM and add them all to the manager + * @param managerEl - The root element of the manager's definition + * @param managerBuilder - The current manager builder's state + */ +export const addGuardsFromDOM = (managerEl: HTMLElement, managerBuilder: GdprManagerBuilder): GuardParseResult[] => { + return childSelectorAll(managerEl, "[data-gdpr-group]") + .flatMap(el => { + return addGroup(el as HTMLElement, managerBuilder, false); + }); +}; diff --git a/src/domainLogic/listeners.ts b/src/domainLogic/listeners.ts new file mode 100644 index 0000000..388cabf --- /dev/null +++ b/src/domainLogic/listeners.ts @@ -0,0 +1,217 @@ +import { GdprGuard, GdprManager, GdprManagerFactory, GdprSavior } from "gdpr-guard"; +import { GdprManagerEventHub } from "gdpr-guard/dist/GdprManagerEventHub"; +import { GlobalEventBus } from "@/utils/eventBus"; +import { GuardParseResult } from "@/domainLogic/guardsParsing"; + +/** + * Add listeners to the change event of the manager's and guards' checkboxes + * @param manager - The manager to handle state changes for + * @param managerCheckbox - The global manager toggle checkbox + * @param parsedGuards - The guards that have been parsed from the DOM + * @param hadManager - Whether the manager came from the savior instead of the factory + */ +export const setupCheckboxListeners = (manager: GdprManager, managerCheckbox: HTMLInputElement, parsedGuards: GuardParseResult[], hadManager: boolean) => { + const handleInitialSync = (checkbox: HTMLInputElement, guard: GdprGuard) => { + if (hadManager) { + if ((checkbox.checked && !guard.enabled) || (!checkbox.checked && guard.enabled)) { + checkbox.click(); + } + } + }; + + handleInitialSync(managerCheckbox, manager); + + managerCheckbox.addEventListener("click", () => { + manager.toggle(); + }); + + parsedGuards.forEach(({ name, checkbox }) => { + const guard = manager.getGuard(name)!; + + handleInitialSync(checkbox, guard); + + checkbox.addEventListener("click", () => { + guard.toggle(); + }); + }); +}; + +/** + * Setup item activation in the `` tag (i.e. to execute code when the corresponding guard is enabled) + * @param manager - The manager to attach the activation logic to + * @param itemSelector - The selector to query all the related items (must include `[data-gdpr-on-enable]`) + * @param setupItemHook - The function to call to set up the item before putting it in the DOM + */ +export const setupInHeadActivation = ( + manager: GdprManager, + itemSelector: string, + setupItemHook: (item: ItemType) => void +) => { + document.querySelectorAll(itemSelector) + .forEach(item => { + const guardName = item.dataset.gdprOnEnable!; + + if (manager.hasGuard(guardName)) { + manager.events.onEnable(guardName, () => { + /* + Script tags have an internal attribute checking whether + they have already been loaded. Cloning a script will + always clone that flag as well (which is unwanted). + */ + + const isScript = item.matches("script"); + + const clonedItem = ( + isScript + ? document.createElement("script") + : item.cloneNode(true) + ) as ItemType; + + if (isScript) { + // Copy attributes over + item.getAttributeNames().forEach(attrName => { + const attrValue = item.getAttribute(attrName)!; + clonedItem.setAttribute(attrName, attrValue); + }); + } + + setupItemHook(clonedItem); + clonedItem.removeAttribute("data-gdpr-on-enable"); + item.remove(); + document.head.appendChild(clonedItem); + }); + } else { + item.remove(); + } + }); +}; + + +/** + * Setup scripts activation logic to load them when the corresponding guard is enabled (type must initially be text and the src attribute mst be present) + * @param manager - The manager to attach the activation logic to + */ +export const setupScriptActivation = (manager: GdprManager) => { + setupInHeadActivation( + manager, + "script[type='text'][src][data-gdpr-on-enable]", + actualScript => { + actualScript.setAttribute("type", "text/javascript"); + } + ); +}; + +/** + * Setup stylesheets activation logic to load them when the corresponding guard is enabled (rel attribute must be different from stylesheet and the href attribute must be present) + * @param manager - The manager to attach the activation logic to + */ +export const setupStyleSheetsActivation = (manager: GdprManager) => { + setupInHeadActivation( + manager, + "link[href][data-gdpr-on-enable]", + actualStyleSheet => { + actualStyleSheet.setAttribute("rel", "stylesheet"); + } + ); +}; + +export type BindEventsCallback = (eventsHub: GdprManagerEventHub) => void; + +export type StoreErrorHandler = (didStore: boolean, error?: Error) => void; + +export interface SetupButtonListenersHooks { + onDeclineAllErrorHook: StoreErrorHandler; + onAllowAllErrorHook: StoreErrorHandler; + onCancelErrorHook: StoreErrorHandler; + onSaveErrorHook: StoreErrorHandler; + onBannerClose: () => void; + onBannerOpen: () => void; +} + +/** + * Bind event listeners to the general buttons + * @param manager + * @param gdprSavior + * @param hooks + * @param restoreFactory + */ +export const setupButtonsListeners = ( + manager: GdprManager, + gdprSavior: GdprSavior, + hooks: SetupButtonListenersHooks, + restoreFactory: GdprManagerFactory +) => { + const doClose = () => { + manager.closeBanner(); + hooks.onBannerClose(); + }; + + GlobalEventBus.on("click", "[data-gdpr-open]", e => { + e.preventDefault(); + + manager.resetAndShowBanner(); + hooks.onBannerOpen(); + }); + + GlobalEventBus.on("click", "[data-gdpr-decline-all]", e => { + e.preventDefault(); + + manager.disable(); + + gdprSavior.store(manager.raw()) + .then(didStore => { + if (!didStore) { + hooks.onDeclineAllErrorHook(didStore); + } else { + doClose(); + } + }).catch(e => hooks.onDeclineAllErrorHook(false, e)); + }); + + GlobalEventBus.on("click", "[data-gdpr-allow-all]", e => { + e.preventDefault(); + + manager.enable(); + + gdprSavior.store(manager.raw()) + .then(didStore => { + if (!didStore) { + hooks.onAllowAllErrorHook(didStore); + } else { + doClose(); + } + }).catch(e => hooks.onAllowAllErrorHook(false, e)); + }); + + GlobalEventBus.on("click", "[data-gdpr-cancel]", e => { + e.preventDefault(); + + (async () => { + try { + const hadManager = await gdprSavior.exists(false); + + if (hadManager) { + await gdprSavior.restore(true); + } else { + await gdprSavior.restoreOrCreate(restoreFactory); + //TODO: Use save/restore new API (when it's out, for now the savior API has to suffice) + } + } catch(e) { + hooks.onCancelErrorHook(true, e as Error); + } + })(); + }); + + GlobalEventBus.on("click", "[data-gdpr-save]", e => { + e.preventDefault(); + + gdprSavior.store(manager.raw()) + .then(didStore => { + if (!didStore) { + hooks.onSaveErrorHook(didStore); + } else { + doClose(); + } + }).catch(e => hooks.onSaveErrorHook(e)); + }); +}; diff --git a/src/errors/HtmlGdprGuardError.ts b/src/errors/HtmlGdprGuardError.ts new file mode 100644 index 0000000..3953d71 --- /dev/null +++ b/src/errors/HtmlGdprGuardError.ts @@ -0,0 +1,5 @@ +export class HtmlGdprGuardError extends Error { + constructor(message: string) { + super(message); + } +} diff --git a/src/errors/NoCheckboxError.ts b/src/errors/NoCheckboxError.ts new file mode 100644 index 0000000..9c1e175 --- /dev/null +++ b/src/errors/NoCheckboxError.ts @@ -0,0 +1,9 @@ +import { HtmlGdprGuardError } from "@/errors/HtmlGdprGuardError"; + +export class NoCheckboxError extends HtmlGdprGuardError { + static defaultMessage: string = "No checkbox found for that guard"; + + constructor(message: string = NoCheckboxError.defaultMessage) { + super(message); + } +} diff --git a/src/errors/NoManagerDefinitionError.ts b/src/errors/NoManagerDefinitionError.ts new file mode 100644 index 0000000..13169c5 --- /dev/null +++ b/src/errors/NoManagerDefinitionError.ts @@ -0,0 +1,14 @@ +import { HtmlGdprGuardError } from "@/errors/HtmlGdprGuardError"; + +/** + * Error thrown when the library does not find + * a root {@link HTMLElement} to get the manager's + * data from + */ +export class NoManagerDefinitionError extends HtmlGdprGuardError { + static defaultMessage: string = "No definition found for the GDPR manager"; + + constructor(message = NoManagerDefinitionError.defaultMessage) { + super(message); + } +} diff --git a/src/errors/NoNameError.ts b/src/errors/NoNameError.ts new file mode 100644 index 0000000..fc9d6c5 --- /dev/null +++ b/src/errors/NoNameError.ts @@ -0,0 +1,9 @@ +import { HtmlGdprGuardError } from "@/errors/HtmlGdprGuardError"; + +export class NoNameError extends HtmlGdprGuardError { + static defaultMessage: string = "Guard definition is missing the guard's name"; + + constructor(message: string = NoNameError.defaultMessage) { + super(message); + } +} diff --git a/src/errors/index.ts b/src/errors/index.ts new file mode 100644 index 0000000..a4940f5 --- /dev/null +++ b/src/errors/index.ts @@ -0,0 +1,4 @@ +export * from "./HtmlGdprGuardError"; +export * from "./NoCheckboxError"; +export * from "./NoManagerDefinitionError"; +export * from "./NoNameError"; diff --git a/src/index.ts b/src/index.ts new file mode 100644 index 0000000..ea3ee7b --- /dev/null +++ b/src/index.ts @@ -0,0 +1,152 @@ +import { NoManagerDefinitionError } from "@/errors/NoManagerDefinitionError"; +import { GdprManager, GdprManagerBuilder, GdprSavior } from "gdpr-guard"; +import { parseManagerDetails } from "@/domainLogic/dataExtractors"; +import { GdprManagerEventHub } from "gdpr-guard/dist/GdprManagerEventHub"; +import { addGuardsFromDOM } from "@/domainLogic/guardsParsing"; +import { + BindEventsCallback, + setupButtonsListeners, + setupCheckboxListeners, + setupScriptActivation, + setupStyleSheetsActivation, + StoreErrorHandler, +} from "@/domainLogic/listeners"; + +export type AddGuardsCallback = (managerBuilder: GdprManagerBuilder) => void; + +export interface GdprHtmlManagerOptions { + /** + * The element that serves as the root of the GDPR manager's definition in the DOM + * @default document.querySelector("[data-gdpr]") + */ + gdprEl?: HTMLElement; + + /** + * Whether to auto close the banner (only if it has already been displayed to the user) + * @default true + */ + autoCloseBanner?: boolean; + + /** + * A callback to attach event listeners to the {@link GdprManagerEventHub} before finalizing the setup + * @default () => {} + */ + bindEventHandlersHook?: BindEventsCallback; + + /** + * Add guards before the ones parsed from the DOM + * @param managerBuilder + * @default () => {} + */ + addGuardsBeforeHook?: AddGuardsCallback; + + /** + * Add guards after the ones parsed from the DOM + * @param managerBuilder + * @default () => {} + */ + addGuardsAfterHook?: AddGuardsCallback; + + /** + * Handle failure of declining all + */ + onDeclineAllErrorHook?: StoreErrorHandler; + + /** + * Handle failure of allowing all + */ + onAllowAllErrorHook?: StoreErrorHandler; + + /** + * Handle failure of saving + */ + onSaveErrorHook?: StoreErrorHandler; + + /** + * Handle failure of cancelling + */ + onCancelErrorHook?: StoreErrorHandler; + + /** + * Execute code when closing the banner + */ + onBannerClose?: () => void; + + /** + * Execute code when opening the banner + */ + onBannerOpen?: () => void; +} + +// TODO: Reset API in gdpr-guard? + +/** + * Initialize the gdpr-guard logic from the DOM or the provided {@link GdprSavior} + * @param gdprSavior - The savior to use to restore and save the {@link GdprManager} data + * @param {GdprHtmlManagerOptions} [options] - The setup's options + * @returns {Promise} The restored GDPR manager + * @throws {NoManagerDefinitionError} - If no manager definition can be found + * (either {@link gdprEl} is `undefined` or `document.querySelector("[data-gdpr]")` returned `null`) + */ +export const restoreHtmlGdprManager = async (gdprSavior: GdprSavior, { + gdprEl = undefined, + autoCloseBanner = true, + + bindEventHandlersHook = () => {}, + addGuardsBeforeHook = () => {}, + addGuardsAfterHook = () => {}, + + onDeclineAllErrorHook = (didStore, err) => console.error("[HtmlGdprGuard @ onDeclineAllErrorHook]", {didStore, err}), + onAllowAllErrorHook = (didStore, err) => console.error("[HtmlGdprGuard @ onAllowAllErrorHook]", {didStore, err}), + onSaveErrorHook = (didStore, err) => console.error("[HtmlGdprGuard @ onSaveErrorHook]", {didStore, err}), + onCancelErrorHook = (didStore, err) => console.error("[HtmlGdprGuard @ onCancelErrorHook]", {didStore, err}), + + onBannerClose = () => {}, + onBannerOpen = () => {}, +}: GdprHtmlManagerOptions = {}): Promise => { + if (typeof gdprEl === "undefined") { + gdprEl = document.querySelector("[data-gdpr]") ?? undefined; + + if (typeof gdprEl === "undefined") { + throw new NoManagerDefinitionError(); + } + } + + const { managerEl, managerCheckbox } = parseManagerDetails(gdprEl); + + const managerBuilder = GdprManagerBuilder.make(); + + addGuardsBeforeHook(managerBuilder); + const parsedGuards = addGuardsFromDOM(managerEl, managerBuilder); + addGuardsAfterHook(managerBuilder); + + const managerFactory = async () => managerBuilder.build(); + const hadManager = await gdprSavior.exists(false); + const manager = await gdprSavior.restoreOrCreate(managerFactory); + + setupScriptActivation(manager); + setupStyleSheetsActivation(manager); + setupCheckboxListeners(manager, managerCheckbox, parsedGuards, hadManager); + setupButtonsListeners(manager, gdprSavior, { + onDeclineAllErrorHook, + onAllowAllErrorHook, + onSaveErrorHook, + onCancelErrorHook, + onBannerClose, + onBannerOpen, + }, managerFactory); + + bindEventHandlersHook(manager.events); + + if (autoCloseBanner && manager.bannerWasShown) { + manager.closeBanner(); + onBannerClose(); + } else { // Allows banner to be in closed state by default and open it when JS is ready + manager.resetAndShowBanner(); + onBannerOpen(); + } + + return manager; +}; + +export * from "./errors"; diff --git a/src/utils/dom.ts b/src/utils/dom.ts new file mode 100644 index 0000000..cb2cdbf --- /dev/null +++ b/src/utils/dom.ts @@ -0,0 +1,63 @@ +/** + * Execute an action/callback on each child + * @param rootEl - The parent element + * @param action - The action/callback to execute on each child + */ +export const forEachChild = (rootEl: HTMLElement, action: (el: HTMLElement) => void) => { + for (let i = 0; i < rootEl.childElementCount; i += 1) { + const el = rootEl.children.item(i); + + if (el) { + action(el as HTMLElement); + } + } +} + +export const findChild = (rootEl: HTMLElement, predicate: (el: HTMLElement) => boolean) => { + for (let i = 0; i < rootEl.childElementCount; i += 1) { + const el = rootEl.children.item(i); + + if (el && predicate(el as HTMLElement)) { + return el as HTMLElement; + } + } + + return null; +} + +/** + * Find all the children that satisfy the given predicate + * @param rootEl - The parent element + * @param predicate - The predicate to satisfy + */ +export const findAllChildren = (rootEl: HTMLElement, predicate: (el: HTMLElement) => boolean) => { + const ret = [] as HTMLElement[]; + + for (let i = 0; i < rootEl.childElementCount; i += 1) { + const el = rootEl.children.item(i); + + if (el && predicate(el as HTMLElement)) { + ret.push(el as HTMLElement); + } + } + + return ret; +}; + +/** + * Get the first child that matches the given selector + * @param rootEl - The parent element + * @param selector - The children selector + */ +export const childSelector = (rootEl: HTMLElement, selector: string) => { + return findChild(rootEl, el => el.matches(selector)); +} + +/** + * Get all the children of the given root that match the given selector + * @param rootEl - The parent element + * @param selector - The children selector + */ +export const childSelectorAll = (rootEl: HTMLElement, selector: string) => { + return findAllChildren(rootEl, el => el.matches(selector)); +}; diff --git a/src/utils/eventBus.ts b/src/utils/eventBus.ts new file mode 100644 index 0000000..72350d2 --- /dev/null +++ b/src/utils/eventBus.ts @@ -0,0 +1,47 @@ +/** + * Type for event listeners used in the {@link GlobalEventBus} + */ +type Listener = (e: Event) => void; +type EventName = string; +type Selector = string; + +export const GlobalEventBus = { + /** + * Store the event managers and their listeners + */ + events: {} as Record>, + + /** + * Add an event listener on the given selector as a live listener (i.e. is not limited to the current matching set of {@link HTMLElement}) + * @param event - The name of the event + * @param selector - The selector to match against + * @param listener - The listener to call when the event is triggered on an element that matches the given selector + */ + on(event: EventName, selector: Selector, listener: Listener) { + if (!(event in this.events)) { // This event had no selectors or listeners attached yet + this.events[event] = { + [selector]: [listener], + }; + + window.addEventListener(event, e => { + Object.entries(this.events[event]) + .forEach(([selector, listeners]: [Selector, Listener[]]) => { + const target = e.target as HTMLElement|null; + + if (target?.matches?.(selector)) { + listeners.forEach(listener => listener(e)); + } + }); + }); + } else { + const eventManager = this.events[event]; + + if (!(selector in eventManager)) { // This event didn't have the selector registered yet + eventManager[selector] = []; + } + + eventManager[selector].push(listener); + } + + } +}; diff --git a/src/utils/misc.ts b/src/utils/misc.ts new file mode 100644 index 0000000..076c46b --- /dev/null +++ b/src/utils/misc.ts @@ -0,0 +1,7 @@ +export const isMeaningfulStr = (str?: string|null): str is string => { + return !!str && !/^\s*$/.test(str); +}; + +export const toCamelCase = (str: string): string => { + return str.replace(/-(\w)/g, (_, letter: string) => letter.toUpperCase()); +}; diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..a738b06 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,37 @@ +{ + "compilerOptions": { + "baseUrl": ".", + "paths": { + "@/*": ["src/*"] + }, + "outDir": "./dist/", + "module": "ESNext", + "target": "es5", + "jsx": "react", + "allowJs": true, + "declaration": true, + "declarationDir": "./lib/", + "lib": [ + "esnext", + "dom" + ], + "esModuleInterop": true, + "skipLibCheck": true, + "sourceMap": true, + "strict": true, + "downlevelIteration": true, + "noImplicitAny": false, + "noImplicitReturns": true, + "noImplicitThis": true, + "moduleResolution": "node" + }, + "exclude": [ + "node_modules", + "lib", + "tests", + "dist" + ], + "include": [ + "src" + ] +} diff --git a/typedoc.config.js b/typedoc.config.js new file mode 100644 index 0000000..7b73d6d --- /dev/null +++ b/typedoc.config.js @@ -0,0 +1,16 @@ +module.exports = { + out: "docs", + emit: "docs", + entryPointStrategy: "expand", + entryPoints: ["src"], + exclude: [ + "node_modules/" + ], + theme: "default", + includeVersion: true, + readme: "README.md", + githubPages: true, + + // mode: "file", + hideGenerator: true, +}; diff --git a/webpack.config.js b/webpack.config.js new file mode 100644 index 0000000..795d159 --- /dev/null +++ b/webpack.config.js @@ -0,0 +1,42 @@ +// const webpack = require("webpack"); +const path = require("path"); + +/** + * Create an absolute URL to the given URI inside the current directory + * @param {string} [uri = ""] - The URI to the desired file + * @returns {string} + */ +const here = (uri = "") => path.resolve(__dirname, uri); + +module.exports = { + mode: "production", + entry: here("./src/index.ts"), + devtool: "source-map", + plugins: [], + module: { + rules: [ + { + test: /(?!\.d)\.tsx?$/i, + use: "ts-loader", + include: here("src/"), + exclude: [ + "node_modules/", + "tests/", + "example/", + ].map(here), + }, + ], + }, + resolve: { + extensions: ["ts", "js", "tsx"].map(ext => `.${ext}`), + alias: { + "@": path.resolve(__dirname, "src"), + }, + }, + output: { + filename: "index.js", + path: here("dist"), + library: "htmlGdprGuard", + libraryTarget: "umd2", + }, +};