@makolabs/ripple 3.8.1 → 3.9.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/dist/ai/MessageBox.svelte +2 -1
  2. package/dist/button/Button.svelte +89 -7
  3. package/dist/elements/file-viewer/FilePreviewModal.svelte +102 -0
  4. package/dist/elements/file-viewer/FilePreviewModal.svelte.d.ts +4 -0
  5. package/dist/elements/file-viewer/FileViewer.svelte +96 -0
  6. package/dist/elements/file-viewer/FileViewer.svelte.d.ts +4 -0
  7. package/dist/elements/file-viewer/file-preview-modal-types.d.ts +62 -0
  8. package/dist/elements/file-viewer/file-preview-modal-types.js +1 -0
  9. package/dist/elements/file-viewer/file-viewer-types.d.ts +51 -0
  10. package/dist/elements/file-viewer/file-viewer-types.js +127 -0
  11. package/dist/elements/image-viewer/ImageViewer.svelte +133 -0
  12. package/dist/elements/image-viewer/ImageViewer.svelte.d.ts +4 -0
  13. package/dist/elements/image-viewer/image-viewer-types.d.ts +16 -0
  14. package/dist/elements/image-viewer/image-viewer-types.js +1 -0
  15. package/dist/elements/pdf-viewer/PdfViewer.svelte +225 -34
  16. package/dist/elements/pdf-viewer/pdf-viewer-types.d.ts +13 -4
  17. package/dist/elements/text-viewer/TextViewer.svelte +141 -0
  18. package/dist/elements/text-viewer/TextViewer.svelte.d.ts +4 -0
  19. package/dist/elements/text-viewer/text-viewer-types.d.ts +10 -0
  20. package/dist/elements/text-viewer/text-viewer-types.js +1 -0
  21. package/dist/elements/viewer-shared/UnsupportedPreview.svelte +84 -0
  22. package/dist/elements/viewer-shared/UnsupportedPreview.svelte.d.ts +4 -0
  23. package/dist/elements/viewer-shared/ViewerToolbar.svelte +128 -0
  24. package/dist/elements/viewer-shared/ViewerToolbar.svelte.d.ts +4 -0
  25. package/dist/elements/viewer-shared/unsupported-preview-types.d.ts +17 -0
  26. package/dist/elements/viewer-shared/unsupported-preview-types.js +1 -0
  27. package/dist/elements/viewer-shared/viewer-toolbar-types.d.ts +14 -0
  28. package/dist/elements/viewer-shared/viewer-toolbar-types.js +1 -0
  29. package/dist/helper/is-safe-http-url.d.ts +33 -0
  30. package/dist/helper/is-safe-http-url.js +214 -0
  31. package/dist/helper/pdf-assets.d.ts +42 -0
  32. package/dist/helper/pdf-assets.js +57 -0
  33. package/dist/helper/pdf-safety.d.ts +38 -0
  34. package/dist/helper/pdf-safety.js +85 -0
  35. package/dist/helper/resource-limits.d.ts +13 -0
  36. package/dist/helper/resource-limits.js +16 -0
  37. package/dist/helper/sanitize-html.d.ts +5 -0
  38. package/dist/helper/sanitize-html.js +12 -0
  39. package/dist/index.d.ts +9 -0
  40. package/dist/index.js +8 -0
  41. package/package.json +4 -2
@@ -0,0 +1,42 @@
1
+ /**
2
+ * pdfjs ships its image codecs (JPEG2000/JPX, JBIG2) and colour management as
3
+ * separate WebAssembly modules that live in `pdfjs-dist/wasm/`. Since pdfjs v4+
4
+ * the JPX decoder is one of these wasm modules, so a page whose images are
5
+ * JPEG2000-encoded (`/Filter /JPXDecode`) renders BLANK unless pdfjs can load
6
+ * `openjpeg.wasm` at runtime. pdfjs's own `wasmUrl` option expects a directory
7
+ * URL and then fetches `<wasmUrl>openjpeg.wasm` by its literal name — but a
8
+ * bundler (Vite/webpack) content-hashes emitted assets and can't emit a bare
9
+ * directory, so a plain `wasmUrl` can't be resolved reliably from a library.
10
+ *
11
+ * Instead we resolve each wasm file individually with the same bundler-agnostic
12
+ * `new URL('<file>', import.meta.url)` mechanism used for the pdf worker (every
13
+ * major bundler rewrites it to the emitted asset URL), fetch the bytes, and hand
14
+ * them straight to pdfjs through a custom `BinaryDataFactory`. This sidesteps
15
+ * both the directory requirement and asset hashing: we already hold the correct
16
+ * (hashed) URL for each file, so the exact emitted name never has to be guessed.
17
+ *
18
+ * pdfjs only reaches this factory for image-codec wasm (JPX/JBIG2); ICC colour
19
+ * (`qcms_bg.wasm`) is loaded by pdfjs via a separate synchronous path that still
20
+ * needs `wasmUrl` and is left unconfigured (non-fatal — ICC profiles are rare in
21
+ * scanned docs and pdfjs simply warns and skips them). Predefined CMaps and
22
+ * standard fonts are likewise unconfigured, matching the prior behaviour.
23
+ */
24
+ /** Argument shape pdfjs passes to `BinaryDataFactory#fetch`. */
25
+ type FetchRequest = {
26
+ kind: string;
27
+ filename: string;
28
+ };
29
+ /**
30
+ * A pdfjs `BinaryDataFactory` that serves the image-codec wasm modules from
31
+ * bundler-emitted asset URLs. Pass the class (not an instance) as the
32
+ * `BinaryDataFactory` option to `getDocument` — pdfjs instantiates it itself.
33
+ *
34
+ * For any request it doesn't recognise (predefined CMaps, standard fonts) it
35
+ * throws the same "API parameter not provided" error pdfjs's default factory
36
+ * would, so behaviour for those unconfigured assets is unchanged.
37
+ */
38
+ export declare class PdfBinaryDataFactory {
39
+ constructor(_options?: unknown);
40
+ fetch({ kind, filename }: FetchRequest): Promise<Uint8Array>;
41
+ }
42
+ export {};
@@ -0,0 +1,57 @@
1
+ /**
2
+ * pdfjs ships its image codecs (JPEG2000/JPX, JBIG2) and colour management as
3
+ * separate WebAssembly modules that live in `pdfjs-dist/wasm/`. Since pdfjs v4+
4
+ * the JPX decoder is one of these wasm modules, so a page whose images are
5
+ * JPEG2000-encoded (`/Filter /JPXDecode`) renders BLANK unless pdfjs can load
6
+ * `openjpeg.wasm` at runtime. pdfjs's own `wasmUrl` option expects a directory
7
+ * URL and then fetches `<wasmUrl>openjpeg.wasm` by its literal name — but a
8
+ * bundler (Vite/webpack) content-hashes emitted assets and can't emit a bare
9
+ * directory, so a plain `wasmUrl` can't be resolved reliably from a library.
10
+ *
11
+ * Instead we resolve each wasm file individually with the same bundler-agnostic
12
+ * `new URL('<file>', import.meta.url)` mechanism used for the pdf worker (every
13
+ * major bundler rewrites it to the emitted asset URL), fetch the bytes, and hand
14
+ * them straight to pdfjs through a custom `BinaryDataFactory`. This sidesteps
15
+ * both the directory requirement and asset hashing: we already hold the correct
16
+ * (hashed) URL for each file, so the exact emitted name never has to be guessed.
17
+ *
18
+ * pdfjs only reaches this factory for image-codec wasm (JPX/JBIG2); ICC colour
19
+ * (`qcms_bg.wasm`) is loaded by pdfjs via a separate synchronous path that still
20
+ * needs `wasmUrl` and is left unconfigured (non-fatal — ICC profiles are rare in
21
+ * scanned docs and pdfjs simply warns and skips them). Predefined CMaps and
22
+ * standard fonts are likewise unconfigured, matching the prior behaviour.
23
+ */
24
+ /**
25
+ * Bundler-resolved URLs for the wasm image codecs. The `new URL(<literal>,
26
+ * import.meta.url)` calls must use string literals so Vite/webpack can statically
27
+ * detect them and emit the assets. Keyed by the exact filename pdfjs requests.
28
+ */
29
+ const WASM_ASSET_URLS = {
30
+ 'openjpeg.wasm': new URL('pdfjs-dist/wasm/openjpeg.wasm', import.meta.url),
31
+ 'jbig2.wasm': new URL('pdfjs-dist/wasm/jbig2.wasm', import.meta.url)
32
+ };
33
+ /**
34
+ * A pdfjs `BinaryDataFactory` that serves the image-codec wasm modules from
35
+ * bundler-emitted asset URLs. Pass the class (not an instance) as the
36
+ * `BinaryDataFactory` option to `getDocument` — pdfjs instantiates it itself.
37
+ *
38
+ * For any request it doesn't recognise (predefined CMaps, standard fonts) it
39
+ * throws the same "API parameter not provided" error pdfjs's default factory
40
+ * would, so behaviour for those unconfigured assets is unchanged.
41
+ */
42
+ export class PdfBinaryDataFactory {
43
+ // pdfjs constructs this with { cMapUrl, standardFontDataUrl, wasmUrl }; we
44
+ // resolve wasm ourselves and ignore the (unset) URL options.
45
+ constructor(_options) { }
46
+ async fetch({ kind, filename }) {
47
+ const assetUrl = WASM_ASSET_URLS[filename];
48
+ if (!assetUrl) {
49
+ throw new Error(`Ensure that the \`${kind}\` API parameter is provided.`);
50
+ }
51
+ const response = await fetch(assetUrl);
52
+ if (!response.ok) {
53
+ throw new Error(`Unable to load pdf wasm asset "${filename}" (HTTP ${response.status})`);
54
+ }
55
+ return new Uint8Array(await response.arrayBuffer());
56
+ }
57
+ }
@@ -0,0 +1,38 @@
1
+ /** Options passed to pdfjs getDocument to neutralise eval/XFA and silence logging. */
2
+ export declare const PDFJS_DOCUMENT_OPTIONS: {
3
+ readonly isEvalSupported: false;
4
+ readonly enableXfa: false;
5
+ readonly verbosity: 0;
6
+ };
7
+ /** True when a pdfjs-dist version is at/above the CVE-2024-4367 fix (4.2.67). */
8
+ export declare function isPdfJsVersionSafe(version: string | undefined): boolean;
9
+ export type CanvasDimensions = {
10
+ cssWidth: number;
11
+ cssHeight: number;
12
+ pixelWidth: number;
13
+ pixelHeight: number;
14
+ effectivePixelRatio: number;
15
+ };
16
+ /**
17
+ * Compute canvas backing-store + CSS dimensions for a page, clamping the
18
+ * backing store to MAX_CANVAS_SIDE/MAX_CANVAS_AREA so a giant MediaBox can't
19
+ * OOM the tab. CSS (display) size is preserved; only resolution is reduced.
20
+ */
21
+ export declare function computeCanvasDimensions(baseWidth: number, baseHeight: number, scale: number, rawPixelRatio: number): CanvasDimensions;
22
+ /** Number of pages to eagerly render: min(numPages, maxPages); 0 if invalid. */
23
+ export declare function pagesToRender(numPages: number, maxPages: number): number;
24
+ /** How the viewer auto-sizes a page to its container. `fit-width` spans the
25
+ * available width (scroll vertically); `fit-page` fits the whole first page. */
26
+ export type FitMode = 'fit-width' | 'fit-page';
27
+ /**
28
+ * Resolve a `fit-width`/`fit-page` request into a concrete render scale for the
29
+ * given page and container, clamped to [minScale, maxScale]. `padding` is the
30
+ * total horizontal (and, for `fit-page`, vertical) chrome to subtract from the
31
+ * container before fitting. Invalid geometry falls back to a clamped scale of 1
32
+ * so the caller always gets a usable number.
33
+ */
34
+ export declare function computeFitScale(pageWidth: number, pageHeight: number, containerWidth: number, containerHeight: number, mode: FitMode, opts: {
35
+ minScale: number;
36
+ maxScale: number;
37
+ padding?: number;
38
+ }): number;
@@ -0,0 +1,85 @@
1
+ /** Pure pdfjs hardening helpers — testable without a browser/canvas. See spec §5.2. */
2
+ import { MAX_CANVAS_AREA, MAX_CANVAS_SIDE, clampPixelRatio } from './resource-limits.js';
3
+ /** Options passed to pdfjs getDocument to neutralise eval/XFA and silence logging. */
4
+ export const PDFJS_DOCUMENT_OPTIONS = {
5
+ isEvalSupported: false,
6
+ enableXfa: false,
7
+ verbosity: 0
8
+ };
9
+ /** True when a pdfjs-dist version is at/above the CVE-2024-4367 fix (4.2.67). */
10
+ export function isPdfJsVersionSafe(version) {
11
+ if (!version || typeof version !== 'string')
12
+ return false;
13
+ const m = version.match(/^(\d+)\.(\d+)\.(\d+)/);
14
+ if (!m)
15
+ return false;
16
+ const major = Number(m[1]);
17
+ const minor = Number(m[2]);
18
+ const patch = Number(m[3]);
19
+ if (major > 4)
20
+ return true;
21
+ if (major < 4)
22
+ return false;
23
+ if (minor > 2)
24
+ return true;
25
+ if (minor < 2)
26
+ return false;
27
+ return patch >= 67;
28
+ }
29
+ /**
30
+ * Compute canvas backing-store + CSS dimensions for a page, clamping the
31
+ * backing store to MAX_CANVAS_SIDE/MAX_CANVAS_AREA so a giant MediaBox can't
32
+ * OOM the tab. CSS (display) size is preserved; only resolution is reduced.
33
+ */
34
+ export function computeCanvasDimensions(baseWidth, baseHeight, scale, rawPixelRatio) {
35
+ const pr = clampPixelRatio(rawPixelRatio);
36
+ const cssWidth = baseWidth * scale;
37
+ const cssHeight = baseHeight * scale;
38
+ let pixelWidth = cssWidth * pr;
39
+ let pixelHeight = cssHeight * pr;
40
+ const sideScale = Math.min(1, MAX_CANVAS_SIDE / pixelWidth, MAX_CANVAS_SIDE / pixelHeight);
41
+ pixelWidth *= sideScale;
42
+ pixelHeight *= sideScale;
43
+ const area = pixelWidth * pixelHeight;
44
+ const areaScale = area > MAX_CANVAS_AREA ? Math.sqrt(MAX_CANVAS_AREA / area) : 1;
45
+ pixelWidth *= areaScale;
46
+ pixelHeight *= areaScale;
47
+ return {
48
+ cssWidth,
49
+ cssHeight,
50
+ pixelWidth: Math.max(1, Math.floor(pixelWidth)),
51
+ pixelHeight: Math.max(1, Math.floor(pixelHeight)),
52
+ effectivePixelRatio: pr * sideScale * areaScale
53
+ };
54
+ }
55
+ /** Number of pages to eagerly render: min(numPages, maxPages); 0 if invalid. */
56
+ export function pagesToRender(numPages, maxPages) {
57
+ if (!Number.isFinite(numPages) || numPages <= 0)
58
+ return 0;
59
+ return Math.min(numPages, Math.max(0, maxPages));
60
+ }
61
+ /**
62
+ * Resolve a `fit-width`/`fit-page` request into a concrete render scale for the
63
+ * given page and container, clamped to [minScale, maxScale]. `padding` is the
64
+ * total horizontal (and, for `fit-page`, vertical) chrome to subtract from the
65
+ * container before fitting. Invalid geometry falls back to a clamped scale of 1
66
+ * so the caller always gets a usable number.
67
+ */
68
+ export function computeFitScale(pageWidth, pageHeight, containerWidth, containerHeight, mode, opts) {
69
+ const { minScale, maxScale, padding = 0 } = opts;
70
+ const clamp = (value) => Math.min(Math.max(value, minScale), maxScale);
71
+ const finiteAndPositive = (n) => Number.isFinite(n) && n > 0;
72
+ if (!finiteAndPositive(pageWidth) ||
73
+ !finiteAndPositive(pageHeight) ||
74
+ !finiteAndPositive(containerWidth) ||
75
+ !finiteAndPositive(containerHeight)) {
76
+ return clamp(1);
77
+ }
78
+ const availWidth = Math.max(0, containerWidth - padding);
79
+ const widthScale = availWidth / pageWidth;
80
+ if (mode === 'fit-page') {
81
+ const availHeight = Math.max(0, containerHeight - padding);
82
+ return clamp(Math.min(widthScale, availHeight / pageHeight));
83
+ }
84
+ return clamp(widthScale);
85
+ }
@@ -0,0 +1,13 @@
1
+ /** Shared resource caps for the file-preview viewers. See spec §4. */
2
+ /** Max PDF pages PdfViewer will eagerly render before showing a "first N" banner. */
3
+ export declare const MAX_PAGES = 200;
4
+ /** Max canvas area (px²) — 16 MP is safe across Chrome/Safari/Firefox. */
5
+ export declare const MAX_CANVAS_AREA = 16000000;
6
+ /** Max canvas side length (px). */
7
+ export declare const MAX_CANVAS_SIDE = 8192;
8
+ /** Max decoded image pixels (w×h) before falling back to download. */
9
+ export declare const MAX_IMAGE_PIXELS = 40000000;
10
+ /** Max decoded text bytes TextViewer will buffer before truncating. */
11
+ export declare const MAX_TEXT_BYTES: number;
12
+ /** Clamp a devicePixelRatio into [1, 2]; invalid input falls back to 1. */
13
+ export declare function clampPixelRatio(dpr?: number): number;
@@ -0,0 +1,16 @@
1
+ /** Shared resource caps for the file-preview viewers. See spec §4. */
2
+ /** Max PDF pages PdfViewer will eagerly render before showing a "first N" banner. */
3
+ export const MAX_PAGES = 200;
4
+ /** Max canvas area (px²) — 16 MP is safe across Chrome/Safari/Firefox. */
5
+ export const MAX_CANVAS_AREA = 16_000_000;
6
+ /** Max canvas side length (px). */
7
+ export const MAX_CANVAS_SIDE = 8192;
8
+ /** Max decoded image pixels (w×h) before falling back to download. */
9
+ export const MAX_IMAGE_PIXELS = 40_000_000;
10
+ /** Max decoded text bytes TextViewer will buffer before truncating. */
11
+ export const MAX_TEXT_BYTES = 2 * 1024 * 1024;
12
+ /** Clamp a devicePixelRatio into [1, 2]; invalid input falls back to 1. */
13
+ export function clampPixelRatio(dpr) {
14
+ const value = typeof dpr === 'number' && Number.isFinite(dpr) && dpr > 0 ? dpr : 1;
15
+ return Math.min(value, 2);
16
+ }
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Sanitise an untrusted HTML string with DOMPurify. Returns '' when no DOM is
3
+ * available (SSR) so unsanitised HTML can never reach the page. See spec §5.9.
4
+ */
5
+ export declare function sanitizeHtml(dirty: string): string;
@@ -0,0 +1,12 @@
1
+ import DOMPurify from 'dompurify';
2
+ /**
3
+ * Sanitise an untrusted HTML string with DOMPurify. Returns '' when no DOM is
4
+ * available (SSR) so unsanitised HTML can never reach the page. See spec §5.9.
5
+ */
6
+ export function sanitizeHtml(dirty) {
7
+ if (typeof dirty !== 'string')
8
+ return '';
9
+ if (typeof window === 'undefined')
10
+ return '';
11
+ return DOMPurify.sanitize(dirty);
12
+ }
package/dist/index.d.ts CHANGED
@@ -47,6 +47,9 @@ export type { SpinnerProps } from './elements/spinner/spinner-types.js';
47
47
  export type { SkeletonProps, SkeletonVariant } from './elements/skeleton/skeleton-types.js';
48
48
  export type { EmptyStateProps, EmptyStateSize } from './elements/empty-state/empty-state-types.js';
49
49
  export type { PdfViewerProps } from './elements/pdf-viewer/pdf-viewer-types.js';
50
+ export type { FileViewerProps, FileKindValue } from './elements/file-viewer/file-viewer-types.js';
51
+ export { FileKind, fileKindFromMime, fileKindFromFileName } from './elements/file-viewer/file-viewer-types.js';
52
+ export type { FilePreviewModalProps } from './elements/file-viewer/file-preview-modal-types.js';
50
53
  export type { TooltipProps, TooltipPlacement, TooltipSize, TooltipVariant } from './elements/tooltip/tooltip-types.js';
51
54
  export type { PopoverProps, PopoverPlacement, PopoverTrigger } from './elements/popover/popover-types.js';
52
55
  export type { CalendarProps, CalendarMode } from './forms/calendar/calendar-types.js';
@@ -65,6 +68,10 @@ export type { ChatMessageType, StreamingCallback, ChatAction, ChatMessage, ChatR
65
68
  export type { GetUsersOptions, GetUsersResult, UserEmail, UserPhone, User, Permission, Role, UserTableProps, UserModalProps, UserModalSavePayload, UserViewModalProps, UserApproveModalProps, UserManagementAdapter, UserManagementProps, FormErrors } from './user-management/user-management-types.js';
66
69
  export { tv, cn } from './helper/cls.js';
67
70
  export { isRouteActive } from './helper/nav.svelte.js';
71
+ export * from './helper/resource-limits.js';
72
+ export * from './helper/is-safe-http-url.js';
73
+ export * from './helper/pdf-safety.js';
74
+ export * from './helper/sanitize-html.js';
68
75
  export { default as Button } from './button/Button.svelte';
69
76
  export { default as Modal } from './modal/Modal.svelte';
70
77
  export { default as ConfirmDialog } from './modal/ConfirmDialog.svelte';
@@ -101,6 +108,8 @@ export { spinner as spinnerVariants } from './elements/spinner/spinner.js';
101
108
  export { default as EmptyState } from './elements/empty-state/EmptyState.svelte';
102
109
  export { emptyState as emptyStateVariants } from './elements/empty-state/empty-state.js';
103
110
  export { default as PdfViewer } from './elements/pdf-viewer/PdfViewer.svelte';
111
+ export { default as FileViewer } from './elements/file-viewer/FileViewer.svelte';
112
+ export { default as FilePreviewModal } from './elements/file-viewer/FilePreviewModal.svelte';
104
113
  export { default as Tooltip } from './elements/tooltip/Tooltip.svelte';
105
114
  export { default as Popover } from './elements/popover/Popover.svelte';
106
115
  export { default as ComboBox } from './elements/combobox/ComboBox.svelte';
package/dist/index.js CHANGED
@@ -12,12 +12,17 @@ export { buildTestId } from './helper/testid.js';
12
12
  export { ALL_COUNTRY_CODES, COUNTRY_NAMES } from './forms/market/country-data.js';
13
13
  export { Market } from './forms/market/market.js';
14
14
  export { countryCodeToFlagEmoji } from './forms/market/flag-emoji.js';
15
+ export { FileKind, fileKindFromMime, fileKindFromFileName } from './elements/file-viewer/file-viewer-types.js';
15
16
  export { defaultDatePresets, toIsoDate, fromIsoDate } from './filters/date-presets.js';
16
17
  // ============================================================================
17
18
  // Helper utilities
18
19
  // ============================================================================
19
20
  export { tv, cn } from './helper/cls.js';
20
21
  export { isRouteActive } from './helper/nav.svelte.js';
22
+ export * from './helper/resource-limits.js';
23
+ export * from './helper/is-safe-http-url.js';
24
+ export * from './helper/pdf-safety.js';
25
+ export * from './helper/sanitize-html.js';
21
26
  // ============================================================================
22
27
  // Direct Component Exports
23
28
  // ============================================================================
@@ -78,6 +83,9 @@ export { default as EmptyState } from './elements/empty-state/EmptyState.svelte'
78
83
  export { emptyState as emptyStateVariants } from './elements/empty-state/empty-state.js';
79
84
  // Elements - PdfViewer
80
85
  export { default as PdfViewer } from './elements/pdf-viewer/PdfViewer.svelte';
86
+ // Elements - File viewers
87
+ export { default as FileViewer } from './elements/file-viewer/FileViewer.svelte';
88
+ export { default as FilePreviewModal } from './elements/file-viewer/FilePreviewModal.svelte';
81
89
  // Elements - Tooltip
82
90
  export { default as Tooltip } from './elements/tooltip/Tooltip.svelte';
83
91
  // Elements - Popover
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@makolabs/ripple",
3
- "version": "3.8.1",
3
+ "version": "3.9.2",
4
4
  "description": "Simple Svelte 5 powered component library ✨",
5
5
  "license": "SEE LICENSE IN LICENSE",
6
6
  "repository": {
@@ -55,7 +55,7 @@
55
55
  },
56
56
  "peerDependencies": {
57
57
  "@sveltejs/kit": "^2.0.0",
58
- "pdfjs-dist": "^4.0.0 || ^5.0.0",
58
+ "pdfjs-dist": "^4.2.67 || ^5.0.0",
59
59
  "svelte": "^5.0.0 || ^6.0.0"
60
60
  },
61
61
  "peerDependenciesMeta": {
@@ -79,6 +79,7 @@
79
79
  "@testing-library/jest-dom": "^6.9.1",
80
80
  "@testing-library/svelte": "^5.2.4",
81
81
  "@types/node": "^22.19.1",
82
+ "@vitest/coverage-v8": "^4.1.9",
82
83
  "eslint": "^9.39.1",
83
84
  "eslint-config-prettier": "^10.0.1",
84
85
  "eslint-plugin-storybook": "^10.0.7",
@@ -147,6 +148,7 @@
147
148
  "@aws-sdk/s3-request-presigner": "^3.1029.0",
148
149
  "@friendofsvelte/mermaid": "^0.0.4",
149
150
  "dayjs": "^1.11.19",
151
+ "dompurify": "^3.4.11",
150
152
  "echarts": "^6.0.0",
151
153
  "marked": "^17.0.0",
152
154
  "svelte-highlight": "^7.9.0",