From 5a84ff81d8b6d2e2321b4b219391eae38e42cdd0 Mon Sep 17 00:00:00 2001 From: Ghislain B Date: Tue, 7 May 2024 00:50:41 -0400 Subject: [PATCH] feat!: make DOMPurify as optional (#1195) * feat!: make DOMPurify as optional - replace `isomorphic-dompurify` with `dompurify` and make it a dev deps * chore: fix failing unit tests --- docs/column-functionalities/editors.md | 3 - .../editors/select-dropdown-editor.md | 3 - .../filters/select-filter.md | 4 - docs/column-functionalities/formatters.md | 2 +- docs/developer-guides/csp-compliance.md | 39 +++++---- docs/getting-started/quick-start.md | 5 +- packages/aurelia-slickgrid/package.json | 2 +- .../__tests__/slickRowDetailView.spec.ts | 1 + .../src/extensions/slickRowDetailView.ts | 5 +- packages/demo/package.json | 2 +- packages/demo/src/main.ts | 4 + pnpm-lock.yaml | 84 ++++++++++++------- 12 files changed, 86 insertions(+), 68 deletions(-) diff --git a/docs/column-functionalities/editors.md b/docs/column-functionalities/editors.md index a8c9738e3..cfc77aed2 100644 --- a/docs/column-functionalities/editors.md +++ b/docs/column-functionalities/editors.md @@ -373,9 +373,6 @@ this.columnDefinitions = [ ]; ``` -### Change Default DOMPurify Options (sanitize html) -If you find that the HTML that you passed is being sanitized and you wish to change it, then you can change the default `sanitizeHtmlOptions` property defined in the Global Grid Options, for more info on how to change these global options, see the [Wiki - Global Grid Options](../grid-functionalities/global-options.md) and also take a look at the [GitHub - DOMPurify](https://github.com/cure53/DOMPurify#can-i-configure-it) configurations. - ## Editor Options #### Column Editor `editorOptions` diff --git a/docs/column-functionalities/editors/select-dropdown-editor.md b/docs/column-functionalities/editors/select-dropdown-editor.md index d427556f2..facc53f02 100644 --- a/docs/column-functionalities/editors/select-dropdown-editor.md +++ b/docs/column-functionalities/editors/select-dropdown-editor.md @@ -224,6 +224,3 @@ this.columnDefinitions = [ } ]; ``` - -### Change Default DOMPurify Options (sanitize html) -If you find that the HTML that you passed is being sanitized and you wish to change it, then you can change the default `sanitizeHtmlOptions` property defined in the Global Grid Options, for more info on how to change these global options, see the `Global Grid Options` and also take a look at the [GitHub - DOMPurify](https://github.com/cure53/DOMPurify#can-i-configure-it) configurations. diff --git a/docs/column-functionalities/filters/select-filter.md b/docs/column-functionalities/filters/select-filter.md index 121b6050f..7f3eaba03 100644 --- a/docs/column-functionalities/filters/select-filter.md +++ b/docs/column-functionalities/filters/select-filter.md @@ -426,10 +426,6 @@ this.columnDefinitions = [ ]; ``` -#### Change Default DOMPurify Options (sanitize html) -If you find that the HTML that you passed is being sanitized and you wish to change it, then you can change the default `sanitizeHtmlOptions` property defined in the Global Grid Options, for more info on how to change these global options, see the [Wiki - Global Grid Options](../../grid-functionalities/Global-Options.md) and also take a look at the [GitHub - DOMPurify](https://github.com/cure53/DOMPurify#can-i-configure-it) configurations. - - ### Collection Add Blank Entry In some cases a blank entry at the beginning of the collection could be useful, the most common example for this is to use the first option as a blank entry to tell our Filter to show everything. So for that we can use the `addBlankEntry` flag in `collectionOptions diff --git a/docs/column-functionalities/formatters.md b/docs/column-functionalities/formatters.md index a830b9890..39bafd64e 100644 --- a/docs/column-functionalities/formatters.md +++ b/docs/column-functionalities/formatters.md @@ -202,7 +202,7 @@ Since version 7.x, you can now also return native DOM element instead of an HTML 2. Performance (the reasons are similar to point 1.) - since it's native it can be appended directly to the grid cell - when it's an HTML string, it has to do 2 extra steps (which is an overhead process) - i. sanitize the string (we use [DOMPurify](https://github.com/cure53/DOMPurify) by default) + i. sanitize the string (when a sanitizer, for example [DOMPurify](https://github.com/cure53/DOMPurify)) ii. SlickGrid then has to convert it to native element by using `innerHTML` on the grid cell Demo diff --git a/docs/developer-guides/csp-compliance.md b/docs/developer-guides/csp-compliance.md index 573eb9de9..0bfb4b9e8 100644 --- a/docs/developer-guides/csp-compliance.md +++ b/docs/developer-guides/csp-compliance.md @@ -1,27 +1,34 @@ ## CSP Compliance -The library is now, at least mostly, CSP (Content Security Policy) compliant since `v4.0`, however there are some exceptions to be aware of. When using any html string as template (for example with Custom Formatter returning an html string), you will not be fully compliant unless you return `TrustedHTML`. You can achieve this by using the `sanitizer` method in combo with [DOMPurify](https://github.com/cure53/DOMPurify) to return `TrustedHTML` as shown below and with that in place you should be CSP compliant. +The library is for the most part CSP (Content Security Policy) compliant since `v4.0` **but** only if you configure the `sanitizer` grid option. We were previously using `DOMPurify` internally in the project (in version <=4.x) but it was made optional in version 5 and higher. The main reason to make it optional was because most users would use `dompurify` but some users who require SSR support would want to use `isomorphic-dompurify`. You could also skip the `sanitizer` configuration, but that is not recommended. -> **Note** the default sanitizer in Slickgrid-Universal is actually already configured to return `TrustedHTML` but the CSP safe in the DataView is opt-in via `useCSPSafeFilter` +> **Note** even if the `sanitizer` is optional, we **strongly suggest** that you configure it as a global grid option to avoid possible XSS attacks from your data and also to be CSP compliant. Note that for Salesforce users, you do not have to configure it since Salesforce already use DOMPurify internally. -```typescript -import DOMPurify from 'dompurify'; -import { GridOption } from 'aurelia-slickgrid'; +As mentioned above, the project is mostly CSP compliant, however there are some exceptions to be aware of. When using any html string as template (for example with Custom Formatter returning an html string), you will not be fully compliant unless you return `TrustedHTML`. You can achieve this by using the `sanitizer` method in combo with [DOMPurify](https://github.com/cure53/DOMPurify) to return `TrustedHTML` as shown below and with that in place you should be CSP compliant. -export class Example1 { - gridOptions: GridOption; +```ts +// prefer the global grid options if possible +this.gridOptions = { + sanitizer: (dirtyHtml) => DOMPurify.sanitize(dirtyHtml, { ADD_ATTR: ['level'], RETURN_TRUSTED_TYPE: true }) +}; +``` - prepareGrid() { - // ... +> **Note** If you're wondering about the `ADD_ATTR: ['level']`, well the "level" is a custom attribute used by SlickGrid Grouping/Draggable Grouping to track the grouping level depth and it must be kept. - this.gridOptions = { - // NOTE: DOM Purify is already configured in Slickgrid-Universal with the configuration shown below - sanitizer: (html) => DOMPurify.sanitize(html, { RETURN_TRUSTED_TYPE: true }), - // you could also optionally use the sanitizerOptions instead - // sanitizerOptions: { RETURN_TRUSTED_TYPE: true } - } - } +> **Note** the DataView is not CSP safe by default, it is opt-in via the `useCSPSafeFilter` option. + +```typescript +import DOMPurify from 'dompurify'; +import { Slicker, SlickVanillaGridBundle } from '@slickgrid-universal/vanilla-bundle'; + +// DOM Purify is already configured in Slickgrid-Universal with the configuration shown below +this.gridOptions = { + sanitizer: (html) => DOMPurify.sanitize(html, { RETURN_TRUSTED_TYPE: true }), + // you could also optionally use the sanitizerOptions instead + // sanitizerOptions: { RETURN_TRUSTED_TYPE: true } } +this.sgb = new Slicker.GridBundle(gridContainerElm, this.columnDefinitions, this.gridOptions, this.dataset); ``` + with this code in place, we can use the following CSP meta tag (which is what we use in the lib demo, ref: [index.html](https://github.com/ghiscoding/slickgrid-universal/blob/master/examples/vite-demo-vanilla-bundle/index.html#L8-L14)) ```html diff --git a/docs/getting-started/quick-start.md b/docs/getting-started/quick-start.md index 7257a77a5..bf6e4b15f 100644 --- a/docs/getting-started/quick-start.md +++ b/docs/getting-started/quick-start.md @@ -8,10 +8,7 @@ The easiest is to simply clone the [Aurelia-Slickgrid-Demos](https://github.com/ ### 1. Install NPM Package Install the `Aurelia-Slickgrid`, `Bootstrap` and potentially a font library like `Font-Awesome` ```bash -npm install --save aurelia-slickgrid bootstrap # the last deps are optional - -# install required @types -npm install --save-dev @types/sortablejs @types/dompurify +npm install --save aurelia-slickgrid bootstrap # Bootstrap is optional ``` _Note: `Bootstrap` is optional, you can use any other lib that you want_ diff --git a/packages/aurelia-slickgrid/package.json b/packages/aurelia-slickgrid/package.json index f379befcb..a7ba60283 100644 --- a/packages/aurelia-slickgrid/package.json +++ b/packages/aurelia-slickgrid/package.json @@ -61,13 +61,13 @@ "@slickgrid-universal/row-detail-view-plugin": "~5.0.0-beta.1", "@slickgrid-universal/utils": "~5.0.0-beta.1", "dequal": "^2.0.3", - "isomorphic-dompurify": "^2.8.0", "sortablejs": "^1.15.2", "vanilla-calendar-picker": "^2.11.4" }, "devDependencies": { "@types/dompurify": "^3.0.5", "copyfiles": "^2.4.1", + "dompurify": "^3.1.2", "rimraf": "^5.0.5", "tslib": "^2.6.2", "typescript": "^5.4.5" diff --git a/packages/aurelia-slickgrid/src/extensions/__tests__/slickRowDetailView.spec.ts b/packages/aurelia-slickgrid/src/extensions/__tests__/slickRowDetailView.spec.ts index 95156443d..3fd917bec 100644 --- a/packages/aurelia-slickgrid/src/extensions/__tests__/slickRowDetailView.spec.ts +++ b/packages/aurelia-slickgrid/src/extensions/__tests__/slickRowDetailView.spec.ts @@ -88,6 +88,7 @@ const gridStub = { getSelectionModel: jest.fn(), registerPlugin: jest.fn(), setSelectionModel: jest.fn(), + sanitizeHtmlString: (s: string) => s, onColumnsReordered: new SlickEvent(), onSelectedRowsChanged: new SlickEvent(), onSort: new SlickEvent(), diff --git a/packages/aurelia-slickgrid/src/extensions/slickRowDetailView.ts b/packages/aurelia-slickgrid/src/extensions/slickRowDetailView.ts index 54485e5af..b10cb231c 100644 --- a/packages/aurelia-slickgrid/src/extensions/slickRowDetailView.ts +++ b/packages/aurelia-slickgrid/src/extensions/slickRowDetailView.ts @@ -12,7 +12,6 @@ import { import { EventPubSubService } from '@slickgrid-universal/event-pub-sub'; import { SlickRowDetailView as UniversalSlickRowDetailView } from '@slickgrid-universal/row-detail-view-plugin'; import { Constructable, resolve, transient } from 'aurelia'; -import DOMPurify from 'isomorphic-dompurify'; import { AureliaViewOutput, GridOption, RowDetailView, ViewModelBindableInputData } from '../models/index'; import { AureliaUtilService } from '../services/aureliaUtil.service'; @@ -109,11 +108,11 @@ export class SlickRowDetailView extends UniversalSlickRowDetailView { // when those are Aurelia View/ViewModel, we need to create View Slot & provide the html containers to the Plugin (preTemplate/postTemplate methods) if (!this.gridOptions.rowDetailView.preTemplate) { this._preloadViewModel = this.gridOptions?.rowDetailView?.preloadViewModel; - this.addonOptions.preTemplate = () => DOMPurify.sanitize(`
`); + this.addonOptions.preTemplate = () => this._grid.sanitizeHtmlString(`
`) as string; } if (!this.gridOptions.rowDetailView.postTemplate) { this._viewModel = this.gridOptions?.rowDetailView?.viewModel; - this.addonOptions.postTemplate = (itemDetail: any) => DOMPurify.sanitize(`
`); + this.addonOptions.postTemplate = (itemDetail: any) => this._grid.sanitizeHtmlString(`
`) as string; } if (this._grid && this.gridOptions) { diff --git a/packages/demo/package.json b/packages/demo/package.json index 25603cbab..73c95b8d1 100644 --- a/packages/demo/package.json +++ b/packages/demo/package.json @@ -57,7 +57,6 @@ "bootstrap": "^5.3.3", "i18next": "^23.11.2", "i18next-fetch-backend": "^5.0.2", - "isomorphic-dompurify": "^2.8.0", "rxjs": "^7.8.1" }, "devDependencies": { @@ -75,6 +74,7 @@ "copy-webpack-plugin": "^12.0.2", "copyfiles": "^2.4.1", "css-loader": "^7.1.1", + "dompurify": "^3.1.2", "dotenv-webpack": "^8.1.0", "fetch-jsonp": "^1.3.0", "html-webpack-plugin": "^5.6.0", diff --git a/packages/demo/src/main.ts b/packages/demo/src/main.ts index 0742ef401..3a11ba7eb 100644 --- a/packages/demo/src/main.ts +++ b/packages/demo/src/main.ts @@ -5,6 +5,7 @@ import { MyApp } from './my-app'; // However, css files imported in other js/ts files are processed by style-loader. // import shared from './shared.css'; import { AureliaSlickGridConfiguration } from 'aurelia-slickgrid'; +import DOMPurify from 'dompurify'; import { I18nConfiguration } from '@aurelia/i18n'; import Fetch from 'i18next-fetch-backend'; import { RouterConfiguration } from '@aurelia/router'; @@ -53,6 +54,9 @@ Aurelia .register(AureliaSlickGridConfiguration.customize(config => { // change any of the default global options config.options.gridMenu!.iconCssClass = 'mdi mdi-menu'; + + // we strongly suggest you add DOMPurify as a sanitizer + config.options.sanitizer = (dirtyHtml) => DOMPurify.sanitize(dirtyHtml, { ADD_ATTR: ['level'], RETURN_TRUSTED_TYPE: true }); })) .register(DecimalValueConverter, StringifyValueConverter, DateFormatValueConverter) .app(MyApp) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index f42c42b01..915b8920d 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -140,9 +140,6 @@ importers: dequal: specifier: ^2.0.3 version: 2.0.3 - isomorphic-dompurify: - specifier: ^2.8.0 - version: 2.8.0 sortablejs: specifier: ^1.15.2 version: 1.15.2 @@ -156,6 +153,9 @@ importers: copyfiles: specifier: ^2.4.1 version: 2.4.1 + dompurify: + specifier: ^3.1.2 + version: 3.1.2 rimraf: specifier: ^5.0.5 version: 5.0.5 @@ -243,9 +243,6 @@ importers: i18next-fetch-backend: specifier: ^5.0.2 version: 5.0.2 - isomorphic-dompurify: - specifier: ^2.8.0 - version: 2.8.0 rxjs: specifier: ^7.8.1 version: 7.8.1 @@ -292,6 +289,9 @@ importers: css-loader: specifier: ^7.1.1 version: 7.1.1(webpack@5.91.0) + dompurify: + specifier: ^3.1.2 + version: 3.1.2 dotenv-webpack: specifier: ^8.1.0 version: 8.1.0(webpack@5.91.0) @@ -967,7 +967,6 @@ packages: /@formkit/tempo@0.1.1: resolution: {integrity: sha512-nepRwKnCIjukLkblqh339sSXYI6P3cqktF/T7ECj3vURW+Pd+YzTv/I/lwjRqPGmlQJG93LORodIAkvgoExIAg==} - dev: false /@humanwhocodes/config-array@0.13.0: resolution: {integrity: sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==} @@ -2584,6 +2583,7 @@ packages: debug: 4.3.4(supports-color@8.1.1) transitivePeerDependencies: - supports-color + dev: true /aggregate-error@3.1.0: resolution: {integrity: sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==} @@ -2843,6 +2843,7 @@ packages: /asynckit@0.4.0: resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} + dev: true /at-least-node@1.0.0: resolution: {integrity: sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==} @@ -3431,6 +3432,7 @@ packages: engines: {node: '>= 0.8'} dependencies: delayed-stream: 1.0.0 + dev: true /commander@10.0.1: resolution: {integrity: sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==} @@ -3766,6 +3768,7 @@ packages: engines: {node: '>=18'} dependencies: rrweb-cssom: 0.6.0 + dev: true /cypress-real-events@1.12.0(cypress@13.8.1): resolution: {integrity: sha512-oiy+4kGKkzc2PT36k3GGQqkGxNiVypheWjMtfyi89iIk6bYmTzeqxapaLHS3pnhZOX1IEbTDUVxh8T4Nhs1tyQ==} @@ -3857,6 +3860,7 @@ packages: dependencies: whatwg-mimetype: 4.0.0 whatwg-url: 14.0.0 + dev: true /data-view-buffer@1.0.1: resolution: {integrity: sha512-0lht7OugA5x3iJLOWFhWK/5ehONdprk0ISXqVFn/NFrDu+cuc8iADFrGQz5BnRK7LLU3JmkbXSxaqX+/mXYtUA==} @@ -3927,9 +3931,11 @@ packages: dependencies: ms: 2.1.2 supports-color: 8.1.1 + dev: true /decimal.js@10.4.3: resolution: {integrity: sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA==} + dev: true /dedent@1.5.1: resolution: {integrity: sha512-+LxW+KLWxu3HW3M2w2ympwtqPrqYRzU8fqi6Fhd18fBALe15blJPI/I4+UHveMVG6lJqB4JNd4UG0S5cnVHwIg==} @@ -4028,6 +4034,7 @@ packages: /delayed-stream@1.0.0: resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} engines: {node: '>=0.4.0'} + dev: true /depd@1.1.2: resolution: {integrity: sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==} @@ -4131,9 +4138,9 @@ packages: domelementtype: 2.3.0 dev: true - /dompurify@3.1.1: - resolution: {integrity: sha512-tVP8C/GJwnABOn/7cx/ymx/hXpmBfWIPihC1aOEvS8GbMqy3pgeYtJk1HXN3CO7tu+8bpY18f6isjR5Cymj0TQ==} - dev: false + /dompurify@3.1.2: + resolution: {integrity: sha512-hLGGBI1tw5N8qTELr3blKjAML/LY4ANxksbS612UiJyDfyf/2D092Pvm+S7pmeTGJRqvlJkFzBoHBQKgQlOQVg==} + dev: true /domutils@2.8.0: resolution: {integrity: sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==} @@ -4266,6 +4273,7 @@ packages: /entities@4.5.0: resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==} engines: {node: '>=0.12'} + dev: true /env-paths@2.2.1: resolution: {integrity: sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==} @@ -5027,6 +5035,7 @@ packages: asynckit: 0.4.0 combined-stream: 1.0.8 mime-types: 2.1.35 + dev: true /formdata-polyfill@4.0.10: resolution: {integrity: sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==} @@ -5421,6 +5430,7 @@ packages: /has-flag@4.0.0: resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} engines: {node: '>=8'} + dev: true /has-property-descriptors@1.0.2: resolution: {integrity: sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==} @@ -5489,6 +5499,7 @@ packages: engines: {node: '>=18'} dependencies: whatwg-encoding: 3.1.1 + dev: true /html-entities@2.5.2: resolution: {integrity: sha512-K//PSRMQk4FZ78Kyau+mZurHn3FH0Vwr+H36eE0rPbeYkRRi9YxceYPhuN60UwWorxyKHhqoAJl2OFKa4BVtaA==} @@ -5609,6 +5620,7 @@ packages: debug: 4.3.4(supports-color@8.1.1) transitivePeerDependencies: - supports-color + dev: true /http-proxy-middleware@2.0.6(@types/express@4.17.21): resolution: {integrity: sha512-ya/UeJ6HVBYxrgYotAZo1KvPWlgB48kUJLDePFeneHsVujFaW5WNj2NgWCAE//B1Dl02BIfYlpNgBy8Kf8Rjmw==} @@ -5667,6 +5679,7 @@ packages: debug: 4.3.4(supports-color@8.1.1) transitivePeerDependencies: - supports-color + dev: true /human-signals@1.1.1: resolution: {integrity: sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==} @@ -5706,6 +5719,7 @@ packages: engines: {node: '>=0.10.0'} dependencies: safer-buffer: 2.1.2 + dev: true /icss-utils@5.1.0(postcss@8.4.38): resolution: {integrity: sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==} @@ -6040,6 +6054,7 @@ packages: /is-potential-custom-element-name@1.0.1: resolution: {integrity: sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==} + dev: true /is-regex@1.1.4: resolution: {integrity: sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==} @@ -6153,20 +6168,6 @@ packages: engines: {node: '>=0.10.0'} dev: true - /isomorphic-dompurify@2.8.0: - resolution: {integrity: sha512-8c+MZ8cKDqsqT9ZCOpoeiaG5AAkvdp8S+VPn2iuxRox0lbE8d039nKRhVDHbEdrqyJoEmPYAFAJzJpRUc0OJfg==} - engines: {node: '>=18'} - dependencies: - '@types/dompurify': 3.0.5 - dompurify: 3.1.1 - jsdom: 24.0.0 - transitivePeerDependencies: - - bufferutil - - canvas - - supports-color - - utf-8-validate - dev: false - /isomorphic-fetch@3.0.0: resolution: {integrity: sha512-qvUtwJ3j6qwsF3jLxkZ72qCgjMysPzDfeV240JHiGZsANBYd+EEuu35v7dfrJ9Up0Ak07D7GGSkGhCHTqg/5wA==} dependencies: @@ -6824,6 +6825,7 @@ packages: - bufferutil - supports-color - utf-8-validate + dev: true /jsesc@2.5.2: resolution: {integrity: sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==} @@ -7181,12 +7183,14 @@ packages: /mime-db@1.52.0: resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} engines: {node: '>= 0.6'} + dev: true /mime-types@2.1.35: resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} engines: {node: '>= 0.6'} dependencies: mime-db: 1.52.0 + dev: true /mime@1.6.0: resolution: {integrity: sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==} @@ -7322,14 +7326,6 @@ packages: source-map: 0.7.4 dev: true - /moment-mini@2.29.4: - resolution: {integrity: sha512-uhXpYwHFeiTbY9KSgPPRoo1nt8OxNVdMVoTBYHfSEKeRkIkwGpO+gERmhuhBtzfaeOyTkykSrm2+noJBgqt3Hg==} - dev: false - - /moment-tiny@2.30.3: - resolution: {integrity: sha512-FgTYWVw+j63lHaUex7u1W0ix+2K5r4xEpGkLwkdIfuvl4g1v7NJgCQMHCi7BsSp3IcFdXOnCoroRUPRPlJGr5w==} - dev: false - /mrmime@2.0.0: resolution: {integrity: sha512-eu38+hdgojoyq63s+yTpN4XMBdt5l8HhMhc4VKLO9KM5caLIBvUm4thi7fFaxyTmCKeNnXZ5pAlBwCUnhA09uw==} engines: {node: '>=10'} @@ -7341,6 +7337,7 @@ packages: /ms@2.1.2: resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} + dev: true /ms@2.1.3: resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} @@ -7628,6 +7625,7 @@ packages: /nwsapi@2.2.7: resolution: {integrity: sha512-ub5E4+FBPKwAZx0UwIQOjYWGHTEq5sPqHQNRN8Z9e4A7u3Tj1weLJsL59yH9vmvqEtBHaOmT6cYQKIZOxp35FQ==} + dev: true /object-assign@4.1.1: resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} @@ -7956,6 +7954,7 @@ packages: resolution: {integrity: sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==} dependencies: entities: 4.5.0 + dev: true /parseurl@1.3.3: resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==} @@ -8281,6 +8280,7 @@ packages: /psl@1.9.0: resolution: {integrity: sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==} + dev: true /pump@3.0.0: resolution: {integrity: sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==} @@ -8292,6 +8292,7 @@ packages: /punycode@2.3.1: resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} engines: {node: '>=6'} + dev: true /pure-rand@6.1.0: resolution: {integrity: sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA==} @@ -8313,6 +8314,7 @@ packages: /querystringify@2.2.0: resolution: {integrity: sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==} + dev: true /queue-microtask@1.2.3: resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} @@ -8482,6 +8484,7 @@ packages: /requires-port@1.0.0: resolution: {integrity: sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==} + dev: true /resolve-cwd@3.0.0: resolution: {integrity: sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==} @@ -8562,6 +8565,7 @@ packages: /rrweb-cssom@0.6.0: resolution: {integrity: sha512-APM0Gt1KoXBz0iIkkdB/kfvGOwC4UuJFeG/c+yV7wSc7q96cG/kJ0HiYCnzivD9SB53cLV1MlHFNfOuPaadYSw==} + dev: true /run-applescript@7.0.0: resolution: {integrity: sha512-9by4Ij99JUr/MCFBUkDKLWK3G9HVXmabKz9U5MlIAIuvuzkiOicRYs8XJLxX+xahD+mLiiCYDqF9dKAgtzKP1A==} @@ -8613,6 +8617,7 @@ packages: /safer-buffer@2.1.2: resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} + dev: true /sass-loader@14.2.1(sass@1.75.0)(webpack@5.91.0): resolution: {integrity: sha512-G0VcnMYU18a4N7VoNDegg2OuMjYtxnqzQWARVWCIVSZwJeiL9kg8QMsuIZOplsJgTzZLF6jGxI3AClj8I9nRdQ==} @@ -8655,6 +8660,7 @@ packages: engines: {node: '>=v12.22.7'} dependencies: xmlchars: 2.2.0 + dev: true /schema-utils@3.3.0: resolution: {integrity: sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==} @@ -9225,6 +9231,7 @@ packages: engines: {node: '>=10'} dependencies: has-flag: 4.0.0 + dev: true /supports-preserve-symlinks-flag@1.0.0: resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} @@ -9233,6 +9240,7 @@ packages: /symbol-tree@3.2.4: resolution: {integrity: sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==} + dev: true /tapable@2.2.1: resolution: {integrity: sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==} @@ -9378,6 +9386,7 @@ packages: punycode: 2.3.1 universalify: 0.2.0 url-parse: 1.5.10 + dev: true /tr46@0.0.3: resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} @@ -9395,6 +9404,7 @@ packages: engines: {node: '>=18'} dependencies: punycode: 2.3.1 + dev: true /ts-api-utils@1.3.0(typescript@5.4.5): resolution: {integrity: sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==} @@ -9697,6 +9707,7 @@ packages: /universalify@0.2.0: resolution: {integrity: sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==} engines: {node: '>= 4.0.0'} + dev: true /universalify@2.0.1: resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==} @@ -9735,6 +9746,7 @@ packages: dependencies: querystringify: 2.2.0 requires-port: 1.0.0 + dev: true /util-deprecate@1.0.2: resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} @@ -9816,6 +9828,7 @@ packages: engines: {node: '>=18'} dependencies: xml-name-validator: 5.0.0 + dev: true /walker@1.0.8: resolution: {integrity: sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==} @@ -9855,6 +9868,7 @@ packages: /webidl-conversions@7.0.0: resolution: {integrity: sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==} engines: {node: '>=12'} + dev: true /webpack-bundle-analyzer@4.10.2: resolution: {integrity: sha512-vJptkMm9pk5si4Bv922ZbKLV8UTT4zib4FPgXMhgzUny0bfDDkLXAVQs3ly3fS4/TN9ROFtb0NFrm04UXFE/Vw==} @@ -10069,6 +10083,7 @@ packages: engines: {node: '>=18'} dependencies: iconv-lite: 0.6.3 + dev: true /whatwg-fetch@3.6.20: resolution: {integrity: sha512-EqhiFU6daOA8kpjOWTL0olhVOF3i7OrFzSYiGsEMB8GcXS+RrzauAERX65xMeNWVqxA6HXH2m69Z9LaKKdisfg==} @@ -10082,6 +10097,7 @@ packages: /whatwg-mimetype@4.0.0: resolution: {integrity: sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==} engines: {node: '>=18'} + dev: true /whatwg-url@11.0.0: resolution: {integrity: sha512-RKT8HExMpoYx4igMiVMY83lN6UeITKJlBQ+vR/8ZJ8OCdSiN3RwCq+9gH0+Xzj0+5IrM6i4j/6LuvzbZIQgEcQ==} @@ -10097,6 +10113,7 @@ packages: dependencies: tr46: 5.0.0 webidl-conversions: 7.0.0 + dev: true /whatwg-url@5.0.0: resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==} @@ -10257,6 +10274,7 @@ packages: optional: true utf-8-validate: optional: true + dev: true /xml-name-validator@4.0.0: resolution: {integrity: sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==} @@ -10266,6 +10284,7 @@ packages: /xml-name-validator@5.0.0: resolution: {integrity: sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==} engines: {node: '>=18'} + dev: true /xml@1.0.1: resolution: {integrity: sha512-huCv9IH9Tcf95zuYCsQraZtWnJvBtLVE0QHMOs8bWyZAFZNDcYjsPq1nEx8jKA9y+Beo9v+7OBPRisQTjinQMw==} @@ -10273,6 +10292,7 @@ packages: /xmlchars@2.2.0: resolution: {integrity: sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==} + dev: true /xtend@4.0.2: resolution: {integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==}