@file-viewer/core 2.1.27 → 2.1.29

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.
@@ -217,6 +217,8 @@ export interface FileRenderExportAdapter {
217
217
  exportHtml?: boolean;
218
218
  includeDocumentStyles?: boolean;
219
219
  beforeSnapshot?: () => Promise<void> | void;
220
+ /** Live page surfaces used by the interactive print-mask designer. */
221
+ getPrintMaskPages?: () => readonly HTMLElement[];
220
222
  printStyle?: string | ((options: FileRenderExportOptions) => Promise<string> | string);
221
223
  toHtml?: (options: FileRenderExportOptions) => Promise<string> | string;
222
224
  }
@@ -806,6 +808,8 @@ export interface FileViewerPrintMaskRegion {
806
808
  top: number;
807
809
  width: number;
808
810
  height: number;
811
+ /** Zero-based rendered page index. Omitted regions retain legacy whole-document coordinates. */
812
+ pageIndex?: number;
809
813
  }
810
814
  export interface FileViewerPrintMaskOptions {
811
815
  /** Solid black cover blocks, matching common OFD/business redaction UX. */
@@ -1,5 +1,6 @@
1
1
  import type { FileViewerPrintMaskOptions, FileViewerPrintMaskRegion } from '../contracts/types';
2
2
  export declare const normalizeFileViewerPrintMaskRegion: (region: Partial<FileViewerPrintMaskRegion> | null | undefined) => FileViewerPrintMaskRegion | null;
3
3
  export declare const normalizeFileViewerPrintMaskOptions: (mask?: FileViewerPrintMaskOptions | null) => FileViewerPrintMaskOptions | null;
4
- export declare const buildFileViewerPrintMaskOverlayHtml: (mask?: FileViewerPrintMaskOptions | null) => string;
5
- export declare const FILE_VIEWER_PRINT_MASK_STYLE = "\n .viewer-export-print-mask{position:absolute;inset:0;z-index:15;pointer-events:none;print-color-adjust:exact;-webkit-print-color-adjust:exact;}\n .viewer-export-print-mask-block{position:absolute;box-sizing:border-box;print-color-adjust:exact;-webkit-print-color-adjust:exact;}\n";
4
+ export declare const buildFileViewerPrintMaskOverlayHtml: (mask?: FileViewerPrintMaskOptions | null, pageScoped?: boolean) => string;
5
+ export declare const FILE_VIEWER_PRINT_MASK_STYLE = "\n .viewer-export-print-mask{position:absolute;inset:0;z-index:15;pointer-events:none;print-color-adjust:exact;-webkit-print-color-adjust:exact;}\n .viewer-export-print-mask--page{z-index:2147483647;}\n .viewer-export-print-mask-block{position:absolute;box-sizing:border-box;print-color-adjust:exact;-webkit-print-color-adjust:exact;}\n [data-viewer-print-page-index]{position:relative!important;isolation:isolate;}\n";
6
+ export declare const applyFileViewerPagePrintMasksToHtml: (contentHtml: string, mask?: FileViewerPrintMaskOptions | null) => string;
@@ -3,6 +3,11 @@ export const normalizeFileViewerPrintMaskRegion = (region) => {
3
3
  if (!region) {
4
4
  return null;
5
5
  }
6
+ const pageIndex = region.pageIndex;
7
+ if (pageIndex !== undefined &&
8
+ (!Number.isInteger(pageIndex) || pageIndex < 0)) {
9
+ return null;
10
+ }
6
11
  const left = clampPercent(Number(region.left) || 0);
7
12
  const top = clampPercent(Number(region.top) || 0);
8
13
  const width = clampPercent(Number(region.width) || 0);
@@ -15,6 +20,7 @@ export const normalizeFileViewerPrintMaskRegion = (region) => {
15
20
  top,
16
21
  width: Math.min(width, 100 - left),
17
22
  height: Math.min(height, 100 - top),
23
+ ...(pageIndex === undefined ? {} : { pageIndex }),
18
24
  };
19
25
  };
20
26
  export const normalizeFileViewerPrintMaskOptions = (mask) => {
@@ -32,7 +38,7 @@ export const normalizeFileViewerPrintMaskOptions = (mask) => {
32
38
  color: mask.color || '#000000',
33
39
  };
34
40
  };
35
- export const buildFileViewerPrintMaskOverlayHtml = (mask) => {
41
+ export const buildFileViewerPrintMaskOverlayHtml = (mask, pageScoped = false) => {
36
42
  var _a;
37
43
  const normalized = normalizeFileViewerPrintMaskOptions(mask);
38
44
  if (!((_a = normalized === null || normalized === void 0 ? void 0 : normalized.regions) === null || _a === void 0 ? void 0 : _a.length)) {
@@ -40,9 +46,43 @@ export const buildFileViewerPrintMaskOverlayHtml = (mask) => {
40
46
  }
41
47
  const color = normalized.color || '#000000';
42
48
  const blocks = normalized.regions.map(region => (`<div class="viewer-export-print-mask-block" style="left:${region.left}%;top:${region.top}%;width:${region.width}%;height:${region.height}%;background:${color};"></div>`)).join('');
43
- return `<div class="viewer-export-print-mask" aria-hidden="true">${blocks}</div>`;
49
+ const className = pageScoped
50
+ ? 'viewer-export-print-mask viewer-export-print-mask--page'
51
+ : 'viewer-export-print-mask';
52
+ return `<div class="${className}" aria-hidden="true">${blocks}</div>`;
44
53
  };
45
54
  export const FILE_VIEWER_PRINT_MASK_STYLE = `
46
55
  .viewer-export-print-mask{position:absolute;inset:0;z-index:15;pointer-events:none;print-color-adjust:exact;-webkit-print-color-adjust:exact;}
56
+ .viewer-export-print-mask--page{z-index:2147483647;}
47
57
  .viewer-export-print-mask-block{position:absolute;box-sizing:border-box;print-color-adjust:exact;-webkit-print-color-adjust:exact;}
58
+ [data-viewer-print-page-index]{position:relative!important;isolation:isolate;}
48
59
  `;
60
+ export const applyFileViewerPagePrintMasksToHtml = (contentHtml, mask) => {
61
+ var _a;
62
+ const normalized = normalizeFileViewerPrintMaskOptions(mask);
63
+ if (!normalized) {
64
+ return contentHtml;
65
+ }
66
+ const regionsByPage = new Map();
67
+ (_a = normalized.regions) === null || _a === void 0 ? void 0 : _a.forEach(region => {
68
+ if (region.pageIndex === undefined) {
69
+ return;
70
+ }
71
+ const pageRegions = regionsByPage.get(region.pageIndex) || [];
72
+ pageRegions.push(region);
73
+ regionsByPage.set(region.pageIndex, pageRegions);
74
+ });
75
+ if (!regionsByPage.size) {
76
+ return contentHtml;
77
+ }
78
+ return contentHtml.replace(/(<[A-Za-z][^>]*\sdata-viewer-print-page-index=(['"])(\d+)\2[^>]*>)/g, (match, openingTag, _quote, rawPageIndex) => {
79
+ const pageRegions = regionsByPage.get(Number(rawPageIndex));
80
+ if (!(pageRegions === null || pageRegions === void 0 ? void 0 : pageRegions.length)) {
81
+ return match;
82
+ }
83
+ return `${openingTag}${buildFileViewerPrintMaskOverlayHtml({
84
+ regions: pageRegions,
85
+ color: normalized.color,
86
+ }, true)}`;
87
+ });
88
+ };
@@ -2,6 +2,7 @@ import type { FileViewerPrintMaskOptions, FileViewerPrintMaskRegion } from '../c
2
2
  import { type FileViewerI18nInput } from '../i18n/messages';
3
3
  export interface OpenFileViewerPrintMaskDesignerOptions {
4
4
  root: HTMLElement;
5
+ pages?: readonly HTMLElement[];
5
6
  i18n?: FileViewerI18nInput;
6
7
  color?: string;
7
8
  initialRegions?: FileViewerPrintMaskRegion[];
@@ -10,7 +11,7 @@ export interface FileViewerPrintMaskDesignerResult {
10
11
  mask: FileViewerPrintMaskOptions;
11
12
  }
12
13
  /**
13
- * Opens an interactive print-mask designer over the rendered content.
14
- * Loaded asynchronously so the main viewer bundle stays lean.
14
+ * Opens a page-aware print-mask designer. Browsing remains the default mode;
15
+ * drawing is armed for the currently visible page only and disarms after one block.
15
16
  */
16
17
  export declare const openFileViewerPrintMaskDesigner: (options: OpenFileViewerPrintMaskDesignerOptions) => Promise<FileViewerPrintMaskDesignerResult | null>;
@@ -1,14 +1,15 @@
1
1
  import { createFileViewerTranslator } from '../i18n/messages.js';
2
2
  import { normalizeFileViewerPrintMaskRegion } from './printMask.js';
3
3
  const DESIGNER_STYLE = `
4
- .fv-print-mask-layer{position:absolute;inset:0;z-index:40;pointer-events:none;}
5
- .fv-print-mask-canvas{position:absolute;inset:0;pointer-events:auto;cursor:crosshair;touch-action:none;}
4
+ .fv-print-mask-layer{position:absolute;inset:0;z-index:2147483000;pointer-events:none;}
5
+ .fv-print-mask-canvas{position:absolute;inset:0;z-index:2147483000;pointer-events:none;cursor:default;}
6
+ .fv-print-mask-canvas.is-armed{pointer-events:auto;cursor:crosshair;touch-action:none;}
6
7
  .fv-print-mask-block{position:absolute;background:#000;box-sizing:border-box;pointer-events:auto;}
7
8
  .fv-print-mask-block-remove{position:absolute;right:-8px;top:-8px;width:18px;height:18px;border:0;border-radius:999px;background:#111;color:#fff;font:700 12px/18px system-ui,sans-serif;cursor:pointer;padding:0;}
8
- .fv-print-mask-toolbar{position:absolute;left:50%;bottom:16px;transform:translateX(-50%);z-index:41;display:inline-flex;align-items:center;gap:6px;padding:6px 8px;border:1px solid rgba(20,35,53,.12);border-radius:999px;background:rgba(255,255,255,.94);box-shadow:0 12px 28px rgba(15,23,42,.16);pointer-events:auto;max-width:calc(100% - 24px);flex-wrap:wrap;justify-content:center;}
9
+ .fv-print-mask-toolbar{position:absolute;left:50%;bottom:16px;transform:translateX(-50%);z-index:2147483001;display:inline-flex;align-items:center;gap:6px;padding:6px 8px;border:1px solid rgba(20,35,53,.12);border-radius:999px;background:rgba(255,255,255,.94);box-shadow:0 12px 28px rgba(15,23,42,.16);pointer-events:auto;max-width:calc(100% - 24px);flex-wrap:wrap;justify-content:center;}
9
10
  .fv-print-mask-toolbar span{font:600 12px/1.2 system-ui,sans-serif;color:#40546a;white-space:nowrap;}
10
11
  .fv-print-mask-toolbar button{min-width:42px;height:30px;padding:0 10px;border:0;border-radius:999px;background:transparent;color:#40546a;font:800 12px/1 system-ui,sans-serif;cursor:pointer;}
11
- .fv-print-mask-toolbar button:hover{background:rgba(33,163,102,.1);color:#16774c;}
12
+ .fv-print-mask-toolbar button:hover,.fv-print-mask-toolbar button.is-active{background:rgba(33,163,102,.1);color:#16774c;}
12
13
  .fv-print-mask-toolbar button.primary{background:#16774c;color:#fff;}
13
14
  .fv-print-mask-toolbar button.primary:hover{background:#0f5f3c;}
14
15
  `;
@@ -21,7 +22,7 @@ const ensureDesignerStyle = (documentRef) => {
21
22
  style.textContent = DESIGNER_STYLE;
22
23
  documentRef.head.appendChild(style);
23
24
  };
24
- const toPercentRegion = (start, end, bounds) => {
25
+ const toPercentRegion = (start, end, bounds, pageIndex) => {
25
26
  if (!bounds.width || !bounds.height) {
26
27
  return null;
27
28
  }
@@ -37,11 +38,18 @@ const toPercentRegion = (start, end, bounds) => {
37
38
  top: (topPx / bounds.height) * 100,
38
39
  width: (widthPx / bounds.width) * 100,
39
40
  height: (heightPx / bounds.height) * 100,
41
+ pageIndex,
40
42
  });
41
43
  };
44
+ const visibleArea = (element, viewport) => {
45
+ const rect = element.getBoundingClientRect();
46
+ const width = Math.max(0, Math.min(rect.right, viewport.right) - Math.max(rect.left, viewport.left));
47
+ const height = Math.max(0, Math.min(rect.bottom, viewport.bottom) - Math.max(rect.top, viewport.top));
48
+ return width * height;
49
+ };
42
50
  /**
43
- * Opens an interactive print-mask designer over the rendered content.
44
- * Loaded asynchronously so the main viewer bundle stays lean.
51
+ * Opens a page-aware print-mask designer. Browsing remains the default mode;
52
+ * drawing is armed for the currently visible page only and disarms after one block.
45
53
  */
46
54
  export const openFileViewerPrintMaskDesigner = (options) => {
47
55
  const root = options.root;
@@ -51,25 +59,59 @@ export const openFileViewerPrintMaskDesigner = (options) => {
51
59
  const regions = [...(options.initialRegions || [])]
52
60
  .map(region => normalizeFileViewerPrintMaskRegion(region))
53
61
  .filter((region) => !!region);
62
+ const providedPages = Array.from(new Set(options.pages || []))
63
+ .filter(page => page === root || root.contains(page));
64
+ const pageScoped = providedPages.length > 0;
65
+ const pageElements = pageScoped ? providedPages : [root];
54
66
  ensureDesignerStyle(documentRef);
55
- const previousPosition = root.style.position;
56
- if (!previousPosition || previousPosition === 'static') {
57
- root.style.position = 'relative';
58
- }
67
+ const ensureOverlayContainingBlock = (element) => {
68
+ var _a, _b, _c;
69
+ const previousPosition = element.style.position;
70
+ const computedPosition = ((_c = (_b = (_a = documentRef.defaultView) === null || _a === void 0 ? void 0 : _a.getComputedStyle) === null || _b === void 0 ? void 0 : _b.call(_a, element)) === null || _c === void 0 ? void 0 : _c.position) ||
71
+ previousPosition ||
72
+ 'static';
73
+ if (computedPosition === 'static') {
74
+ element.style.position = 'relative';
75
+ }
76
+ return previousPosition;
77
+ };
78
+ // The toolbar layer is positioned against the viewer root even when page
79
+ // canvases live on child page elements.
80
+ const previousRootPosition = ensureOverlayContainingBlock(root);
59
81
  return new Promise(resolve => {
60
82
  let settled = false;
61
83
  let drawing = null;
62
84
  const layer = documentRef.createElement('div');
63
85
  layer.className = 'fv-print-mask-layer';
64
86
  layer.setAttribute('data-viewer-print-mask-designer', 'true');
65
- const canvas = documentRef.createElement('div');
66
- canvas.className = 'fv-print-mask-canvas';
87
+ const createSurface = (element, pageIndex) => {
88
+ const previousPosition = ensureOverlayContainingBlock(element);
89
+ const canvas = documentRef.createElement('div');
90
+ canvas.className = 'fv-print-mask-canvas';
91
+ element.appendChild(canvas);
92
+ return {
93
+ element,
94
+ pageIndex,
95
+ canvas,
96
+ previousPosition,
97
+ };
98
+ };
99
+ const surfaces = pageElements.map((element, index) => (createSurface(element, pageScoped ? index : undefined)));
100
+ const legacySurface = pageScoped &&
101
+ !surfaces.some(surface => surface.element === root) &&
102
+ regions.some(region => region.pageIndex === undefined)
103
+ ? createSurface(root)
104
+ : null;
105
+ const allSurfaces = legacySurface ? [...surfaces, legacySurface] : surfaces;
67
106
  const toolbar = documentRef.createElement('div');
68
107
  toolbar.className = 'fv-print-mask-toolbar';
69
108
  toolbar.setAttribute('role', 'toolbar');
70
109
  toolbar.setAttribute('aria-label', t('toolbar.printMaskTitle'));
71
110
  const hint = documentRef.createElement('span');
72
111
  hint.textContent = t('toolbar.printMaskHint');
112
+ const addButton = documentRef.createElement('button');
113
+ addButton.type = 'button';
114
+ addButton.textContent = t('toolbar.printMaskAdd');
73
115
  const clearButton = documentRef.createElement('button');
74
116
  clearButton.type = 'button';
75
117
  clearButton.textContent = t('toolbar.printMaskClear');
@@ -80,26 +122,49 @@ export const openFileViewerPrintMaskDesigner = (options) => {
80
122
  confirmButton.type = 'button';
81
123
  confirmButton.className = 'primary';
82
124
  confirmButton.textContent = t('toolbar.printMaskConfirm');
83
- toolbar.append(hint, clearButton, cancelButton, confirmButton);
84
- layer.append(canvas, toolbar);
125
+ toolbar.append(hint, addButton, clearButton, cancelButton, confirmButton);
126
+ layer.append(toolbar);
85
127
  root.appendChild(layer);
128
+ const disarm = () => {
129
+ surfaces.forEach(surface => surface.canvas.classList.remove('is-armed'));
130
+ addButton.classList.remove('is-active');
131
+ };
86
132
  const finish = (result) => {
87
133
  if (settled) {
88
134
  return;
89
135
  }
90
136
  settled = true;
91
137
  layer.remove();
92
- if (!previousPosition) {
138
+ allSurfaces.forEach(surface => {
139
+ surface.canvas.remove();
140
+ if (!surface.previousPosition) {
141
+ surface.element.style.removeProperty('position');
142
+ }
143
+ else {
144
+ surface.element.style.position = surface.previousPosition;
145
+ }
146
+ });
147
+ if (!previousRootPosition) {
93
148
  root.style.removeProperty('position');
94
149
  }
95
150
  else {
96
- root.style.position = previousPosition;
151
+ root.style.position = previousRootPosition;
97
152
  }
98
153
  resolve(result);
99
154
  };
155
+ const surfaceForRegion = (region) => {
156
+ if (region.pageIndex === undefined) {
157
+ return legacySurface || surfaces[0];
158
+ }
159
+ return surfaces.find(surface => surface.pageIndex === region.pageIndex) || null;
160
+ };
100
161
  const renderRegions = () => {
101
- canvas.replaceChildren();
162
+ allSurfaces.forEach(surface => surface.canvas.replaceChildren());
102
163
  regions.forEach((region, index) => {
164
+ const surface = surfaceForRegion(region);
165
+ if (!surface) {
166
+ return;
167
+ }
103
168
  const block = documentRef.createElement('div');
104
169
  block.className = 'fv-print-mask-block';
105
170
  block.style.left = `${region.left}%`;
@@ -120,66 +185,86 @@ export const openFileViewerPrintMaskDesigner = (options) => {
120
185
  renderRegions();
121
186
  });
122
187
  block.appendChild(remove);
123
- canvas.appendChild(block);
188
+ surface.canvas.appendChild(block);
124
189
  });
125
190
  };
126
- const pointFromEvent = (event) => {
191
+ const pointFromEvent = (event, canvas) => {
127
192
  const bounds = canvas.getBoundingClientRect();
128
193
  return {
129
194
  x: Math.max(0, Math.min(bounds.width, event.clientX - bounds.left)),
130
195
  y: Math.max(0, Math.min(bounds.height, event.clientY - bounds.top)),
131
196
  };
132
197
  };
133
- canvas.addEventListener('pointerdown', event => {
134
- if (event.button !== 0) {
135
- return;
136
- }
137
- event.preventDefault();
138
- const start = pointFromEvent(event);
139
- const preview = documentRef.createElement('div');
140
- preview.className = 'fv-print-mask-block';
141
- preview.style.background = color;
142
- preview.style.opacity = '0.72';
143
- canvas.appendChild(preview);
144
- drawing = { start, preview };
145
- canvas.setPointerCapture(event.pointerId);
198
+ surfaces.forEach(surface => {
199
+ surface.canvas.addEventListener('pointerdown', event => {
200
+ if (event.button !== 0 || !surface.canvas.classList.contains('is-armed')) {
201
+ return;
202
+ }
203
+ event.preventDefault();
204
+ const start = pointFromEvent(event, surface.canvas);
205
+ const preview = documentRef.createElement('div');
206
+ preview.className = 'fv-print-mask-block';
207
+ preview.style.background = color;
208
+ preview.style.opacity = '0.72';
209
+ surface.canvas.appendChild(preview);
210
+ drawing = { surface, start, preview, pointerId: event.pointerId };
211
+ surface.canvas.setPointerCapture(event.pointerId);
212
+ });
213
+ surface.canvas.addEventListener('pointermove', event => {
214
+ if (!drawing || drawing.surface !== surface) {
215
+ return;
216
+ }
217
+ const end = pointFromEvent(event, surface.canvas);
218
+ const left = Math.min(drawing.start.x, end.x);
219
+ const top = Math.min(drawing.start.y, end.y);
220
+ drawing.preview.style.left = `${left}px`;
221
+ drawing.preview.style.top = `${top}px`;
222
+ drawing.preview.style.width = `${Math.abs(end.x - drawing.start.x)}px`;
223
+ drawing.preview.style.height = `${Math.abs(end.y - drawing.start.y)}px`;
224
+ });
225
+ surface.canvas.addEventListener('pointerup', event => {
226
+ if (!drawing || drawing.surface !== surface) {
227
+ return;
228
+ }
229
+ const end = pointFromEvent(event, surface.canvas);
230
+ const region = toPercentRegion(drawing.start, end, surface.canvas.getBoundingClientRect(), surface.pageIndex);
231
+ drawing.preview.remove();
232
+ try {
233
+ surface.canvas.releasePointerCapture(drawing.pointerId);
234
+ }
235
+ catch {
236
+ // Pointer capture may already be released by the browser.
237
+ }
238
+ drawing = null;
239
+ disarm();
240
+ if (region) {
241
+ regions.push(region);
242
+ }
243
+ renderRegions();
244
+ });
245
+ surface.canvas.addEventListener('pointercancel', () => {
246
+ if (!drawing || drawing.surface !== surface) {
247
+ return;
248
+ }
249
+ drawing.preview.remove();
250
+ drawing = null;
251
+ disarm();
252
+ renderRegions();
253
+ });
146
254
  });
147
- canvas.addEventListener('pointermove', event => {
148
- if (!drawing) {
149
- return;
150
- }
151
- const end = pointFromEvent(event);
152
- const left = Math.min(drawing.start.x, end.x);
153
- const top = Math.min(drawing.start.y, end.y);
154
- drawing.preview.style.left = `${left}px`;
155
- drawing.preview.style.top = `${top}px`;
156
- drawing.preview.style.width = `${Math.abs(end.x - drawing.start.x)}px`;
157
- drawing.preview.style.height = `${Math.abs(end.y - drawing.start.y)}px`;
255
+ addButton.addEventListener('click', () => {
256
+ var _a;
257
+ disarm();
258
+ const viewport = root.getBoundingClientRect();
259
+ const activeSurface = ((_a = surfaces
260
+ .map(surface => ({ surface, area: visibleArea(surface.element, viewport) }))
261
+ .sort((left, right) => right.area - left.area)[0]) === null || _a === void 0 ? void 0 : _a.surface) || surfaces[0];
262
+ activeSurface === null || activeSurface === void 0 ? void 0 : activeSurface.canvas.classList.add('is-armed');
263
+ addButton.classList.toggle('is-active', Boolean(activeSurface));
158
264
  });
159
- const endDrawing = (event) => {
160
- if (!drawing) {
161
- return;
162
- }
163
- const end = pointFromEvent(event);
164
- const bounds = canvas.getBoundingClientRect();
165
- const region = toPercentRegion(drawing.start, end, bounds);
166
- drawing.preview.remove();
167
- drawing = null;
168
- try {
169
- canvas.releasePointerCapture(event.pointerId);
170
- }
171
- catch {
172
- // ignore
173
- }
174
- if (region) {
175
- regions.push(region);
176
- renderRegions();
177
- }
178
- };
179
- canvas.addEventListener('pointerup', endDrawing);
180
- canvas.addEventListener('pointercancel', endDrawing);
181
265
  clearButton.addEventListener('click', () => {
182
266
  regions.splice(0, regions.length);
267
+ disarm();
183
268
  renderRegions();
184
269
  });
185
270
  cancelButton.addEventListener('click', () => finish(null));
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import type { FileRenderContext, FileViewerRenderedInstance } from './contracts/types';
2
- export { DEFAULT_FILE_VIEWER_ARCHIVE_WORKER_PATH, DEFAULT_FILE_VIEWER_ARCHIVE_WASM_PATH, DEFAULT_FILE_VIEWER_CAD_DWF_WASM_PATH, DEFAULT_FILE_VIEWER_CAD_WASM_PATH, DEFAULT_FILE_VIEWER_CAD_WORKER_PATH, DEFAULT_FILE_VIEWER_DATA_SQL_WASM_URL, DEFAULT_FILE_VIEWER_DOCX_WORKER_JSZIP_PATH, DEFAULT_FILE_VIEWER_DOCX_WORKER_PATH, DEFAULT_FILE_VIEWER_PDF_CMAP_PATH, DEFAULT_FILE_VIEWER_PDF_STANDARD_FONT_PATH, DEFAULT_FILE_VIEWER_PDF_WASM_PATH, DEFAULT_FILE_VIEWER_PDF_WORKER_PATH, DEFAULT_FILE_VIEWER_RENDERER_ASSET_MANIFESTS, DEFAULT_FILE_VIEWER_SPREADSHEET_WORKER_PATH, DEFAULT_FILE_VIEWER_TYPST_COMPILER_WASM_URL, DEFAULT_FILE_VIEWER_TYPST_RENDERER_WASM_URL, DEFAULT_FILE_VIEWER_TYPST_RENDERER_WASM_PACKAGE_PATH, getFileViewerRendererAssetManifest, listFileViewerRendererAssetManifests, resolveFileViewerArchiveWasmUrl, resolveFileViewerArchiveWorkerUrl, resolveFileViewerAssetUrl, resolveFileViewerCadAssetUrls, resolveFileViewerDataSqlWasmUrl, resolveFileViewerDocxWorkerJsZipUrl, resolveFileViewerDocxWorkerUrl, resolveFileViewerDrawioViewerScriptUrl, resolveFileViewerPdfAssetUrls, resolveFileViewerRendererAssets, resolveFileViewerSpreadsheetWorkerUrl, resolveFileViewerTypstCompilerWasmUrl, resolveFileViewerTypstRendererWasmUrl, } from './assets';
2
+ export { DEFAULT_FILE_VIEWER_ARCHIVE_WORKER_PATH, DEFAULT_FILE_VIEWER_ARCHIVE_WASM_PATH, DEFAULT_FILE_VIEWER_CAD_DWF_WASM_PATH, DEFAULT_FILE_VIEWER_CAD_WASM_PATH, DEFAULT_FILE_VIEWER_CAD_WORKER_PATH, DEFAULT_FILE_VIEWER_DATA_SQL_WASM_URL, DEFAULT_FILE_VIEWER_DOCX_WORKER_JSZIP_PATH, DEFAULT_FILE_VIEWER_DOCX_WORKER_PATH, DEFAULT_FILE_VIEWER_PDF_CMAP_PATH, DEFAULT_FILE_VIEWER_PDF_STANDARD_FONT_PATH, DEFAULT_FILE_VIEWER_PDF_WASM_PATH, DEFAULT_FILE_VIEWER_PDF_WORKER_PATH, DEFAULT_FILE_VIEWER_RENDERER_ASSET_MANIFESTS, DEFAULT_FILE_VIEWER_SPREADSHEET_WORKER_PATH, DEFAULT_FILE_VIEWER_TYPST_COMPILER_WASM_URL, DEFAULT_FILE_VIEWER_TYPST_RENDERER_WASM_URL, DEFAULT_FILE_VIEWER_TYPST_RENDERER_WASM_PACKAGE_PATH, getFileViewerRendererAssetManifest, listFileViewerRendererAssetManifests, resolveFileViewerArchiveWasmUrl, resolveFileViewerArchiveWorkerUrl, resolveFileViewerAssetUrl, resolveFileViewerCadAssetUrls, resolveFileViewerDataSqlWasmUrl, resolveFileViewerDocxWorkerJsZipUrl, resolveFileViewerDocxWorkerUrl, resolveFileViewerDrawioViewerScriptUrl, resolveFileViewerPdfAssetUrls, resolveFileViewerRendererAssets, resolveFileViewerRuntimeAssetBaseUrl, resolveFileViewerSpreadsheetWorkerUrl, resolveFileViewerTypstCompilerWasmUrl, resolveFileViewerTypstRendererWasmUrl, } from './assets';
3
3
  export { ARCHIVE_EXTENSIONS, DEFAULT_RENDERER_DEFINITIONS, DEFAULT_SUPPORTED_EXTENSIONS, IMAGE_EXTENSIONS, MODEL_EXTENSIONS, TEXT_EXTENSIONS, } from './registry/formats';
4
4
  export { DEFAULT_FILE_VIEWER_TEXT_CHUNK_OVERLAP, DEFAULT_FILE_VIEWER_TEXT_CHUNK_SIZE, DEFAULT_FILE_VIEWER_ZOOM_SCALE, buildFileViewerDocumentTextChunks, createEmptyFileViewerSearchState, createFileViewerZoomState, normalizeFileViewerAiOptions, normalizeFileViewerSearchOptions, } from './features/document/model';
5
5
  export { DEFAULT_FILE_VIEWER_SEARCH_ACTIVE_CLASS, DEFAULT_FILE_VIEWER_SEARCH_MATCH_CLASS, DEFAULT_FILE_VIEWER_SEARCH_MAX_MATCHES, applyFileViewerSearchState, cloneFileViewerSearchState, createFileViewerDomSearchController, createFileViewerDomSearchControllerActionHandlers, destroyFileViewerDomSearchController, observeFileViewerDomSearchController, runFileViewerDomSearchControllerAction, syncFileViewerDomSearchControllerState, } from './features/document/search';
@@ -67,7 +67,7 @@ export { DEFAULT_FILE_VIEWER_STATE_THEME, DEFAULT_FILE_VIEWER_UNSUPPORTED_DESCRI
67
67
  export type { FileViewerErrorMessageFormatter, FileViewerRendererInstallHint, } from './viewer/state';
68
68
  export { buildFileViewerWatermarkBackgroundImage, buildFileViewerWatermarkInlineStyle, buildFileViewerWatermarkStyle, buildFileViewerWatermarkSvg, normalizeFileViewerWatermark, resolveFileViewerWatermarkPresentationState, } from './features/watermark';
69
69
  export type { FileViewerWatermarkPresentationState, FileViewerWatermarkStyle, } from './features/watermark';
70
- export { buildFileViewerPrintMaskOverlayHtml, normalizeFileViewerPrintMaskOptions, normalizeFileViewerPrintMaskRegion, FILE_VIEWER_PRINT_MASK_STYLE, } from './features/printMask';
70
+ export { buildFileViewerPrintMaskOverlayHtml, applyFileViewerPagePrintMasksToHtml, normalizeFileViewerPrintMaskOptions, normalizeFileViewerPrintMaskRegion, FILE_VIEWER_PRINT_MASK_STYLE, } from './features/printMask';
71
71
  export { openFileViewerPrintMaskDesignerAsync, } from './features/printMaskLoader';
72
72
  export type { FileViewerPrintMaskDesignerResult, OpenFileViewerPrintMaskDesignerOptions, } from './features/printMaskDesigner';
73
73
  export { cancelFileViewerPreviewRequest, DEFAULT_FILE_VIEWER_STREAMING_PDF_FILENAME, DEFAULT_FILE_VIEWER_PREVIEW_LOAD_ERROR_LOGGER, DEFAULT_PDF_RANGE_CHUNK_SIZE, FILE_VIEWER_PREVIEW_LOAD_ERROR_PREFIXES, FILE_VIEWER_REMOTE_MISSING_DATA_ERROR_MESSAGE, applyFileViewerEmptyPreviewState, applyFileViewerPreviewFilenameState, applyFileViewerPreviewSourceUrlState, applyFileViewerReadPreviewState, applyFileViewerRenderReadinessState, applyFileViewerPreviewRequestResetState, commitFileViewerEmptyPreviewResetState, commitFileViewerLoadStartState, commitFileViewerPreviewRequestStartState, commitFileViewerRenderCompleteState, commitFileViewerRemoteDownloadState, createFileViewerEmptyPreviewState, createFileViewerLoadStartState, createFileViewerPreviewStateTarget, createFileViewerSourceLoadingActionHandlers, createFileViewerReadPreviewState, createFileViewerPreviewRequestResetState, createFileViewerRenderCompleteState, createFileViewerRequestController, createFileViewerRequestScope, createFileViewerStreamingPdfPlaceholderFile, finalizeFileViewerPreviewLoadState, hasFileViewerPreviewSource, isFileViewerAbortError, isSameOriginUrl, normalizeFileViewerSourceUrl, normalizePdfStreamingMode, resolveFileViewerFileRefSourcePlan, resolveFileViewerLoadStartMessage, resolveFileViewerMissingRemoteDataErrorMessage, resolveFileViewerPreviewLoadErrorMessage, resolveFileViewerPreviewRequestReason, resolveFileViewerRemoteSourcePlan, resolveFileViewerPageHref, reportFileViewerMissingRemoteData, reportFileViewerPreviewLoadError, runFileViewerLocalFilePreview, runFileViewerPreviewComponentUnmount, runFileViewerPreviewRequest, runFileViewerPreviewSourceChange, runFileViewerRemoteFilePreview, runFileViewerReadAndRenderFile, runFileViewerStreamingPdfPreview, shouldStreamPdfUrl, } from './source/loading';
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- export { DEFAULT_FILE_VIEWER_ARCHIVE_WORKER_PATH, DEFAULT_FILE_VIEWER_ARCHIVE_WASM_PATH, DEFAULT_FILE_VIEWER_CAD_DWF_WASM_PATH, DEFAULT_FILE_VIEWER_CAD_WASM_PATH, DEFAULT_FILE_VIEWER_CAD_WORKER_PATH, DEFAULT_FILE_VIEWER_DATA_SQL_WASM_URL, DEFAULT_FILE_VIEWER_DOCX_WORKER_JSZIP_PATH, DEFAULT_FILE_VIEWER_DOCX_WORKER_PATH, DEFAULT_FILE_VIEWER_PDF_CMAP_PATH, DEFAULT_FILE_VIEWER_PDF_STANDARD_FONT_PATH, DEFAULT_FILE_VIEWER_PDF_WASM_PATH, DEFAULT_FILE_VIEWER_PDF_WORKER_PATH, DEFAULT_FILE_VIEWER_RENDERER_ASSET_MANIFESTS, DEFAULT_FILE_VIEWER_SPREADSHEET_WORKER_PATH, DEFAULT_FILE_VIEWER_TYPST_COMPILER_WASM_URL, DEFAULT_FILE_VIEWER_TYPST_RENDERER_WASM_URL, DEFAULT_FILE_VIEWER_TYPST_RENDERER_WASM_PACKAGE_PATH, getFileViewerRendererAssetManifest, listFileViewerRendererAssetManifests, resolveFileViewerArchiveWasmUrl, resolveFileViewerArchiveWorkerUrl, resolveFileViewerAssetUrl, resolveFileViewerCadAssetUrls, resolveFileViewerDataSqlWasmUrl, resolveFileViewerDocxWorkerJsZipUrl, resolveFileViewerDocxWorkerUrl, resolveFileViewerDrawioViewerScriptUrl, resolveFileViewerPdfAssetUrls, resolveFileViewerRendererAssets, resolveFileViewerSpreadsheetWorkerUrl, resolveFileViewerTypstCompilerWasmUrl, resolveFileViewerTypstRendererWasmUrl, } from './assets.js';
1
+ export { DEFAULT_FILE_VIEWER_ARCHIVE_WORKER_PATH, DEFAULT_FILE_VIEWER_ARCHIVE_WASM_PATH, DEFAULT_FILE_VIEWER_CAD_DWF_WASM_PATH, DEFAULT_FILE_VIEWER_CAD_WASM_PATH, DEFAULT_FILE_VIEWER_CAD_WORKER_PATH, DEFAULT_FILE_VIEWER_DATA_SQL_WASM_URL, DEFAULT_FILE_VIEWER_DOCX_WORKER_JSZIP_PATH, DEFAULT_FILE_VIEWER_DOCX_WORKER_PATH, DEFAULT_FILE_VIEWER_PDF_CMAP_PATH, DEFAULT_FILE_VIEWER_PDF_STANDARD_FONT_PATH, DEFAULT_FILE_VIEWER_PDF_WASM_PATH, DEFAULT_FILE_VIEWER_PDF_WORKER_PATH, DEFAULT_FILE_VIEWER_RENDERER_ASSET_MANIFESTS, DEFAULT_FILE_VIEWER_SPREADSHEET_WORKER_PATH, DEFAULT_FILE_VIEWER_TYPST_COMPILER_WASM_URL, DEFAULT_FILE_VIEWER_TYPST_RENDERER_WASM_URL, DEFAULT_FILE_VIEWER_TYPST_RENDERER_WASM_PACKAGE_PATH, getFileViewerRendererAssetManifest, listFileViewerRendererAssetManifests, resolveFileViewerArchiveWasmUrl, resolveFileViewerArchiveWorkerUrl, resolveFileViewerAssetUrl, resolveFileViewerCadAssetUrls, resolveFileViewerDataSqlWasmUrl, resolveFileViewerDocxWorkerJsZipUrl, resolveFileViewerDocxWorkerUrl, resolveFileViewerDrawioViewerScriptUrl, resolveFileViewerPdfAssetUrls, resolveFileViewerRendererAssets, resolveFileViewerRuntimeAssetBaseUrl, resolveFileViewerSpreadsheetWorkerUrl, resolveFileViewerTypstCompilerWasmUrl, resolveFileViewerTypstRendererWasmUrl, } from './assets.js';
2
2
  export { ARCHIVE_EXTENSIONS, DEFAULT_RENDERER_DEFINITIONS, DEFAULT_SUPPORTED_EXTENSIONS, IMAGE_EXTENSIONS, MODEL_EXTENSIONS, TEXT_EXTENSIONS, } from './registry/formats.js';
3
3
  export { DEFAULT_FILE_VIEWER_TEXT_CHUNK_OVERLAP, DEFAULT_FILE_VIEWER_TEXT_CHUNK_SIZE, DEFAULT_FILE_VIEWER_ZOOM_SCALE, buildFileViewerDocumentTextChunks, createEmptyFileViewerSearchState, createFileViewerZoomState, normalizeFileViewerAiOptions, normalizeFileViewerSearchOptions, } from './features/document/model.js';
4
4
  export { DEFAULT_FILE_VIEWER_SEARCH_ACTIVE_CLASS, DEFAULT_FILE_VIEWER_SEARCH_MATCH_CLASS, DEFAULT_FILE_VIEWER_SEARCH_MAX_MATCHES, applyFileViewerSearchState, cloneFileViewerSearchState, createFileViewerDomSearchController, createFileViewerDomSearchControllerActionHandlers, destroyFileViewerDomSearchController, observeFileViewerDomSearchController, runFileViewerDomSearchControllerAction, syncFileViewerDomSearchControllerState, } from './features/document/search.js';
@@ -173,7 +173,7 @@ export { appendFileViewerStyle, buildFileRenderContextFromLoadContext, applyFile
173
173
  export { DEFAULT_FILE_VIEWER_SOURCE_FILENAME, decodeFilename, getExtension, normalizeFileExtension, normalizeFilename, resolveFileViewerSourceFilename, normalizeSource, readFileViewerBuffer, readFileViewerDataUrl, readFileViewerText, wrapFileViewerFileRef, } from './source/index.js';
174
174
  export { DEFAULT_FILE_VIEWER_STATE_THEME, DEFAULT_FILE_VIEWER_UNSUPPORTED_DESCRIPTION, FILE_VIEWER_PREVIEW_MESSAGES, createFileViewerEmptyState, createFileViewerErrorState, createFileViewerPreviewLoadingState, createFileViewerReadyState, createFileViewerUnsupportedState, formatFileViewerErrorMessage, normalizeFileViewerErrorMessage, resolveFileViewerRendererInstallHint, } from './viewer/state.js';
175
175
  export { buildFileViewerWatermarkBackgroundImage, buildFileViewerWatermarkInlineStyle, buildFileViewerWatermarkStyle, buildFileViewerWatermarkSvg, normalizeFileViewerWatermark, resolveFileViewerWatermarkPresentationState, } from './features/watermark.js';
176
- export { buildFileViewerPrintMaskOverlayHtml, normalizeFileViewerPrintMaskOptions, normalizeFileViewerPrintMaskRegion, FILE_VIEWER_PRINT_MASK_STYLE, } from './features/printMask.js';
176
+ export { buildFileViewerPrintMaskOverlayHtml, applyFileViewerPagePrintMasksToHtml, normalizeFileViewerPrintMaskOptions, normalizeFileViewerPrintMaskRegion, FILE_VIEWER_PRINT_MASK_STYLE, } from './features/printMask.js';
177
177
  export { openFileViewerPrintMaskDesignerAsync, } from './features/printMaskLoader.js';
178
178
  export { cancelFileViewerPreviewRequest, DEFAULT_FILE_VIEWER_STREAMING_PDF_FILENAME, DEFAULT_FILE_VIEWER_PREVIEW_LOAD_ERROR_LOGGER, DEFAULT_PDF_RANGE_CHUNK_SIZE, FILE_VIEWER_PREVIEW_LOAD_ERROR_PREFIXES, FILE_VIEWER_REMOTE_MISSING_DATA_ERROR_MESSAGE, applyFileViewerEmptyPreviewState, applyFileViewerPreviewFilenameState, applyFileViewerPreviewSourceUrlState, applyFileViewerReadPreviewState, applyFileViewerRenderReadinessState, applyFileViewerPreviewRequestResetState, commitFileViewerEmptyPreviewResetState, commitFileViewerLoadStartState, commitFileViewerPreviewRequestStartState, commitFileViewerRenderCompleteState, commitFileViewerRemoteDownloadState, createFileViewerEmptyPreviewState, createFileViewerLoadStartState, createFileViewerPreviewStateTarget, createFileViewerSourceLoadingActionHandlers, createFileViewerReadPreviewState, createFileViewerPreviewRequestResetState, createFileViewerRenderCompleteState, createFileViewerRequestController, createFileViewerRequestScope, createFileViewerStreamingPdfPlaceholderFile, finalizeFileViewerPreviewLoadState, hasFileViewerPreviewSource, isFileViewerAbortError, isSameOriginUrl, normalizeFileViewerSourceUrl, normalizePdfStreamingMode, resolveFileViewerFileRefSourcePlan, resolveFileViewerLoadStartMessage, resolveFileViewerMissingRemoteDataErrorMessage, resolveFileViewerPreviewLoadErrorMessage, resolveFileViewerPreviewRequestReason, resolveFileViewerRemoteSourcePlan, resolveFileViewerPageHref, reportFileViewerMissingRemoteData, reportFileViewerPreviewLoadError, runFileViewerLocalFilePreview, runFileViewerPreviewComponentUnmount, runFileViewerPreviewRequest, runFileViewerPreviewSourceChange, runFileViewerRemoteFilePreview, runFileViewerReadAndRenderFile, runFileViewerStreamingPdfPreview, shouldStreamPdfUrl, } from './source/loading.js';
179
179
  export { createViewer } from './viewer/createViewer.js';
@@ -1,4 +1,4 @@
1
- import { buildFileViewerPrintMaskOverlayHtml, FILE_VIEWER_PRINT_MASK_STYLE, normalizeFileViewerPrintMaskOptions, } from '../features/printMask.js';
1
+ import { applyFileViewerPagePrintMasksToHtml, buildFileViewerPrintMaskOverlayHtml, FILE_VIEWER_PRINT_MASK_STYLE, normalizeFileViewerPrintMaskOptions, } from '../features/printMask.js';
2
2
  const escapeHtmlAttribute = (value) => value
3
3
  .replace(/&/g, '&amp;')
4
4
  .replace(/"/g, '&quot;')
@@ -289,13 +289,22 @@ export const collectDocumentStyles = () => {
289
289
  .join('\n');
290
290
  };
291
291
  export const buildExportHtmlDocument = ({ contentHtml, includeDocumentStyles = true, printStyle = '', title, watermarkInlineStyle = '', mask = null, }) => {
292
+ var _a;
292
293
  const watermark = watermarkInlineStyle
293
294
  ? `<div class="viewer-export-watermark" style="${watermarkInlineStyle}"></div>`
294
295
  : '';
295
- const maskHtml = buildFileViewerPrintMaskOverlayHtml(mask);
296
+ const normalizedMask = normalizeFileViewerPrintMaskOptions(mask);
297
+ const globalMask = normalizedMask
298
+ ? {
299
+ ...normalizedMask,
300
+ regions: (_a = normalizedMask.regions) === null || _a === void 0 ? void 0 : _a.filter(region => region.pageIndex === undefined),
301
+ }
302
+ : null;
303
+ const maskHtml = buildFileViewerPrintMaskOverlayHtml(globalMask);
304
+ const maskedContentHtml = applyFileViewerPagePrintMasksToHtml(contentHtml, normalizedMask);
296
305
  const styles = includeDocumentStyles ? collectDocumentStyles() : '';
297
306
  const printOverrideStyle = printStyle ? `<style data-viewer-print-style>${printStyle}</style>` : '';
298
- const maskStyle = maskHtml ? `<style data-viewer-print-mask-style>${FILE_VIEWER_PRINT_MASK_STYLE}</style>` : '';
307
+ const maskStyle = normalizedMask ? `<style data-viewer-print-mask-style>${FILE_VIEWER_PRINT_MASK_STYLE}</style>` : '';
299
308
  const safeTitle = escapeHtmlAttribute(title);
300
309
  return `<!doctype html>
301
310
  <html lang="zh-CN">
@@ -309,7 +318,7 @@ export const buildExportHtmlDocument = ({ contentHtml, includeDocumentStyles = t
309
318
  </head>
310
319
  <body>
311
320
  <main class="viewer-export-shell">
312
- <div class="viewer-export-content">${contentHtml}</div>
321
+ <div class="viewer-export-content">${maskedContentHtml}</div>
313
322
  ${maskHtml}
314
323
  ${watermark}
315
324
  </main>
@@ -29,6 +29,14 @@ export interface ResolveFileViewerAssetUrlOptions {
29
29
  documentBaseUrl?: string;
30
30
  trimTrailingSlash?: boolean;
31
31
  }
32
+ /**
33
+ * Resolves the stable public base for runtime assets without reading
34
+ * bundler-specific environment metadata or webpack public-path variables.
35
+ * Explicit HTML `<base>` configuration stays authoritative; for SPA fallback
36
+ * routes, emitted Vite/Webpack/UMI entry scripts reveal the deployment root
37
+ * more reliably than the route-derived page URL.
38
+ */
39
+ export declare const resolveFileViewerRuntimeAssetBaseUrl: (documentRef: Document) => string;
32
40
  export interface ResolvedFileViewerCadAssetUrls {
33
41
  wasmPath: string;
34
42
  workerUrl: string;
@@ -71,7 +79,7 @@ export interface ResolveFileViewerRendererAssetsOptions extends ResolveFileViewe
71
79
  export declare const DEFAULT_FILE_VIEWER_RENDERER_ASSET_MANIFESTS: readonly FileViewerRendererAssetManifest[];
72
80
  export declare const resolveFileViewerAssetUrl: (value: string | URL | undefined, fallback: string, options?: ResolveFileViewerAssetUrlOptions) => string;
73
81
  export declare const resolveFileViewerArchiveWorkerUrl: (options?: Pick<FileViewerArchiveOptions, "workerUrl"> | null, baseUrl?: string) => string;
74
- export declare const resolveFileViewerArchiveWasmUrl: (options?: Pick<FileViewerArchiveOptions, "wasmUrl"> | null, fallback?: string) => string;
82
+ export declare const resolveFileViewerArchiveWasmUrl: (options?: Pick<FileViewerArchiveOptions, "wasmUrl"> | null, fallback?: string, documentBaseUrl?: string) => string;
75
83
  export declare const resolveFileViewerCadAssetUrls: (options?: Pick<FileViewerCadOptions, "wasmPath" | "workerUrl" | "dwfWasmUrl"> | null, documentBaseUrl?: string) => ResolvedFileViewerCadAssetUrls;
76
84
  export declare const resolveFileViewerPdfAssetUrls: (options?: Pick<FileViewerPdfOptions, "assetBaseUrl" | "workerUrl" | "cMapUrl" | "wasmUrl" | "standardFontDataUrl" | "cjkFontFallbackPath"> | null, documentBaseUrl?: string) => ResolvedFileViewerPdfAssetUrls;
77
85
  export declare const resolveFileViewerDrawioViewerScriptUrl: (options?: Pick<FileViewerDrawingOptions, "viewerScriptUrl"> | null, documentBaseUrl?: string) => string;
@@ -25,6 +25,68 @@ export const DEFAULT_FILE_VIEWER_TYPST_COMPILER_WASM_PACKAGE_PATH = '@myriaddrea
25
25
  export const DEFAULT_FILE_VIEWER_TYPST_RENDERER_WASM_PACKAGE_PATH = '@myriaddreamin/typst-ts-renderer/pkg/typst_ts_renderer_bg.wasm';
26
26
  export const DEFAULT_FILE_VIEWER_DATA_SQL_WASM_URL = 'wasm/data/sql-wasm.wasm';
27
27
  export const DEFAULT_FILE_VIEWER_DATA_SQL_WASM_PACKAGE_PATH = 'sql.js/dist/sql-wasm.wasm';
28
+ const resolveFileViewerScriptAssetBaseCandidate = (script, documentBaseUrl, index) => {
29
+ try {
30
+ const rawScriptUrl = script.src || script.getAttribute('src') || '';
31
+ if (!rawScriptUrl) {
32
+ return null;
33
+ }
34
+ const scriptUrl = new URL(rawScriptUrl, documentBaseUrl);
35
+ const viteClient = scriptUrl.pathname.match(/^(.*\/)@vite\/client$/i);
36
+ const isSourceModule = /\/(?:src|node_modules|@fs|@id|@vite)(?:\/|$)/i.test(scriptUrl.pathname);
37
+ const assetDirectory = scriptUrl.pathname.match(/^(.*\/)(?:assets|static|js)\/.+\.(?:m?js)$/i);
38
+ const entryScript = isSourceModule
39
+ ? null
40
+ : scriptUrl.pathname.match(/^(.*\/)(?:app|index|main|runtime|umi)(?:[.-][^/]*)?\.(?:m?js)$/i);
41
+ const basePath = (viteClient === null || viteClient === void 0 ? void 0 : viteClient[1]) || (!isSourceModule ? assetDirectory === null || assetDirectory === void 0 ? void 0 : assetDirectory[1] : null) || (entryScript === null || entryScript === void 0 ? void 0 : entryScript[1]);
42
+ if (!basePath) {
43
+ return null;
44
+ }
45
+ const url = new URL(basePath, scriptUrl).href;
46
+ const documentUrl = new URL(documentBaseUrl);
47
+ const candidateUrl = new URL(url);
48
+ const scriptName = scriptUrl.pathname.slice(scriptUrl.pathname.lastIndexOf('/') + 1);
49
+ let score = index / 10000;
50
+ if (candidateUrl.origin === documentUrl.origin) {
51
+ score += 8;
52
+ }
53
+ if (documentUrl.pathname.startsWith(candidateUrl.pathname)) {
54
+ score += 4;
55
+ }
56
+ if (script.type === 'module') {
57
+ score += 2;
58
+ }
59
+ if (/^(?:app|index|main|runtime|umi)(?:[.-]|$)/i.test(scriptName)) {
60
+ score += 2;
61
+ }
62
+ if (viteClient) {
63
+ score += 8;
64
+ }
65
+ return { url, score };
66
+ }
67
+ catch {
68
+ return null;
69
+ }
70
+ };
71
+ /**
72
+ * Resolves the stable public base for runtime assets without reading
73
+ * bundler-specific environment metadata or webpack public-path variables.
74
+ * Explicit HTML `<base>` configuration stays authoritative; for SPA fallback
75
+ * routes, emitted Vite/Webpack/UMI entry scripts reveal the deployment root
76
+ * more reliably than the route-derived page URL.
77
+ */
78
+ export const resolveFileViewerRuntimeAssetBaseUrl = (documentRef) => {
79
+ var _a;
80
+ const documentBaseUrl = documentRef.baseURI || documentRef.URL || 'file:///';
81
+ if (documentRef.querySelector('base[href]')) {
82
+ return documentBaseUrl;
83
+ }
84
+ const candidates = Array.from(documentRef.querySelectorAll('script[src]'))
85
+ .map((script, index) => resolveFileViewerScriptAssetBaseCandidate(script, documentBaseUrl, index))
86
+ .filter((candidate) => Boolean(candidate))
87
+ .sort((left, right) => right.score - left.score);
88
+ return ((_a = candidates[0]) === null || _a === void 0 ? void 0 : _a.url) || documentBaseUrl;
89
+ };
28
90
  export const DEFAULT_FILE_VIEWER_RENDERER_ASSET_MANIFESTS = [
29
91
  {
30
92
  rendererId: 'drawing',
@@ -290,11 +352,13 @@ export const resolveFileViewerAssetUrl = (value, fallback, options = {}) => {
290
352
  export const resolveFileViewerArchiveWorkerUrl = (options, baseUrl) => {
291
353
  return resolveFileViewerAssetUrl(options === null || options === void 0 ? void 0 : options.workerUrl, DEFAULT_FILE_VIEWER_ARCHIVE_WORKER_PATH, { baseUrl });
292
354
  };
293
- export const resolveFileViewerArchiveWasmUrl = (options, fallback = '') => {
355
+ export const resolveFileViewerArchiveWasmUrl = (options, fallback = '', documentBaseUrl) => {
294
356
  if (!(options === null || options === void 0 ? void 0 : options.wasmUrl)) {
295
357
  return fallback;
296
358
  }
297
- return resolveFileViewerAssetUrl(options.wasmUrl, fallback || options.wasmUrl);
359
+ return resolveFileViewerAssetUrl(options.wasmUrl, fallback || options.wasmUrl, {
360
+ documentBaseUrl,
361
+ });
298
362
  };
299
363
  export const resolveFileViewerCadAssetUrls = (options, documentBaseUrl) => {
300
364
  return {
@@ -315,4 +315,4 @@ export declare const DEFAULT_RENDERER_DEFINITIONS: readonly [{
315
315
  readonly search: true;
316
316
  };
317
317
  }];
318
- export declare const DEFAULT_SUPPORTED_EXTENSIONS: readonly ("markdown" | "webp" | "jpeg" | "png" | "xyz" | "wasm" | "pdf" | "typst" | "zip" | "zipx" | "7z" | "rar" | "tar" | "gz" | "gzip" | "tgz" | "bz2" | "bzip2" | "tbz" | "tbz2" | "xz" | "txz" | "lzma" | "zst" | "tzst" | "cab" | "ar" | "cpio" | "iso" | "xar" | "lha" | "lzh" | "jar" | "war" | "ear" | "apk" | "cbz" | "cbr" | "glb" | "gltf" | "obj" | "stl" | "ply" | "fbx" | "dae" | "3ds" | "3mf" | "amf" | "usd" | "usda" | "usdc" | "usdz" | "kmz" | "step" | "stp" | "iges" | "igs" | "ifc" | "3dm" | "brep" | "pcd" | "wrl" | "vrml" | "vtk" | "vtp" | "txt" | "json" | "js" | "mjs" | "cjs" | "css" | "java" | "py" | "html" | "htm" | "jsx" | "ts" | "tsx" | "xml" | "log" | "vue" | "yaml" | "yml" | "ini" | "sh" | "bash" | "sql" | "go" | "rs" | "php" | "c" | "cpp" | "cc" | "h" | "hpp" | "cs" | "diff" | "patch" | "bundle" | "bdl" | "jsonc" | "json5" | "ipynb" | "toml" | "proto" | "hcl" | "tex" | "gv" | "http" | "react" | "rb" | "swift" | "kt" | "gif" | "jpg" | "bmp" | "tiff" | "tif" | "svg" | "avif" | "ico" | "heic" | "heif" | "jxl" | "docx" | "docm" | "dotx" | "dotm" | "doc" | "dot" | "pptx" | "pptm" | "potx" | "potm" | "ppsx" | "ppsm" | "rtf" | "odt" | "odp" | "xlsx" | "xltx" | "xlsm" | "xlsb" | "xls" | "xlt" | "xltm" | "csv" | "ods" | "fods" | "numbers" | "ofd" | "typ" | "eml" | "msg" | "mbox" | "olb" | "dra" | "gds" | "oas" | "oasis" | "dxf" | "dwg" | "dwf" | "dwfx" | "xps" | "geojson" | "kml" | "gpx" | "shp" | "excalidraw" | "drawio" | "dio" | "mermaid" | "mmd" | "plantuml" | "puml" | "xmind" | "epub" | "umd" | "md" | "mp4" | "webm" | "m3u8" | "mp3" | "mpeg" | "wav" | "ogg" | "oga" | "opus" | "m4a" | "aac" | "flac" | "weba" | "midi" | "mid" | "ttf" | "otf" | "woff" | "woff2" | "psd" | "ai" | "eps" | "sqlite" | "parquet" | "avro" | "webarchive")[];
318
+ export declare const DEFAULT_SUPPORTED_EXTENSIONS: readonly ("markdown" | "webp" | "jpeg" | "png" | "xyz" | "wasm" | "pdf" | "typst" | "html" | "svg" | "rb" | "zip" | "zipx" | "7z" | "rar" | "tar" | "gz" | "gzip" | "tgz" | "bz2" | "bzip2" | "tbz" | "tbz2" | "xz" | "txz" | "lzma" | "zst" | "tzst" | "cab" | "ar" | "cpio" | "iso" | "xar" | "lha" | "lzh" | "jar" | "war" | "ear" | "apk" | "cbz" | "cbr" | "glb" | "gltf" | "obj" | "stl" | "ply" | "fbx" | "dae" | "3ds" | "3mf" | "amf" | "usd" | "usda" | "usdc" | "usdz" | "kmz" | "step" | "stp" | "iges" | "igs" | "ifc" | "3dm" | "brep" | "pcd" | "wrl" | "vrml" | "vtk" | "vtp" | "txt" | "json" | "js" | "mjs" | "cjs" | "css" | "java" | "py" | "htm" | "jsx" | "ts" | "tsx" | "xml" | "log" | "vue" | "yaml" | "yml" | "ini" | "sh" | "bash" | "sql" | "go" | "rs" | "php" | "c" | "cpp" | "cc" | "h" | "hpp" | "cs" | "diff" | "patch" | "bundle" | "bdl" | "jsonc" | "json5" | "ipynb" | "toml" | "proto" | "hcl" | "tex" | "gv" | "http" | "react" | "swift" | "kt" | "gif" | "jpg" | "bmp" | "tiff" | "tif" | "avif" | "ico" | "heic" | "heif" | "jxl" | "docx" | "docm" | "dotx" | "dotm" | "doc" | "dot" | "pptx" | "pptm" | "potx" | "potm" | "ppsx" | "ppsm" | "rtf" | "odt" | "odp" | "xlsx" | "xltx" | "xlsm" | "xlsb" | "xls" | "xlt" | "xltm" | "csv" | "ods" | "fods" | "numbers" | "ofd" | "typ" | "eml" | "msg" | "mbox" | "olb" | "dra" | "gds" | "oas" | "oasis" | "dxf" | "dwg" | "dwf" | "dwfx" | "xps" | "geojson" | "kml" | "gpx" | "shp" | "excalidraw" | "drawio" | "dio" | "mermaid" | "mmd" | "plantuml" | "puml" | "xmind" | "epub" | "umd" | "md" | "mp4" | "webm" | "m3u8" | "mp3" | "mpeg" | "wav" | "ogg" | "oga" | "opus" | "m4a" | "aac" | "flac" | "weba" | "midi" | "mid" | "ttf" | "otf" | "woff" | "woff2" | "psd" | "ai" | "eps" | "sqlite" | "parquet" | "avro" | "webarchive")[];
@@ -634,12 +634,13 @@ export const createViewer = (container, createOptions = {}) => {
634
634
  });
635
635
  },
636
636
  async printWithMask(printOptions = {}) {
637
- var _a, _b;
637
+ var _a, _b, _c, _d;
638
638
  const result = await openFileViewerPrintMaskDesignerAsync({
639
639
  root: container,
640
+ pages: (_b = (_a = renderSurfaceState.exportAdapter) === null || _a === void 0 ? void 0 : _a.getPrintMaskPages) === null || _b === void 0 ? void 0 : _b.call(_a),
640
641
  i18n: options,
641
- color: (_a = printOptions.mask) === null || _a === void 0 ? void 0 : _a.color,
642
- initialRegions: (_b = printOptions.mask) === null || _b === void 0 ? void 0 : _b.regions,
642
+ color: (_c = printOptions.mask) === null || _c === void 0 ? void 0 : _c.color,
643
+ initialRegions: (_d = printOptions.mask) === null || _d === void 0 ? void 0 : _d.regions,
643
644
  });
644
645
  if (!(result === null || result === void 0 ? void 0 : result.mask)) {
645
646
  return;
@@ -246,18 +246,20 @@ export const createFileViewerOperationActionHandlers = ({ getBuffer, getFile, ge
246
246
  }
247
247
  },
248
248
  async printWithMask(options = {}) {
249
- var _a, _b, _c, _d, _e;
249
+ var _a, _b, _c, _d, _e, _f, _g;
250
250
  try {
251
251
  const source = getRenderedSource();
252
252
  if (!source) {
253
253
  throw new Error(translateFileViewerMessage(resolveI18n(), 'error.noExportContent'));
254
254
  }
255
255
  const { openFileViewerPrintMaskDesignerAsync } = await import('../features/printMaskLoader.js');
256
+ const adapter = (_a = getAdapter === null || getAdapter === void 0 ? void 0 : getAdapter()) !== null && _a !== void 0 ? _a : null;
256
257
  const result = await openFileViewerPrintMaskDesignerAsync({
257
258
  root: source,
259
+ pages: (_b = adapter === null || adapter === void 0 ? void 0 : adapter.getPrintMaskPages) === null || _b === void 0 ? void 0 : _b.call(adapter),
258
260
  i18n: resolveI18n(),
259
- color: (_a = options.mask) === null || _a === void 0 ? void 0 : _a.color,
260
- initialRegions: (_b = options.mask) === null || _b === void 0 ? void 0 : _b.regions,
261
+ color: (_c = options.mask) === null || _c === void 0 ? void 0 : _c.color,
262
+ initialRegions: (_d = options.mask) === null || _d === void 0 ? void 0 : _d.regions,
261
263
  });
262
264
  if (!(result === null || result === void 0 ? void 0 : result.mask)) {
263
265
  return undefined;
@@ -265,9 +267,9 @@ export const createFileViewerOperationActionHandlers = ({ getBuffer, getFile, ge
265
267
  return await executeFileViewerPrintOperation({
266
268
  ...getRenderedOperationInput(),
267
269
  ...options,
268
- watermarkInlineStyle: (_d = (_c = options.watermarkInlineStyle) !== null && _c !== void 0 ? _c : getWatermarkInlineStyle === null || getWatermarkInlineStyle === void 0 ? void 0 : getWatermarkInlineStyle()) !== null && _d !== void 0 ? _d : undefined,
270
+ watermarkInlineStyle: (_f = (_e = options.watermarkInlineStyle) !== null && _e !== void 0 ? _e : getWatermarkInlineStyle === null || getWatermarkInlineStyle === void 0 ? void 0 : getWatermarkInlineStyle()) !== null && _f !== void 0 ? _f : undefined,
269
271
  mask: result.mask,
270
- printAvailable: (_e = getPrintAvailable === null || getPrintAvailable === void 0 ? void 0 : getPrintAvailable()) !== null && _e !== void 0 ? _e : true,
272
+ printAvailable: (_g = getPrintAvailable === null || getPrintAvailable === void 0 ? void 0 : getPrintAvailable()) !== null && _g !== void 0 ? _g : true,
271
273
  });
272
274
  }
273
275
  catch (error) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@file-viewer/core",
3
- "version": "2.1.27",
3
+ "version": "2.1.29",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "description": "Framework-neutral modular TypeScript core for Flyfish File Viewer renderer orchestration, lifecycle APIs, search, zoom, print, and export",