@file-viewer/core 2.0.11 → 2.1.1

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 (116) hide show
  1. package/README.en.md +2 -2
  2. package/README.md +2 -2
  3. package/dist/config/options.d.ts +1 -1
  4. package/dist/config/options.js +1 -1
  5. package/dist/contracts/types.d.ts +76 -1
  6. package/dist/headless.d.ts +3 -3
  7. package/dist/headless.js +2 -2
  8. package/dist/index.d.ts +10 -7
  9. package/dist/index.js +106 -49
  10. package/dist/lifecycle/operations.d.ts +1 -0
  11. package/dist/lifecycle/operations.js +65 -6
  12. package/dist/platform/assets.d.ts +3 -1
  13. package/dist/platform/assets.js +43 -6
  14. package/dist/registry/capabilities.d.ts +2 -2
  15. package/dist/registry/capabilities.js +2 -1
  16. package/dist/registry/formats.d.ts +20 -7
  17. package/dist/registry/formats.js +14 -5
  18. package/dist/registry/registry.d.ts +8 -1
  19. package/dist/registry/registry.js +29 -0
  20. package/dist/renderers/image.js +1 -10
  21. package/dist/renderers/index.d.ts +320 -2
  22. package/dist/renderers/index.js +27 -157
  23. package/dist/viewer/createViewer.js +86 -3
  24. package/package.json +17 -44
  25. package/dist/renderers/archive.d.ts +0 -2
  26. package/dist/renderers/archive.js +0 -547
  27. package/dist/renderers/archiveCache.d.ts +0 -10
  28. package/dist/renderers/archiveCache.js +0 -96
  29. package/dist/renderers/archiveFallback.d.ts +0 -7
  30. package/dist/renderers/archiveFallback.js +0 -166
  31. package/dist/renderers/archiveShared.d.ts +0 -23
  32. package/dist/renderers/archiveShared.js +0 -71
  33. package/dist/renderers/audio.d.ts +0 -8
  34. package/dist/renderers/audio.js +0 -219
  35. package/dist/renderers/cad.d.ts +0 -2
  36. package/dist/renderers/cad.js +0 -446
  37. package/dist/renderers/code.d.ts +0 -11
  38. package/dist/renderers/code.js +0 -233
  39. package/dist/renderers/data.d.ts +0 -7
  40. package/dist/renderers/data.js +0 -370
  41. package/dist/renderers/drawing.d.ts +0 -10
  42. package/dist/renderers/drawing.js +0 -882
  43. package/dist/renderers/eda.d.ts +0 -2
  44. package/dist/renderers/eda.js +0 -434
  45. package/dist/renderers/edaParser.d.ts +0 -77
  46. package/dist/renderers/edaParser.js +0 -569
  47. package/dist/renderers/email.d.ts +0 -2
  48. package/dist/renderers/email.js +0 -463
  49. package/dist/renderers/epub.d.ts +0 -2
  50. package/dist/renderers/epub.js +0 -331
  51. package/dist/renderers/geo.d.ts +0 -2
  52. package/dist/renderers/geo.js +0 -284
  53. package/dist/renderers/markdown.d.ts +0 -2
  54. package/dist/renderers/markdown.js +0 -83
  55. package/dist/renderers/model.d.ts +0 -2
  56. package/dist/renderers/model.js +0 -567
  57. package/dist/renderers/ofd.d.ts +0 -2
  58. package/dist/renderers/ofd.js +0 -256
  59. package/dist/renderers/openDocument.d.ts +0 -2
  60. package/dist/renderers/openDocument.js +0 -122
  61. package/dist/renderers/pdf.d.ts +0 -3
  62. package/dist/renderers/pdf.js +0 -1001
  63. package/dist/renderers/pdfStyles.d.ts +0 -1
  64. package/dist/renderers/pdfStyles.js +0 -1
  65. package/dist/renderers/pptx.d.ts +0 -2
  66. package/dist/renderers/pptx.js +0 -217
  67. package/dist/renderers/spreadsheet/state.d.ts +0 -80
  68. package/dist/renderers/spreadsheet/state.js +0 -96
  69. package/dist/renderers/spreadsheet/view.d.ts +0 -25
  70. package/dist/renderers/spreadsheet/view.js +0 -833
  71. package/dist/renderers/spreadsheet/worker/index.d.ts +0 -2
  72. package/dist/renderers/spreadsheet/worker/index.js +0 -1
  73. package/dist/renderers/spreadsheet/worker/sheetjs/SheetJsModel.d.ts +0 -73
  74. package/dist/renderers/spreadsheet/worker/sheetjs/SheetJsModel.js +0 -623
  75. package/dist/renderers/spreadsheet/worker/sheetjs/color.d.ts +0 -2
  76. package/dist/renderers/spreadsheet/worker/sheetjs/color.js +0 -73
  77. package/dist/renderers/spreadsheet/worker/sheetjs/index.d.ts +0 -1
  78. package/dist/renderers/spreadsheet/worker/sheetjs/index.js +0 -1
  79. package/dist/renderers/spreadsheet/worker/sheetjs/parser.d.ts +0 -18
  80. package/dist/renderers/spreadsheet/worker/sheetjs/parser.js +0 -106
  81. package/dist/renderers/spreadsheet/worker/sheetjs/sheet.worker.d.ts +0 -1
  82. package/dist/renderers/spreadsheet/worker/sheetjs/sheet.worker.js +0 -11
  83. package/dist/renderers/spreadsheet/worker/type.d.ts +0 -57
  84. package/dist/renderers/spreadsheet/worker/type.js +0 -1
  85. package/dist/renderers/spreadsheet.d.ts +0 -3
  86. package/dist/renderers/spreadsheet.js +0 -929
  87. package/dist/renderers/typst.d.ts +0 -8
  88. package/dist/renderers/typst.js +0 -547
  89. package/dist/renderers/umd/parser.d.ts +0 -30
  90. package/dist/renderers/umd/parser.js +0 -408
  91. package/dist/renderers/umd.d.ts +0 -2
  92. package/dist/renderers/umd.js +0 -297
  93. package/dist/renderers/video.d.ts +0 -8
  94. package/dist/renderers/video.js +0 -108
  95. package/dist/renderers/wordDoc.d.ts +0 -5
  96. package/dist/renderers/wordDoc.js +0 -284
  97. package/dist/renderers/wordDocx.d.ts +0 -5
  98. package/dist/renderers/wordDocx.js +0 -985
  99. package/dist/renderers/wordDocx.worker.d.ts +0 -1
  100. package/dist/renderers/wordDocx.worker.js +0 -96
  101. package/vendor/ofd/dltech/jbig2/arithmetic_decoder.js +0 -183
  102. package/vendor/ofd/dltech/jbig2/ccitt.js +0 -1070
  103. package/vendor/ofd/dltech/jbig2/compatibility.js +0 -12
  104. package/vendor/ofd/dltech/jbig2/core_utils.js +0 -180
  105. package/vendor/ofd/dltech/jbig2/is_node.js +0 -27
  106. package/vendor/ofd/dltech/jbig2/jbig2.js +0 -2589
  107. package/vendor/ofd/dltech/jbig2/jbig2_stream.js +0 -81
  108. package/vendor/ofd/dltech/jbig2/primitives.js +0 -387
  109. package/vendor/ofd/dltech/jbig2/stream.js +0 -1348
  110. package/vendor/ofd/dltech/jbig2/util.js +0 -972
  111. package/vendor/ofd/dltech/ofd/ofd.d.ts +0 -11
  112. package/vendor/ofd/dltech/ofd/ofd.js +0 -100
  113. package/vendor/ofd/dltech/ofd/ofd_parser.js +0 -395
  114. package/vendor/ofd/dltech/ofd/ofd_render.js +0 -473
  115. package/vendor/ofd/dltech/ofd/ofd_util.js +0 -350
  116. package/vendor/ofd/dltech/ofd/pipeline.js +0 -26
@@ -1,882 +0,0 @@
1
- import { registerFileViewerZoomProvider, unregisterFileViewerZoomProvider, } from '../features/document/dom/index.js';
2
- import { createFileViewerZoomChangeEmitter } from '../features/document/zoom.js';
3
- import { waitForFileViewerNextPaint } from '../output/export.js';
4
- import { resolveFileViewerDrawioViewerScriptUrl } from '../platform/assets.js';
5
- import { readFileViewerText } from '../source/index.js';
6
- const SVG_NS = 'http://www.w3.org/2000/svg';
7
- const EXCALIDRAW_OFFICIAL_TIMEOUT = 6000;
8
- const DRAWIO_OFFICIAL_TIMEOUT = 6000;
9
- const diagramsViewerPromises = new WeakMap();
10
- const drawingStyle = `
11
- .drawing-viewer{display:flex;height:100%;min-height:360px;flex-direction:column;background:#edf2f7;color:#172033}
12
- .drawing-toolbar{position:sticky;top:0;z-index:2;display:flex;min-height:46px;align-items:center;justify-content:space-between;gap:16px;padding:8px 14px;border-bottom:1px solid rgba(148,163,184,.35);background:rgba(248,250,252,.92);backdrop-filter:blur(12px)}
13
- .drawing-title{display:flex;min-width:0;align-items:center;gap:10px}
14
- .drawing-title span{display:inline-flex;height:24px;align-items:center;justify-content:center;border-radius:6px;padding:0 8px;background:#0f766e;color:#fff;font-size:11px;font-weight:800;letter-spacing:0}
15
- .drawing-title strong{overflow:hidden;color:#172033;font-size:13px;font-weight:800;text-overflow:ellipsis;white-space:nowrap}
16
- .drawing-actions{display:flex;flex-shrink:0;align-items:center;gap:6px}
17
- .drawing-actions button{min-width:32px;height:28px;border:1px solid rgba(100,116,139,.28);border-radius:6px;background:#fff;color:#0f172a;cursor:pointer;font-size:12px;font-weight:800}
18
- .drawing-actions button:hover{border-color:rgba(15,118,110,.5);color:#0f766e}
19
- .drawing-actions span{min-width:48px;color:#64748b;font-size:12px;font-weight:800;text-align:center}
20
- .drawing-stage{position:relative;min-height:0;flex:1;overflow:hidden}
21
- .drawing-scroll{height:100%;overflow:auto;padding:22px}
22
- .drawing-canvas{width:100%;min-height:420px;transition:transform .18s ease,zoom .18s ease}
23
- .drawing-canvas .drawing-svg,.drawing-canvas svg{display:block;max-width:100%;height:auto;margin:0 auto;border-radius:10px;background:#fff;box-shadow:0 18px 42px rgba(15,23,42,.12)}
24
- .drawing-canvas .drawing-mxgraph{min-height:420px;overflow:hidden;border-radius:10px;background:#fff;box-shadow:0 18px 42px rgba(15,23,42,.12)}
25
- .drawing-state{position:absolute;inset:0;z-index:1;display:flex;align-items:center;justify-content:center;padding:24px;color:#64748b;font-size:14px;font-weight:700;text-align:center}
26
- .drawing-state[hidden]{display:none!important}
27
- .drawing-state.error{color:#b42318}
28
- @media (max-width:720px){.drawing-toolbar{align-items:flex-start;flex-direction:column}.drawing-actions{width:100%;justify-content:space-between}.drawing-scroll{padding:12px}}
29
- `;
30
- const createStyle = (documentRef) => {
31
- const style = documentRef.createElement('style');
32
- style.textContent = drawingStyle;
33
- return style;
34
- };
35
- const createElement = (documentRef, tagName, className, text) => {
36
- const element = documentRef.createElement(tagName);
37
- if (className) {
38
- element.className = className;
39
- }
40
- if (text !== undefined) {
41
- element.textContent = text;
42
- }
43
- return element;
44
- };
45
- const createSvgElement = (documentRef, tagName) => {
46
- return documentRef.createElementNS(SVG_NS, tagName);
47
- };
48
- const normalizeDrawingType = (type) => {
49
- return (type === null || type === void 0 ? void 0 : type.toLowerCase()) === 'excalidraw' ? 'excalidraw' : 'drawio';
50
- };
51
- const formatDrawingLabel = (type) => {
52
- const normalized = (type || 'drawio').toLowerCase();
53
- return normalized === 'dio' ? 'DRAWIO' : normalized.toUpperCase();
54
- };
55
- const clampZoom = (value) => {
56
- return Math.min(3, Math.max(0.5, Number(value.toFixed(2))));
57
- };
58
- const toNumber = (value, fallback = 0) => {
59
- const parsed = Number(value);
60
- return Number.isFinite(parsed) ? parsed : fallback;
61
- };
62
- const isTransparent = (color) => {
63
- return !color || color === 'transparent' || color === 'rgba(0, 0, 0, 0)';
64
- };
65
- const resolveDrawingViewerScriptUrl = (options, documentRef) => {
66
- return resolveFileViewerDrawioViewerScriptUrl(options, (documentRef === null || documentRef === void 0 ? void 0 : documentRef.baseURI) || (documentRef === null || documentRef === void 0 ? void 0 : documentRef.URL));
67
- };
68
- const resolveDirectoryUrl = (url) => {
69
- try {
70
- return new URL('.', url).href;
71
- }
72
- catch {
73
- const slashIndex = url.lastIndexOf('/');
74
- return slashIndex >= 0 ? url.slice(0, slashIndex + 1) : '';
75
- }
76
- };
77
- const configureOfflineDiagramsViewerAssets = (documentRef, scriptUrl) => {
78
- const ownerWindow = documentRef.defaultView || (typeof window !== 'undefined' ? window : undefined);
79
- if (!ownerWindow) {
80
- return;
81
- }
82
- const viewerWindow = ownerWindow;
83
- const baseUrl = resolveDirectoryUrl(scriptUrl);
84
- const setDefault = (key, value) => {
85
- if (viewerWindow[key] === undefined || viewerWindow[key] === '') {
86
- viewerWindow[key] = value;
87
- }
88
- };
89
- // viewer-static.min.js still contains public diagrams.net defaults. Setting
90
- // these before the script executes keeps every secondary asset on the same
91
- // self-hosted directory as the viewer script.
92
- setDefault('PROXY_URL', `${baseUrl}proxy`);
93
- setDefault('STYLE_PATH', `${baseUrl}styles`);
94
- setDefault('SHAPES_PATH', `${baseUrl}shapes`);
95
- setDefault('STENCIL_PATH', `${baseUrl}stencils`);
96
- setDefault('DRAW_MATH_URL', `${baseUrl}math4/es5`);
97
- setDefault('GRAPH_IMAGE_PATH', `${baseUrl}img`);
98
- setDefault('mxImageBasePath', `${baseUrl}mxgraph/images`);
99
- setDefault('mxBasePath', `${baseUrl}mxgraph/`);
100
- setDefault('mxLoadStylesheets', false);
101
- setDefault('DRAWIO_BASE_URL', baseUrl.replace(/\/$/, ''));
102
- setDefault('DRAWIO_LIGHTBOX_URL', baseUrl.replace(/\/$/, ''));
103
- setDefault('DRAWIO_SERVER_URL', baseUrl);
104
- setDefault('DRAWIO_VIEWER_URL', `${baseUrl}viewer-static.min.js`);
105
- setDefault('DRAWIO_LOG_URL', '');
106
- setDefault('EXPORT_URL', `${baseUrl}export`);
107
- setDefault('PLANT_URL', `${baseUrl}plant`);
108
- setDefault('VSS_CONVERT_URL', `${baseUrl}VsdConverter/api/converter`);
109
- setDefault('DRAWIO_GITLAB_URL', baseUrl);
110
- setDefault('DRAWIO_GITHUB_URL', baseUrl);
111
- setDefault('DRAWIO_GITHUB_API_URL', baseUrl);
112
- setDefault('RT_WEBSOCKET_URL', `${baseUrl}rt`);
113
- setDefault('NOTIFICATIONS_URL', `${baseUrl}notifications`);
114
- };
115
- const getDiagramsViewerPromiseMap = (documentRef) => {
116
- let promiseMap = diagramsViewerPromises.get(documentRef);
117
- if (!promiseMap) {
118
- promiseMap = new Map();
119
- diagramsViewerPromises.set(documentRef, promiseMap);
120
- }
121
- return promiseMap;
122
- };
123
- const deleteDiagramsViewerPromise = (documentRef, scriptUrl) => {
124
- const promiseMap = diagramsViewerPromises.get(documentRef);
125
- promiseMap === null || promiseMap === void 0 ? void 0 : promiseMap.delete(scriptUrl);
126
- if (promiseMap && promiseMap.size === 0) {
127
- diagramsViewerPromises.delete(documentRef);
128
- }
129
- };
130
- const loadDiagramsViewer = (documentRef, scriptUrl) => {
131
- const ownerWindow = documentRef.defaultView || (typeof window !== 'undefined' ? window : undefined);
132
- if (ownerWindow === null || ownerWindow === void 0 ? void 0 : ownerWindow.GraphViewer) {
133
- return Promise.resolve();
134
- }
135
- configureOfflineDiagramsViewerAssets(documentRef, scriptUrl);
136
- const promiseMap = getDiagramsViewerPromiseMap(documentRef);
137
- const existingPromise = promiseMap.get(scriptUrl);
138
- if (existingPromise) {
139
- return existingPromise;
140
- }
141
- const nextPromise = new Promise((resolve, reject) => {
142
- const existed = Array.from(documentRef.querySelectorAll('script[src]'))
143
- .find(script => script.src === scriptUrl);
144
- if (existed) {
145
- existed.addEventListener('load', () => resolve(), { once: true });
146
- existed.addEventListener('error', () => reject(new Error('diagrams.net viewer 加载失败')), { once: true });
147
- return;
148
- }
149
- const script = documentRef.createElement('script');
150
- script.src = scriptUrl;
151
- script.async = true;
152
- script.onload = () => resolve();
153
- script.onerror = () => reject(new Error('diagrams.net viewer 加载失败'));
154
- documentRef.head.appendChild(script);
155
- });
156
- promiseMap.set(scriptUrl, nextPromise);
157
- return nextPromise;
158
- };
159
- const runWithTimeout = async (task, timeout, message) => {
160
- let timer;
161
- try {
162
- return await Promise.race([
163
- task,
164
- new Promise((_, reject) => {
165
- timer = setTimeout(() => reject(new Error(message)), timeout);
166
- }),
167
- ]);
168
- }
169
- finally {
170
- if (timer) {
171
- clearTimeout(timer);
172
- }
173
- }
174
- };
175
- const markRendered = (target, mode) => {
176
- if (target.dataset.drawingRendered) {
177
- return false;
178
- }
179
- target.dataset.drawingRendered = mode;
180
- return true;
181
- };
182
- const appendRenderedSvg = (target, svg, mode) => {
183
- if (!markRendered(target, mode)) {
184
- return;
185
- }
186
- svg.classList.add('drawing-svg');
187
- target.appendChild(svg);
188
- };
189
- const suppressExcalidrawWorkerWarning = () => {
190
- const originalError = console.error;
191
- const patchedError = (...args) => {
192
- const message = args.map(arg => String(arg)).join(' ');
193
- if (message.includes('Failed to use workers for subsetting') ||
194
- message.includes('Failed to fetch font family')) {
195
- return;
196
- }
197
- originalError(...args);
198
- };
199
- console.error = patchedError;
200
- return () => {
201
- if (console.error === patchedError) {
202
- console.error = originalError;
203
- }
204
- };
205
- };
206
- const getElementPoints = (element) => {
207
- if (Array.isArray(element.points) && element.points.length) {
208
- return element.points.map((point) => [
209
- toNumber(element.x) + toNumber(point[0]),
210
- toNumber(element.y) + toNumber(point[1]),
211
- ]);
212
- }
213
- return [
214
- [toNumber(element.x), toNumber(element.y)],
215
- [toNumber(element.x) + toNumber(element.width), toNumber(element.y) + toNumber(element.height)],
216
- ];
217
- };
218
- const getElementBounds = (element) => {
219
- const points = getElementPoints(element);
220
- const xs = points.map(point => point[0]);
221
- const ys = points.map(point => point[1]);
222
- if (!Array.isArray(element.points)) {
223
- xs.push(toNumber(element.x) + toNumber(element.width));
224
- ys.push(toNumber(element.y) + toNumber(element.height));
225
- }
226
- return {
227
- minX: Math.min(...xs),
228
- minY: Math.min(...ys),
229
- maxX: Math.max(...xs),
230
- maxY: Math.max(...ys),
231
- };
232
- };
233
- const getSceneBounds = (elements) => {
234
- const initial = {
235
- minX: Number.POSITIVE_INFINITY,
236
- minY: Number.POSITIVE_INFINITY,
237
- maxX: Number.NEGATIVE_INFINITY,
238
- maxY: Number.NEGATIVE_INFINITY,
239
- };
240
- const bounds = elements.reduce((scene, element) => {
241
- const elementBounds = getElementBounds(element);
242
- return {
243
- minX: Math.min(scene.minX, elementBounds.minX),
244
- minY: Math.min(scene.minY, elementBounds.minY),
245
- maxX: Math.max(scene.maxX, elementBounds.maxX),
246
- maxY: Math.max(scene.maxY, elementBounds.maxY),
247
- };
248
- }, initial);
249
- if (!Number.isFinite(bounds.minX)) {
250
- return { minX: 0, minY: 0, maxX: 800, maxY: 480 };
251
- }
252
- return bounds;
253
- };
254
- const getRoughOptions = (element) => {
255
- const fill = isTransparent(element.backgroundColor) ? undefined : element.backgroundColor;
256
- return {
257
- stroke: element.strokeColor || '#1e1e1e',
258
- strokeWidth: Math.max(1, toNumber(element.strokeWidth, 1)),
259
- roughness: Math.max(0, toNumber(element.roughness, 1)),
260
- fill,
261
- fillStyle: element.fillStyle || 'hachure',
262
- seed: toNumber(element.seed, 1),
263
- strokeLineDash: element.strokeStyle === 'dashed'
264
- ? [10, 8]
265
- : element.strokeStyle === 'dotted'
266
- ? [2, 6]
267
- : undefined,
268
- };
269
- };
270
- const appendWithOpacity = (group, element, node) => {
271
- const opacity = toNumber(element.opacity, 100) / 100;
272
- if (opacity < 1) {
273
- node.setAttribute('opacity', String(opacity));
274
- }
275
- group.appendChild(node);
276
- };
277
- const createElementGroup = (documentRef, element) => {
278
- const group = createSvgElement(documentRef, 'g');
279
- const angle = toNumber(element.angle);
280
- if (angle) {
281
- const cx = toNumber(element.x) + toNumber(element.width) / 2;
282
- const cy = toNumber(element.y) + toNumber(element.height) / 2;
283
- group.setAttribute('transform', `rotate(${angle * 180 / Math.PI} ${cx} ${cy})`);
284
- }
285
- return group;
286
- };
287
- const renderTextFallback = (documentRef, group, element) => {
288
- const text = String(element.text || '');
289
- if (!text.trim()) {
290
- return;
291
- }
292
- const textNode = createSvgElement(documentRef, 'text');
293
- const fontSize = Math.max(8, toNumber(element.fontSize, 20));
294
- const lineHeight = fontSize * 1.25;
295
- const lines = text.split(/\r?\n/);
296
- const familyMap = {
297
- 1: 'Virgil, Segoe Print, Comic Sans MS, sans-serif',
298
- 2: 'Helvetica, Arial, sans-serif',
299
- 3: 'Cascadia Mono, Menlo, Consolas, monospace',
300
- };
301
- textNode.setAttribute('x', String(toNumber(element.x)));
302
- textNode.setAttribute('y', String(toNumber(element.y) + fontSize));
303
- textNode.setAttribute('fill', element.strokeColor || '#1e1e1e');
304
- textNode.setAttribute('font-size', String(fontSize));
305
- textNode.setAttribute('font-family', familyMap[toNumber(element.fontFamily, 1)] || familyMap[1]);
306
- textNode.setAttribute('font-weight', String(element.fontWeight || 400));
307
- textNode.setAttribute('text-anchor', element.textAlign === 'center' ? 'middle' : element.textAlign === 'right' ? 'end' : 'start');
308
- if (element.textAlign === 'center') {
309
- textNode.setAttribute('x', String(toNumber(element.x) + toNumber(element.width) / 2));
310
- }
311
- else if (element.textAlign === 'right') {
312
- textNode.setAttribute('x', String(toNumber(element.x) + toNumber(element.width)));
313
- }
314
- lines.forEach((line, index) => {
315
- const lineNode = createSvgElement(documentRef, 'tspan');
316
- lineNode.setAttribute('x', textNode.getAttribute('x') || String(toNumber(element.x)));
317
- lineNode.setAttribute('dy', index === 0 ? '0' : String(lineHeight));
318
- lineNode.textContent = line;
319
- textNode.appendChild(lineNode);
320
- });
321
- appendWithOpacity(group, element, textNode);
322
- };
323
- const appendArrowHead = (documentRef, group, element, points) => {
324
- const endArrow = element.endArrowhead || element.startArrowhead;
325
- if (!endArrow || points.length < 2) {
326
- return;
327
- }
328
- const end = points[points.length - 1];
329
- const before = points[points.length - 2];
330
- const angle = Math.atan2(end[1] - before[1], end[0] - before[0]);
331
- const size = Math.max(10, toNumber(element.strokeWidth, 1) * 7);
332
- const left = [
333
- end[0] - size * Math.cos(angle - Math.PI / 7),
334
- end[1] - size * Math.sin(angle - Math.PI / 7),
335
- ];
336
- const right = [
337
- end[0] - size * Math.cos(angle + Math.PI / 7),
338
- end[1] - size * Math.sin(angle + Math.PI / 7),
339
- ];
340
- const arrow = createSvgElement(documentRef, 'polygon');
341
- arrow.setAttribute('points', `${end.join(',')} ${left.join(',')} ${right.join(',')}`);
342
- arrow.setAttribute('fill', element.strokeColor || '#1e1e1e');
343
- arrow.setAttribute('stroke', element.strokeColor || '#1e1e1e');
344
- appendWithOpacity(group, element, arrow);
345
- };
346
- const renderRoughFallback = async (documentRef, payload, elements, target) => {
347
- var _a;
348
- const { default: rough } = await import('roughjs');
349
- const bounds = getSceneBounds(elements);
350
- const padding = 80;
351
- const width = Math.max(320, bounds.maxX - bounds.minX + padding * 2);
352
- const height = Math.max(220, bounds.maxY - bounds.minY + padding * 2);
353
- const svg = createSvgElement(documentRef, 'svg');
354
- const root = createSvgElement(documentRef, 'g');
355
- const rc = rough.svg(svg);
356
- svg.setAttribute('viewBox', `${bounds.minX - padding} ${bounds.minY - padding} ${width} ${height}`);
357
- svg.setAttribute('width', String(width));
358
- svg.setAttribute('height', String(height));
359
- svg.setAttribute('role', 'img');
360
- svg.setAttribute('aria-label', 'Excalidraw rough.js preview');
361
- const background = createSvgElement(documentRef, 'rect');
362
- background.setAttribute('x', String(bounds.minX - padding));
363
- background.setAttribute('y', String(bounds.minY - padding));
364
- background.setAttribute('width', String(width));
365
- background.setAttribute('height', String(height));
366
- background.setAttribute('fill', ((_a = payload.appState) === null || _a === void 0 ? void 0 : _a.viewBackgroundColor) || '#ffffff');
367
- svg.appendChild(background);
368
- svg.appendChild(root);
369
- elements.forEach(element => {
370
- const group = createElementGroup(documentRef, element);
371
- const options = getRoughOptions(element);
372
- const x = toNumber(element.x);
373
- const y = toNumber(element.y);
374
- const width = toNumber(element.width);
375
- const height = toNumber(element.height);
376
- if (element.type === 'text') {
377
- renderTextFallback(documentRef, group, element);
378
- }
379
- else if (element.type === 'rectangle') {
380
- appendWithOpacity(group, element, rc.rectangle(x, y, width, height, options));
381
- }
382
- else if (element.type === 'diamond') {
383
- appendWithOpacity(group, element, rc.polygon([
384
- [x + width / 2, y],
385
- [x + width, y + height / 2],
386
- [x + width / 2, y + height],
387
- [x, y + height / 2],
388
- ], options));
389
- }
390
- else if (element.type === 'ellipse') {
391
- appendWithOpacity(group, element, rc.ellipse(x + width / 2, y + height / 2, Math.abs(width), Math.abs(height), options));
392
- }
393
- else if (element.type === 'line' || element.type === 'arrow' || element.type === 'freedraw') {
394
- const points = getElementPoints(element);
395
- appendWithOpacity(group, element, rc.linearPath(points, options));
396
- if (element.type === 'arrow') {
397
- appendArrowHead(documentRef, group, element, points);
398
- }
399
- }
400
- if (group.childNodes.length) {
401
- root.appendChild(group);
402
- }
403
- });
404
- appendRenderedSvg(target, svg, 'rough');
405
- };
406
- const renderOfficialExcalidraw = async (payload, elements, target) => {
407
- // Excalidraw 在部分浏览器会把字体子集 worker 降级记为 console.error;
408
- // 实际会继续使用主线程导出,这里只屏蔽这条已知噪声。
409
- const restoreConsole = suppressExcalidrawWorkerWarning();
410
- const restoreTimer = setTimeout(restoreConsole, EXCALIDRAW_OFFICIAL_TIMEOUT + 1000);
411
- const { exportToSvg, restore } = await import('@excalidraw/excalidraw');
412
- try {
413
- const restored = restore({
414
- elements: elements,
415
- appState: payload.appState || {},
416
- files: payload.files || {},
417
- }, null, null, {
418
- repairBindings: true,
419
- refreshDimensions: true,
420
- });
421
- const restoredElements = restored.elements.filter((element) => !element.isDeleted);
422
- const svg = await exportToSvg({
423
- elements: restoredElements,
424
- appState: {
425
- ...restored.appState,
426
- exportBackground: true,
427
- viewBackgroundColor: restored.appState.viewBackgroundColor || '#ffffff',
428
- },
429
- files: restored.files || {},
430
- });
431
- appendRenderedSvg(target, svg, 'official');
432
- }
433
- finally {
434
- clearTimeout(restoreTimer);
435
- setTimeout(restoreConsole, 3000);
436
- }
437
- };
438
- const renderExcalidraw = async (documentRef, text, target) => {
439
- const payload = JSON.parse(text);
440
- const elements = Array.isArray(payload.elements)
441
- ? payload.elements.filter((element) => !element.isDeleted)
442
- : [];
443
- if (!elements.length) {
444
- throw new Error('Excalidraw 文件中没有可预览图元');
445
- }
446
- try {
447
- await runWithTimeout(renderOfficialExcalidraw(payload, elements, target), EXCALIDRAW_OFFICIAL_TIMEOUT, 'Excalidraw 官方导出超时,自动切换 rough.js 兼容渲染');
448
- }
449
- catch (error) {
450
- console.warn(error);
451
- await renderRoughFallback(documentRef, payload, elements, target);
452
- }
453
- };
454
- const getDirectChild = (parent, tagName) => {
455
- return Array.from(parent.children).find(child => child.localName === tagName) || null;
456
- };
457
- const parseDrawioStyle = (style) => {
458
- const entries = new Map();
459
- for (const item of (style || '').split(';')) {
460
- if (!item) {
461
- continue;
462
- }
463
- const [key, ...rest] = item.split('=');
464
- entries.set(key, rest.join('=') || '1');
465
- }
466
- return entries;
467
- };
468
- const getDrawioStyleValue = (style, key, fallback) => {
469
- const value = style.get(key);
470
- return value && value !== 'none' ? value : fallback;
471
- };
472
- const parseDrawioGeometry = (cell) => {
473
- const geometry = getDirectChild(cell, 'mxGeometry');
474
- if (!geometry) {
475
- return null;
476
- }
477
- return {
478
- x: toNumber(geometry.getAttribute('x')),
479
- y: toNumber(geometry.getAttribute('y')),
480
- width: Math.max(1, toNumber(geometry.getAttribute('width'), 80)),
481
- height: Math.max(1, toNumber(geometry.getAttribute('height'), 40)),
482
- points: Array.from(geometry.querySelectorAll('mxPoint')).map(point => ({
483
- x: toNumber(point.getAttribute('x')),
484
- y: toNumber(point.getAttribute('y')),
485
- })),
486
- };
487
- };
488
- const normalizeDrawioText = (documentRef, value) => {
489
- if (!value) {
490
- return '';
491
- }
492
- const helper = documentRef.createElement('textarea');
493
- helper.innerHTML = value;
494
- return helper.value
495
- .replace(/<br\s*\/?>/gi, '\n')
496
- .replace(/<[^>]+>/g, '')
497
- .replace(/\u00a0/g, ' ')
498
- .replace(/[ \t]+/g, ' ')
499
- .trim();
500
- };
501
- const appendDrawioWrappedText = (documentRef, svg, text, x, y, width, height, fontSize, fill) => {
502
- if (!text) {
503
- return;
504
- }
505
- const textNode = createSvgElement(documentRef, 'text');
506
- const maxChars = Math.max(4, Math.floor(width / Math.max(7, fontSize * 0.55)));
507
- const words = text.includes(' ') ? text.split(/\s+/) : text.match(new RegExp(`.{1,${maxChars}}`, 'g')) || [text];
508
- const lines = [];
509
- let current = '';
510
- for (const word of words) {
511
- const next = current ? `${current} ${word}` : word;
512
- if (next.length > maxChars && current) {
513
- lines.push(current);
514
- current = word;
515
- }
516
- else {
517
- current = next;
518
- }
519
- }
520
- if (current) {
521
- lines.push(current);
522
- }
523
- const lineHeight = fontSize * 1.24;
524
- const totalHeight = lineHeight * lines.length;
525
- textNode.setAttribute('x', String(x + width / 2));
526
- textNode.setAttribute('y', String(y + height / 2 - totalHeight / 2 + fontSize));
527
- textNode.setAttribute('fill', fill);
528
- textNode.setAttribute('font-size', String(fontSize));
529
- textNode.setAttribute('font-family', 'Inter, Segoe UI, Arial, sans-serif');
530
- textNode.setAttribute('font-weight', '600');
531
- textNode.setAttribute('text-anchor', 'middle');
532
- textNode.setAttribute('pointer-events', 'none');
533
- lines.slice(0, 5).forEach((line, index) => {
534
- const lineNode = createSvgElement(documentRef, 'tspan');
535
- lineNode.setAttribute('x', String(x + width / 2));
536
- lineNode.setAttribute('dy', index === 0 ? '0' : String(lineHeight));
537
- lineNode.textContent = line;
538
- textNode.appendChild(lineNode);
539
- });
540
- svg.appendChild(textNode);
541
- };
542
- const renderDrawioFallback = (documentRef, text, target) => {
543
- var _a;
544
- const parser = new DOMParser();
545
- const parsed = parser.parseFromString(text, 'text/xml');
546
- const parseError = parsed.querySelector('parsererror');
547
- if (parseError) {
548
- throw new Error(`Draw.io XML 解析失败:${parseError.textContent || 'invalid xml'}`);
549
- }
550
- const firstDiagram = parsed.querySelector('diagram');
551
- const graphModel = (firstDiagram === null || firstDiagram === void 0 ? void 0 : firstDiagram.querySelector('mxGraphModel')) || parsed.querySelector('mxGraphModel');
552
- if (!graphModel) {
553
- throw new Error('当前 Draw.io 文件没有可直接渲染的 mxGraphModel。');
554
- }
555
- const cells = Array.from(graphModel.querySelectorAll('mxCell'));
556
- const vertices = cells
557
- .filter(cell => cell.getAttribute('vertex') === '1' && cell.getAttribute('connectable') !== '0')
558
- .map(cell => ({
559
- cell,
560
- id: cell.getAttribute('id') || '',
561
- geometry: parseDrawioGeometry(cell),
562
- style: parseDrawioStyle(cell.getAttribute('style')),
563
- text: normalizeDrawioText(documentRef, cell.getAttribute('value')),
564
- }))
565
- .filter(item => item.id && item.geometry);
566
- if (!vertices.length) {
567
- throw new Error('当前 Draw.io 文件没有可预览图元。');
568
- }
569
- const vertexById = new Map(vertices.map(vertex => [vertex.id, vertex]));
570
- const allX = vertices.flatMap(vertex => [vertex.geometry.x, vertex.geometry.x + vertex.geometry.width]);
571
- const allY = vertices.flatMap(vertex => [vertex.geometry.y, vertex.geometry.y + vertex.geometry.height]);
572
- const edgePoints = [];
573
- const edges = cells.filter(cell => cell.getAttribute('edge') === '1');
574
- for (const edge of edges) {
575
- const source = vertexById.get(edge.getAttribute('source') || '');
576
- const targetVertex = vertexById.get(edge.getAttribute('target') || '');
577
- const geometry = parseDrawioGeometry(edge);
578
- if (source === null || source === void 0 ? void 0 : source.geometry) {
579
- edgePoints.push({
580
- x: source.geometry.x + source.geometry.width / 2,
581
- y: source.geometry.y + source.geometry.height / 2,
582
- });
583
- }
584
- geometry === null || geometry === void 0 ? void 0 : geometry.points.forEach(point => edgePoints.push(point));
585
- if (targetVertex === null || targetVertex === void 0 ? void 0 : targetVertex.geometry) {
586
- edgePoints.push({
587
- x: targetVertex.geometry.x + targetVertex.geometry.width / 2,
588
- y: targetVertex.geometry.y + targetVertex.geometry.height / 2,
589
- });
590
- }
591
- }
592
- allX.push(...edgePoints.map(point => point.x));
593
- allY.push(...edgePoints.map(point => point.y));
594
- const padding = 96;
595
- const minX = Math.min(...allX) - padding;
596
- const minY = Math.min(...allY) - padding;
597
- const width = Math.max(480, Math.max(...allX) - Math.min(...allX) + padding * 2);
598
- const height = Math.max(320, Math.max(...allY) - Math.min(...allY) + padding * 2);
599
- const svg = createSvgElement(documentRef, 'svg');
600
- svg.setAttribute('viewBox', `${minX} ${minY} ${width} ${height}`);
601
- svg.setAttribute('width', String(Math.ceil(width)));
602
- svg.setAttribute('height', String(Math.ceil(height)));
603
- svg.setAttribute('role', 'img');
604
- svg.setAttribute('aria-label', (firstDiagram === null || firstDiagram === void 0 ? void 0 : firstDiagram.getAttribute('name')) || 'Draw.io local SVG preview');
605
- const defs = createSvgElement(documentRef, 'defs');
606
- const marker = createSvgElement(documentRef, 'marker');
607
- marker.setAttribute('id', 'drawio-arrow');
608
- marker.setAttribute('viewBox', '0 0 10 10');
609
- marker.setAttribute('refX', '9');
610
- marker.setAttribute('refY', '5');
611
- marker.setAttribute('markerWidth', '7');
612
- marker.setAttribute('markerHeight', '7');
613
- marker.setAttribute('orient', 'auto-start-reverse');
614
- const arrow = createSvgElement(documentRef, 'path');
615
- arrow.setAttribute('d', 'M 0 0 L 10 5 L 0 10 z');
616
- arrow.setAttribute('fill', '#64748b');
617
- marker.appendChild(arrow);
618
- defs.appendChild(marker);
619
- svg.appendChild(defs);
620
- const background = createSvgElement(documentRef, 'rect');
621
- background.setAttribute('x', String(minX));
622
- background.setAttribute('y', String(minY));
623
- background.setAttribute('width', String(width));
624
- background.setAttribute('height', String(height));
625
- background.setAttribute('fill', '#ffffff');
626
- svg.appendChild(background);
627
- for (const edge of edges) {
628
- const source = vertexById.get(edge.getAttribute('source') || '');
629
- const targetVertex = vertexById.get(edge.getAttribute('target') || '');
630
- if (!(source === null || source === void 0 ? void 0 : source.geometry) || !(targetVertex === null || targetVertex === void 0 ? void 0 : targetVertex.geometry)) {
631
- continue;
632
- }
633
- const style = parseDrawioStyle(edge.getAttribute('style'));
634
- const stroke = getDrawioStyleValue(style, 'strokeColor', '#64748b');
635
- const points = [
636
- {
637
- x: source.geometry.x + source.geometry.width / 2,
638
- y: source.geometry.y + source.geometry.height / 2,
639
- },
640
- ...(((_a = parseDrawioGeometry(edge)) === null || _a === void 0 ? void 0 : _a.points) || []),
641
- {
642
- x: targetVertex.geometry.x + targetVertex.geometry.width / 2,
643
- y: targetVertex.geometry.y + targetVertex.geometry.height / 2,
644
- },
645
- ];
646
- const polyline = createSvgElement(documentRef, 'polyline');
647
- polyline.setAttribute('points', points.map(point => `${point.x},${point.y}`).join(' '));
648
- polyline.setAttribute('fill', 'none');
649
- polyline.setAttribute('stroke', stroke);
650
- polyline.setAttribute('stroke-width', '2');
651
- if (style.get('dashed') === '1') {
652
- polyline.setAttribute('stroke-dasharray', '8 7');
653
- }
654
- if (style.get('endArrow') !== 'none') {
655
- polyline.setAttribute('marker-end', 'url(#drawio-arrow)');
656
- }
657
- svg.appendChild(polyline);
658
- }
659
- for (const vertex of vertices) {
660
- const geometry = vertex.geometry;
661
- const fill = getDrawioStyleValue(vertex.style, 'fillColor', '#f8fafc');
662
- const stroke = getDrawioStyleValue(vertex.style, 'strokeColor', '#64748b');
663
- const fontSize = Math.max(10, toNumber(vertex.style.get('fontSize'), 14));
664
- const shape = vertex.style.has('ellipse')
665
- ? 'ellipse'
666
- : vertex.style.get('shape') === 'rhombus'
667
- ? 'diamond'
668
- : 'rect';
669
- if (shape === 'ellipse') {
670
- const ellipse = createSvgElement(documentRef, 'ellipse');
671
- ellipse.setAttribute('cx', String(geometry.x + geometry.width / 2));
672
- ellipse.setAttribute('cy', String(geometry.y + geometry.height / 2));
673
- ellipse.setAttribute('rx', String(geometry.width / 2));
674
- ellipse.setAttribute('ry', String(geometry.height / 2));
675
- ellipse.setAttribute('fill', fill);
676
- ellipse.setAttribute('stroke', stroke);
677
- ellipse.setAttribute('stroke-width', '2');
678
- svg.appendChild(ellipse);
679
- }
680
- else if (shape === 'diamond') {
681
- const diamond = createSvgElement(documentRef, 'polygon');
682
- diamond.setAttribute('points', [
683
- `${geometry.x + geometry.width / 2},${geometry.y}`,
684
- `${geometry.x + geometry.width},${geometry.y + geometry.height / 2}`,
685
- `${geometry.x + geometry.width / 2},${geometry.y + geometry.height}`,
686
- `${geometry.x},${geometry.y + geometry.height / 2}`,
687
- ].join(' '));
688
- diamond.setAttribute('fill', fill);
689
- diamond.setAttribute('stroke', stroke);
690
- diamond.setAttribute('stroke-width', '2');
691
- svg.appendChild(diamond);
692
- }
693
- else {
694
- const rect = createSvgElement(documentRef, 'rect');
695
- rect.setAttribute('x', String(geometry.x));
696
- rect.setAttribute('y', String(geometry.y));
697
- rect.setAttribute('width', String(geometry.width));
698
- rect.setAttribute('height', String(geometry.height));
699
- rect.setAttribute('rx', vertex.style.get('rounded') === '1' ? '10' : '2');
700
- rect.setAttribute('fill', fill);
701
- rect.setAttribute('stroke', stroke);
702
- rect.setAttribute('stroke-width', '2');
703
- svg.appendChild(rect);
704
- }
705
- appendDrawioWrappedText(documentRef, svg, vertex.text, geometry.x, geometry.y, geometry.width, geometry.height, fontSize, getDrawioStyleValue(vertex.style, 'fontColor', '#172033'));
706
- }
707
- appendRenderedSvg(target, svg, 'rough');
708
- };
709
- const renderOfficialDrawio = async (documentRef, text, target, scriptUrl) => {
710
- const ownerWindow = documentRef.defaultView || (typeof window !== 'undefined' ? window : undefined);
711
- await loadDiagramsViewer(documentRef, scriptUrl);
712
- await waitForFileViewerNextPaint(ownerWindow);
713
- const host = createElement(documentRef, 'div', 'mxgraph drawing-mxgraph');
714
- host.setAttribute('data-mxgraph', JSON.stringify({
715
- xml: text,
716
- toolbar: 'zoom layers lightbox',
717
- nav: true,
718
- resize: true,
719
- 'auto-fit': true,
720
- 'auto-crop': true,
721
- 'auto-origin': true,
722
- 'allow-zoom-in': true,
723
- 'allow-zoom-out': true,
724
- border: 16,
725
- highlight: '#0f766e',
726
- }));
727
- target.appendChild(host);
728
- if (!(ownerWindow === null || ownerWindow === void 0 ? void 0 : ownerWindow.GraphViewer)) {
729
- throw new Error('diagrams.net viewer 未正确初始化');
730
- }
731
- ownerWindow.GraphViewer.createViewerForElement(host);
732
- markRendered(target, 'official');
733
- };
734
- const renderDrawio = async (documentRef, text, target, options) => {
735
- if ((options === null || options === void 0 ? void 0 : options.preferOfficial) === false) {
736
- renderDrawioFallback(documentRef, text, target);
737
- return;
738
- }
739
- const scriptUrl = resolveDrawingViewerScriptUrl(options, documentRef);
740
- try {
741
- await runWithTimeout(renderOfficialDrawio(documentRef, text, target, scriptUrl), DRAWIO_OFFICIAL_TIMEOUT, 'diagrams.net 官方 Viewer 加载超时,自动切换本地 SVG 预览');
742
- }
743
- catch (error) {
744
- console.warn(error);
745
- deleteDiagramsViewerPromise(documentRef, scriptUrl);
746
- delete target.dataset.drawingRendered;
747
- target.replaceChildren();
748
- renderDrawioFallback(documentRef, text, target);
749
- }
750
- };
751
- export default async function renderDrawing(buffer, target, type = 'drawio', context) {
752
- const documentRef = target.ownerDocument || document;
753
- const kind = normalizeDrawingType(type);
754
- const zoomEmitter = createFileViewerZoomChangeEmitter();
755
- let status = 'loading';
756
- let errorMessage = '';
757
- let zoom = 1;
758
- let disposed = false;
759
- const root = createElement(documentRef, 'div', 'drawing-viewer');
760
- root.dataset.viewerZoomProvider = 'drawing';
761
- const toolbar = createElement(documentRef, 'div', 'drawing-toolbar');
762
- const title = createElement(documentRef, 'div', 'drawing-title');
763
- title.append(createElement(documentRef, 'span', undefined, formatDrawingLabel(type)), createElement(documentRef, 'strong', undefined, kind === 'excalidraw'
764
- ? 'Excalidraw 官方 SVG 预览'
765
- : 'Draw.io 离线 SVG 预览'));
766
- const actions = createElement(documentRef, 'div', 'drawing-actions');
767
- const zoomOutButton = createElement(documentRef, 'button', undefined, '-');
768
- const zoomLabel = createElement(documentRef, 'span');
769
- const zoomInButton = createElement(documentRef, 'button', undefined, '+');
770
- const resetButton = createElement(documentRef, 'button', undefined, '适合');
771
- [zoomOutButton, zoomInButton, resetButton].forEach(button => {
772
- button.type = 'button';
773
- });
774
- zoomOutButton.title = '缩小';
775
- zoomInButton.title = '放大';
776
- resetButton.title = '适合宽度';
777
- actions.append(zoomOutButton, zoomLabel, zoomInButton, resetButton);
778
- toolbar.append(title, actions);
779
- const stageWrapper = createElement(documentRef, 'div', 'drawing-stage');
780
- const state = createElement(documentRef, 'div', 'drawing-state');
781
- const scroll = createElement(documentRef, 'div', 'drawing-scroll');
782
- const canvas = createElement(documentRef, 'div', 'drawing-canvas');
783
- scroll.append(canvas);
784
- stageWrapper.append(state, scroll);
785
- root.append(toolbar, stageWrapper);
786
- target.replaceChildren(createStyle(documentRef), root);
787
- const clearStage = () => {
788
- delete canvas.dataset.drawingRendered;
789
- canvas.replaceChildren();
790
- };
791
- const getDrawingZoomState = () => ({
792
- scale: zoom,
793
- label: `${Math.round(zoom * 100)}%`,
794
- canZoomIn: zoom < 3,
795
- canZoomOut: zoom > 0.5,
796
- canReset: zoom !== 1,
797
- minScale: 0.5,
798
- maxScale: 3,
799
- });
800
- const applyZoom = () => {
801
- if (kind === 'excalidraw') {
802
- canvas.style.transform = `scale(${zoom})`;
803
- canvas.style.transformOrigin = 'top center';
804
- canvas.style.zoom = '';
805
- }
806
- else {
807
- canvas.style.transform = '';
808
- canvas.style.transformOrigin = '';
809
- canvas.style.zoom = String(zoom);
810
- }
811
- zoomLabel.textContent = `${Math.round(zoom * 100)}%`;
812
- };
813
- const setZoom = (scale) => {
814
- zoom = clampZoom(scale);
815
- applyZoom();
816
- zoomEmitter.emit();
817
- return getDrawingZoomState();
818
- };
819
- const syncUi = () => {
820
- state.hidden = status === 'ready';
821
- state.classList.toggle('error', status === 'error');
822
- state.textContent = status === 'error'
823
- ? errorMessage
824
- : '正在加载绘图预览...';
825
- applyZoom();
826
- };
827
- const loadDrawing = async () => {
828
- var _a;
829
- status = 'loading';
830
- errorMessage = '';
831
- zoom = 1;
832
- clearStage();
833
- syncUi();
834
- try {
835
- const text = await readFileViewerText(buffer);
836
- if (disposed) {
837
- return;
838
- }
839
- if (kind === 'excalidraw') {
840
- await renderExcalidraw(documentRef, text, canvas);
841
- }
842
- else {
843
- await renderDrawio(documentRef, text, canvas, (_a = context === null || context === void 0 ? void 0 : context.options) === null || _a === void 0 ? void 0 : _a.drawing);
844
- }
845
- if (disposed) {
846
- return;
847
- }
848
- status = 'ready';
849
- syncUi();
850
- }
851
- catch (error) {
852
- if (disposed) {
853
- return;
854
- }
855
- console.error(error);
856
- errorMessage = error instanceof Error ? error.message : String(error);
857
- status = 'error';
858
- syncUi();
859
- }
860
- };
861
- registerFileViewerZoomProvider(root, {
862
- zoomIn: () => setZoom(zoom + 0.15),
863
- zoomOut: () => setZoom(zoom - 0.15),
864
- resetZoom: () => setZoom(1),
865
- setZoom,
866
- getState: getDrawingZoomState,
867
- subscribe: zoomEmitter.subscribe,
868
- });
869
- zoomOutButton.addEventListener('click', () => setZoom(zoom - 0.15));
870
- zoomInButton.addEventListener('click', () => setZoom(zoom + 0.15));
871
- resetButton.addEventListener('click', () => setZoom(1));
872
- syncUi();
873
- void loadDrawing();
874
- return {
875
- $el: root,
876
- unmount() {
877
- disposed = true;
878
- unregisterFileViewerZoomProvider(root);
879
- target.replaceChildren();
880
- },
881
- };
882
- }