diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5ab8cc36..ab57ef66 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -34,6 +34,8 @@ jobs: run: pnpm --filter @mdbase-reader/app exec playwright install --with-deps chromium - name: Verify PDF gestures and mobile highlight persistence run: pnpm --filter @mdbase-reader/app test:pdf-touch + - name: Verify imported SVG rendering in the HTML sandbox + run: pnpm --filter @mdbase-reader/app test:html-svg - name: Verify private feedback with sample data and intercepted delivery env: VITE_MDBASE_FEEDBACK_URL: http://127.0.0.1:8891/v1/feedback diff --git a/apps/reader/package.json b/apps/reader/package.json index a6bb2713..3832ba88 100644 --- a/apps/reader/package.json +++ b/apps/reader/package.json @@ -18,6 +18,7 @@ "preview": "vite preview --host 127.0.0.1", "test": "pnpm manifest && pnpm manifest:verify && node --test scripts/*.test.mjs && vitest run src capture --maxWorkers=2 --testTimeout=15000", "test:browser": "node scripts/audit-reader.mjs", + "test:html-svg": "node scripts/audit-html-svg.mjs", "test:feedback": "node scripts/feedback-browser-test.mjs", "test:pdf-touch": "node scripts/run-pdf-touch-audits.mjs", "typecheck": "tsc -p tsconfig.json", diff --git a/apps/reader/scripts/audit-html-svg.mjs b/apps/reader/scripts/audit-html-svg.mjs new file mode 100644 index 00000000..52614c0c --- /dev/null +++ b/apps/reader/scripts/audit-html-svg.mjs @@ -0,0 +1,76 @@ +import { readFile } from "node:fs/promises"; +import { resolve } from "node:path"; + +import { chromium, expect } from "@playwright/test"; +import { createServer } from "vite"; + +// The production reproduction, rendered in Reader's script-disabled HTML sandbox. +const root = resolve(import.meta.dirname, ".."); +const fixture = await readFile( + resolve(root, "../../packages/renderer-html/src/fixtures/imported-svg.html"), + "utf8", +); +const server = await createServer({ + root, + server: { host: "127.0.0.1", port: 0, strictPort: true }, +}); +let browser; +try { + await server.listen(); + const address = server.httpServer.address(); + const origin = `http://127.0.0.1:${address.port}`; + browser = await chromium.launch({ headless: true }); + const page = await browser.newPage(); + const externalRequests = []; + await page.route("**/*", (route) => { + if (new URL(route.request().url()).origin === origin) return route.continue(); + externalRequests.push(route.request().url()); + return route.abort(); + }); + // No app, collection, daemon or production network access is needed. + await page.route(`${origin}/svg-test`, (route) => + route.fulfill({ + contentType: "text/html", + body: "SVG regression", + }), + ); + await page.goto(`${origin}/svg-test`); + const moduleUrl = `/@fs${resolve(root, "../../packages/renderer-html/src/html-document.ts")}`; + for (const passes of [0, 1, 2]) { + await page.evaluate( + async ({ fixture, moduleUrl, passes }) => { + const { prepareHtmlDocument } = await import(moduleUrl); + let source = fixture; + for (let pass = 0; pass < passes; pass++) source = prepareHtmlDocument(source); + const frame = globalThis.document.createElement("iframe"); + frame.sandbox = "allow-same-origin"; + frame.title = "HTML reading document"; + globalThis.document.body.replaceChildren(frame); + await new Promise((resolveLoad) => { + frame.onload = resolveLoad; + frame.srcdoc = source; + }); + }, + { fixture, moduleUrl, passes }, + ); + const frame = page.frameLocator("iframe"); + const image = frame.getByAltText("Test image"); + await expect + .poll(() => image.evaluate((image) => [image.naturalWidth, image.naturalHeight])) + .toEqual([30, 30]); + await expect(frame.locator("code")).toHaveText("const example = 42;"); + if (passes) { + await expect(frame.locator('meta[http-equiv="Content-Security-Policy"]')).toHaveAttribute( + "content", + "default-src 'none'; img-src data: blob:; style-src 'unsafe-inline'; font-src data:; base-uri 'none'; form-action 'none'", + ); + } + } + expect(externalRequests).toEqual([]); + console.log( + "Imported SVG: 30×30 in Chrome and after both Reader sanitization passes; CSP unchanged.", + ); +} finally { + await browser?.close(); + await server.close(); +} diff --git a/packages/renderer-html/package.json b/packages/renderer-html/package.json index 6f151198..dfd4d59b 100644 --- a/packages/renderer-html/package.json +++ b/packages/renderer-html/package.json @@ -15,10 +15,12 @@ "@lingui/react": "6.9.0", "@mdbase-reader/core": "workspace:*", "@mdbase-reader/reading-surface": "workspace:*", + "dompurify": "^3.4.17", "react": "^19.2.8" }, "devDependencies": { "@types/react": "^19.2.14", - "happy-dom": "^20.11.2" + "happy-dom": "^20.11.2", + "jsdom": "28.1.0" } } diff --git a/packages/renderer-html/src/fixtures/imported-svg.html b/packages/renderer-html/src/fixtures/imported-svg.html new file mode 100644 index 00000000..c4be4349 --- /dev/null +++ b/packages/renderer-html/src/fixtures/imported-svg.html @@ -0,0 +1,26 @@ + + + + [test] agent-20261029T030716Z-R2-1a2 reader + + + +

[test] agent-20261029T030716Z-R2-1a2 reader

+

Unicode: café 漢字 🐨

+ + + + + + + + + +
ItemValue
Alpha42
+
const example = 42;
+ Test image + + diff --git a/packages/renderer-html/src/html-document.test.ts b/packages/renderer-html/src/html-document.test.ts index 3c02a6e3..ba0625c3 100644 --- a/packages/renderer-html/src/html-document.test.ts +++ b/packages/renderer-html/src/html-document.test.ts @@ -1,9 +1,22 @@ -// @vitest-environment happy-dom +// @vitest-environment jsdom +import { readFileSync } from "node:fs"; +import { resolve } from "node:path"; + import { describe, expect, it } from "vitest"; import { extractArchivedHtmlText, prepareHtmlDocument } from "./html-document.js"; describe("prepareHtmlDocument", () => { + it("retains the embedded SVG image from the production import fixture", () => { + const source = readFileSync(resolve(import.meta.dirname, "fixtures/imported-svg.html"), "utf8"); + const rendered = new DOMParser().parseFromString(prepareHtmlDocument(source), "text/html"); + const image = rendered.querySelector("img"); + expect(image?.getAttribute("src")).toMatch(/^data:image\/svg\+xml,/u); + expect(image?.getAttribute("alt")).toBe("Test image"); + expect(rendered.querySelector("td")?.textContent).toBe("Alpha"); + expect(rendered.querySelector("code")?.textContent).toBe("const example = 42;"); + expect(rendered.body.textContent).toContain("Unicode: café 漢字 🐨"); + }); it("shares background index text with the rendered document, without executing markup", () => { const source = "Not body text

CAFÉ 世界文学

"; diff --git a/packages/renderer-html/src/html-document.ts b/packages/renderer-html/src/html-document.ts index 2fc57a3a..4470b207 100644 --- a/packages/renderer-html/src/html-document.ts +++ b/packages/renderer-html/src/html-document.ts @@ -1,6 +1,7 @@ import { highlightPalette } from "@mdbase-reader/core"; import { annotationHighlightCss } from "./html-css-highlights.js"; +import { sanitizedSvgImage } from "./svg-image.js"; const blockedElements = [ "script", @@ -60,12 +61,19 @@ export function prepareHtmlDocument(source: string): string { function sanitizeAttributes(element: Element): void { for (const attribute of [...element.attributes]) { const name = attribute.name.toLocaleLowerCase(); - if (name.startsWith("on") || name === "srcdoc" || name === "style") { + if (name.startsWith("on") || name === "srcdoc" || name === "srcset" || name === "style") { element.removeAttribute(attribute.name); } } for (const name of urlAttributes) { const value = element.getAttribute(name)?.trim(); + if (name === "src" && element.localName === "img" && value) { + const svg = sanitizedSvgImage(value); + if (svg) { + element.setAttribute(name, svg); + continue; + } + } if (value && !safeResource(name, value)) { element.removeAttribute(name); } diff --git a/packages/renderer-html/src/svg-image.test.ts b/packages/renderer-html/src/svg-image.test.ts new file mode 100644 index 00000000..ad0b9993 --- /dev/null +++ b/packages/renderer-html/src/svg-image.test.ts @@ -0,0 +1,140 @@ +// @vitest-environment jsdom +import { describe, expect, it } from "vitest"; + +import { prepareHtmlDocument } from "./html-document.js"; +import { sanitizedSvgImage } from "./svg-image.js"; + +const drawing = `café 漢字 🐨`; + +function decodedImage(url: string | null): Document { + expect(url).toMatch(/^data:image\/svg\+xml,/u); + return new DOMParser().parseFromString(decodeURIComponent(url!.split(",")[1]!), "image/svg+xml"); +} + +describe("sanitizedSvgImage", () => { + it.each(["percent", "base64"])("preserves geometry and Unicode in %s images", (encoding) => { + const url = + encoding === "percent" + ? `data:image/svg+xml,${encodeURIComponent(drawing)}` + : `data:image/svg+xml;charset=utf-8;base64,${btoa(String.fromCharCode(...new TextEncoder().encode(drawing)))}`; + const svg = decodedImage(sanitizedSvgImage(url)); + expect(svg.documentElement.getAttribute("width")).toBe("30"); + expect(svg.querySelector("rect")?.getAttribute("fill")).toBe("blue"); + expect(svg.querySelector("title")?.textContent).toBe("café 漢字 🐨"); + }); + + it("strips scripts, event handlers, foreign content, animation, CSS and external references", () => { + const source = ` + `, + ), + "text/html", + ); + expect(unsafeLocation.querySelector("iframe")).toBeNull(); + expect(unsafeLocation.querySelector("video")?.hasAttribute("poster")).toBe(false); + }); +}); diff --git a/packages/renderer-html/src/svg-image.ts b/packages/renderer-html/src/svg-image.ts new file mode 100644 index 00000000..8ffdce41 --- /dev/null +++ b/packages/renderer-html/src/svg-image.ts @@ -0,0 +1,61 @@ +import purify from "dompurify"; + +/** Keep embedded images static and self-contained before putting them back in a data URL. */ +export function sanitizedSvgImage(value: string): string | null { + const match = /^data:image\/svg\+xml((?:;[^,]*)?),([\s\S]*)$/iu.exec(value); + if (!match || !purify.isSupported) { + return null; + } + try { + const payload = decodeURIComponent((match[2] ?? "").replace(/%(?![\da-f]{2})/giu, "%25")); + const source = /(?:^|;)base64(?:;|$)/iu.test(match[1] ?? "") + ? new TextDecoder("utf-8", { fatal: true }).decode( + Uint8Array.from(atob(payload), (character) => character.charCodeAt(0)), + ) + : payload; + const parsed = new DOMParser().parseFromString(source, "image/svg+xml"); + if ( + parsed.querySelector("parsererror") || + parsed.documentElement.localName !== "svg" || + parsed.documentElement.namespaceURI !== "http://www.w3.org/2000/svg" + ) { + return null; + } + // Only the root is kept; source doctypes and processing instructions never reach the image. + const clean = purify.sanitize(parsed.documentElement, { + USE_PROFILES: { svg: true, svgFilters: true }, + ADD_TAGS: ["use"], + FORBID_TAGS: ["style", "animate", "animatemotion", "animatetransform", "set", "discard"], + FORBID_ATTR: ["style"], + RETURN_DOM_FRAGMENT: true, + }); + const svg = clean.firstElementChild; + if (svg?.localName !== "svg") { + return null; + } + sanitizeSvgReferences(svg); + return `data:image/svg+xml,${encodeURIComponent(new XMLSerializer().serializeToString(svg))}`; + } catch { + return null; + } +} + +function sanitizeSvgReferences(svg: Element): void { + for (const element of [svg, ...svg.querySelectorAll("*")]) { + for (const attribute of [...element.attributes]) { + // Presentation attributes can also load resources; permit only local fragment paints. + const references = attribute.value.replace(/url\(\s*(['"]?)#[\w.-]+\1\s*\)/giu, ""); + const embeddedRaster = + element.localName === "image" && + /^data:image\/(?:png|gif|jpeg|webp|avif);base64,/iu.test(attribute.value); + if ( + (attribute.localName === "href" && + !attribute.value.trim().startsWith("#") && + !embeddedRaster) || + /\\|url\s*\(/iu.test(references) + ) { + element.removeAttribute(attribute.name); + } + } + } +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index d72ab404..e69e7d85 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -82,7 +82,7 @@ importers: version: 8.66.0(eslint@9.39.5(jiti@2.7.0))(typescript@5.9.3) vitest: specifier: ^4.1.10 - version: 4.1.10(@types/node@22.20.1)(happy-dom@20.11.2)(vite@8.3.4(@types/node@22.20.1)(jiti@2.7.0)(yaml@2.9.0)) + version: 4.1.10(@types/node@22.20.1)(happy-dom@20.11.2)(jsdom@28.1.0(@noble/hashes@2.4.0))(vite@8.3.4(@types/node@22.20.1)(jiti@2.7.0)(yaml@2.9.0)) yaml: specifier: ^2.9.0 version: 2.9.0 @@ -494,6 +494,9 @@ importers: '@mdbase-reader/reading-surface': specifier: workspace:* version: link:../reading-surface + dompurify: + specifier: ^3.4.17 + version: 3.4.17 react: specifier: ^19.2.8 version: 19.2.8 @@ -504,6 +507,9 @@ importers: happy-dom: specifier: ^20.11.2 version: 20.11.2 + jsdom: + specifier: 28.1.0 + version: 28.1.0(@noble/hashes@2.4.0) packages/renderer-pdf: dependencies: @@ -608,6 +614,23 @@ importers: packages: + '@acemir/cssom@0.9.32': + resolution: {integrity: sha512-OijrAUu7rrJhSIoHNg6LMPS5e344nwUHA+1EFYYjrh64D+GmytUsfBQjci45TjT+rd5Spsp8B5xsZDT+TgyXXQ==} + + '@asamuzakjp/css-color@5.1.11': + resolution: {integrity: sha512-KVw6qIiCTUQhByfTd78h2yD1/00waTmm9uy/R7Ck/ctUyAPj+AEDLkQIdJW0T8+qGgj3j5bpNKK7Q3G+LedJWg==} + engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} + + '@asamuzakjp/dom-selector@6.8.1': + resolution: {integrity: sha512-MvRz1nCqW0fsy8Qz4dnLIvhOlMzqDVBabZx6lH+YywFDdjXhMY37SmpV1XFX3JzG5GWHn63j6HX6QPr3lZXHvQ==} + + '@asamuzakjp/generational-cache@1.0.1': + resolution: {integrity: sha512-wajfB8KqzMCN2KGNFdLkReeHncd0AslUSrvHVvvYWuU8ghncRJoA50kT3zP9MVL0+9g4/67H+cdvBskj9THPzg==} + engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} + + '@asamuzakjp/nwsapi@2.3.9': + resolution: {integrity: sha512-n8GuYSrI9bF7FFZ/SjhwevlHc8xaVlb/7HmHelnc/PZXBD2ZR49NnN9sMMuDdEGPeeRQ5d0hqlSlEpgCX3Wl0Q==} + '@babel/code-frame@7.29.7': resolution: {integrity: sha512-Aup7aUOfpbAUg2ROOJN6Iw5f9DMBlzu0mIkm/malLQFN/YQgO48wCj0Kxa3sEHJvPVFg7siR+qRInwXd2qhQKw==} engines: {node: '>=6.9.0'} @@ -679,6 +702,10 @@ packages: resolution: {integrity: sha512-Vj1jF3cPfxg7OAfoI7QnVKLoILlm2JF9pnVHrX8qx7AHMiYWT+NDAA7jChlNgRS4WTLc/fD1lXLmPixluj+3Gg==} engines: {node: '>=6.9.0'} + '@bramus/specificity@2.4.3': + resolution: {integrity: sha512-0GEz8qJWokkUVYQYRukmkSHIFNoBH8QTreeHrAFbvz1XFYc3Y+puhMs8PQ5x8GNugiC2l5jvDBXKLbBIByeSBw==} + hasBin: true + '@callumalpass/mdbase@0.3.0-rc.9': resolution: {integrity: sha512-bXYhTqRqd928j9osTFGQTmzKG59W1pelmBV+UaEF1WOL+E5WEQVl4sBKvvdGvBVD9VMAq7IF1zJTkr3gqNb4Mw==} hasBin: true @@ -767,6 +794,42 @@ packages: resolution: {integrity: sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==} engines: {node: '>=0.1.90'} + '@csstools/color-helpers@6.1.2': + resolution: {integrity: sha512-grhRy3OKmniaAEKXMjua5z/EODX0MSqBGjunw8+j/3HQjOnahs2AGhvEOIYVUWcU6ScApbhLhVrQTX8XqrMrow==} + engines: {node: '>=20.19.0'} + + '@csstools/css-calc@3.4.3': + resolution: {integrity: sha512-iex20d8CHVkyvg6B7UKV7uHnI2Bqo9g+EFfT9E0y+GvTvhZ/DwONJ+9aKb1dlqm0ZiGsL5RXjp0fCoJYnkeDjA==} + engines: {node: '>=20.19.0'} + peerDependencies: + '@csstools/css-parser-algorithms': ^4.0.2 + '@csstools/css-tokenizer': ^4.0.2 + + '@csstools/css-color-parser@4.2.6': + resolution: {integrity: sha512-iiPQ3iRWwnJkeEn6RIu6SJPr7hYrLz6XZ9s/QZl+2/LI5KQVjpl2fdmDSZKuD4xP6GMmMPgHFFXg6k1Wkz0Trg==} + engines: {node: '>=20.19.0'} + peerDependencies: + '@csstools/css-parser-algorithms': ^4.0.2 + '@csstools/css-tokenizer': ^4.0.2 + + '@csstools/css-parser-algorithms@4.0.2': + resolution: {integrity: sha512-40cSKyMvK+tq4qz6Awrlye2WGuOKt3FwPgtGg6KTfbHOWNw+Rk1rzbAtZnZ6IBhsY491HLRnDXwoyBAijmmILA==} + engines: {node: '>=20.19.0'} + peerDependencies: + '@csstools/css-tokenizer': ^4.0.2 + + '@csstools/css-syntax-patches-for-csstree@1.1.15': + resolution: {integrity: sha512-J0u7HkVl2nzSlhsiTOp4AmwcUQ3D+mGEEKfBy/7To5/y7F2OHwyLrXfrhR0SMgr4p5Lo+eaMVSeai24zUcBIxA==} + peerDependencies: + css-tree: ^3.2.1 + peerDependenciesMeta: + css-tree: + optional: true + + '@csstools/css-tokenizer@4.0.2': + resolution: {integrity: sha512-OoKoR0f76dCY666JlcbhmVTs2drYj1GUXZTYTcbUgJjh9Nv41aFfZ21bPQTERm5+L5cBDo466NltB2lplS5GBw==} + engines: {node: '>=20.19.0'} + '@electron-internal/extract-zip@1.0.4': resolution: {integrity: sha512-Zr1Vs7E9tpCNhZHDAbFVXc2gEVCG9RqPDjrno5+bdgB6LRAuvgyMHJut4NCVyYwtAieapMzc3fiQ3CSTi75ARg==} engines: {node: '>=22.12.0'} @@ -1193,6 +1256,15 @@ packages: resolution: {integrity: sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@exodus/bytes@1.16.0': + resolution: {integrity: sha512-IcpW84uEn3N7ETtNZMlxKhfl6Pec8rUNGOTBtWbK1FKhJxIFAptZyVrvVRVBimAJxJCgc3PxepxkdWWG4DVzfA==} + engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} + peerDependencies: + '@noble/hashes': ^1.8.0 || ^2.0.0 + peerDependenciesMeta: + '@noble/hashes': + optional: true + '@fontsource-variable/atkinson-hyperlegible-next@5.3.0': resolution: {integrity: sha512-UnLzNUy1RWoLDfydAatP4NaRm99X/WbQEph7q/PymJnCFIOOwKOx3pBmp5ys8trO0dM+CKGuJgeZP9fAR4mQpA==} @@ -1476,22 +1548,22 @@ packages: '@lingui/react': 6.9.0 react: ^19.2.0 - '@mdbase-dev/sdk@file:packages/connect/vendor/sdk-dev-eaa4e697-lab.tgz': - resolution: {integrity: sha512-9z3vnOUNkKJHB0PGFNjoT7DJJmwcJs0k/GADCKESN/1YTcgEZJH5w0G746HTVBsC/RhX5h15ABkV9ifNDU9Hyw==, tarball: file:packages/connect/vendor/sdk-dev-eaa4e697-lab.tgz} + '@mdbase-dev/sdk@file:packages/connect/vendor/sdk-dce61ff5-production-beta141.tgz': + resolution: {integrity: sha512-qBmdxJVMeKh3nv4lWl6fOcwurW57BjxBESQHyhSpcFvgLCTBzpZwFayRXoCilIYC9H9tZXc7L+DhwelmEgxlzA==, tarball: file:packages/connect/vendor/sdk-dce61ff5-production-beta141.tgz} version: 0.0.0 engines: {node: '>=20'} bundledDependencies: - '@mdbase-dev/connect-protocol' - '@mdbase-dev/sdk@file:packages/connect/vendor/sdk-dev-eaa4e697-staging.tgz': - resolution: {integrity: sha512-OZcexDhkjwROq0pSf/rSV1aU9H2AArhB5S2/UQU4ZTYMqJz7mpOhSFznZKSjDh6nb4EVROvBS926O3+HUePbjA==, tarball: file:packages/connect/vendor/sdk-dev-eaa4e697-staging.tgz} + '@mdbase-dev/sdk@file:packages/connect/vendor/sdk-dev-eaa4e697-lab.tgz': + resolution: {integrity: sha512-9z3vnOUNkKJHB0PGFNjoT7DJJmwcJs0k/GADCKESN/1YTcgEZJH5w0G746HTVBsC/RhX5h15ABkV9ifNDU9Hyw==, tarball: file:packages/connect/vendor/sdk-dev-eaa4e697-lab.tgz} version: 0.0.0 engines: {node: '>=20'} bundledDependencies: - '@mdbase-dev/connect-protocol' - '@mdbase-dev/sdk@file:packages/connect/vendor/sdk-dce61ff5-production-beta141.tgz': - resolution: {integrity: sha512-qBmdxJVMeKh3nv4lWl6fOcwurW57BjxBESQHyhSpcFvgLCTBzpZwFayRXoCilIYC9H9tZXc7L+DhwelmEgxlzA==, tarball: file:packages/connect/vendor/sdk-dce61ff5-production-beta141.tgz} + '@mdbase-dev/sdk@file:packages/connect/vendor/sdk-dev-eaa4e697-staging.tgz': + resolution: {integrity: sha512-OZcexDhkjwROq0pSf/rSV1aU9H2AArhB5S2/UQU4ZTYMqJz7mpOhSFznZKSjDh6nb4EVROvBS926O3+HUePbjA==, tarball: file:packages/connect/vendor/sdk-dev-eaa4e697-staging.tgz} version: 0.0.0 engines: {node: '>=20'} bundledDependencies: @@ -2066,6 +2138,10 @@ packages: engines: {node: '>=0.4.0'} hasBin: true + agent-base@7.1.4: + resolution: {integrity: sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==} + engines: {node: '>= 14'} + ajv-formats@3.0.1: resolution: {integrity: sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==} peerDependencies: @@ -2179,6 +2255,9 @@ packages: engines: {node: '>=6.0.0'} hasBin: true + bidi-js@1.1.0: + resolution: {integrity: sha512-fX1Onk0tdVPC7obPWB5EbJ1z7NVhLq4m2xZLq2YXBkxzMXIGRpNMU88n0EPgWseKl12J7zXs7qrDxPK4sRs2fg==} + big-integer@1.6.52: resolution: {integrity: sha512-QxD8cf2eVqJOOz63z6JIN9BzvVs/dlySa5HGSBH5xtR8dPteIRQnBxxKqkNTiT6jbDTF6jAfrd4oMcND9RGbQg==} engines: {node: '>=0.6'} @@ -2323,6 +2402,10 @@ packages: resolution: {integrity: sha512-snmjEVXy+1LnwXdxhYvTMj1d9tOh4HxkA1YmoayVBeeyR2C14Pum7fcxJIm4SswYspVy866eYNwlH6xC3/VH5g==} engines: {node: '>=20.19.0'} + css-tree@3.2.1: + resolution: {integrity: sha512-X7sjQzceUhu1u7Y/ylrRZFU2FS6LRiFVp6rKLPg23y3x3c3DOKAwuXGDp+PAGjh6CSnCjYeAul8pcT8bAl+lSA==} + engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0} + css-what@8.0.0: resolution: {integrity: sha512-DH0Bqq3DNp5tdOReuNyAA+Ev4Y2GS5FMbZpeTLP6C4CDi0h5nL0BmUPChXw3o/qbHLDWHl49sbNqQVY7bMSDdw==} engines: {node: '>=20.19.0'} @@ -2330,6 +2413,10 @@ packages: cssom@0.5.0: resolution: {integrity: sha512-iKuQcq+NdHqlAcwUY0o/HL69XQrUaQdMjmStJ8JFmUaiiQErlhrmuigkg/CU4E2J0IyUKUrMAgl36TvN67MqTw==} + cssstyle@6.2.0: + resolution: {integrity: sha512-Fm5NvhYathRnXNVndkUsCCuR63DCLVVwGOOwQw782coXFi5HhkXdu289l59HlXZBawsyNccXfWRYvLzcDCdDig==} + engines: {node: '>=20'} + csstype@3.2.3: resolution: {integrity: sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==} @@ -2340,6 +2427,10 @@ packages: resolution: {integrity: sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==} engines: {node: '>= 12'} + data-urls@7.0.0: + resolution: {integrity: sha512-23XHcCF+coGYevirZceTVD7NdJOqVn+49IHyxgszm+JIiHLoB2TkmPtsYkNWT1pvRSGkc35L6NHs0yHkN2SumA==} + engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} + data-view-buffer@1.0.2: resolution: {integrity: sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==} engines: {node: '>= 0.4'} @@ -2364,6 +2455,9 @@ packages: supports-color: optional: true + decimal.js@10.6.0: + resolution: {integrity: sha512-YpgQiITW3JXGntzdUmyUR1V812Hn8T1YVXhCu+wO3OpS4eU9l4YdD3qjyiKdV6mvV29zapkMeD390UVEf2lkUg==} + deep-is@0.1.4: resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} @@ -2424,6 +2518,9 @@ packages: resolution: {integrity: sha512-gYzvtM72ZtxQO0T048kd6HWSbbGCNOUwcnfQ01cqIJ4X2IYKFFHZ5mKvrQETcFXxsRObZulDaKmy//R7TPtsBg==} engines: {node: '>=20.19.0'} + dompurify@3.4.17: + resolution: {integrity: sha512-B/pSlYVHQ58kqISD/yDjuJ1yfzI34m1gF4lAod2bwSRhiN4K5Cl3H8Af7hqB2PmTL911tdEudnnXn5FnhRoz0w==} + domutils@3.2.2: resolution: {integrity: sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==} @@ -2829,12 +2926,24 @@ packages: hermes-parser@0.25.1: resolution: {integrity: sha512-6pEjquH3rqaI6cYAXYPcz9MS4rY6R4ngRgrgfDshRptUZIc3lw0MCIJIGDj9++mfySOuPTHB4nrSW99BCvOPIA==} + html-encoding-sniffer@6.0.0: + resolution: {integrity: sha512-CV9TW3Y3f8/wT0BRFc1/KAVQ3TUHiXmaAb6VW9vtiMFf7SLoMd1PdAc4W3KFOFETBJUb90KatHqlsZMWV+R9Gg==} + engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} + html-escaper@3.0.3: resolution: {integrity: sha512-RuMffC89BOWQoY0WKGpIhn5gX3iI54O6nRA0yC124NYVtzjmFWBIiFd8M0x+ZdX0P9R4lADg1mgP8C7PxGOWuQ==} htmlparser2@10.1.0: resolution: {integrity: sha512-VTZkM9GWRAtEpveh7MSF6SjjrpNVNNVJfFup7xTY3UpFtm67foy9HDVXneLtFVt4pMz5kZtgNcvCniNFb1hlEQ==} + http-proxy-agent@7.0.2: + resolution: {integrity: sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==} + engines: {node: '>= 14'} + + https-proxy-agent@7.0.6: + resolution: {integrity: sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==} + engines: {node: '>= 14'} + ignore@5.3.2: resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==} engines: {node: '>= 4'} @@ -2946,6 +3055,9 @@ packages: resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} engines: {node: '>=0.12.0'} + is-potential-custom-element-name@1.0.1: + resolution: {integrity: sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==} + is-reference@3.0.3: resolution: {integrity: sha512-ixkJoqQvAP88E6wLydLGGqCJsrFUnqoH6HnaczB8XmDH1oaWU+xxdptvikTgaEhtZ53Ky6YXiBuUI2WXLMCwjw==} @@ -3028,6 +3140,15 @@ packages: resolution: {integrity: sha512-CY6crGq313MX8GkwvB7tzgp99vjQxY1++5y10/BKN/GUfHqWaOGQMNZkBvqSzsZKWk/ijwHlWzzkLulsGHhjWQ==} hasBin: true + jsdom@28.1.0: + resolution: {integrity: sha512-0+MoQNYyr2rBHqO1xilltfDjV9G7ymYGlAUazgcDLQaUf8JDHbuGwsxN6U9qWaElZ4w1B2r7yEGIL3GdeW3Rug==} + engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} + peerDependencies: + canvas: ^3.0.0 + peerDependenciesMeta: + canvas: + optional: true + jsesc@3.1.0: resolution: {integrity: sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==} engines: {node: '>=6'} @@ -3193,6 +3314,10 @@ packages: resolution: {integrity: sha512-4pfM1Ff0x50o0tQwb5ucw/RzNyD0/YJME6IVcStalZuMWxdt3sR3huStTtxz4PUmvZfRguvDejasvQ2kifR11g==} engines: {node: 20 || >=22} + lru-cache@11.5.3: + resolution: {integrity: sha512-U4N8FgzmWxc8k1VH8Kr6lQg18U7Fjvby6wXHVRX/ZZ7IwWbRMgrRbP0Wrb5q5NVinryp4SQampHKdvtecItxUg==} + engines: {node: 20 || >=22} + lru-cache@5.1.1: resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} @@ -3206,6 +3331,9 @@ packages: mathml-to-latex@1.8.0: resolution: {integrity: sha512-gQ0uK3zqB8HwlfaXJkEL5rgaZNbKUiBMmBP/B/W+b+t6KcseLSuYb1b0BjLgS9ZiQa24ePkqTX8/6FaQuDL7wQ==} + mdn-data@2.27.1: + resolution: {integrity: sha512-9Yubnt3e8A0OKwxYSXyhLymGW4sCufcLG6VdiDdUGVkPhpqLxlvP5vl1983gQjJl3tqbrM731mjaZaP68AgosQ==} + micromatch@4.0.8: resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} engines: {node: '>=8.6'} @@ -3336,6 +3464,9 @@ packages: resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} engines: {node: '>=6'} + parse5@8.0.1: + resolution: {integrity: sha512-z1e/HMG90obSGeidlli3hj7cbocou0/wa5HacvI3ASx34PecNjNQeaHNo5WIZpWofN9kgkqV1q5YvXe3F0FoPw==} + path-exists@4.0.0: resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} engines: {node: '>=8'} @@ -3515,6 +3646,10 @@ packages: resolution: {integrity: sha512-42tBVwLWnaQvW5zc4HbZrTuWccECCZfBi92FDuwtqxasH+JbPB3/FOKb1m222K42R4WxuxzzMsTswfzgtSu64Q==} engines: {node: '>=11.0.0'} + saxes@6.0.0: + resolution: {integrity: sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==} + engines: {node: '>=v12.22.7'} + scheduler@0.27.0: resolution: {integrity: sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==} @@ -3688,6 +3823,9 @@ packages: resolution: {integrity: sha512-PY8LOw7xP6c8IOiVqdo0sbbZVYhXRSfklOQLAUyGBKqjTX0wx/z4l/9J+PmBpmlLnxzEb1NqltxQ5/wZme/Cmg==} engines: {node: '>=18'} + symbol-tree@3.2.4: + resolution: {integrity: sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==} + sync-fetch@0.6.0: resolution: {integrity: sha512-IELLEvzHuCfc1uTsshPK58ViSdNqXxlml1U+fmwJIKLYKOr/rAtBrorE2RYm5IHaMpDNlmC0fr1LAvdXvyheEQ==} engines: {node: '>=18'} @@ -3729,10 +3867,25 @@ packages: resolution: {integrity: sha512-yau8yJdTt989Mm0Bd/236QnzEiPf2xLLTqUZRUJOo/3CB078LSwzei343DgtJVmfJKJE3TMINY1u42SQsP6mXw==} engines: {node: '>=14.0.0'} + tldts-core@7.4.20: + resolution: {integrity: sha512-C630TWXZCZmLq0F2bW4QqwnaaxCQ/svpAqvJwnC4JvgEM5ohhBnGsEzTLSOXcN+xjz+kEaHS5uoWIw2klnqd0A==} + + tldts@7.4.19: + resolution: {integrity: sha512-48dH6aSpQnpbzDUc4vIQZ1VjB8tkK+e8c1yx05/SZK+rkssgjEOlxDd/yU8/a4vGYQ9vRgJr9dwMq9TJ0b3X2Q==} + hasBin: true + to-regex-range@5.0.1: resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} engines: {node: '>=8.0'} + tough-cookie@6.0.2: + resolution: {integrity: sha512-exgYmnmL/sJpR3upZfXG5PoatXQii55xAiXGXzY+sROLZ/Y+SLcp9PgJNI9Vz37HpQ74WvDcLT8eqm+kV3FzrA==} + engines: {node: '>=16'} + + tr46@6.0.0: + resolution: {integrity: sha512-bLVMLPtstlZ4iMQHpFHTR7GAGj2jxi8Dg0s2h2MafAE4uSWF98FC/3MomU51iQAMf8/qDUbKWf5GxuvvVcXEhw==} + engines: {node: '>=20'} + tree-kill@1.2.2: resolution: {integrity: sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==} hasBin: true @@ -3942,10 +4095,18 @@ packages: w3c-keyname@2.2.8: resolution: {integrity: sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ==} + w3c-xmlserializer@5.0.0: + resolution: {integrity: sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==} + engines: {node: '>=18'} + web-streams-polyfill@3.3.3: resolution: {integrity: sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==} engines: {node: '>= 8'} + webidl-conversions@8.0.1: + resolution: {integrity: sha512-BMhLD/Sw+GbJC21C/UgyaZX41nPt8bUTg+jWyDeg7e7YN4xOM05YPSIXceACnXVtqyEw/LMClUQMtMZ+PGGpqQ==} + engines: {node: '>=20'} + whatwg-mimetype@3.0.0: resolution: {integrity: sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q==} engines: {node: '>=12'} @@ -3954,6 +4115,14 @@ packages: resolution: {integrity: sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==} engines: {node: '>=18'} + whatwg-mimetype@5.0.0: + resolution: {integrity: sha512-sXcNcHOC51uPGF0P/D4NVtrkjSU2fNsm9iog4ZvZJsL3rjoDAzXZhkm2MWt1y+PUdggKAYVoMAIYcs78wJ51Cw==} + engines: {node: '>=20'} + + whatwg-url@16.0.1: + resolution: {integrity: sha512-1to4zXBxmXHV3IiSSEInrreIlu02vUOvrhxJJH5vcxYTBDAx51cqZiKdyTxlecdKNSjj8EcxGBxNf6Vg+945gw==} + engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} + which-boxed-primitive@1.1.1: resolution: {integrity: sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==} engines: {node: '>= 0.4'} @@ -4004,6 +4173,10 @@ packages: resolution: {integrity: sha512-kCz5k7J7XbJtjABOvkc5lJmkiDh8VhjVCGNiqdKCscmVpdVUpEAyXv1xmCLkQJ5dsHqx3IPO4XW+NTDhU/fatA==} engines: {node: '>=10.0.0'} + xml-name-validator@5.0.0: + resolution: {integrity: sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==} + engines: {node: '>=18'} + xml-naming@0.3.0: resolution: {integrity: sha512-ghig2TBE/H11aOVgmahA3MhimvkBr6JIYknH/Dhdk10nXwdbIqBJsbfMxpvFPG8bAw77gN29aQWvKpmVoPlvPQ==} engines: {node: '>=16.0.0'} @@ -4020,6 +4193,9 @@ packages: resolution: {integrity: sha512-yMqGBqtXyeN1e3TGYvgNgDVZ3j84W4cwkOXQswghol6APgZWaff9lnbvN7MHYJOiXsvGPXtjTYJEiC9J2wv9Eg==} engines: {node: '>=8.0'} + xmlchars@2.2.0: + resolution: {integrity: sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==} + yallist@3.1.1: resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} @@ -4062,6 +4238,28 @@ packages: snapshots: + '@acemir/cssom@0.9.32': {} + + '@asamuzakjp/css-color@5.1.11': + dependencies: + '@asamuzakjp/generational-cache': 1.0.1 + '@csstools/css-calc': 3.4.3(@csstools/css-parser-algorithms@4.0.2(@csstools/css-tokenizer@4.0.2))(@csstools/css-tokenizer@4.0.2) + '@csstools/css-color-parser': 4.2.6(@csstools/css-parser-algorithms@4.0.2(@csstools/css-tokenizer@4.0.2))(@csstools/css-tokenizer@4.0.2) + '@csstools/css-parser-algorithms': 4.0.2(@csstools/css-tokenizer@4.0.2) + '@csstools/css-tokenizer': 4.0.2 + + '@asamuzakjp/dom-selector@6.8.1': + dependencies: + '@asamuzakjp/nwsapi': 2.3.9 + bidi-js: 1.1.0 + css-tree: 3.2.1 + is-potential-custom-element-name: 1.0.1 + lru-cache: 11.5.3 + + '@asamuzakjp/generational-cache@1.0.1': {} + + '@asamuzakjp/nwsapi@2.3.9': {} + '@babel/code-frame@7.29.7': dependencies: '@babel/helper-validator-identifier': 7.29.7 @@ -4193,6 +4391,10 @@ snapshots: '@babel/helper-string-parser': 7.29.7 '@babel/helper-validator-identifier': 7.29.7 + '@bramus/specificity@2.4.3': + dependencies: + css-tree: 3.2.1 + '@callumalpass/mdbase@0.3.0-rc.9': dependencies: '@marcbachmann/cel-js': 8.0.0 @@ -4359,6 +4561,30 @@ snapshots: '@colors/colors@1.5.0': optional: true + '@csstools/color-helpers@6.1.2': {} + + '@csstools/css-calc@3.4.3(@csstools/css-parser-algorithms@4.0.2(@csstools/css-tokenizer@4.0.2))(@csstools/css-tokenizer@4.0.2)': + dependencies: + '@csstools/css-parser-algorithms': 4.0.2(@csstools/css-tokenizer@4.0.2) + '@csstools/css-tokenizer': 4.0.2 + + '@csstools/css-color-parser@4.2.6(@csstools/css-parser-algorithms@4.0.2(@csstools/css-tokenizer@4.0.2))(@csstools/css-tokenizer@4.0.2)': + dependencies: + '@csstools/color-helpers': 6.1.2 + '@csstools/css-calc': 3.4.3(@csstools/css-parser-algorithms@4.0.2(@csstools/css-tokenizer@4.0.2))(@csstools/css-tokenizer@4.0.2) + '@csstools/css-parser-algorithms': 4.0.2(@csstools/css-tokenizer@4.0.2) + '@csstools/css-tokenizer': 4.0.2 + + '@csstools/css-parser-algorithms@4.0.2(@csstools/css-tokenizer@4.0.2)': + dependencies: + '@csstools/css-tokenizer': 4.0.2 + + '@csstools/css-syntax-patches-for-csstree@1.1.15(css-tree@3.2.1)': + optionalDependencies: + css-tree: 3.2.1 + + '@csstools/css-tokenizer@4.0.2': {} + '@electron-internal/extract-zip@1.0.4': {} '@electron/get@5.0.0': @@ -4854,6 +5080,10 @@ snapshots: '@eslint/core': 0.17.0 levn: 0.4.1 + '@exodus/bytes@1.16.0(@noble/hashes@2.4.0)': + optionalDependencies: + '@noble/hashes': 2.4.0 + '@fontsource-variable/atkinson-hyperlegible-next@5.3.0': {} '@fontsource-variable/source-serif-4@5.3.1': {} @@ -5245,19 +5475,19 @@ snapshots: - rolldown - supports-color - '@mdbase-dev/sdk@file:packages/connect/vendor/sdk-dev-eaa4e697-lab.tgz': + '@mdbase-dev/sdk@file:packages/connect/vendor/sdk-dce61ff5-production-beta141.tgz': dependencies: '@noble/ciphers': 2.4.0 '@noble/curves': 2.4.0 '@noble/hashes': 2.4.0 - '@mdbase-dev/sdk@file:packages/connect/vendor/sdk-dev-eaa4e697-staging.tgz': + '@mdbase-dev/sdk@file:packages/connect/vendor/sdk-dev-eaa4e697-lab.tgz': dependencies: '@noble/ciphers': 2.4.0 '@noble/curves': 2.4.0 '@noble/hashes': 2.4.0 - '@mdbase-dev/sdk@file:packages/connect/vendor/sdk-dce61ff5-production-beta141.tgz': + '@mdbase-dev/sdk@file:packages/connect/vendor/sdk-dev-eaa4e697-staging.tgz': dependencies: '@noble/ciphers': 2.4.0 '@noble/curves': 2.4.0 @@ -5788,6 +6018,8 @@ snapshots: acorn@8.18.0: {} + agent-base@7.1.4: {} + ajv-formats@3.0.1(ajv@8.20.0): optionalDependencies: ajv: 8.20.0 @@ -5894,6 +6126,10 @@ snapshots: baseline-browser-mapping@2.11.13: {} + bidi-js@1.1.0: + dependencies: + require-from-string: 2.0.2 + big-integer@1.6.52: {} boolbase@2.0.0: @@ -6027,18 +6263,37 @@ snapshots: nth-check: 3.0.1 optional: true + css-tree@3.2.1: + dependencies: + mdn-data: 2.27.1 + source-map-js: 1.2.2 + css-what@8.0.0: optional: true cssom@0.5.0: optional: true + cssstyle@6.2.0: + dependencies: + '@asamuzakjp/css-color': 5.1.11 + '@csstools/css-syntax-patches-for-csstree': 1.1.15(css-tree@3.2.1) + css-tree: 3.2.1 + lru-cache: 11.5.3 + csstype@3.2.3: {} damerau-levenshtein@1.0.8: {} data-uri-to-buffer@4.0.1: {} + data-urls@7.0.0(@noble/hashes@2.4.0): + dependencies: + whatwg-mimetype: 5.0.0 + whatwg-url: 16.0.1(@noble/hashes@2.4.0) + transitivePeerDependencies: + - '@noble/hashes' + data-view-buffer@1.0.2: dependencies: call-bound: 1.0.4 @@ -6063,6 +6318,8 @@ snapshots: dependencies: ms: 2.1.3 + decimal.js@10.6.0: {} + deep-is@0.1.4: {} define-data-property@1.1.4: @@ -6136,6 +6393,10 @@ snapshots: domelementtype: 3.0.0 optional: true + dompurify@3.4.17: + optionalDependencies: + '@types/trusted-types': 2.0.7 + domutils@3.2.2: dependencies: dom-serializer: 2.0.0 @@ -6650,6 +6911,12 @@ snapshots: dependencies: hermes-estree: 0.25.1 + html-encoding-sniffer@6.0.0(@noble/hashes@2.4.0): + dependencies: + '@exodus/bytes': 1.16.0(@noble/hashes@2.4.0) + transitivePeerDependencies: + - '@noble/hashes' + html-escaper@3.0.3: optional: true @@ -6661,6 +6928,20 @@ snapshots: entities: 7.0.1 optional: true + http-proxy-agent@7.0.2: + dependencies: + agent-base: 7.1.4 + debug: 4.4.3 + transitivePeerDependencies: + - supports-color + + https-proxy-agent@7.0.6: + dependencies: + agent-base: 7.1.4 + debug: 4.4.3 + transitivePeerDependencies: + - supports-color + ignore@5.3.2: {} ignore@7.0.6: {} @@ -6763,6 +7044,8 @@ snapshots: is-number@7.0.0: {} + is-potential-custom-element-name@1.0.1: {} + is-reference@3.0.3: dependencies: '@types/estree': 1.0.9 @@ -6844,6 +7127,33 @@ snapshots: dependencies: argparse: 2.0.1 + jsdom@28.1.0(@noble/hashes@2.4.0): + dependencies: + '@acemir/cssom': 0.9.32 + '@asamuzakjp/dom-selector': 6.8.1 + '@bramus/specificity': 2.4.3 + '@exodus/bytes': 1.16.0(@noble/hashes@2.4.0) + cssstyle: 6.2.0 + data-urls: 7.0.0(@noble/hashes@2.4.0) + decimal.js: 10.6.0 + html-encoding-sniffer: 6.0.0(@noble/hashes@2.4.0) + http-proxy-agent: 7.0.2 + https-proxy-agent: 7.0.6 + is-potential-custom-element-name: 1.0.1 + parse5: 8.0.1 + saxes: 6.0.0 + symbol-tree: 3.2.4 + tough-cookie: 6.0.2 + undici: 7.29.0 + w3c-xmlserializer: 5.0.0 + webidl-conversions: 8.0.1 + whatwg-mimetype: 5.0.0 + whatwg-url: 16.0.1(@noble/hashes@2.4.0) + xml-name-validator: 5.0.0 + transitivePeerDependencies: + - '@noble/hashes' + - supports-color + jsesc@3.1.0: {} json-buffer@3.0.1: {} @@ -6971,6 +7281,8 @@ snapshots: lru-cache@11.5.2: {} + lru-cache@11.5.3: {} + lru-cache@5.1.1: dependencies: yallist: 3.1.1 @@ -6985,6 +7297,8 @@ snapshots: dependencies: '@xmldom/xmldom': 0.9.10 + mdn-data@2.27.1: {} + micromatch@4.0.8: dependencies: braces: 3.0.3 @@ -7131,6 +7445,10 @@ snapshots: dependencies: callsites: 3.1.0 + parse5@8.0.1: + dependencies: + entities: 8.1.0 + path-exists@4.0.0: {} path-expression-matcher@1.6.2: {} @@ -7309,6 +7627,10 @@ snapshots: sax@1.6.1: {} + saxes@6.0.0: + dependencies: + xmlchars: 2.2.0 + scheduler@0.27.0: {} section-matter@1.0.0: @@ -7515,6 +7837,8 @@ snapshots: transitivePeerDependencies: - '@typescript-eslint/types' + symbol-tree@3.2.4: {} + sync-fetch@0.6.0: dependencies: node-fetch: 3.3.2 @@ -7553,10 +7877,24 @@ snapshots: tinyrainbow@3.1.1: {} + tldts-core@7.4.20: {} + + tldts@7.4.19: + dependencies: + tldts-core: 7.4.20 + to-regex-range@5.0.1: dependencies: is-number: 7.0.0 + tough-cookie@6.0.2: + dependencies: + tldts: 7.4.19 + + tr46@6.0.0: + dependencies: + punycode: 2.3.1 + tree-kill@1.2.2: {} ts-api-utils@2.5.0(typescript@5.9.3): @@ -7720,7 +8058,7 @@ snapshots: jiti: 2.7.0 yaml: 2.9.1 - vitest@4.1.10(@types/node@22.20.1)(happy-dom@20.11.2)(vite@8.3.4(@types/node@22.20.1)(jiti@2.7.0)(yaml@2.9.0)): + vitest@4.1.10(@types/node@22.20.1)(happy-dom@20.11.2)(jsdom@28.1.0(@noble/hashes@2.4.0))(vite@8.3.4(@types/node@22.20.1)(jiti@2.7.0)(yaml@2.9.0)): dependencies: '@vitest/expect': 4.1.10 '@vitest/mocker': 4.1.10(vite@8.3.4(@types/node@22.20.1)(jiti@2.7.0)(yaml@2.9.0)) @@ -7745,6 +8083,7 @@ snapshots: optionalDependencies: '@types/node': 22.20.1 happy-dom: 20.11.2 + jsdom: 28.1.0(@noble/hashes@2.4.0) transitivePeerDependencies: - msw @@ -7760,12 +8099,28 @@ snapshots: w3c-keyname@2.2.8: {} + w3c-xmlserializer@5.0.0: + dependencies: + xml-name-validator: 5.0.0 + web-streams-polyfill@3.3.3: {} + webidl-conversions@8.0.1: {} + whatwg-mimetype@3.0.0: {} whatwg-mimetype@4.0.0: {} + whatwg-mimetype@5.0.0: {} + + whatwg-url@16.0.1(@noble/hashes@2.4.0): + dependencies: + '@exodus/bytes': 1.16.0(@noble/hashes@2.4.0) + tr46: 6.0.0 + webidl-conversions: 8.0.1 + transitivePeerDependencies: + - '@noble/hashes' + which-boxed-primitive@1.1.1: dependencies: is-bigint: 1.1.0 @@ -7831,6 +8186,8 @@ snapshots: simple-plist: 1.3.1 uuid: 7.0.3 + xml-name-validator@5.0.0: {} + xml-naming@0.3.0: {} xml2js@0.6.2: @@ -7842,6 +8199,8 @@ snapshots: xmlbuilder@15.1.1: {} + xmlchars@2.2.0: {} + yallist@3.1.1: {} yallist@5.0.0: {}