diff --git a/.browserslistrc b/.browserslistrc new file mode 100644 index 0000000000..6114ba78d8 --- /dev/null +++ b/.browserslistrc @@ -0,0 +1,2 @@ +defaults and supports es6-module +maintained node versions diff --git a/package.json b/package.json index 83edc8695e..e2bd566a4c 100644 --- a/package.json +++ b/package.json @@ -25,7 +25,6 @@ "@rushstack/eslint-patch": "1.2.0", "@testing-library/jest-dom": "5.16.5", "@testing-library/vue": "6.6.0", - "@types/dompurify": "^2", "@types/lodash-es": "4.17.6", "@types/marked": "^4", "@types/testing-library__jest-dom": "5.14.5", @@ -71,9 +70,9 @@ "chart.js": "3.9.1", "date-fns": "2.29.3", "defu": "6.1.0", - "dompurify": "^2.4.0", "fuse.js": "6.6.2", "interactjs": "1.10.17", + "isomorphic-dompurify": "^0.23.0", "lodash-es": "4.17.21", "marked": "^4.1.1", "p-queue": "^7.3.0", diff --git a/src/components/markdown/index.spec.ts b/src/components/markdown/index.spec.ts new file mode 100644 index 0000000000..d489d54610 --- /dev/null +++ b/src/components/markdown/index.spec.ts @@ -0,0 +1,102 @@ +import { render } from '@testing-library/vue' +import { + markdown, + pMd, + vPMd, +} from '.' + +describe('markdown', () => { + it('should able render markdown', () => { + const result = markdown('**Hello** _world_') + + expect(result).toBe('

Hello world

\n') + }) + + it('should sanitize result by default', () => { + const result = markdown("123I am a dolphin!") + + expect(result).toBe('

123I am a dolphin!

\n') + }) + + it('should render inline when options.inline set to true', () => { + const result = markdown('**Hello** _world_', { inline: true }) + + expect(result).toBe('Hello world') + }) + + it('should not sanitize when options.unsecure set to true', () => { + const result = markdown("123I am a dolphin!", { unsecure: true }) + + expect(result).toBe("

123I am a dolphin!

\n") + }) +}) + +describe('v-p-md', () => { + it('should able render markdown', () => { + const screen = render({ + directives: { pMd }, + template : ` +
+ `, + }) + + const sample = screen.getByTestId('sample') + + expect(sample.innerHTML).toBe('

Hello world

\n') + }) + + it('should sanitize result by default', () => { + const screen = render({ + directives: { pMd }, + template : ` +
+ `, + }) + + const sample = screen.getByTestId('sample') + + expect(sample.innerHTML).toBe('

123I am a dolphin!

\n') + }) + + it('should render inline when add modifiers `inline`', () => { + const screen = render({ + directives: { pMd }, + template : ` +
+ `, + }) + + const sample = screen.getByTestId('sample') + + expect(sample.innerHTML).toBe('Hello world') + }) + + it('should not sanitize when add modifiers `unsecure`', () => { + const screen = render({ + directives: { pMd }, + template : ` +
+ `, + }) + + const sample = screen.getByTestId('sample') + + expect(sample.innerHTML).toBe('

123I am a dolphin!

\n') + }) + + it('should export alias vPMd', () => { + expect(pMd).toBe(vPMd) + }) +}) diff --git a/src/components/markdown/index.ts b/src/components/markdown/index.ts index f41560aca5..d407be0e34 100644 --- a/src/components/markdown/index.ts +++ b/src/components/markdown/index.ts @@ -1,19 +1,41 @@ import { Directive } from 'vue-demi' import { marked } from 'marked' -import DOMPurify from 'dompurify' +import { sanitize } from 'isomorphic-dompurify' -export function markdown (text: string, { inline = false, sanitize = true }) { - const html = inline +export interface MarkdownOption { + /** + * Use inline parsing + * @default false + * @link https://marked.js.org/using_advanced#inline + */ + inline: boolean, + /** + * Disabled sanitize HTML result + * @default false + */ + unsecure: boolean, +} + +/** + * Parse markdown to html string + * @param text markdown string + * @param options parsing options + */ +export function markdown (text: string = '', options: Partial = {}) { + const html = options.inline ? marked.parseInline(text) : marked.parse(text) - return sanitize ? DOMPurify.sanitize(html) : html + if (html && !options.unsecure) + return sanitize(html) + + return html ?? '' } export const pMd: Directive = (el, { value, modifiers }) => { el.innerHTML = markdown(value, { inline : modifiers.inline, - sanitize: !modifiers.unsecure, + unsecure: modifiers.unsecure, }) } diff --git a/src/components/tooltip/index.spec.ts b/src/components/tooltip/index.spec.ts new file mode 100644 index 0000000000..e4db691a8e --- /dev/null +++ b/src/components/tooltip/index.spec.ts @@ -0,0 +1,242 @@ +import { render, fireEvent } from '@testing-library/vue' +import { delay } from 'nanodelay' +import { ref } from 'vue-demi' +import { pTooltip, vPTooltip } from '.' + +it('should able render the tooltip', async () => { + const screen = render({ + directives: { PTooltip: pTooltip }, + template : ` +
+ `, + }) + + await delay(0) + + const sample = screen.queryByTestId('sample') + const tooltip = screen.queryByTestId('tooltip') + + await fireEvent.mouseEnter(sample) + await delay(0) + + expect(tooltip).toBeInTheDocument() + expect(tooltip).toBeVisible() + expect(tooltip).toHaveClass('tooltip') + expect(tooltip).toHaveTextContent('Hello World') + + await fireEvent.mouseLeave(sample) + await delay(0) + + expect(tooltip).not.toBeVisible() +}) + +it('should able to change color using color modifiers (.white)', async () => { + const screen = render({ + directives: { PTooltip: pTooltip }, + template : ` +
+ `, + }) + + await delay(0) + + const tooltip = screen.queryByTestId('tooltip') + + expect(tooltip).toBeInTheDocument() + expect(tooltip).toHaveClass('tooltip--white') + expect(tooltip).not.toHaveClass('tooltip--black') +}) + +it('should able to change tooltip placement using placement modifiers (.top, .left, .right, .bottom)', async () => { + const screen = render({ + directives: { PTooltip: pTooltip }, + template : ` +
+ `, + }) + + await delay(0) + + const tooltip = screen.queryByTestId('tooltip') + + expect(tooltip).toBeInTheDocument() + expect(tooltip).toHaveAttribute('data-popper-placement', 'bottom-end') +}) + +it('should able to change tooltip trigger using trigger modifiers (.click, .focus, .hover)', async () => { + const screen = render({ + directives: { PTooltip: pTooltip }, + template : ` +
+ `, + }) + + await delay(0) + + const sample = screen.queryByTestId('sample') + const tooltip = screen.queryByTestId('tooltip') + + await fireEvent.mouseEnter(sample) + await delay(0) + + expect(tooltip).toBeInTheDocument() + expect(tooltip).not.toBeVisible() + + await fireEvent.click(sample) + await delay(0) + + expect(tooltip).toBeVisible() + + await fireEvent.click(sample) + await delay(0) + + expect(tooltip).not.toBeVisible() +}) + +it('should able to use text from attribute title', async () => { + const screen = render({ + directives: { PTooltip: pTooltip }, + template : ` +
+ `, + }) + + await delay(0) + + const tooltip = screen.queryByTestId('tooltip') + + expect(tooltip).toHaveTextContent('Hello World') + expect(tooltip).not.toHaveAttribute('title') +}) + +it('should reactive when title changed', async () => { + const title = ref('Hello World') + const screen = render({ + directives: { PTooltip: pTooltip }, + template : ` +
+ `, + setup () { + return { title } + }, + }) + + await delay(0) + + const tooltip = screen.queryByTestId('tooltip') + + expect(tooltip).toHaveTextContent('Hello World') + expect(tooltip).not.toHaveAttribute('title') + + title.value = 'Hello Reyhan' + await delay(0) + + expect(tooltip).toHaveTextContent('Hello Reyhan') +}) + +it('should not shown the tooltip if text not provided', async () => { + const screen = render({ + directives: { PTooltip: pTooltip }, + template : ` +
+ `, + }) + + await delay(0) + + const sample = screen.queryByTestId('sample') + const tooltip = screen.queryByTestId('tooltip') + + await fireEvent.mouseEnter(sample) + await delay(0) + + expect(tooltip).toBeInTheDocument() + expect(tooltip).not.toBeVisible() +}) + +it('should not shown the tooltip if v-p-tooltip set to `false`', async () => { + const active = ref(false) + const screen = render({ + directives: { PTooltip: pTooltip }, + template : ` +
+ `, + setup () { + return { active } + }, + }) + + await delay(0) + + const sample = screen.queryByTestId('sample') + const tooltip = screen.queryByTestId('tooltip') + + await fireEvent.mouseEnter(sample) + await delay(0) + + expect(tooltip).toBeInTheDocument() + expect(tooltip).not.toBeVisible() + + active.value = true + await delay(0) + + await fireEvent.mouseEnter(sample) + await delay(0) + + expect(tooltip).toBeVisible() +}) + +it('should hide the tooltip if v-p-tooltip set to `false` when it\'s shown before', async () => { + const active = ref(true) + const screen = render({ + directives: { PTooltip: pTooltip }, + template : ` +
+ `, + setup () { + return { active } + }, + }) + + await delay(0) + + const sample = screen.queryByTestId('sample') + const tooltip = screen.queryByTestId('tooltip') + + await fireEvent.mouseEnter(sample) + await delay(0) + + expect(tooltip).toBeInTheDocument() + expect(tooltip).toBeVisible() + + active.value = false + await delay(0) + + expect(tooltip).not.toBeVisible() +}) + +it('should export alias vPTooltip', () => { + expect(pTooltip).toBe(vPTooltip) +}) diff --git a/src/components/tooltip/index.ts b/src/components/tooltip/index.ts index 1342aaac7d..bd5822ba78 100644 --- a/src/components/tooltip/index.ts +++ b/src/components/tooltip/index.ts @@ -30,13 +30,14 @@ const handleMouseLeave = createHandler('hover', 'hide') const handleFocus = createHandler('focus', 'show') const handleBlur = createHandler('focus', 'hide') -export const PTooltip: Directive = { +export const pTooltip: Directive = { async mounted (el, bindings) { const tooltip = await useSingleton(TooltipContainer) const action = parseAction(el, bindings) const color = parseColor(el, bindings) const text = parseText(el, bindings) const placement = parsePlacement(el, bindings) + const enable = bindings.value !== false && !!text const id = tooltip.add({ target : el, @@ -48,9 +49,9 @@ export const PTooltip: Directive = { el.dataset.tooltipId = id el.dataset.tooltipAction = action el.dataset.tooltipText = text - el.dataset.tooltipEnable = (bindings.value !== false && text) ? 'true' : 'false' + el.dataset.tooltipEnable = enable ? 'true' : 'false' - el.removeAttribute('title') + el.removeAttribute('title') // remove attribute title, we don't want native-browser's tooltip to shown el.addEventListener('click', handleClick) el.addEventListener('mouseenter', handleMouseEnter, { passive: true }) el.addEventListener('mouseleave', handleMouseLeave, { passive: true }) @@ -65,10 +66,11 @@ export const PTooltip: Directive = { const color = parseColor(el, bindings) const text = parseText(el, bindings) const placement = parsePlacement(el, bindings) + const enable = bindings.value !== false && !!text el.dataset.tooltipAction = action el.dataset.tooltipText = text - el.dataset.tooltipEnable = (bindings.value !== false && text) ? 'true' : 'false' + el.dataset.tooltipEnable = enable ? 'true' : 'false' tooltip.update(id, { target : el, @@ -77,6 +79,9 @@ export const PTooltip: Directive = { color : color, }) + if (!enable) + tooltip.hide(id) + el.removeAttribute('title') }, @@ -101,4 +106,4 @@ export const PTooltip: Directive = { }, } -export const vPTooltip = PTooltip +export const vPTooltip = pTooltip diff --git a/src/components/tooltip/utils/parse-bindings.spec.ts b/src/components/tooltip/utils/parse-bindings.spec.ts index 2f8c5491db..de5e83a41e 100644 --- a/src/components/tooltip/utils/parse-bindings.spec.ts +++ b/src/components/tooltip/utils/parse-bindings.spec.ts @@ -156,8 +156,8 @@ describe('parseText', () => { el.setAttribute('title', 'Hello World') const text = parseText(el, { - value : '', - oldValue : '', + value : undefined, + oldValue : undefined, instance : undefined, modifiers: undefined, dir : undefined, @@ -185,12 +185,11 @@ describe('parseText', () => { it('should return text from dataset TooltipText (attribute `data-tooltip-text`) if value nor attr title present', () => { const el = document.createElement('div') - el.setAttribute('title', '') el.dataset.tooltipText = 'Hello World' const text = parseText(el, { - value : '', - oldValue : '', + value : undefined, + oldValue : undefined, instance : undefined, modifiers: undefined, dir : undefined, diff --git a/src/components/tooltip/utils/parse-bindings.ts b/src/components/tooltip/utils/parse-bindings.ts index d014e3bc93..59dd266086 100644 --- a/src/components/tooltip/utils/parse-bindings.ts +++ b/src/components/tooltip/utils/parse-bindings.ts @@ -84,11 +84,13 @@ export function parseAction (_el: HTMLElement, { modifiers }: DirectiveBinding): * @param bindings directive bindings options */ export function parseText (el: HTMLElement, bindings: DirectiveBinding): string { - if (bindings.value && typeof bindings.value === 'string') + if (typeof bindings.value === 'string') return bindings.value - // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing - return el.getAttribute('title') || el.dataset.tooltipText + if (el.hasAttribute('title')) + return el.getAttribute('title') + + return el.dataset.tooltipText ?? '' } /** diff --git a/yarn.lock b/yarn.lock index 1dc31bda19..b2f1fb3b56 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1348,7 +1348,6 @@ __metadata: "@rushstack/eslint-patch": 1.2.0 "@testing-library/jest-dom": 5.16.5 "@testing-library/vue": 6.6.0 - "@types/dompurify": ^2 "@types/lodash-es": 4.17.6 "@types/marked": ^4 "@types/testing-library__jest-dom": 5.14.5 @@ -1367,7 +1366,6 @@ __metadata: chart.js: 3.9.1 date-fns: 2.29.3 defu: 6.1.0 - dompurify: ^2.4.0 eslint: 8.23.1 eslint-config-standard-with-typescript: latest eslint-formatter-pretty: 4.1.0 @@ -1383,6 +1381,7 @@ __metadata: happy-dom: 6.0.4 husky: 8.0.1 interactjs: 1.10.17 + isomorphic-dompurify: ^0.23.0 jest-extended: 3.1.0 lint-staged: 13.0.3 lodash-es: 4.17.21 @@ -1792,7 +1791,7 @@ __metadata: languageName: node linkType: hard -"@types/dompurify@npm:^2": +"@types/dompurify@npm:^2.3.4": version: 2.3.4 resolution: "@types/dompurify@npm:2.3.4" dependencies: @@ -2829,6 +2828,13 @@ __metadata: languageName: node linkType: hard +"abab@npm:^2.0.6": + version: 2.0.6 + resolution: "abab@npm:2.0.6" + checksum: 6ffc1af4ff315066c62600123990d87551ceb0aafa01e6539da77b0f5987ac7019466780bf480f1787576d4385e3690c81ccc37cfda12819bf510b8ab47e5a3e + languageName: node + linkType: hard + "abbrev@npm:1": version: 1.1.1 resolution: "abbrev@npm:1.1.1" @@ -2846,6 +2852,16 @@ __metadata: languageName: node linkType: hard +"acorn-globals@npm:^7.0.0": + version: 7.0.1 + resolution: "acorn-globals@npm:7.0.1" + dependencies: + acorn: ^8.1.0 + acorn-walk: ^8.0.2 + checksum: 2a2998a547af6d0db5f0cdb90acaa7c3cbca6709010e02121fb8b8617c0fbd8bab0b869579903fde358ac78454356a14fadcc1a672ecb97b04b1c2ccba955ce8 + languageName: node + linkType: hard + "acorn-jsx@npm:^5.3.2": version: 5.3.2 resolution: "acorn-jsx@npm:5.3.2" @@ -2873,6 +2889,13 @@ __metadata: languageName: node linkType: hard +"acorn-walk@npm:^8.0.2": + version: 8.2.0 + resolution: "acorn-walk@npm:8.2.0" + checksum: 1715e76c01dd7b2d4ca472f9c58968516a4899378a63ad5b6c2d668bba8da21a71976c14ec5f5b75f887b6317c4ae0b897ab141c831d741dc76024d8745f1ad1 + languageName: node + linkType: hard + "acorn@npm:^7.0.0": version: 7.4.1 resolution: "acorn@npm:7.4.1" @@ -2882,6 +2905,15 @@ __metadata: languageName: node linkType: hard +"acorn@npm:^8.1.0": + version: 8.8.1 + resolution: "acorn@npm:8.8.1" + bin: + acorn: bin/acorn + checksum: 4079b67283b94935157698831967642f24a075c52ce3feaaaafe095776dfbe15d86a1b33b1e53860fc0d062ed6c83f4284a5c87c85b9ad51853a01173da6097f + languageName: node + linkType: hard + "acorn@npm:^8.5.0, acorn@npm:^8.6.0, acorn@npm:^8.8.0": version: 8.8.0 resolution: "acorn@npm:8.8.0" @@ -3965,7 +3997,7 @@ __metadata: languageName: node linkType: hard -"combined-stream@npm:^1.0.6": +"combined-stream@npm:^1.0.6, combined-stream@npm:^1.0.8": version: 1.0.8 resolution: "combined-stream@npm:1.0.8" dependencies: @@ -4305,6 +4337,29 @@ __metadata: languageName: node linkType: hard +"cssom@npm:^0.5.0": + version: 0.5.0 + resolution: "cssom@npm:0.5.0" + checksum: 823471aa30091c59e0a305927c30e7768939b6af70405808f8d2ce1ca778cddcb24722717392438329d1691f9a87cb0183b64b8d779b56a961546d54854fde01 + languageName: node + linkType: hard + +"cssom@npm:~0.3.6": + version: 0.3.8 + resolution: "cssom@npm:0.3.8" + checksum: 24beb3087c76c0d52dd458be9ee1fbc80ac771478a9baef35dd258cdeb527c68eb43204dd439692bb2b1ae5272fa5f2946d10946edab0d04f1078f85e06bc7f6 + languageName: node + linkType: hard + +"cssstyle@npm:^2.3.0": + version: 2.3.0 + resolution: "cssstyle@npm:2.3.0" + dependencies: + cssom: ~0.3.6 + checksum: 5f05e6fd2e3df0b44695c2f08b9ef38b011862b274e320665176467c0725e44a53e341bc4959a41176e83b66064ab786262e7380fd1cabeae6efee0d255bb4e3 + languageName: node + linkType: hard + "csstype@npm:^2.6.8": version: 2.6.20 resolution: "csstype@npm:2.6.20" @@ -4326,6 +4381,17 @@ __metadata: languageName: node linkType: hard +"data-urls@npm:^3.0.2": + version: 3.0.2 + resolution: "data-urls@npm:3.0.2" + dependencies: + abab: ^2.0.6 + whatwg-mimetype: ^3.0.0 + whatwg-url: ^11.0.0 + checksum: 033fc3dd0fba6d24bc9a024ddcf9923691dd24f90a3d26f6545d6a2f71ec6956f93462f2cdf2183cc46f10dc01ed3bcb36731a8208456eb1a08147e571fe2a76 + languageName: node + linkType: hard + "date-fns@npm:2.29.3": version: 2.29.3 resolution: "date-fns@npm:2.29.3" @@ -4387,6 +4453,13 @@ __metadata: languageName: node linkType: hard +"decimal.js@npm:^10.4.1": + version: 10.4.2 + resolution: "decimal.js@npm:10.4.2" + checksum: 536cd6816a3197f2e1aa3da4860856cb5a2db73f6fafe8cb3b924ccc63f9b7d78296acc13dccbd419bd958ccc6357921fb15467f883b37cab04bfba7044cada2 + languageName: node + linkType: hard + "deep-eql@npm:^3.0.1": version: 3.0.1 resolution: "deep-eql@npm:3.0.1" @@ -4403,7 +4476,7 @@ __metadata: languageName: node linkType: hard -"deep-is@npm:^0.1.3": +"deep-is@npm:^0.1.3, deep-is@npm:~0.1.3": version: 0.1.4 resolution: "deep-is@npm:0.1.4" checksum: edb65dd0d7d1b9c40b2f50219aef30e116cedd6fc79290e740972c132c09106d2e80aa0bc8826673dd5a00222d4179c84b36a790eef63a4c4bca75a37ef90804 @@ -4656,6 +4729,15 @@ __metadata: languageName: node linkType: hard +"domexception@npm:^4.0.0": + version: 4.0.0 + resolution: "domexception@npm:4.0.0" + dependencies: + webidl-conversions: ^7.0.0 + checksum: ddbc1268edf33a8ba02ccc596735ede80375ee0cf124b30d2f05df5b464ba78ef4f49889b6391df4a04954e63d42d5631c7fcf8b1c4f12bc531252977a5f13d5 + languageName: node + linkType: hard + "domhandler@npm:^4.2.0, domhandler@npm:^4.3.1": version: 4.3.1 resolution: "domhandler@npm:4.3.1" @@ -4815,6 +4897,13 @@ __metadata: languageName: node linkType: hard +"entities@npm:^4.4.0": + version: 4.4.0 + resolution: "entities@npm:4.4.0" + checksum: 84d250329f4b56b40fa93ed067b194db21e8815e4eb9b59f43a086f0ecd342814f6bc483de8a77da5d64e0f626033192b1b4f1792232a7ea6b970ebe0f3187c2 + languageName: node + linkType: hard + "env-paths@npm:^2.2.0": version: 2.2.1 resolution: "env-paths@npm:2.2.1" @@ -5590,6 +5679,25 @@ __metadata: languageName: node linkType: hard +"escodegen@npm:^2.0.0": + version: 2.0.0 + resolution: "escodegen@npm:2.0.0" + dependencies: + esprima: ^4.0.1 + estraverse: ^5.2.0 + esutils: ^2.0.2 + optionator: ^0.8.1 + source-map: ~0.6.1 + dependenciesMeta: + source-map: + optional: true + bin: + escodegen: bin/escodegen.js + esgenerate: bin/esgenerate.js + checksum: 5aa6b2966fafe0545e4e77936300cc94ad57cfe4dc4ebff9950492eaba83eef634503f12d7e3cbd644ecc1bab388ad0e92b06fd32222c9281a75d1cf02ec6cef + languageName: node + linkType: hard + "eslint-config-standard-with-typescript@npm:latest": version: 21.0.1 resolution: "eslint-config-standard-with-typescript@npm:21.0.1" @@ -5941,6 +6049,16 @@ __metadata: languageName: node linkType: hard +"esprima@npm:^4.0.1": + version: 4.0.1 + resolution: "esprima@npm:4.0.1" + bin: + esparse: ./bin/esparse.js + esvalidate: ./bin/esvalidate.js + checksum: b45bc805a613dbea2835278c306b91aff6173c8d034223fa81498c77dcbce3b2931bf6006db816f62eacd9fd4ea975dfd85a5b7f3c6402cfd050d4ca3c13a628 + languageName: node + linkType: hard + "esquery@npm:^1.4.0": version: 1.4.0 resolution: "esquery@npm:1.4.0" @@ -6119,7 +6237,7 @@ __metadata: languageName: node linkType: hard -"fast-levenshtein@npm:^2.0.6": +"fast-levenshtein@npm:^2.0.6, fast-levenshtein@npm:~2.0.6": version: 2.0.6 resolution: "fast-levenshtein@npm:2.0.6" checksum: 92cfec0a8dfafd9c7a15fba8f2cc29cd0b62b85f056d99ce448bbcd9f708e18ab2764bda4dd5158364f4145a7c72788538994f0d1787b956ef0d1062b0f7c24c @@ -6266,6 +6384,17 @@ __metadata: languageName: node linkType: hard +"form-data@npm:^4.0.0": + version: 4.0.0 + resolution: "form-data@npm:4.0.0" + dependencies: + asynckit: ^0.4.0 + combined-stream: ^1.0.8 + mime-types: ^2.1.12 + checksum: 01135bf8675f9d5c61ff18e2e2932f719ca4de964e3be90ef4c36aacfc7b9cb2fceb5eca0b7e0190e3383fe51c5b37f4cb80b62ca06a99aaabfcfd6ac7c9328c + languageName: node + linkType: hard + "formdata-polyfill@npm:^4.0.10": version: 4.0.10 resolution: "formdata-polyfill@npm:4.0.10" @@ -6825,6 +6954,15 @@ __metadata: languageName: node linkType: hard +"html-encoding-sniffer@npm:^3.0.0": + version: 3.0.0 + resolution: "html-encoding-sniffer@npm:3.0.0" + dependencies: + whatwg-encoding: ^2.0.0 + checksum: 8d806aa00487e279e5ccb573366a951a9f68f65c90298eac9c3a2b440a7ffe46615aff2995a2f61c6746c639234e6179a97e18ca5ccbbf93d3725ef2099a4502 + languageName: node + linkType: hard + "html-escaper@npm:^2.0.0": version: 2.0.2 resolution: "html-escaper@npm:2.0.2" @@ -6954,6 +7092,16 @@ __metadata: languageName: node linkType: hard +"https-proxy-agent@npm:^5.0.1": + version: 5.0.1 + resolution: "https-proxy-agent@npm:5.0.1" + dependencies: + agent-base: 6 + debug: 4 + checksum: 571fccdf38184f05943e12d37d6ce38197becdd69e58d03f43637f7fa1269cf303a7d228aa27e5b27bbd3af8f09fd938e1c91dcfefff2df7ba77c20ed8dfc765 + languageName: node + linkType: hard + "human-signals@npm:^2.1.0": version: 2.1.0 resolution: "human-signals@npm:2.1.0" @@ -7395,6 +7543,13 @@ __metadata: languageName: node linkType: hard +"is-potential-custom-element-name@npm:^1.0.1": + version: 1.0.1 + resolution: "is-potential-custom-element-name@npm:1.0.1" + checksum: ced7bbbb6433a5b684af581872afe0e1767e2d1146b2207ca0068a648fb5cab9d898495d1ac0583524faaf24ca98176a7d9876363097c2d14fee6dd324f3a1ab + languageName: node + linkType: hard + "is-primitive@npm:^3.0.1": version: 3.0.1 resolution: "is-primitive@npm:3.0.1" @@ -7524,6 +7679,17 @@ __metadata: languageName: node linkType: hard +"isomorphic-dompurify@npm:^0.23.0": + version: 0.23.0 + resolution: "isomorphic-dompurify@npm:0.23.0" + dependencies: + "@types/dompurify": ^2.3.4 + dompurify: ^2.4.0 + jsdom: ^20.0.1 + checksum: bcd5a99fb7cfae6c63446b31a0787ec79a629e42459a0eae99f222949b7ffbcbb0d6d524f105eca21939b4308fdf112e1c2fa7fc915b352cf5d938e11923e95c + languageName: node + linkType: hard + "istanbul-lib-coverage@npm:^3.0.0, istanbul-lib-coverage@npm:^3.2.0": version: 3.2.0 resolution: "istanbul-lib-coverage@npm:3.2.0" @@ -7682,6 +7848,45 @@ __metadata: languageName: node linkType: hard +"jsdom@npm:^20.0.1": + version: 20.0.1 + resolution: "jsdom@npm:20.0.1" + dependencies: + abab: ^2.0.6 + acorn: ^8.8.0 + acorn-globals: ^7.0.0 + cssom: ^0.5.0 + cssstyle: ^2.3.0 + data-urls: ^3.0.2 + decimal.js: ^10.4.1 + domexception: ^4.0.0 + escodegen: ^2.0.0 + form-data: ^4.0.0 + html-encoding-sniffer: ^3.0.0 + http-proxy-agent: ^5.0.0 + https-proxy-agent: ^5.0.1 + is-potential-custom-element-name: ^1.0.1 + nwsapi: ^2.2.2 + parse5: ^7.1.1 + saxes: ^6.0.0 + symbol-tree: ^3.2.4 + tough-cookie: ^4.1.2 + w3c-xmlserializer: ^3.0.0 + webidl-conversions: ^7.0.0 + whatwg-encoding: ^2.0.0 + whatwg-mimetype: ^3.0.0 + whatwg-url: ^11.0.0 + ws: ^8.9.0 + xml-name-validator: ^4.0.0 + peerDependencies: + canvas: ^2.5.0 + peerDependenciesMeta: + canvas: + optional: true + checksum: 9fc0b66a866f58a28e95f5a39b167ea663dc01c9754a019c356cc517d27ff0216055f37ace69e0f4414c51084adca8d5ec71c1e6faee3b8df0941a494167c3a0 + languageName: node + linkType: hard + "jsesc@npm:^2.5.1": version: 2.5.2 resolution: "jsesc@npm:2.5.2" @@ -7870,6 +8075,16 @@ __metadata: languageName: node linkType: hard +"levn@npm:~0.3.0": + version: 0.3.0 + resolution: "levn@npm:0.3.0" + dependencies: + prelude-ls: ~1.1.2 + type-check: ~0.3.2 + checksum: 0d084a524231a8246bb10fec48cdbb35282099f6954838604f3c7fc66f2e16fa66fd9cc2f3f20a541a113c4dafdf181e822c887c8a319c9195444e6c64ac395e + languageName: node + linkType: hard + "lilconfig@npm:2.0.5, lilconfig@npm:^2.0.5": version: 2.0.5 resolution: "lilconfig@npm:2.0.5" @@ -9056,6 +9271,13 @@ __metadata: languageName: node linkType: hard +"nwsapi@npm:^2.2.2": + version: 2.2.2 + resolution: "nwsapi@npm:2.2.2" + checksum: 43769106292bc95f776756ca2f3513dab7b4d506a97c67baec32406447841a35f65f29c1f95ab5d42785210fd41668beed33ca16fa058780be43b101ad73e205 + languageName: node + linkType: hard + "object-assign@npm:^4.1.1": version: 4.1.1 resolution: "object-assign@npm:4.1.1" @@ -9209,6 +9431,20 @@ __metadata: languageName: node linkType: hard +"optionator@npm:^0.8.1": + version: 0.8.3 + resolution: "optionator@npm:0.8.3" + dependencies: + deep-is: ~0.1.3 + fast-levenshtein: ~2.0.6 + levn: ~0.3.0 + prelude-ls: ~1.1.2 + type-check: ~0.3.2 + word-wrap: ~1.2.3 + checksum: b8695ddf3d593203e25ab0900e265d860038486c943ff8b774f596a310f8ceebdb30c6832407a8198ba3ec9debe1abe1f51d4aad94843612db3b76d690c61d34 + languageName: node + linkType: hard + "optionator@npm:^0.9.1": version: 0.9.1 resolution: "optionator@npm:0.9.1" @@ -9415,6 +9651,15 @@ __metadata: languageName: node linkType: hard +"parse5@npm:^7.1.1": + version: 7.1.1 + resolution: "parse5@npm:7.1.1" + dependencies: + entities: ^4.4.0 + checksum: 8f72fbfa6df83a3f29f58e1818f7bd46b47ff3e26d79c74e10b8fc7ef7ee76163f205113f1b2f6a5b8dc4e31e726f490444f04890cead6e974dbcbe8172b1321 + languageName: node + linkType: hard + "parseurl@npm:^1.3.2, parseurl@npm:~1.3.3": version: 1.3.3 resolution: "parseurl@npm:1.3.3" @@ -10185,6 +10430,13 @@ __metadata: languageName: node linkType: hard +"prelude-ls@npm:~1.1.2": + version: 1.1.2 + resolution: "prelude-ls@npm:1.1.2" + checksum: c4867c87488e4a0c233e158e4d0d5565b609b105d75e4c05dc760840475f06b731332eb93cc8c9cecb840aa8ec323ca3c9a56ad7820ad2e63f0261dadcb154e4 + languageName: node + linkType: hard + "pretty-bytes@npm:^5.6.0": version: 5.6.0 resolution: "pretty-bytes@npm:5.6.0" @@ -10268,7 +10520,14 @@ __metadata: languageName: node linkType: hard -"punycode@npm:^2.1.0": +"psl@npm:^1.1.33": + version: 1.9.0 + resolution: "psl@npm:1.9.0" + checksum: 20c4277f640c93d393130673f392618e9a8044c6c7bf61c53917a0fddb4952790f5f362c6c730a9c32b124813e173733f9895add8d26f566ed0ea0654b2e711d + languageName: node + linkType: hard + +"punycode@npm:^2.1.0, punycode@npm:^2.1.1": version: 2.1.1 resolution: "punycode@npm:2.1.1" checksum: 823bf443c6dd14f669984dea25757b37993f67e8d94698996064035edd43bed8a5a17a9f12e439c2b35df1078c6bec05a6c86e336209eb1061e8025c481168e8 @@ -10284,6 +10543,13 @@ __metadata: languageName: node linkType: hard +"querystringify@npm:^2.1.1": + version: 2.2.0 + resolution: "querystringify@npm:2.2.0" + checksum: 5641ea231bad7ef6d64d9998faca95611ed4b11c2591a8cae741e178a974f6a8e0ebde008475259abe1621cb15e692404e6b6626e927f7b849d5c09392604b15 + languageName: node + linkType: hard + "queue-microtask@npm:^1.2.2": version: 1.2.3 resolution: "queue-microtask@npm:1.2.3" @@ -10863,6 +11129,15 @@ __metadata: languageName: node linkType: hard +"saxes@npm:^6.0.0": + version: 6.0.0 + resolution: "saxes@npm:6.0.0" + dependencies: + xmlchars: ^2.2.0 + checksum: d3fa3e2aaf6c65ed52ee993aff1891fc47d5e47d515164b5449cbf5da2cbdc396137e55590472e64c5c436c14ae64a8a03c29b9e7389fc6f14035cf4e982ef3b + languageName: node + linkType: hard + "schema-utils@npm:^3.0.0": version: 3.1.1 resolution: "schema-utils@npm:3.1.1" @@ -11154,7 +11429,7 @@ __metadata: languageName: node linkType: hard -"source-map@npm:^0.6.0, source-map@npm:^0.6.1": +"source-map@npm:^0.6.0, source-map@npm:^0.6.1, source-map@npm:~0.6.1": version: 0.6.1 resolution: "source-map@npm:0.6.1" checksum: 59ce8640cf3f3124f64ac289012c2b8bd377c238e316fb323ea22fbfe83da07d81e000071d7242cad7a23cd91c7de98e4df8830ec3f133cb6133a5f6e9f67bc2 @@ -11489,6 +11764,13 @@ __metadata: languageName: node linkType: hard +"symbol-tree@npm:^3.2.4": + version: 3.2.4 + resolution: "symbol-tree@npm:3.2.4" + checksum: 6e8fc7e1486b8b54bea91199d9535bb72f10842e40c79e882fc94fb7b14b89866adf2fd79efa5ebb5b658bc07fb459ccce5ac0e99ef3d72f474e74aaf284029d + languageName: node + linkType: hard + "sync-request@npm:^6.1.0": version: 6.1.0 resolution: "sync-request@npm:6.1.0" @@ -11788,6 +12070,27 @@ __metadata: languageName: node linkType: hard +"tough-cookie@npm:^4.1.2": + version: 4.1.2 + resolution: "tough-cookie@npm:4.1.2" + dependencies: + psl: ^1.1.33 + punycode: ^2.1.1 + universalify: ^0.2.0 + url-parse: ^1.5.3 + checksum: a7359e9a3e875121a84d6ba40cc184dec5784af84f67f3a56d1d2ae39b87c0e004e6ba7c7331f9622a7d2c88609032473488b28fe9f59a1fec115674589de39a + languageName: node + linkType: hard + +"tr46@npm:^3.0.0": + version: 3.0.0 + resolution: "tr46@npm:3.0.0" + dependencies: + punycode: ^2.1.1 + checksum: 44c3cc6767fb800490e6e9fd64fd49041aa4e49e1f6a012b34a75de739cc9ed3a6405296072c1df8b6389ae139c5e7c6496f659cfe13a04a4bff3a1422981270 + languageName: node + linkType: hard + "tr46@npm:~0.0.3": version: 0.0.3 resolution: "tr46@npm:0.0.3" @@ -11862,6 +12165,15 @@ __metadata: languageName: node linkType: hard +"type-check@npm:~0.3.2": + version: 0.3.2 + resolution: "type-check@npm:0.3.2" + dependencies: + prelude-ls: ~1.1.2 + checksum: dd3b1495642731bc0e1fc40abe5e977e0263005551ac83342ecb6f4f89551d106b368ec32ad3fb2da19b3bd7b2d1f64330da2ea9176d8ddbfe389fb286eb5124 + languageName: node + linkType: hard + "type-detect@npm:^4.0.0, type-detect@npm:^4.0.5": version: 4.0.8 resolution: "type-detect@npm:4.0.8" @@ -12139,6 +12451,13 @@ __metadata: languageName: node linkType: hard +"universalify@npm:^0.2.0": + version: 0.2.0 + resolution: "universalify@npm:0.2.0" + checksum: e86134cb12919d177c2353196a4cc09981524ee87abf621f7bc8d249dbbbebaec5e7d1314b96061497981350df786e4c5128dbf442eba104d6e765bc260678b5 + languageName: node + linkType: hard + "universalify@npm:^2.0.0": version: 2.0.0 resolution: "universalify@npm:2.0.0" @@ -12283,6 +12602,16 @@ __metadata: languageName: node linkType: hard +"url-parse@npm:^1.5.3": + version: 1.5.10 + resolution: "url-parse@npm:1.5.10" + dependencies: + querystringify: ^2.1.1 + requires-port: ^1.0.0 + checksum: fbdba6b1d83336aca2216bbdc38ba658d9cfb8fc7f665eb8b17852de638ff7d1a162c198a8e4ed66001ddbf6c9888d41e4798912c62b4fd777a31657989f7bdf + languageName: node + linkType: hard + "utf8@npm:^3.0.0": version: 3.0.0 resolution: "utf8@npm:3.0.0" @@ -12772,6 +13101,15 @@ __metadata: languageName: node linkType: hard +"w3c-xmlserializer@npm:^3.0.0": + version: 3.0.0 + resolution: "w3c-xmlserializer@npm:3.0.0" + dependencies: + xml-name-validator: ^4.0.0 + checksum: 0af8589942eeb11c9fe29eb31a1a09f3d5dd136aea53a9848dfbabff79ac0dd26fe13eb54d330d5555fe27bb50b28dca0715e09f9cc2bfa7670ccc8b7f919ca2 + languageName: node + linkType: hard + "wcwidth@npm:^1.0.1": version: 1.0.1 resolution: "wcwidth@npm:1.0.1" @@ -12846,6 +13184,16 @@ __metadata: languageName: node linkType: hard +"whatwg-url@npm:^11.0.0": + version: 11.0.0 + resolution: "whatwg-url@npm:11.0.0" + dependencies: + tr46: ^3.0.0 + webidl-conversions: ^7.0.0 + checksum: ed4826aaa57e66bb3488a4b25c9cd476c46ba96052747388b5801f137dd740b73fde91ad207d96baf9f17fbcc80fc1a477ad65181b5eb5fa718d27c69501d7af + languageName: node + linkType: hard + "whatwg-url@npm:^5.0.0": version: 5.0.0 resolution: "whatwg-url@npm:5.0.0" @@ -12889,7 +13237,7 @@ __metadata: languageName: node linkType: hard -"word-wrap@npm:^1.2.3": +"word-wrap@npm:^1.2.3, word-wrap@npm:~1.2.3": version: 1.2.3 resolution: "word-wrap@npm:1.2.3" checksum: 30b48f91fcf12106ed3186ae4fa86a6a1842416df425be7b60485de14bec665a54a68e4b5156647dec3a70f25e84d270ca8bc8cd23182ed095f5c7206a938c1f @@ -12958,6 +13306,13 @@ __metadata: languageName: node linkType: hard +"xmlchars@npm:^2.2.0": + version: 2.2.0 + resolution: "xmlchars@npm:2.2.0" + checksum: 8c70ac94070ccca03f47a81fcce3b271bd1f37a591bf5424e787ae313fcb9c212f5f6786e1fa82076a2c632c0141552babcd85698c437506dfa6ae2d58723062 + languageName: node + linkType: hard + "xtend@npm:^4.0.2": version: 4.0.2 resolution: "xtend@npm:4.0.2"