@file-viewer/core 2.0.10 → 2.1.0

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 (114) 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 +71 -1
  6. package/dist/headless.d.ts +2 -2
  7. package/dist/headless.js +1 -1
  8. package/dist/index.d.ts +9 -6
  9. package/dist/index.js +105 -48
  10. package/dist/platform/assets.d.ts +3 -1
  11. package/dist/platform/assets.js +18 -2
  12. package/dist/registry/capabilities.d.ts +2 -2
  13. package/dist/registry/capabilities.js +2 -1
  14. package/dist/registry/formats.d.ts +20 -7
  15. package/dist/registry/formats.js +14 -5
  16. package/dist/registry/registry.d.ts +8 -1
  17. package/dist/registry/registry.js +29 -0
  18. package/dist/renderers/image.js +1 -10
  19. package/dist/renderers/index.d.ts +320 -2
  20. package/dist/renderers/index.js +27 -157
  21. package/dist/viewer/createViewer.js +86 -3
  22. package/package.json +17 -44
  23. package/dist/renderers/archive.d.ts +0 -2
  24. package/dist/renderers/archive.js +0 -547
  25. package/dist/renderers/archiveCache.d.ts +0 -10
  26. package/dist/renderers/archiveCache.js +0 -96
  27. package/dist/renderers/archiveFallback.d.ts +0 -7
  28. package/dist/renderers/archiveFallback.js +0 -166
  29. package/dist/renderers/archiveShared.d.ts +0 -23
  30. package/dist/renderers/archiveShared.js +0 -71
  31. package/dist/renderers/audio.d.ts +0 -8
  32. package/dist/renderers/audio.js +0 -219
  33. package/dist/renderers/cad.d.ts +0 -2
  34. package/dist/renderers/cad.js +0 -446
  35. package/dist/renderers/code.d.ts +0 -11
  36. package/dist/renderers/code.js +0 -233
  37. package/dist/renderers/data.d.ts +0 -7
  38. package/dist/renderers/data.js +0 -370
  39. package/dist/renderers/drawing.d.ts +0 -10
  40. package/dist/renderers/drawing.js +0 -882
  41. package/dist/renderers/eda.d.ts +0 -2
  42. package/dist/renderers/eda.js +0 -434
  43. package/dist/renderers/edaParser.d.ts +0 -77
  44. package/dist/renderers/edaParser.js +0 -569
  45. package/dist/renderers/email.d.ts +0 -2
  46. package/dist/renderers/email.js +0 -463
  47. package/dist/renderers/epub.d.ts +0 -2
  48. package/dist/renderers/epub.js +0 -331
  49. package/dist/renderers/geo.d.ts +0 -2
  50. package/dist/renderers/geo.js +0 -284
  51. package/dist/renderers/markdown.d.ts +0 -2
  52. package/dist/renderers/markdown.js +0 -83
  53. package/dist/renderers/model.d.ts +0 -2
  54. package/dist/renderers/model.js +0 -567
  55. package/dist/renderers/ofd.d.ts +0 -2
  56. package/dist/renderers/ofd.js +0 -256
  57. package/dist/renderers/openDocument.d.ts +0 -2
  58. package/dist/renderers/openDocument.js +0 -122
  59. package/dist/renderers/pdf.d.ts +0 -3
  60. package/dist/renderers/pdf.js +0 -1001
  61. package/dist/renderers/pdfStyles.d.ts +0 -1
  62. package/dist/renderers/pdfStyles.js +0 -1
  63. package/dist/renderers/pptx.d.ts +0 -2
  64. package/dist/renderers/pptx.js +0 -217
  65. package/dist/renderers/spreadsheet/state.d.ts +0 -80
  66. package/dist/renderers/spreadsheet/state.js +0 -96
  67. package/dist/renderers/spreadsheet/view.d.ts +0 -25
  68. package/dist/renderers/spreadsheet/view.js +0 -833
  69. package/dist/renderers/spreadsheet/worker/index.d.ts +0 -2
  70. package/dist/renderers/spreadsheet/worker/index.js +0 -1
  71. package/dist/renderers/spreadsheet/worker/sheetjs/SheetJsModel.d.ts +0 -73
  72. package/dist/renderers/spreadsheet/worker/sheetjs/SheetJsModel.js +0 -623
  73. package/dist/renderers/spreadsheet/worker/sheetjs/color.d.ts +0 -2
  74. package/dist/renderers/spreadsheet/worker/sheetjs/color.js +0 -73
  75. package/dist/renderers/spreadsheet/worker/sheetjs/index.d.ts +0 -1
  76. package/dist/renderers/spreadsheet/worker/sheetjs/index.js +0 -1
  77. package/dist/renderers/spreadsheet/worker/sheetjs/parser.d.ts +0 -18
  78. package/dist/renderers/spreadsheet/worker/sheetjs/parser.js +0 -106
  79. package/dist/renderers/spreadsheet/worker/sheetjs/sheet.worker.d.ts +0 -1
  80. package/dist/renderers/spreadsheet/worker/sheetjs/sheet.worker.js +0 -11
  81. package/dist/renderers/spreadsheet/worker/type.d.ts +0 -57
  82. package/dist/renderers/spreadsheet/worker/type.js +0 -1
  83. package/dist/renderers/spreadsheet.d.ts +0 -3
  84. package/dist/renderers/spreadsheet.js +0 -929
  85. package/dist/renderers/typst.d.ts +0 -8
  86. package/dist/renderers/typst.js +0 -547
  87. package/dist/renderers/umd/parser.d.ts +0 -30
  88. package/dist/renderers/umd/parser.js +0 -408
  89. package/dist/renderers/umd.d.ts +0 -2
  90. package/dist/renderers/umd.js +0 -297
  91. package/dist/renderers/video.d.ts +0 -8
  92. package/dist/renderers/video.js +0 -108
  93. package/dist/renderers/wordDoc.d.ts +0 -5
  94. package/dist/renderers/wordDoc.js +0 -284
  95. package/dist/renderers/wordDocx.d.ts +0 -5
  96. package/dist/renderers/wordDocx.js +0 -985
  97. package/dist/renderers/wordDocx.worker.d.ts +0 -1
  98. package/dist/renderers/wordDocx.worker.js +0 -96
  99. package/vendor/ofd/dltech/jbig2/arithmetic_decoder.js +0 -183
  100. package/vendor/ofd/dltech/jbig2/ccitt.js +0 -1070
  101. package/vendor/ofd/dltech/jbig2/compatibility.js +0 -12
  102. package/vendor/ofd/dltech/jbig2/core_utils.js +0 -180
  103. package/vendor/ofd/dltech/jbig2/is_node.js +0 -27
  104. package/vendor/ofd/dltech/jbig2/jbig2.js +0 -2589
  105. package/vendor/ofd/dltech/jbig2/jbig2_stream.js +0 -81
  106. package/vendor/ofd/dltech/jbig2/primitives.js +0 -387
  107. package/vendor/ofd/dltech/jbig2/stream.js +0 -1348
  108. package/vendor/ofd/dltech/jbig2/util.js +0 -972
  109. package/vendor/ofd/dltech/ofd/ofd.d.ts +0 -11
  110. package/vendor/ofd/dltech/ofd/ofd.js +0 -100
  111. package/vendor/ofd/dltech/ofd/ofd_parser.js +0 -395
  112. package/vendor/ofd/dltech/ofd/ofd_render.js +0 -473
  113. package/vendor/ofd/dltech/ofd/ofd_util.js +0 -350
  114. 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
- }