diff --git a/apps/live/package.json b/apps/live/package.json index 815fe779e..b773efb44 100644 --- a/apps/live/package.json +++ b/apps/live/package.json @@ -45,7 +45,6 @@ "express-ws": "^5.0.2", "helmet": "^7.1.0", "ioredis": "5.7.0", - "isomorphic-dompurify": "^1.8.0", "uuid": "catalog:", "ws": "^8.18.3", "y-prosemirror": "^1.3.7", diff --git a/apps/live/src/extensions/database.ts b/apps/live/src/extensions/database.ts index 4262ba1f0..5c496f52c 100644 --- a/apps/live/src/extensions/database.ts +++ b/apps/live/src/extensions/database.ts @@ -20,24 +20,32 @@ const fetchDocument = async ({ context, documentName: pageId, instance }: FetchP try { const service = getPageService(context.documentType, context); // fetch details - const response = await service.fetchDescriptionBinary(pageId); + const response = (await service.fetchDescriptionBinary(pageId)) as Buffer; const binaryData = new Uint8Array(response); // if binary data is empty, convert HTML to binary data if (binaryData.byteLength === 0) { const pageDetails = await service.fetchDetails(pageId); - const convertedBinaryData = getBinaryDataFromDocumentEditorHTMLString(pageDetails.description_html ?? "

"); + const convertedBinaryData = getBinaryDataFromDocumentEditorHTMLString( + pageDetails.description_html ?? "

", + pageDetails.name + ); if (convertedBinaryData) { // save the converted binary data back to the database - const { contentBinaryEncoded, contentHTML, contentJSON } = getAllDocumentFormatsFromDocumentEditorBinaryData( - convertedBinaryData, - true - ); - const payload = { - description_binary: contentBinaryEncoded, - description_html: contentHTML, - description: contentJSON, - }; - await service.updateDescriptionBinary(pageId, payload); + try { + const { contentBinaryEncoded, contentHTML, contentJSON } = getAllDocumentFormatsFromDocumentEditorBinaryData( + convertedBinaryData, + true + ); + const payload = { + description_binary: contentBinaryEncoded, + description_html: contentHTML, + description: contentJSON, + }; + await service.updateDescriptionBinary(pageId, payload); + } catch (e) { + const error = new AppError(e); + logger.error("Failed to save binary after first convertion from html:", error); + } return convertedBinaryData; } } diff --git a/apps/live/src/extensions/index.ts b/apps/live/src/extensions/index.ts index e82b1fb60..fb53ab790 100644 --- a/apps/live/src/extensions/index.ts +++ b/apps/live/src/extensions/index.ts @@ -1,5 +1,13 @@ import { Database } from "./database"; +import { ForceCloseHandler } from "./force-close-handler"; import { Logger } from "./logger"; import { Redis } from "./redis"; +import { TitleSyncExtension } from "./title-sync"; -export const getExtensions = () => [new Logger(), new Database(), new Redis()]; +export const getExtensions = () => [ + new Logger(), + new Database(), + new Redis(), + new TitleSyncExtension(), + new ForceCloseHandler(), // Must be after Redis to receive broadcasts +]; diff --git a/apps/live/src/extensions/title-sync.ts b/apps/live/src/extensions/title-sync.ts index 6e760b5f9..ca3783f14 100644 --- a/apps/live/src/extensions/title-sync.ts +++ b/apps/live/src/extensions/title-sync.ts @@ -1,18 +1,22 @@ // hocuspocus import type { Extension, Hocuspocus, Document } from "@hocuspocus/server"; import { TiptapTransformer } from "@hocuspocus/transformer"; +import type { AnyExtension, JSONContent } from "@tiptap/core"; import type * as Y from "yjs"; // editor extensions -import { TITLE_EDITOR_EXTENSIONS, createRealtimeEvent } from "@plane/editor"; +import { + TITLE_EDITOR_EXTENSIONS, + createRealtimeEvent, + extractTextFromHTML, + generateTitleProsemirrorJson, +} from "@plane/editor"; import { logger } from "@plane/logger"; import { AppError } from "@/lib/errors"; // helpers import { getPageService } from "@/services/page/handler"; import type { HocusPocusServerContext, OnLoadDocumentPayloadWithContext } from "@/types"; -import { generateTitleProsemirrorJson } from "@/utils"; import { broadcastMessageToPage } from "@/utils/broadcast-message"; import { TitleUpdateManager } from "./title-update/title-update-manager"; -import { extractTextFromHTML } from "./title-update/title-utils"; /** * Hocuspocus extension for synchronizing document titles @@ -41,15 +45,11 @@ export class TitleSyncExtension implements Extension { // in the yjs binary if (document.isEmpty("title")) { const service = getPageService(context.documentType, context); - // const title = await service.fe - const title = (await service.fetchDetails?.(documentName)).name; + const pageDetails = await service.fetchDetails(documentName); + const title = pageDetails.name; if (title == null) return; - const titleField = TiptapTransformer.toYdoc( - generateTitleProsemirrorJson(title), - "title", - // editor - TITLE_EDITOR_EXTENSIONS as any - ); + const titleJson = (generateTitleProsemirrorJson as (text: string) => JSONContent)(title); + const titleField = TiptapTransformer.toYdoc(titleJson, "title", TITLE_EDITOR_EXTENSIONS as AnyExtension[]); document.merge(titleField); } } catch (error) { diff --git a/apps/live/src/extensions/title-update/title-utils.ts b/apps/live/src/extensions/title-update/title-utils.ts deleted file mode 100644 index a9a145e37..000000000 --- a/apps/live/src/extensions/title-update/title-utils.ts +++ /dev/null @@ -1,21 +0,0 @@ -import DOMPurify from "isomorphic-dompurify"; - -/** - * Sanitizes HTML by removing all HTML tags, leaving only text content - * @param htmlString - The HTML string to sanitize - * @returns The sanitized text with all HTML tags removed - */ -const sanitizeHTML = (htmlString: string): string => { - const sanitizedText = DOMPurify.sanitize(htmlString, { ALLOWED_TAGS: [] }); // sanitize the string to remove all HTML tags - return sanitizedText.trim(); // trim the string to remove leading and trailing whitespaces -}; - -/** - * Utility function to extract text from HTML content - */ -export const extractTextFromHTML = (html: string): string => { - // Use sanitizeHTML to safely extract text and remove all HTML tags - // This is more secure than regex as it handles edge cases and prevents injection - // Note: sanitizeHTML trims whitespace, which is acceptable for title extraction - return sanitizeHTML(html) || ""; -}; diff --git a/apps/live/src/utils/document.ts b/apps/live/src/utils/document.ts deleted file mode 100644 index 318a506e0..000000000 --- a/apps/live/src/utils/document.ts +++ /dev/null @@ -1,21 +0,0 @@ -export const generateTitleProsemirrorJson = (text: string) => { - return { - type: "doc", - content: [ - { - type: "heading", - attrs: { level: 1 }, - ...(text - ? { - content: [ - { - type: "text", - text, - }, - ], - } - : {}), - }, - ], - }; -}; diff --git a/apps/live/src/utils/index.ts b/apps/live/src/utils/index.ts deleted file mode 100644 index fe6d89c0e..000000000 --- a/apps/live/src/utils/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from "./document"; diff --git a/apps/web/core/components/pages/editor/page-root.tsx b/apps/web/core/components/pages/editor/page-root.tsx index d81273f2c..9736be086 100644 --- a/apps/web/core/components/pages/editor/page-root.tsx +++ b/apps/web/core/components/pages/editor/page-root.tsx @@ -69,6 +69,7 @@ export const PageRoot = observer((props: TPageRootProps) => { const { isFetchingFallbackBinary } = usePageFallback({ editorRef, fetchPageDescription: handlers.fetchDescriptionBinary, + page, collaborationState, updatePageDescription: handlers.updateDescription, }); diff --git a/apps/web/core/hooks/use-page-fallback.ts b/apps/web/core/hooks/use-page-fallback.ts index 01475293f..2b88b0d5a 100644 --- a/apps/web/core/hooks/use-page-fallback.ts +++ b/apps/web/core/hooks/use-page-fallback.ts @@ -2,22 +2,22 @@ import { useCallback, useEffect, useRef, useState } from "react"; import type { EditorRefApi, CollaborationState } from "@plane/editor"; // plane editor import { convertBinaryDataToBase64String, getBinaryDataFromDocumentEditorHTMLString } from "@plane/editor"; -// plane propel -import { setToast, TOAST_TYPE } from "@plane/propel/toast"; // plane types import type { TDocumentPayload } from "@plane/types"; // hooks import useAutoSave from "@/hooks/use-auto-save"; +import type { TPageInstance } from "@/store/pages/base-page"; type TArgs = { editorRef: React.RefObject; fetchPageDescription: () => Promise; collaborationState: CollaborationState | null; updatePageDescription: (data: TDocumentPayload) => Promise; + page: TPageInstance; }; export const usePageFallback = (args: TArgs) => { - const { editorRef, fetchPageDescription, collaborationState, updatePageDescription } = args; + const { editorRef, fetchPageDescription, collaborationState, updatePageDescription, page } = args; const hasShownFallbackToast = useRef(false); const [isFetchingFallbackBinary, setIsFetchingFallbackBinary] = useState(false); @@ -32,12 +32,7 @@ export const usePageFallback = (args: TArgs) => { // Show toast notification when fallback mechanism kicks in (only once) if (!hasShownFallbackToast.current) { - // setToast({ - // type: TOAST_TYPE.WARNING, - // title: "Connection lost", - // message: "Your changes are being saved using backup mechanism. ", - // }); - console.log("Connection lost"); + console.warn("Websocket Connection lost, your changes are being saved using backup mechanism."); hasShownFallbackToast.current = true; } @@ -49,7 +44,11 @@ export const usePageFallback = (args: TArgs) => { if (latestEncodedDescription && latestEncodedDescription.byteLength > 0) { latestDecodedDescription = new Uint8Array(latestEncodedDescription); } else { - latestDecodedDescription = getBinaryDataFromDocumentEditorHTMLString("

"); + const pageDescriptionHtml = page.description_html; + latestDecodedDescription = getBinaryDataFromDocumentEditorHTMLString( + pageDescriptionHtml ?? "

", + page.name + ); } editor.setProviderDocument(latestDecodedDescription); @@ -64,15 +63,10 @@ export const usePageFallback = (args: TArgs) => { }); } catch (error: any) { console.error(error); - // setToast({ - // type: TOAST_TYPE.ERROR, - // title: "Error", - // message: `Failed to update description using backup mechanism, ${error?.message}`, - // }); } finally { setIsFetchingFallbackBinary(false); } - }, [editorRef, fetchPageDescription, hasConnectionFailed, updatePageDescription]); + }, [editorRef, fetchPageDescription, hasConnectionFailed, updatePageDescription, page.description_html, page.name]); useEffect(() => { if (hasConnectionFailed) { diff --git a/packages/editor/package.json b/packages/editor/package.json index 0c7cf9c28..f1e79781c 100644 --- a/packages/editor/package.json +++ b/packages/editor/package.json @@ -66,7 +66,6 @@ "emoji-regex": "^10.3.0", "highlight.js": "^11.8.0", "is-emoji-supported": "^0.0.5", - "isomorphic-dompurify": "^1.8.0", "jsx-dom-cjs": "^8.0.3", "linkifyjs": "^4.3.2", "lowlight": "^3.0.0", diff --git a/packages/editor/src/core/helpers/yjs-utils.ts b/packages/editor/src/core/helpers/yjs-utils.ts index b0ff65b30..bb7d1fef6 100644 --- a/packages/editor/src/core/helpers/yjs-utils.ts +++ b/packages/editor/src/core/helpers/yjs-utils.ts @@ -1,5 +1,5 @@ import { Buffer } from "buffer"; -import type { Extensions } from "@tiptap/core"; +import type { Extensions, JSONContent } from "@tiptap/core"; import { getSchema } from "@tiptap/core"; import { generateHTML, generateJSON } from "@tiptap/html"; import { prosemirrorJSONToYDoc, yXmlFragmentToProseMirrorRootNode } from "y-prosemirror"; @@ -11,7 +11,7 @@ import { DocumentEditorExtensionsWithoutProps, } from "@/extensions/core-without-props"; import { TitleExtensions } from "@/extensions/title-extension"; -import DOMPurify from "isomorphic-dompurify"; +import { sanitizeHTML } from "@plane/utils"; // editor extension configs const RICH_TEXT_EDITOR_EXTENSIONS = CoreEditorExtensionsWithoutProps; @@ -69,16 +69,49 @@ export const getBinaryDataFromRichTextEditorHTMLString = (descriptionHTML: strin return encodedData; }; +export const generateTitleProsemirrorJson = (text: string): JSONContent => { + return { + type: "doc", + content: [ + { + type: "heading", + attrs: { level: 1 }, + ...(text + ? { + content: [ + { + type: "text", + text, + }, + ], + } + : {}), + }, + ], + }; +}; + /** * @description this function generates the binary equivalent of html content for the document editor - * @param {string} descriptionHTML + * @param {string} descriptionHTML - The HTML content to convert + * @param {string} [title] - Optional title to append to the document * @returns {Uint8Array} */ -export const getBinaryDataFromDocumentEditorHTMLString = (descriptionHTML: string): Uint8Array => { +export const getBinaryDataFromDocumentEditorHTMLString = (descriptionHTML: string, title?: string): Uint8Array => { // convert HTML to JSON const contentJSON = generateJSON(descriptionHTML ?? "

", DOCUMENT_EDITOR_EXTENSIONS); // convert JSON to Y.Doc format const transformedData = prosemirrorJSONToYDoc(documentEditorSchema, contentJSON, "default"); + + // If title is provided, merge it into the document + if (title != null) { + const titleJSON = generateTitleProsemirrorJson(title); + const titleField = prosemirrorJSONToYDoc(documentEditorSchema, titleJSON, "title"); + // Encode the title YDoc to updates and apply them to the main document + const titleUpdates = Y.encodeStateAsUpdate(titleField); + Y.applyUpdate(transformedData, titleUpdates); + } + // convert Y.Doc to Uint8Array format const encodedData = Y.encodeStateAsUpdate(transformedData); return encodedData; @@ -210,6 +243,6 @@ export const extractTextFromHTML = (html: string): string => { // Use DOMPurify to safely extract text and remove all HTML tags // This is more secure than regex as it handles edge cases and prevents injection // Note: sanitizeHTML trims whitespace, which is acceptable for title extraction - const sanitizedText = DOMPurify.sanitize(html, { ALLOWED_TAGS: [] }); // sanitize the string to remove all HTML tags + const sanitizedText = sanitizeHTML(html); // sanitize the string to remove all HTML tags return sanitizedText.trim() || ""; // trim the string to remove leading and trailing whitespaces }; diff --git a/packages/utils/package.json b/packages/utils/package.json index 1adaf323b..c6294ff07 100644 --- a/packages/utils/package.json +++ b/packages/utils/package.json @@ -27,7 +27,6 @@ "@plane/types": "workspace:*", "clsx": "^2.1.1", "date-fns": "^4.1.0", - "dompurify": "3.2.7", "hast": "^1.0.0", "hast-util-to-mdast": "^10.1.2", "lodash-es": "catalog:", @@ -38,6 +37,7 @@ "rehype-remark": "^10.0.1", "remark-gfm": "^4.0.1", "remark-stringify": "^11.0.0", + "sanitize-html": "2.17.0", "tailwind-merge": "^2.5.5", "unified": "^11.0.5", "uuid": "catalog:" @@ -49,6 +49,7 @@ "@types/mdast": "^4.0.4", "@types/node": "catalog:", "@types/react": "catalog:", + "@types/sanitize-html": "2.16.0", "tsdown": "catalog:", "typescript": "catalog:" }, diff --git a/packages/utils/src/string.ts b/packages/utils/src/string.ts index cf5eb3df6..b23d1b9bd 100644 --- a/packages/utils/src/string.ts +++ b/packages/utils/src/string.ts @@ -1,4 +1,4 @@ -import DOMPurify from "dompurify"; +import sanitizeHtml from "sanitize-html"; import type { Content, JSONContent } from "@plane/types"; /** @@ -120,7 +120,7 @@ const text = stripHTML(html); console.log(text); // Some text */ export const sanitizeHTML = (htmlString: string) => { - const sanitizedText = DOMPurify.sanitize(htmlString, { ALLOWED_TAGS: [] }); // sanitize the string to remove all HTML tags + const sanitizedText = sanitizeHtml(htmlString, { allowedTags: [] }); // sanitize the string to remove all HTML tags return sanitizedText.trim(); // trim the string to remove leading and trailing whitespaces }; @@ -155,8 +155,8 @@ export const checkEmailValidity = (email: string): boolean => { }; export const isEmptyHtmlString = (htmlString: string, allowedHTMLTags: string[] = []) => { - // Remove HTML tags using DOMPurify - const cleanText = DOMPurify.sanitize(htmlString, { ALLOWED_TAGS: allowedHTMLTags }); + // Remove HTML tags using sanitize-html + const cleanText = sanitizeHtml(htmlString, { allowedTags: allowedHTMLTags }); // Trim the string and check if it's empty return cleanText.trim() === ""; }; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index b7778a183..81c799fe1 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -129,7 +129,7 @@ importers: version: 0.1.3 '@vitest/eslint-plugin': specifier: 1.5.1 - version: 1.5.1(eslint@9.39.1(jiti@2.5.1))(typescript@5.8.3)(vitest@4.0.15(@opentelemetry/api@1.9.0)(@types/node@22.12.0)(jiti@2.5.1)(jsdom@23.2.0)(terser@5.43.1)(yaml@2.8.1)) + version: 1.5.1(eslint@9.39.1(jiti@2.5.1))(typescript@5.8.3)(vitest@4.0.15(@opentelemetry/api@1.9.0)(@types/node@22.12.0)(jiti@2.5.1)(jsdom@25.0.1)(terser@5.43.1)(yaml@2.8.1)) eslint: specifier: 9.39.1 version: 9.39.1(jiti@2.5.1) @@ -371,9 +371,6 @@ importers: ioredis: specifier: 5.7.0 version: 5.7.0 - isomorphic-dompurify: - specifier: ^1.8.0 - version: 1.13.0 uuid: specifier: 'catalog:' version: 13.0.0 @@ -784,7 +781,7 @@ importers: version: 17.3.0 vitest: specifier: ^4.0.8 - version: 4.0.15(@opentelemetry/api@1.9.0)(@types/node@22.12.0)(jiti@2.5.1)(jsdom@23.2.0)(terser@5.43.1)(yaml@2.8.1) + version: 4.0.15(@opentelemetry/api@1.9.0)(@types/node@22.12.0)(jiti@2.5.1)(jsdom@25.0.1)(terser@5.43.1)(yaml@2.8.1) packages/constants: dependencies: @@ -942,9 +939,6 @@ importers: is-emoji-supported: specifier: ^0.0.5 version: 0.0.5 - isomorphic-dompurify: - specifier: ^1.8.0 - version: 1.13.0 jsx-dom-cjs: specifier: ^8.0.3 version: 8.1.6 @@ -1457,9 +1451,6 @@ importers: date-fns: specifier: ^4.1.0 version: 4.1.0 - dompurify: - specifier: 3.2.7 - version: 3.2.7 hast: specifier: ^1.0.0 version: 1.0.0 @@ -1490,6 +1481,9 @@ importers: remark-stringify: specifier: ^11.0.0 version: 11.0.0 + sanitize-html: + specifier: 2.17.0 + version: 2.17.0 tailwind-merge: specifier: ^2.5.5 version: 2.6.0 @@ -1518,6 +1512,9 @@ importers: '@types/react': specifier: 'catalog:' version: 18.3.11 + '@types/sanitize-html': + specifier: 2.16.0 + version: 2.16.0 tsdown: specifier: 'catalog:' version: 0.16.0(typescript@5.8.3) @@ -1547,9 +1544,6 @@ packages: '@asamuzakjp/css-color@3.2.0': resolution: {integrity: sha512-K1A6z8tS3XsmCMM86xoWdn7Fkdn9m6RSVtocUrJYIwZnFVkng/PvkEoWtOWmP+Scc6saYWHWZYbndEEXxl24jw==} - '@asamuzakjp/dom-selector@2.0.2': - resolution: {integrity: sha512-x1KXOatwofR6ZAYzXRBL5wrdV0vwNxlTCK9NCuLqAzQYARqGcvFwiJA6A1ERuh+dgeA4Dxm3JBYictIes+SqUQ==} - '@atlaskit/pragmatic-drag-and-drop-auto-scroll@1.4.0': resolution: {integrity: sha512-5GoikoTSW13UX76F9TDeWB8x3jbbGlp/Y+3aRkHe1MOBMkrWkwNpJ42MIVhhX/6NSeaZiPumP0KbGJVs2tOWSQ==} @@ -1836,8 +1830,8 @@ packages: resolution: {integrity: sha512-Ir+AOibqzrIsL6ajt3Rz3LskB7OiMVHqltZmspbW/TJuTVuyOMirVqAkjfY6JISiLHgyNqicAC8AyHHGzNd/dA==} engines: {node: '>=0.1.90'} - '@csstools/color-helpers@5.1.0': - resolution: {integrity: sha512-S11EXWJyy0Mz5SYvRmY8nJYTFFd1LCNV+7cXyAgQtOOuzb4EsgfqDufL+9esx72/eLhsRdGZwaldu/h+E4t4BA==} + '@csstools/color-helpers@5.0.2': + resolution: {integrity: sha512-JqWH1vsgdGcw2RR6VliXXdA0/59LttzlU8UlRT/iUUsEeWfYq8I+K0yhihEUTTHLRm1EXvpsCx3083EU15ecsA==} engines: {node: '>=18'} '@csstools/css-calc@2.1.4': @@ -1847,8 +1841,8 @@ packages: '@csstools/css-parser-algorithms': ^3.0.5 '@csstools/css-tokenizer': ^3.0.4 - '@csstools/css-color-parser@3.1.0': - resolution: {integrity: sha512-nbtKwh3a6xNVIp/VRuXV64yTKnb1IjTAEEh3irzS+HkKjAOYLTGNb9pmVNntZ8iVBHcWDA2Dof0QtPgFI1BaTA==} + '@csstools/css-color-parser@3.0.10': + resolution: {integrity: sha512-TiJ5Ajr6WRd1r8HSiwJvZBiJOqtH86aHpUjq5aEKWHiII2Qfjqd/HCWKPOW8EP4vcspXbHnXrwIDlu5savQipg==} engines: {node: '>=18'} peerDependencies: '@csstools/css-parser-algorithms': ^3.0.5 @@ -4031,10 +4025,6 @@ packages: '@types/dom4@2.0.4': resolution: {integrity: sha512-PD+wqNhrjWFjAlSVd18jvChZvOXB2SOwAILBmuYev5zswBats5qmzs/QFoooLKd2omj9BT05a8MeSeRmXLGY+Q==} - '@types/dompurify@3.2.0': - resolution: {integrity: sha512-Fgg31wv9QbLDA0SpTOXO3MaxySc4DKGLi8sna4/Utjo4r3ZRPdCt4UQee8BWr+Q5z21yifghREPJGYaEOEIACg==} - deprecated: This is a stub types definition. dompurify provides its own type definitions, so you do not need this installed. - '@types/eslint-scope@3.7.7': resolution: {integrity: sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==} @@ -4159,6 +4149,9 @@ packages: '@types/resolve@1.20.6': resolution: {integrity: sha512-A4STmOXPhMUtHH+S6ymgE2GiBSMqf4oTvcQZMcHzokuTLVYzXTB8ttjcgxOVaAp2lGwEdzZ0J+cRbbeevQj1UQ==} + '@types/sanitize-html@2.16.0': + resolution: {integrity: sha512-l6rX1MUXje5ztPT0cAFtUayXF06DqPhRyfVXareEN5gGCFaP/iwsxIyKODr9XDhfxPpN6vXUFNfo5kZMXCxBtw==} + '@types/semver@7.7.1': resolution: {integrity: sha512-FmgJfu+MOcQ370SD0ev7EI8TlCAfKYU+B4m5T3yXc1CiRN94g/SZPtsCkk506aUDtlMnFZvasDwHHUcZUEaYuA==} @@ -4882,9 +4875,6 @@ packages: resolution: {integrity: sha512-xlx1yCK2Oc1APsPXDL2LdlNP6+uu8OCDdhOBSVT279M/S+y75O30C2VuD8T2ogdePBBl7PfPF4504tnLgX3zfw==} engines: {node: '>=14.16'} - caniuse-lite@1.0.30001743: - resolution: {integrity: sha512-e6Ojr7RV14Un7dz6ASD0aZDmQPT/A+eZU+nuTNfjqmRrmkmQlnTNWH0SKmqagx9PeW87UVqapSurtAXifmtdmw==} - caniuse-lite@1.0.30001759: resolution: {integrity: sha512-Pzfx9fOKoKvevQf8oCXoyNRQ5QyxJj+3O0Rqx2V5oxT61KGx8+n6hV/IUyJeifUci2clnmmKVpvtiqRzgiWjSw==} @@ -5169,10 +5159,6 @@ packages: resolution: {integrity: sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q==} engines: {node: '>=8.0.0'} - css-tree@2.3.1: - resolution: {integrity: sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw==} - engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0} - css-what@6.2.2: resolution: {integrity: sha512-u/O3vwbptzhMs3L1fQE82ZSLHQQfto5gyZzwteVIEyeaY5Fc7R4dapF/BvRoSYFeqfBk4m0V1Vafq5Pjv25wvA==} engines: {node: '>= 6'} @@ -5277,15 +5263,6 @@ packages: supports-color: optional: true - debug@4.4.1: - resolution: {integrity: sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==} - engines: {node: '>=6.0'} - peerDependencies: - supports-color: '*' - peerDependenciesMeta: - supports-color: - optional: true - debug@4.4.3: resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==} engines: {node: '>=6.0'} @@ -5447,12 +5424,6 @@ packages: resolution: {integrity: sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==} engines: {node: '>= 4'} - dompurify@3.2.6: - resolution: {integrity: sha512-/2GogDQlohXPZe6D6NOgQvXLPSYBqIWMnZ8zzOhn09REE4eyAzb+Hed3jhoM9OkuaJ8P6ZGTTVWQKAi8ieIzfQ==} - - dompurify@3.2.7: - resolution: {integrity: sha512-WhL/YuveyGXJaerVlMYGWhvQswa7myDG17P7Vu65EWC05o8vfeNbvNf4d/BOvH99+ZW+LlQsc1GDKMa1vNK6dw==} - domutils@2.8.0: resolution: {integrity: sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==} @@ -6315,6 +6286,9 @@ packages: htmlparser2@6.1.0: resolution: {integrity: sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==} + htmlparser2@8.0.2: + resolution: {integrity: sha512-GYdjWKDkbRLkZ5geuHs5NY1puJ+PXwP7+fHPRz06Eirsb9ugf6d8kkXav6ADhcODhFFPMIXyxkxSuMf3D6NCFA==} + http-errors@2.0.0: resolution: {integrity: sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==} engines: {node: '>= 0.8'} @@ -6527,6 +6501,10 @@ packages: resolution: {integrity: sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==} engines: {node: '>=0.10.0'} + is-plain-object@5.0.0: + resolution: {integrity: sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==} + engines: {node: '>=0.10.0'} + is-port-reachable@4.0.0: resolution: {integrity: sha512-9UoipoxYmSk6Xy7QFgRv2HDyaysmgSG75TFQs6S+3pDM7ZhKTF/bskZV+0UlABHzKjNVhPjYCLfeZUEg1wXxig==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} @@ -6599,10 +6577,6 @@ packages: resolution: {integrity: sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==} engines: {node: '>=0.10.0'} - isomorphic-dompurify@1.13.0: - resolution: {integrity: sha512-9qOYGngy9ZR9JB/iLmr7SViPSZ7uWGvepdnLaXYznbTxvJOCuONneKajJ54f+IRQpvL8608ylUy9EK1iPtL3Ag==} - engines: {node: '>=18'} - isomorphic.js@0.2.5: resolution: {integrity: sha512-PIeMbHqMt4DnUP3MA/Flc0HElYjMXArsw1qwJZcm9sqR8mq3l8NYizFMty0pWwE/tzIGH3EKK5+jes5mAr85yw==} @@ -6650,8 +6624,8 @@ packages: resolution: {integrity: sha512-iZ8Bdb84lWRuGHamRXFyML07r21pcwBrLkHEuHgEY5UbCouBwv7ECknDRKzsQIXMiqpPymqtIf8TC/shYKB5rw==} engines: {node: '>=12.0.0'} - jsdom@23.2.0: - resolution: {integrity: sha512-L88oL7D/8ufIES+Zjz7v0aes+oBMh2Xnh3ygWvL0OaICOomKEPKuPnIfBJekiXr+BHbbMjrWn/xqrDQuxFTeyA==} + jsdom@25.0.1: + resolution: {integrity: sha512-8i7LzZj7BF8uplX+ZyOlIz86V6TAsSs+np6m1kpW9u0JWi4z/1t+FzcK1aek+ybTnAC4KhBL4uXCNT0wcUIeCw==} engines: {node: '>=18'} peerDependencies: canvas: ^2.11.2 @@ -6955,9 +6929,6 @@ packages: mdn-data@2.0.14: resolution: {integrity: sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==} - mdn-data@2.0.30: - resolution: {integrity: sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==} - mdurl@2.0.0: resolution: {integrity: sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==} @@ -7374,6 +7345,9 @@ packages: nth-check@2.1.1: resolution: {integrity: sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==} + nwsapi@2.2.21: + resolution: {integrity: sha512-o6nIY3qwiSXl7/LuOU0Dmuctd34Yay0yeuZRLFmDPrrdHpXKFndPj3hM+YEPVHYC5fx2otBx4Ilc/gyYSAUaIA==} + object-assign@4.1.1: resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} engines: {node: '>=0.10.0'} @@ -7529,6 +7503,9 @@ packages: resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} engines: {node: '>=8'} + parse-srcset@1.0.2: + resolution: {integrity: sha512-/2qh0lav6CmI15FzA3i/2Bzk2zCgQhGMkvhOhKNcBVQ1ldgpbfiNTVslmooUmWJcADi1f1kIeynbDRVzNlfR6Q==} + parse-svg-path@0.1.2: resolution: {integrity: sha512-JyPSBnkTJ0AI8GGJLfMXvKq42cj5c006fnLz6fXy6zfoVjJizi8BNTpu8on8ziI1cKy9d9DGNuY17Ce7wuejpQ==} @@ -7914,9 +7891,6 @@ packages: proxy-from-env@1.1.0: resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==} - psl@1.15.0: - resolution: {integrity: sha512-JZd3gMVBAVQkSs6HdNZo9Sdo0LNcQeMNP3CozBJb3JYC/QUYZTnKxP+f8oWRX4rHP5EurWxqAHTSwUCjlNKa1w==} - punycode.js@2.3.1: resolution: {integrity: sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==} engines: {node: '>=6'} @@ -7939,9 +7913,6 @@ packages: quansync@0.2.11: resolution: {integrity: sha512-AifT7QEbW9Nri4tAwR5M/uzpBuqfZf+zwaEM/QkzEjj7NBuFD2rBuy0K3dE+8wltbezDV7JMA0WfnCPYRSYbXA==} - querystringify@2.2.0: - resolution: {integrity: sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==} - queue-microtask@1.2.3: resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} @@ -8236,9 +8207,6 @@ packages: resolution: {integrity: sha512-QT7FVMXfWOYFbeRBF6nu+I6tr2Tf3u0q8RIEjNob/heKY/nh7drD/k7eeMFmSQgnTtCzLDcCu/XEnpW2wk4xCQ==} engines: {node: '>=9.3.0 || >=8.10.0 <9.0.0'} - requires-port@1.0.0: - resolution: {integrity: sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==} - reselect@5.1.1: resolution: {integrity: sha512-K/BG6eIky/SBpzfHZv/dd+9JBFiS4SWV7FIujVyJRux6e45+73RaUHXLmIR1f7WOMaQ0U1km6qwklRQxpJJY0w==} @@ -8313,8 +8281,8 @@ packages: rope-sequence@1.3.4: resolution: {integrity: sha512-UT5EDe2cu2E/6O4igUr5PSFs23nvvukicWHx6GnOPlHAiiYbzNuCRQCuiUdHJQcqKalLKlrYJnjY0ySGsXNQXQ==} - rrweb-cssom@0.6.0: - resolution: {integrity: sha512-APM0Gt1KoXBz0iIkkdB/kfvGOwC4UuJFeG/c+yV7wSc7q96cG/kJ0HiYCnzivD9SB53cLV1MlHFNfOuPaadYSw==} + rrweb-cssom@0.7.1: + resolution: {integrity: sha512-TrEMa7JGdVm0UThDJSx7ddw5nVm3UJS9o9CCIZ72B1vSyEZoziDqBYP3XIoi/12lKrJR8rE3jeFHMok2F/Mnsg==} rrweb-cssom@0.8.0: resolution: {integrity: sha512-guoltQEx+9aMf2gDZ0s62EcV8lsXR+0w8915TC3ITdn2YueuNjdAYh/levpU9nFaoChh9RUS5ZdQMrKfVEN9tw==} @@ -8351,6 +8319,9 @@ packages: safer-buffer@2.1.2: resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} + sanitize-html@2.17.0: + resolution: {integrity: sha512-dLAADUSS8rBwhaevT12yCezvioCA+bmUTPH/u57xKPT8d++voeYE6HeluA/bPbQ15TwDBG2ii+QZIEmYx8VdxA==} + saxes@6.0.0: resolution: {integrity: sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==} engines: {node: '>=v12.22.7'} @@ -8814,6 +8785,13 @@ packages: peerDependencies: '@tiptap/core': ^2.0.3 + tldts-core@6.1.86: + resolution: {integrity: sha512-Je6p7pkk+KMzMv2XXKmAE3McmolOQFdxkKw0R8EYNr7sELW46JqnNeTX8ybPiQgvg1ymCoF8LXs5fzFaZvJPTA==} + + tldts@6.1.86: + resolution: {integrity: sha512-WMi/OQ2axVTf/ykqCQgXiIct+mSQDFdH2fkwhPwgEwvJ1kSzZRiinb0zF2Xb8u4+OqPChmyI6MEu4EezNJz+FQ==} + hasBin: true + tmp@0.2.5: resolution: {integrity: sha512-voyz6MApa1rQGUxT3E+BK7/ROe8itEx7vD8/HEvt4xwXucvQ5G5oeEiHkmHZJuBO21RpOf+YYm9MOivj709jow==} engines: {node: '>=14.14'} @@ -8830,9 +8808,9 @@ packages: resolution: {integrity: sha512-kh9LVIWH5CnL63Ipf0jhlBIy0UsrMj/NJDfpsy1SqOXlLKEVyXXYrnFxFT1yOOYVGBSApeVnjPw/sBz5BfEjAQ==} engines: {node: '>=14.16'} - tough-cookie@4.1.4: - resolution: {integrity: sha512-Loo5UUvLD9ScZ6jh8beX1T6sO1w2/MpCRpEP7V280GKMVUQ0Jzar2U3UJPsrdbziLEMMhu3Ujnq//rhiFuIeag==} - engines: {node: '>=6'} + tough-cookie@5.1.2: + resolution: {integrity: sha512-FVDYdxtnj0G6Qm/DhNPSb8Ju59ULcup3tuJxkFb5K8Bv2pUXILbf0xZWU8PX8Ov19OXljbUyveOFwRMwkXzO+A==} + engines: {node: '>=16'} tr46@0.0.3: resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} @@ -9070,10 +9048,6 @@ packages: unist-util-visit@5.0.0: resolution: {integrity: sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==} - universalify@0.2.0: - resolution: {integrity: sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==} - engines: {node: '>= 4.0.0'} - universalify@2.0.1: resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==} engines: {node: '>= 10.0.0'} @@ -9110,9 +9084,6 @@ packages: uri-js@4.4.1: resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} - url-parse@1.5.10: - resolution: {integrity: sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==} - url@0.11.4: resolution: {integrity: sha512-oCwdVC7mTuWiPyjLUz/COz5TLk6wgp0RCsN+wHZ2Ekneac9w8uuV0njcbbie2ME+Vs+d6duwmYuR3HgQXs1fOg==} engines: {node: '>= 0.4'} @@ -9583,16 +9554,11 @@ snapshots: '@asamuzakjp/css-color@3.2.0': dependencies: '@csstools/css-calc': 2.1.4(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) - '@csstools/css-color-parser': 3.1.0(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) + '@csstools/css-color-parser': 3.0.10(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) '@csstools/css-tokenizer': 3.0.4 lru-cache: 10.4.3 - - '@asamuzakjp/dom-selector@2.0.2': - dependencies: - bidi-js: 1.0.3 - css-tree: 2.3.1 - is-potential-custom-element-name: 1.0.1 + optional: true '@atlaskit/pragmatic-drag-and-drop-auto-scroll@1.4.0': dependencies: @@ -10010,25 +9976,30 @@ snapshots: '@colors/colors@1.6.0': {} - '@csstools/color-helpers@5.1.0': {} + '@csstools/color-helpers@5.0.2': + optional: true '@csstools/css-calc@2.1.4(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4)': dependencies: '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) '@csstools/css-tokenizer': 3.0.4 + optional: true - '@csstools/css-color-parser@3.1.0(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4)': + '@csstools/css-color-parser@3.0.10(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4)': dependencies: - '@csstools/color-helpers': 5.1.0 + '@csstools/color-helpers': 5.0.2 '@csstools/css-calc': 2.1.4(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) '@csstools/css-tokenizer': 3.0.4 + optional: true '@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4)': dependencies: '@csstools/css-tokenizer': 3.0.4 + optional: true - '@csstools/css-tokenizer@3.0.4': {} + '@csstools/css-tokenizer@3.0.4': + optional: true '@dabh/diagnostics@2.0.3': dependencies: @@ -12433,10 +12404,6 @@ snapshots: '@types/dom4@2.0.4': {} - '@types/dompurify@3.2.0': - dependencies: - dompurify: 3.2.6 - '@types/eslint-scope@3.7.7': dependencies: '@types/eslint': 9.6.1 @@ -12581,6 +12548,10 @@ snapshots: '@types/resolve@1.20.6': {} + '@types/sanitize-html@2.16.0': + dependencies: + htmlparser2: 8.0.2 + '@types/semver@7.7.1': {} '@types/send@0.17.5': @@ -12818,14 +12789,14 @@ snapshots: '@unrs/resolver-binding-win32-x64-msvc@1.11.1': optional: true - '@vitest/eslint-plugin@1.5.1(eslint@9.39.1(jiti@2.5.1))(typescript@5.8.3)(vitest@4.0.15(@opentelemetry/api@1.9.0)(@types/node@22.12.0)(jiti@2.5.1)(jsdom@23.2.0)(terser@5.43.1)(yaml@2.8.1))': + '@vitest/eslint-plugin@1.5.1(eslint@9.39.1(jiti@2.5.1))(typescript@5.8.3)(vitest@4.0.15(@opentelemetry/api@1.9.0)(@types/node@22.12.0)(jiti@2.5.1)(jsdom@25.0.1)(terser@5.43.1)(yaml@2.8.1))': dependencies: '@typescript-eslint/scope-manager': 8.49.0 '@typescript-eslint/utils': 8.49.0(eslint@9.39.1(jiti@2.5.1))(typescript@5.8.3) eslint: 9.39.1(jiti@2.5.1) optionalDependencies: typescript: 5.8.3 - vitest: 4.0.15(@opentelemetry/api@1.9.0)(@types/node@22.12.0)(jiti@2.5.1)(jsdom@23.2.0)(terser@5.43.1)(yaml@2.8.1) + vitest: 4.0.15(@opentelemetry/api@1.9.0)(@types/node@22.12.0)(jiti@2.5.1)(jsdom@25.0.1)(terser@5.43.1)(yaml@2.8.1) transitivePeerDependencies: - supports-color @@ -13035,11 +13006,12 @@ snapshots: agent-base@6.0.2: dependencies: - debug: 4.4.1 + debug: 4.4.3 transitivePeerDependencies: - supports-color - agent-base@7.1.4: {} + agent-base@7.1.4: + optional: true ajv-formats@2.1.1(ajv@8.17.1): optionalDependencies: @@ -13399,8 +13371,6 @@ snapshots: camelcase@7.0.1: {} - caniuse-lite@1.0.30001743: {} - caniuse-lite@1.0.30001759: {} capital-case@1.0.4: @@ -13706,11 +13676,6 @@ snapshots: mdn-data: 2.0.14 source-map: 0.6.1 - css-tree@2.3.1: - dependencies: - mdn-data: 2.0.30 - source-map-js: 1.2.1 - css-what@6.2.2: {} css.escape@1.5.1: {} @@ -13721,6 +13686,7 @@ snapshots: dependencies: '@asamuzakjp/css-color': 3.2.0 rrweb-cssom: 0.8.0 + optional: true csstype@3.1.3: {} @@ -13768,6 +13734,7 @@ snapshots: dependencies: whatwg-mimetype: 4.0.0 whatwg-url: 14.2.0 + optional: true data-view-buffer@1.0.2: dependencies: @@ -13799,10 +13766,6 @@ snapshots: dependencies: ms: 2.1.3 - debug@4.4.1: - dependencies: - ms: 2.1.3 - debug@4.4.3: dependencies: ms: 2.1.3 @@ -13933,14 +13896,6 @@ snapshots: dependencies: domelementtype: 2.3.0 - dompurify@3.2.6: - optionalDependencies: - '@types/trusted-types': 2.0.7 - - dompurify@3.2.7: - optionalDependencies: - '@types/trusted-types': 2.0.7 - domutils@2.8.0: dependencies: dom-serializer: 1.4.1 @@ -15006,6 +14961,7 @@ snapshots: html-encoding-sniffer@4.0.0: dependencies: whatwg-encoding: 3.1.1 + optional: true html-entities@2.6.0: {} @@ -15038,6 +14994,13 @@ snapshots: domutils: 2.8.0 entities: 2.2.0 + htmlparser2@8.0.2: + dependencies: + domelementtype: 2.3.0 + domhandler: 5.0.3 + domutils: 3.2.2 + entities: 4.5.0 + http-errors@2.0.0: dependencies: depd: 2.0.0 @@ -15049,23 +15012,25 @@ snapshots: http-proxy-agent@7.0.2: dependencies: agent-base: 7.1.4 - debug: 4.4.1 + debug: 4.4.3 transitivePeerDependencies: - supports-color + optional: true https-proxy-agent@5.0.1: dependencies: agent-base: 6.0.2 - debug: 4.4.1 + debug: 4.4.3 transitivePeerDependencies: - supports-color https-proxy-agent@7.0.6: dependencies: agent-base: 7.1.4 - debug: 4.4.1 + debug: 4.4.3 transitivePeerDependencies: - supports-color + optional: true human-signals@2.1.0: {} @@ -15080,6 +15045,7 @@ snapshots: iconv-lite@0.6.3: dependencies: safer-buffer: 2.1.2 + optional: true icss-utils@5.1.0(postcss@8.5.6): dependencies: @@ -15267,9 +15233,12 @@ snapshots: dependencies: isobject: 3.0.1 + is-plain-object@5.0.0: {} + is-port-reachable@4.0.0: {} - is-potential-custom-element-name@1.0.1: {} + is-potential-custom-element-name@1.0.1: + optional: true is-regex@1.2.1: dependencies: @@ -15328,17 +15297,6 @@ snapshots: isobject@3.0.1: {} - isomorphic-dompurify@1.13.0: - dependencies: - '@types/dompurify': 3.2.0 - dompurify: 3.2.6 - jsdom: 23.2.0 - transitivePeerDependencies: - - bufferutil - - canvas - - supports-color - - utf-8-validate - isomorphic.js@0.2.5: {} iterator.prototype@1.1.5: @@ -15399,9 +15357,8 @@ snapshots: jsdoc-type-pratt-parser@4.8.0: {} - jsdom@23.2.0: + jsdom@25.0.1: dependencies: - '@asamuzakjp/dom-selector': 2.0.2 cssstyle: 4.6.0 data-urls: 5.0.0 decimal.js: 10.6.0 @@ -15410,11 +15367,12 @@ snapshots: http-proxy-agent: 7.0.2 https-proxy-agent: 7.0.6 is-potential-custom-element-name: 1.0.1 + nwsapi: 2.2.21 parse5: 7.3.0 - rrweb-cssom: 0.6.0 + rrweb-cssom: 0.7.1 saxes: 6.0.0 symbol-tree: 3.2.4 - tough-cookie: 4.1.4 + tough-cookie: 5.1.2 w3c-xmlserializer: 5.0.0 webidl-conversions: 7.0.0 whatwg-encoding: 3.1.1 @@ -15426,6 +15384,7 @@ snapshots: - bufferutil - supports-color - utf-8-validate + optional: true jsesc@3.0.2: {} @@ -15613,7 +15572,8 @@ snapshots: devlop: 1.1.0 highlight.js: 11.11.1 - lru-cache@10.4.3: {} + lru-cache@10.4.3: + optional: true lru-cache@11.2.1: {} @@ -15813,8 +15773,6 @@ snapshots: mdn-data@2.0.14: {} - mdn-data@2.0.30: {} - mdurl@2.0.0: {} media-engine@1.0.3: {} @@ -16287,7 +16245,7 @@ snapshots: '@next/env': 14.2.32 '@swc/helpers': 0.5.5 busboy: 1.6.0 - caniuse-lite: 1.0.30001743 + caniuse-lite: 1.0.30001759 graceful-fs: 4.2.11 postcss: 8.4.31 react: 18.3.1 @@ -16313,7 +16271,7 @@ snapshots: '@next/env': 14.2.32 '@swc/helpers': 0.5.5 busboy: 1.6.0 - caniuse-lite: 1.0.30001743 + caniuse-lite: 1.0.30001759 graceful-fs: 4.2.11 postcss: 8.4.31 react: 18.3.1 @@ -16401,6 +16359,9 @@ snapshots: dependencies: boolbase: 1.0.0 + nwsapi@2.2.21: + optional: true + object-assign@4.1.1: {} object-hash@3.0.0: {} @@ -16583,6 +16544,8 @@ snapshots: json-parse-even-better-errors: 2.3.1 lines-and-columns: 1.2.4 + parse-srcset@1.0.2: {} + parse-svg-path@0.1.2: {} parse5@7.3.0: @@ -16956,10 +16919,6 @@ snapshots: proxy-from-env@1.1.0: {} - psl@1.15.0: - dependencies: - punycode: 2.3.1 - punycode.js@2.3.1: {} punycode@1.4.1: {} @@ -16976,8 +16935,6 @@ snapshots: quansync@0.2.11: {} - querystringify@2.2.0: {} - queue-microtask@1.2.3: {} queue@6.0.2: @@ -17385,8 +17342,6 @@ snapshots: transitivePeerDependencies: - supports-color - requires-port@1.0.0: {} - reselect@5.1.1: {} resolve-from@4.0.0: {} @@ -17489,9 +17444,11 @@ snapshots: rope-sequence@1.3.4: {} - rrweb-cssom@0.6.0: {} + rrweb-cssom@0.7.1: + optional: true - rrweb-cssom@0.8.0: {} + rrweb-cssom@0.8.0: + optional: true run-parallel@1.2.0: dependencies: @@ -17528,9 +17485,19 @@ snapshots: safer-buffer@2.1.2: {} + sanitize-html@2.17.0: + dependencies: + deepmerge: 4.3.1 + escape-string-regexp: 4.0.0 + htmlparser2: 8.0.2 + is-plain-object: 5.0.0 + parse-srcset: 1.0.2 + postcss: 8.5.6 + saxes@6.0.0: dependencies: xmlchars: 2.2.0 + optional: true scheduler@0.17.0: dependencies: @@ -17973,7 +17940,8 @@ snapshots: react: 18.3.1 use-sync-external-store: 1.5.0(react@18.3.1) - symbol-tree@3.2.4: {} + symbol-tree@3.2.4: + optional: true tabbable@6.2.0: {} @@ -18084,6 +18052,14 @@ snapshots: markdown-it-task-lists: 2.1.1 prosemirror-markdown: 1.13.2 + tldts-core@6.1.86: + optional: true + + tldts@6.1.86: + dependencies: + tldts-core: 6.1.86 + optional: true + tmp@0.2.5: {} to-regex-range@5.0.1: @@ -18098,18 +18074,17 @@ snapshots: '@tokenizer/token': 0.3.0 ieee754: 1.2.1 - tough-cookie@4.1.4: + tough-cookie@5.1.2: dependencies: - psl: 1.15.0 - punycode: 2.3.1 - universalify: 0.2.0 - url-parse: 1.5.10 + tldts: 6.1.86 + optional: true tr46@0.0.3: {} tr46@5.1.1: dependencies: punycode: 2.3.1 + optional: true tree-kill@1.2.2: {} @@ -18367,8 +18342,6 @@ snapshots: unist-util-is: 6.0.0 unist-util-visit-parents: 6.0.1 - universalify@0.2.0: {} - universalify@2.0.1: {} unpipe@1.0.0: {} @@ -18432,11 +18405,6 @@ snapshots: dependencies: punycode: 2.3.1 - url-parse@1.5.10: - dependencies: - querystringify: 2.2.0 - requires-port: 1.0.0 - url@0.11.4: dependencies: punycode: 1.4.1 @@ -18603,7 +18571,7 @@ snapshots: terser: 5.43.1 yaml: 2.8.1 - vitest@4.0.15(@opentelemetry/api@1.9.0)(@types/node@22.12.0)(jiti@2.5.1)(jsdom@23.2.0)(terser@5.43.1)(yaml@2.8.1): + vitest@4.0.15(@opentelemetry/api@1.9.0)(@types/node@22.12.0)(jiti@2.5.1)(jsdom@25.0.1)(terser@5.43.1)(yaml@2.8.1): dependencies: '@vitest/expect': 4.0.15 '@vitest/mocker': 4.0.15(vite@7.1.11(@types/node@22.12.0)(jiti@2.5.1)(terser@5.43.1)(yaml@2.8.1)) @@ -18628,7 +18596,7 @@ snapshots: optionalDependencies: '@opentelemetry/api': 1.9.0 '@types/node': 22.12.0 - jsdom: 23.2.0 + jsdom: 25.0.1 transitivePeerDependencies: - jiti - less @@ -18647,6 +18615,7 @@ snapshots: w3c-xmlserializer@5.0.0: dependencies: xml-name-validator: 5.0.0 + optional: true warning@4.0.3: dependencies: @@ -18663,7 +18632,8 @@ snapshots: webidl-conversions@3.0.1: {} - webidl-conversions@7.0.0: {} + webidl-conversions@7.0.0: + optional: true webpack-dev-middleware@6.1.3(webpack@5.101.3(@swc/core@1.13.5(@swc/helpers@0.5.17))(esbuild@0.25.0)): dependencies: @@ -18722,13 +18692,16 @@ snapshots: whatwg-encoding@3.1.1: dependencies: iconv-lite: 0.6.3 + optional: true - whatwg-mimetype@4.0.0: {} + whatwg-mimetype@4.0.0: + optional: true whatwg-url@14.2.0: dependencies: tr46: 5.1.1 webidl-conversions: 7.0.0 + optional: true whatwg-url@5.0.0: dependencies: @@ -18846,9 +18819,11 @@ snapshots: ws@8.18.3: {} - xml-name-validator@5.0.0: {} + xml-name-validator@5.0.0: + optional: true - xmlchars@2.2.0: {} + xmlchars@2.2.0: + optional: true xtend@4.0.2: {}