@privado-inc/file-viewer-vite-plugin 3.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +160 -0
- package/NOTICE +13 -0
- package/README.md +35 -0
- package/client.d.ts +22 -0
- package/dist/index.d.ts +151 -0
- package/dist/index.js +2652 -0
- package/package.json +58 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,2652 @@
|
|
|
1
|
+
import { existsSync, readdirSync, readFileSync, statSync } from 'node:fs';
|
|
2
|
+
import { copyFile, cp, lstat, mkdir, readFile, readdir, realpath, rm, stat, writeFile } from 'node:fs/promises';
|
|
3
|
+
import { createRequire } from 'node:module';
|
|
4
|
+
import { dirname, extname, isAbsolute, join, relative, resolve, sep } from 'node:path';
|
|
5
|
+
const virtualModuleId = 'virtual:file-viewer-renderers';
|
|
6
|
+
const resolvedVirtualModuleId = `\0${virtualModuleId}`;
|
|
7
|
+
const packagedPptFallbackModuleId = 'virtual:file-viewer-packaged-ppt-fallback';
|
|
8
|
+
const resolvedPackagedPptFallbackModuleId = `\0${packagedPptFallbackModuleId}`;
|
|
9
|
+
const isPresentationRendererImporter = (importer) => {
|
|
10
|
+
if (!importer)
|
|
11
|
+
return false;
|
|
12
|
+
const normalized = importer.replace(/\\/g, '/');
|
|
13
|
+
return (normalized.includes('/@file-viewer/renderer-presentation/') ||
|
|
14
|
+
normalized.includes('/@file-viewer+renderer-presentation@') ||
|
|
15
|
+
normalized.includes('/packages/renderers/presentation/') ||
|
|
16
|
+
normalized.includes('/@file-viewer/renderer-ppt/') ||
|
|
17
|
+
normalized.includes('/@file-viewer+renderer-ppt@') ||
|
|
18
|
+
normalized.includes('/packages/renderers/presentation-ppt/'));
|
|
19
|
+
};
|
|
20
|
+
const pluginRequire = createRequire(import.meta.url);
|
|
21
|
+
let workspacePackageJsonCache = null;
|
|
22
|
+
const rendererModules = [
|
|
23
|
+
{
|
|
24
|
+
id: 'pdf',
|
|
25
|
+
packageName: '@file-viewer/renderer-pdf',
|
|
26
|
+
exportName: 'pdfRenderer',
|
|
27
|
+
formats: ['pdf'],
|
|
28
|
+
rendererIds: ['pdf'],
|
|
29
|
+
chunkName: 'file-viewer-pdf'
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
id: 'ofd',
|
|
33
|
+
packageName: '@file-viewer/renderer-ofd',
|
|
34
|
+
exportName: 'ofdRenderer',
|
|
35
|
+
formats: ['ofd'],
|
|
36
|
+
rendererIds: ['ofd'],
|
|
37
|
+
chunkName: 'file-viewer-ofd'
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
id: 'cad',
|
|
41
|
+
packageName: '@file-viewer/renderer-cad',
|
|
42
|
+
exportName: 'cadRenderer',
|
|
43
|
+
formats: ['cad', 'dwg', 'dxf', 'dwf', 'dwfx', 'xps'],
|
|
44
|
+
rendererIds: ['cad'],
|
|
45
|
+
chunkName: 'file-viewer-cad'
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
id: 'typst',
|
|
49
|
+
packageName: '@file-viewer/renderer-typst',
|
|
50
|
+
exportName: 'typstRenderer',
|
|
51
|
+
formats: ['typ', 'typst'],
|
|
52
|
+
rendererIds: ['typst'],
|
|
53
|
+
chunkName: 'file-viewer-typst'
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
id: 'presentation',
|
|
57
|
+
packageName: '@file-viewer/renderer-presentation',
|
|
58
|
+
exportName: 'presentationRenderer',
|
|
59
|
+
formats: ['presentation'],
|
|
60
|
+
rendererIds: ['office-presentation-binary', 'office-presentation'],
|
|
61
|
+
chunkName: 'file-viewer-presentation'
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
id: 'presentation-binary',
|
|
65
|
+
packageName: '@file-viewer/renderer-ppt',
|
|
66
|
+
exportName: 'pptRenderer',
|
|
67
|
+
formats: ['ppt', 'pot'],
|
|
68
|
+
rendererIds: ['office-presentation-binary'],
|
|
69
|
+
chunkName: 'file-viewer-presentation-ppt'
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
id: 'presentation-openxml',
|
|
73
|
+
packageName: '@file-viewer/renderer-pptx',
|
|
74
|
+
exportName: 'pptxRenderer',
|
|
75
|
+
formats: ['pptx', 'pptm', 'potx', 'potm', 'ppsx', 'ppsm'],
|
|
76
|
+
rendererIds: ['office-presentation'],
|
|
77
|
+
chunkName: 'file-viewer-presentation-pptx'
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
id: 'word',
|
|
81
|
+
packageName: '@file-viewer/renderer-word',
|
|
82
|
+
exportName: 'wordRenderer',
|
|
83
|
+
formats: ['word', 'doc', 'docx', 'docm', 'dot', 'dotx', 'dotm', 'odt', 'odp', 'rtf'],
|
|
84
|
+
rendererIds: ['office-word-openxml', 'office-word-binary', 'open-document'],
|
|
85
|
+
chunkName: 'file-viewer-word'
|
|
86
|
+
},
|
|
87
|
+
{
|
|
88
|
+
id: 'spreadsheet',
|
|
89
|
+
packageName: '@file-viewer/renderer-spreadsheet',
|
|
90
|
+
exportName: 'spreadsheetRenderer',
|
|
91
|
+
formats: ['spreadsheet', 'excel', 'xls', 'xlsx', 'xltx', 'xlsm', 'xlsb', 'xlt', 'xla', 'xlam', 'xltm', 'csv', 'tsv', 'ods', 'fods', 'dbf'],
|
|
92
|
+
rendererIds: ['spreadsheet-openxml', 'spreadsheet-dbf'],
|
|
93
|
+
chunkName: 'file-viewer-spreadsheet'
|
|
94
|
+
},
|
|
95
|
+
{
|
|
96
|
+
id: 'iwork',
|
|
97
|
+
packageName: '@file-viewer/renderer-iwork',
|
|
98
|
+
exportName: 'iworkRenderer',
|
|
99
|
+
formats: ['iwork', 'pages', 'numbers', 'key', 'keynote'],
|
|
100
|
+
rendererIds: ['apple-pages', 'apple-numbers', 'apple-keynote'],
|
|
101
|
+
chunkName: 'file-viewer-iwork'
|
|
102
|
+
},
|
|
103
|
+
{
|
|
104
|
+
id: 'wordperfect',
|
|
105
|
+
packageName: '@file-viewer/renderer-wordperfect',
|
|
106
|
+
exportName: 'wordPerfectRenderer',
|
|
107
|
+
formats: ['wordperfect', 'wpd', 'wp', 'wp5', 'wp6'],
|
|
108
|
+
rendererIds: ['office-wordperfect'],
|
|
109
|
+
chunkName: 'file-viewer-wordperfect'
|
|
110
|
+
},
|
|
111
|
+
{
|
|
112
|
+
id: 'hangul',
|
|
113
|
+
packageName: '@file-viewer/renderer-hangul',
|
|
114
|
+
exportName: 'hangulRenderer',
|
|
115
|
+
formats: ['hangul', 'hwp', 'hwpx'],
|
|
116
|
+
rendererIds: ['office-hangul'],
|
|
117
|
+
chunkName: 'file-viewer-hangul'
|
|
118
|
+
},
|
|
119
|
+
{
|
|
120
|
+
id: 'drawing',
|
|
121
|
+
packageName: '@file-viewer/renderer-drawing',
|
|
122
|
+
exportName: 'drawingRenderer',
|
|
123
|
+
formats: ['drawing', 'drawio', 'dio', 'excalidraw', 'mermaid', 'mmd', 'plantuml', 'puml'],
|
|
124
|
+
rendererIds: ['drawing'],
|
|
125
|
+
chunkName: 'file-viewer-drawing'
|
|
126
|
+
},
|
|
127
|
+
{
|
|
128
|
+
id: 'bpmn',
|
|
129
|
+
packageName: '@file-viewer/renderer-drawing',
|
|
130
|
+
importPath: '@file-viewer/renderer-drawing/bpmn',
|
|
131
|
+
exportName: 'bpmnRenderer',
|
|
132
|
+
formats: ['bpmn'],
|
|
133
|
+
rendererIds: ['bpmn'],
|
|
134
|
+
chunkName: 'file-viewer-drawing',
|
|
135
|
+
includeInPresetAll: false
|
|
136
|
+
},
|
|
137
|
+
{
|
|
138
|
+
id: 'model',
|
|
139
|
+
packageName: '@file-viewer/renderer-3d',
|
|
140
|
+
exportName: 'modelRenderer',
|
|
141
|
+
formats: [
|
|
142
|
+
'3d',
|
|
143
|
+
'model',
|
|
144
|
+
'stl',
|
|
145
|
+
'obj',
|
|
146
|
+
'gltf',
|
|
147
|
+
'glb',
|
|
148
|
+
'fbx',
|
|
149
|
+
'dae',
|
|
150
|
+
'3ds',
|
|
151
|
+
'3mf',
|
|
152
|
+
'amf',
|
|
153
|
+
'ply',
|
|
154
|
+
'pcd',
|
|
155
|
+
'vrml',
|
|
156
|
+
'wrl',
|
|
157
|
+
'vtk',
|
|
158
|
+
'vtp',
|
|
159
|
+
'xyz',
|
|
160
|
+
'usd',
|
|
161
|
+
'usda',
|
|
162
|
+
'usdc',
|
|
163
|
+
'usdz',
|
|
164
|
+
'kmz',
|
|
165
|
+
'step',
|
|
166
|
+
'stp',
|
|
167
|
+
'iges',
|
|
168
|
+
'igs',
|
|
169
|
+
'ifc',
|
|
170
|
+
'3dm',
|
|
171
|
+
'brep'
|
|
172
|
+
],
|
|
173
|
+
rendererIds: ['model'],
|
|
174
|
+
chunkName: 'file-viewer-3d'
|
|
175
|
+
},
|
|
176
|
+
{
|
|
177
|
+
id: 'archive',
|
|
178
|
+
packageName: '@file-viewer/renderer-archive',
|
|
179
|
+
exportName: 'archiveRenderer',
|
|
180
|
+
formats: [
|
|
181
|
+
'archive',
|
|
182
|
+
'zip',
|
|
183
|
+
'zipx',
|
|
184
|
+
'7z',
|
|
185
|
+
'rar',
|
|
186
|
+
'tar',
|
|
187
|
+
'gz',
|
|
188
|
+
'gzip',
|
|
189
|
+
'tgz',
|
|
190
|
+
'bz2',
|
|
191
|
+
'bzip2',
|
|
192
|
+
'tbz',
|
|
193
|
+
'tbz2',
|
|
194
|
+
'xz',
|
|
195
|
+
'txz',
|
|
196
|
+
'lzma',
|
|
197
|
+
'zst',
|
|
198
|
+
'tzst',
|
|
199
|
+
'cab',
|
|
200
|
+
'ar',
|
|
201
|
+
'cpio',
|
|
202
|
+
'iso',
|
|
203
|
+
'xar',
|
|
204
|
+
'lha',
|
|
205
|
+
'lzh',
|
|
206
|
+
'jar',
|
|
207
|
+
'war',
|
|
208
|
+
'ear',
|
|
209
|
+
'apk',
|
|
210
|
+
'cbz',
|
|
211
|
+
'cbr'
|
|
212
|
+
],
|
|
213
|
+
rendererIds: ['archive'],
|
|
214
|
+
chunkName: 'file-viewer-archive'
|
|
215
|
+
},
|
|
216
|
+
{
|
|
217
|
+
id: 'chm',
|
|
218
|
+
packageName: '@file-viewer/renderer-chm',
|
|
219
|
+
exportName: 'chmRenderer',
|
|
220
|
+
formats: ['chm'],
|
|
221
|
+
rendererIds: ['chm'],
|
|
222
|
+
chunkName: 'file-viewer-chm'
|
|
223
|
+
},
|
|
224
|
+
{
|
|
225
|
+
id: 'email',
|
|
226
|
+
packageName: '@file-viewer/renderer-email',
|
|
227
|
+
exportName: 'emailRenderer',
|
|
228
|
+
formats: ['email', 'eml', 'msg', 'mbox'],
|
|
229
|
+
rendererIds: ['email'],
|
|
230
|
+
chunkName: 'file-viewer-email'
|
|
231
|
+
},
|
|
232
|
+
{
|
|
233
|
+
id: 'ebook',
|
|
234
|
+
packageName: '@file-viewer/renderer-epub',
|
|
235
|
+
exportName: 'ebookRenderer',
|
|
236
|
+
formats: ['ebook', 'epub', 'fb2', 'umd'],
|
|
237
|
+
rendererIds: ['epub', 'ebook-fb2', 'umd'],
|
|
238
|
+
chunkName: 'file-viewer-ebook'
|
|
239
|
+
},
|
|
240
|
+
{
|
|
241
|
+
id: 'text',
|
|
242
|
+
packageName: '@file-viewer/renderer-text',
|
|
243
|
+
exportName: 'textRenderer',
|
|
244
|
+
formats: [
|
|
245
|
+
'text',
|
|
246
|
+
'txt',
|
|
247
|
+
'log',
|
|
248
|
+
'code',
|
|
249
|
+
'md',
|
|
250
|
+
'markdown',
|
|
251
|
+
'js',
|
|
252
|
+
'mjs',
|
|
253
|
+
'cjs',
|
|
254
|
+
'jsx',
|
|
255
|
+
'ts',
|
|
256
|
+
'tsx',
|
|
257
|
+
'json',
|
|
258
|
+
'jsonc',
|
|
259
|
+
'json5',
|
|
260
|
+
'xml',
|
|
261
|
+
'yaml',
|
|
262
|
+
'yml',
|
|
263
|
+
'toml',
|
|
264
|
+
'ini',
|
|
265
|
+
'htm',
|
|
266
|
+
'html',
|
|
267
|
+
'css',
|
|
268
|
+
'vue',
|
|
269
|
+
'py',
|
|
270
|
+
'java',
|
|
271
|
+
'go',
|
|
272
|
+
'rs',
|
|
273
|
+
'c',
|
|
274
|
+
'cpp',
|
|
275
|
+
'cc',
|
|
276
|
+
'h',
|
|
277
|
+
'hpp',
|
|
278
|
+
'cs',
|
|
279
|
+
'diff',
|
|
280
|
+
'patch',
|
|
281
|
+
'bundle',
|
|
282
|
+
'bdl',
|
|
283
|
+
'php',
|
|
284
|
+
'rb',
|
|
285
|
+
'swift',
|
|
286
|
+
'kt',
|
|
287
|
+
'sh',
|
|
288
|
+
'bash',
|
|
289
|
+
'sql',
|
|
290
|
+
'json5',
|
|
291
|
+
'proto',
|
|
292
|
+
'hcl',
|
|
293
|
+
'tex',
|
|
294
|
+
'gv',
|
|
295
|
+
'graphviz',
|
|
296
|
+
'http',
|
|
297
|
+
'react',
|
|
298
|
+
'ipynb'
|
|
299
|
+
],
|
|
300
|
+
rendererIds: ['code', 'markdown'],
|
|
301
|
+
chunkName: 'file-viewer-text'
|
|
302
|
+
},
|
|
303
|
+
{
|
|
304
|
+
id: 'image',
|
|
305
|
+
packageName: '@file-viewer/renderer-image',
|
|
306
|
+
exportName: 'imageRenderer',
|
|
307
|
+
formats: [
|
|
308
|
+
'image',
|
|
309
|
+
'jpg',
|
|
310
|
+
'jpeg',
|
|
311
|
+
'png',
|
|
312
|
+
'gif',
|
|
313
|
+
'webp',
|
|
314
|
+
'svg',
|
|
315
|
+
'bmp',
|
|
316
|
+
'tiff',
|
|
317
|
+
'tif',
|
|
318
|
+
'avif',
|
|
319
|
+
'ico',
|
|
320
|
+
'heic',
|
|
321
|
+
'heif',
|
|
322
|
+
'jxl'
|
|
323
|
+
],
|
|
324
|
+
rendererIds: ['image'],
|
|
325
|
+
chunkName: 'file-viewer-image'
|
|
326
|
+
},
|
|
327
|
+
{
|
|
328
|
+
id: 'dicom',
|
|
329
|
+
packageName: '@file-viewer/renderer-dicom',
|
|
330
|
+
exportName: 'dicomRenderer',
|
|
331
|
+
formats: ['dicom', 'dcm'],
|
|
332
|
+
rendererIds: ['dicom'],
|
|
333
|
+
chunkName: 'file-viewer-dicom',
|
|
334
|
+
includeInPresetAll: false
|
|
335
|
+
},
|
|
336
|
+
{
|
|
337
|
+
id: 'signature',
|
|
338
|
+
packageName: '@file-viewer/renderer-signature',
|
|
339
|
+
exportName: 'signatureRenderer',
|
|
340
|
+
formats: [
|
|
341
|
+
'p7m',
|
|
342
|
+
'p7s',
|
|
343
|
+
'p7c',
|
|
344
|
+
'p7b',
|
|
345
|
+
'pkcs7',
|
|
346
|
+
'cms',
|
|
347
|
+
'cmsc',
|
|
348
|
+
'tsd',
|
|
349
|
+
'tst',
|
|
350
|
+
'tsq',
|
|
351
|
+
'tsr',
|
|
352
|
+
'asics',
|
|
353
|
+
'scs',
|
|
354
|
+
'asice',
|
|
355
|
+
'sce',
|
|
356
|
+
'ers',
|
|
357
|
+
'asc',
|
|
358
|
+
'sig',
|
|
359
|
+
'pgp',
|
|
360
|
+
'gpg',
|
|
361
|
+
'jws'
|
|
362
|
+
],
|
|
363
|
+
rendererIds: ['signature'],
|
|
364
|
+
chunkName: 'file-viewer-signature',
|
|
365
|
+
includeInPresetAll: false
|
|
366
|
+
},
|
|
367
|
+
{
|
|
368
|
+
id: 'media',
|
|
369
|
+
packageName: '@file-viewer/renderer-media',
|
|
370
|
+
exportName: 'mediaRenderer',
|
|
371
|
+
formats: [
|
|
372
|
+
'media',
|
|
373
|
+
'audio',
|
|
374
|
+
'video',
|
|
375
|
+
'mp3',
|
|
376
|
+
'mpeg',
|
|
377
|
+
'wav',
|
|
378
|
+
'ogg',
|
|
379
|
+
'oga',
|
|
380
|
+
'opus',
|
|
381
|
+
'flac',
|
|
382
|
+
'aac',
|
|
383
|
+
'm4a',
|
|
384
|
+
'mp4',
|
|
385
|
+
'webm',
|
|
386
|
+
'weba',
|
|
387
|
+
'mov',
|
|
388
|
+
'm3u8',
|
|
389
|
+
'midi',
|
|
390
|
+
'mid'
|
|
391
|
+
],
|
|
392
|
+
rendererIds: ['audio', 'video'],
|
|
393
|
+
chunkName: 'file-viewer-media'
|
|
394
|
+
},
|
|
395
|
+
{
|
|
396
|
+
id: 'mindmap',
|
|
397
|
+
packageName: '@file-viewer/renderer-mindmap',
|
|
398
|
+
exportName: 'mindmapRenderer',
|
|
399
|
+
formats: ['mindmap', 'xmind'],
|
|
400
|
+
rendererIds: ['mindmap'],
|
|
401
|
+
chunkName: 'file-viewer-mindmap'
|
|
402
|
+
},
|
|
403
|
+
{
|
|
404
|
+
id: 'geo',
|
|
405
|
+
packageName: '@file-viewer/renderer-geo',
|
|
406
|
+
exportName: 'geoRenderer',
|
|
407
|
+
formats: ['geo', 'geojson', 'kml', 'gpx', 'shp'],
|
|
408
|
+
rendererIds: ['geo'],
|
|
409
|
+
chunkName: 'file-viewer-geo'
|
|
410
|
+
},
|
|
411
|
+
{
|
|
412
|
+
id: 'design',
|
|
413
|
+
packageName: '@file-viewer/renderer-design',
|
|
414
|
+
exportName: 'designRenderer',
|
|
415
|
+
includeInPresetAll: false,
|
|
416
|
+
formats: [
|
|
417
|
+
'design',
|
|
418
|
+
'photoshop-design',
|
|
419
|
+
'illustrator-pdf-design',
|
|
420
|
+
'postscript-design',
|
|
421
|
+
'adobe-palette-design',
|
|
422
|
+
'photoshop-resource-design',
|
|
423
|
+
'indesign-idml-design',
|
|
424
|
+
'indesign-exchange-design',
|
|
425
|
+
'adobe-animate-xfl-design',
|
|
426
|
+
'adobe-xd-design',
|
|
427
|
+
'indesign-native-design',
|
|
428
|
+
'psd',
|
|
429
|
+
'psb',
|
|
430
|
+
'pdd',
|
|
431
|
+
'psdt',
|
|
432
|
+
'ai',
|
|
433
|
+
'ait',
|
|
434
|
+
'eps',
|
|
435
|
+
'ps',
|
|
436
|
+
'ase',
|
|
437
|
+
'aco',
|
|
438
|
+
'abr',
|
|
439
|
+
'csh',
|
|
440
|
+
'pat',
|
|
441
|
+
'grd',
|
|
442
|
+
'asl',
|
|
443
|
+
'idml',
|
|
444
|
+
'icml',
|
|
445
|
+
'idms',
|
|
446
|
+
'inx',
|
|
447
|
+
'fla',
|
|
448
|
+
'xfl',
|
|
449
|
+
'xd',
|
|
450
|
+
'indd',
|
|
451
|
+
'indt'
|
|
452
|
+
],
|
|
453
|
+
rendererIds: ['photoshop-design', 'illustrator-pdf-design', 'postscript-design', 'adobe-palette-design', 'photoshop-resource-design', 'indesign-idml-design', 'indesign-exchange-design', 'adobe-animate-xfl-design', 'adobe-xd-design', 'indesign-native-design'],
|
|
454
|
+
chunkName: 'file-viewer-design'
|
|
455
|
+
},
|
|
456
|
+
{
|
|
457
|
+
id: 'data',
|
|
458
|
+
packageName: '@file-viewer/renderer-data',
|
|
459
|
+
exportName: 'dataRenderer',
|
|
460
|
+
formats: [
|
|
461
|
+
'data',
|
|
462
|
+
'data-asset',
|
|
463
|
+
'sqlite',
|
|
464
|
+
'db',
|
|
465
|
+
'sqlite3',
|
|
466
|
+
'parquet',
|
|
467
|
+
'avro',
|
|
468
|
+
'webarchive',
|
|
469
|
+
'wasm',
|
|
470
|
+
'ttf',
|
|
471
|
+
'otf',
|
|
472
|
+
'woff',
|
|
473
|
+
'woff2'
|
|
474
|
+
],
|
|
475
|
+
rendererIds: ['data-asset'],
|
|
476
|
+
chunkName: 'file-viewer-data'
|
|
477
|
+
},
|
|
478
|
+
{
|
|
479
|
+
id: 'binary',
|
|
480
|
+
packageName: '@file-viewer/renderer-binary',
|
|
481
|
+
exportName: 'binaryRenderer',
|
|
482
|
+
formats: ['binary', 'binary-inspector', 'bin', 'hex', 'elf', 'exe', 'dll', 'class', 'macho'],
|
|
483
|
+
rendererIds: ['binary-inspector'],
|
|
484
|
+
chunkName: 'file-viewer-binary',
|
|
485
|
+
includeInPresetAll: false
|
|
486
|
+
},
|
|
487
|
+
{
|
|
488
|
+
id: 'eda',
|
|
489
|
+
packageName: '@file-viewer/renderer-eda',
|
|
490
|
+
exportName: 'edaRenderer',
|
|
491
|
+
formats: ['eda', 'gds', 'oas', 'oasis', 'olb', 'dra', 'dsn'],
|
|
492
|
+
rendererIds: ['eda'],
|
|
493
|
+
chunkName: 'file-viewer-eda'
|
|
494
|
+
}
|
|
495
|
+
];
|
|
496
|
+
const descriptorsById = new Map(rendererModules.map((descriptor) => [descriptor.id, descriptor]));
|
|
497
|
+
const descriptorsByFormat = new Map();
|
|
498
|
+
const descriptorsByRendererId = new Map();
|
|
499
|
+
rendererModules.forEach((descriptor) => {
|
|
500
|
+
descriptor.formats.forEach((format) => descriptorsByFormat.set(format, descriptor));
|
|
501
|
+
descriptor.rendererIds.forEach((rendererId) => descriptorsByRendererId.set(rendererId, descriptor));
|
|
502
|
+
});
|
|
503
|
+
const presetRendererIds = {
|
|
504
|
+
all: rendererModules
|
|
505
|
+
.filter((descriptor) => descriptor.includeInPresetAll !== false)
|
|
506
|
+
.map((descriptor) => descriptor.id),
|
|
507
|
+
lite: ['text', 'image', 'media'],
|
|
508
|
+
standard: [
|
|
509
|
+
'word',
|
|
510
|
+
'pdf',
|
|
511
|
+
'ofd',
|
|
512
|
+
'presentation-openxml',
|
|
513
|
+
'spreadsheet',
|
|
514
|
+
'archive',
|
|
515
|
+
'email',
|
|
516
|
+
'text',
|
|
517
|
+
'image',
|
|
518
|
+
'media'
|
|
519
|
+
],
|
|
520
|
+
office: ['pdf', 'word', 'spreadsheet', 'presentation', 'ofd', 'iwork', 'wordperfect', 'hangul'],
|
|
521
|
+
engineering: [
|
|
522
|
+
'cad',
|
|
523
|
+
'model',
|
|
524
|
+
'drawing',
|
|
525
|
+
'mindmap',
|
|
526
|
+
'geo',
|
|
527
|
+
'typst',
|
|
528
|
+
'archive',
|
|
529
|
+
'data',
|
|
530
|
+
'eda'
|
|
531
|
+
]
|
|
532
|
+
};
|
|
533
|
+
const presetModules = {
|
|
534
|
+
all: {
|
|
535
|
+
id: 'all',
|
|
536
|
+
packageName: '@file-viewer/preset-all',
|
|
537
|
+
exportName: 'allRenderers',
|
|
538
|
+
rendererIds: presetRendererIds.all,
|
|
539
|
+
chunkName: 'file-viewer-preset-all'
|
|
540
|
+
},
|
|
541
|
+
lite: {
|
|
542
|
+
id: 'lite',
|
|
543
|
+
packageName: '@file-viewer/preset-lite',
|
|
544
|
+
exportName: 'liteRenderers',
|
|
545
|
+
rendererIds: presetRendererIds.lite,
|
|
546
|
+
chunkName: 'file-viewer-preset-lite'
|
|
547
|
+
},
|
|
548
|
+
standard: {
|
|
549
|
+
id: 'standard',
|
|
550
|
+
packageName: '@file-viewer/preset-standard',
|
|
551
|
+
exportName: 'standardRenderers',
|
|
552
|
+
rendererIds: presetRendererIds.standard,
|
|
553
|
+
chunkName: 'file-viewer-preset-standard'
|
|
554
|
+
},
|
|
555
|
+
office: {
|
|
556
|
+
id: 'office',
|
|
557
|
+
packageName: '@file-viewer/preset-office',
|
|
558
|
+
exportName: 'officeRenderers',
|
|
559
|
+
rendererIds: presetRendererIds.office,
|
|
560
|
+
chunkName: 'file-viewer-preset-office'
|
|
561
|
+
},
|
|
562
|
+
engineering: {
|
|
563
|
+
id: 'engineering',
|
|
564
|
+
packageName: '@file-viewer/preset-engineering',
|
|
565
|
+
exportName: 'engineeringRenderers',
|
|
566
|
+
rendererIds: presetRendererIds.engineering,
|
|
567
|
+
chunkName: 'file-viewer-preset-engineering'
|
|
568
|
+
}
|
|
569
|
+
};
|
|
570
|
+
const fileViewerFullPackages = [
|
|
571
|
+
'@file-viewer/react-full',
|
|
572
|
+
'@file-viewer/react-legacy-full',
|
|
573
|
+
'@file-viewer/vue3-full',
|
|
574
|
+
'@file-viewer/vue2.7-full',
|
|
575
|
+
'@file-viewer/vue2.6-full',
|
|
576
|
+
'@file-viewer/web-full',
|
|
577
|
+
'@file-viewer/jquery-full',
|
|
578
|
+
'@file-viewer/svelte-full'
|
|
579
|
+
];
|
|
580
|
+
// Vite dep optimization rewrites import.meta.url into node_modules/.vite/deps
|
|
581
|
+
// and can trigger full-preset dev-server re-optimization reloads. Keep File
|
|
582
|
+
// Viewer packages out of dep optimization while still optimizing their
|
|
583
|
+
// CommonJS/UMD helper dependencies below.
|
|
584
|
+
const fileViewerOptimizationExcludedPackages = [
|
|
585
|
+
'@file-viewer/core',
|
|
586
|
+
'@file-viewer/ppt',
|
|
587
|
+
'@file-viewer/pptx',
|
|
588
|
+
...rendererModules.map((descriptor) => descriptor.packageName),
|
|
589
|
+
...Object.values(presetModules).map((preset) => preset.packageName),
|
|
590
|
+
...fileViewerFullPackages
|
|
591
|
+
];
|
|
592
|
+
const cjsInteropPackages = [
|
|
593
|
+
'@file-viewer/docx',
|
|
594
|
+
'@xmldom/xmldom',
|
|
595
|
+
'diff2html',
|
|
596
|
+
'keynote-archives',
|
|
597
|
+
'occt-import-js',
|
|
598
|
+
'jszip',
|
|
599
|
+
'pdf-lib'
|
|
600
|
+
];
|
|
601
|
+
const defaultScanRoots = ['src', 'app', 'pages', 'components'];
|
|
602
|
+
const defaultScanExtensions = [
|
|
603
|
+
'js',
|
|
604
|
+
'jsx',
|
|
605
|
+
'ts',
|
|
606
|
+
'tsx',
|
|
607
|
+
'vue',
|
|
608
|
+
'svelte',
|
|
609
|
+
'html',
|
|
610
|
+
'md',
|
|
611
|
+
'mdx'
|
|
612
|
+
];
|
|
613
|
+
const ignoredScanDirectories = new Set([
|
|
614
|
+
'.git',
|
|
615
|
+
'.idea',
|
|
616
|
+
'.next',
|
|
617
|
+
'.nuxt',
|
|
618
|
+
'.output',
|
|
619
|
+
'.release',
|
|
620
|
+
'.svelte-kit',
|
|
621
|
+
'.vite',
|
|
622
|
+
'coverage',
|
|
623
|
+
'dist',
|
|
624
|
+
'node_modules'
|
|
625
|
+
]);
|
|
626
|
+
const defaultScanMaxFileSize = 1024 * 1024;
|
|
627
|
+
const mimeFormatHints = {
|
|
628
|
+
'application/pdf': ['pdf'],
|
|
629
|
+
'application/ofd': ['ofd'],
|
|
630
|
+
'application/zip': ['zip'],
|
|
631
|
+
'application/x-zip-compressed': ['zip'],
|
|
632
|
+
'application/vnd.openxmlformats-officedocument.wordprocessingml.document': ['docx'],
|
|
633
|
+
'application/msword': ['doc'],
|
|
634
|
+
'application/vnd.ms-excel': ['xls'],
|
|
635
|
+
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet': ['xlsx'],
|
|
636
|
+
'application/vnd.ms-powerpoint': ['ppt'],
|
|
637
|
+
'application/vnd.openxmlformats-officedocument.presentationml.presentation': ['pptx'],
|
|
638
|
+
'application/json': ['json'],
|
|
639
|
+
'application/x-ndjson': ['json'],
|
|
640
|
+
'application/xml': ['xml'],
|
|
641
|
+
'application/x-tar': ['tar'],
|
|
642
|
+
'application/gzip': ['gz'],
|
|
643
|
+
'application/x-7z-compressed': ['7z'],
|
|
644
|
+
'application/vnd.rar': ['rar'],
|
|
645
|
+
'text/markdown': ['md'],
|
|
646
|
+
'text/csv': ['csv'],
|
|
647
|
+
'text/tab-separated-values': ['tsv'],
|
|
648
|
+
'text/html': ['html'],
|
|
649
|
+
'text/css': ['css'],
|
|
650
|
+
'text/plain': ['txt'],
|
|
651
|
+
'image/*': ['image'],
|
|
652
|
+
'image/tiff': ['tiff'],
|
|
653
|
+
'image/heic': ['heic'],
|
|
654
|
+
'image/heif': ['heif'],
|
|
655
|
+
'audio/*': ['audio'],
|
|
656
|
+
'audio/mpeg': ['mp3'],
|
|
657
|
+
'audio/ogg': ['ogg'],
|
|
658
|
+
'audio/flac': ['flac'],
|
|
659
|
+
'audio/midi': ['midi'],
|
|
660
|
+
'video/*': ['video']
|
|
661
|
+
};
|
|
662
|
+
function normalizeToken(value) {
|
|
663
|
+
return value.trim().toLowerCase().replace(/^\./, '');
|
|
664
|
+
}
|
|
665
|
+
function unique(items) {
|
|
666
|
+
return [...new Set(items)];
|
|
667
|
+
}
|
|
668
|
+
function normalizeScanExtension(value) {
|
|
669
|
+
return normalizeToken(value);
|
|
670
|
+
}
|
|
671
|
+
function collectQuotedTokens(value) {
|
|
672
|
+
return [...value.matchAll(/['"`]([^'"`]+)['"`]/g)].flatMap((match) => collectDelimitedTokens(match[1]));
|
|
673
|
+
}
|
|
674
|
+
function collectDelimitedTokens(value) {
|
|
675
|
+
return value
|
|
676
|
+
.split(/[\s,;|]+/g)
|
|
677
|
+
.map((item) => item.trim())
|
|
678
|
+
.filter(Boolean)
|
|
679
|
+
.flatMap((item) => mimeFormatHints[item.toLowerCase()] || [item])
|
|
680
|
+
.map(normalizeToken)
|
|
681
|
+
.filter(Boolean);
|
|
682
|
+
}
|
|
683
|
+
export function extractFileViewerRendererHintTokens(source) {
|
|
684
|
+
const tokens = [];
|
|
685
|
+
const push = (items) => {
|
|
686
|
+
items.forEach((item) => {
|
|
687
|
+
if (item) {
|
|
688
|
+
tokens.push(item);
|
|
689
|
+
}
|
|
690
|
+
});
|
|
691
|
+
};
|
|
692
|
+
// Explicit JavaScript/TypeScript hints:
|
|
693
|
+
// const fileViewerFormats = ['pdf', 'docx']
|
|
694
|
+
// fileViewerRenderers: ['pdf', 'cad']
|
|
695
|
+
for (const match of source.matchAll(/\bfileViewer(?:Formats?|Renderers?)\b\s*[:=]\s*\[([\s\S]*?)\]/g)) {
|
|
696
|
+
push(collectQuotedTokens(match[1]));
|
|
697
|
+
}
|
|
698
|
+
// HTML / template hints:
|
|
699
|
+
// <div data-file-viewer-formats="pdf,docx"></div>
|
|
700
|
+
// <input accept=".pdf,.docx,application/vnd.ms-excel">
|
|
701
|
+
for (const match of source.matchAll(/\bdata-file-viewer-(?:formats?|renderers?)\s*=\s*["']([^"']+)["']/g)) {
|
|
702
|
+
push(collectDelimitedTokens(match[1]));
|
|
703
|
+
}
|
|
704
|
+
for (const match of source.matchAll(/\baccept\s*=\s*["']([^"']+)["']/g)) {
|
|
705
|
+
push(collectDelimitedTokens(match[1]));
|
|
706
|
+
}
|
|
707
|
+
// Comment hints are useful in non-framework projects where the upload UI is
|
|
708
|
+
// assembled dynamically:
|
|
709
|
+
// // file-viewer-formats: pdf,docx,dwg
|
|
710
|
+
for (const match of source.matchAll(/file-viewer-(?:formats?|renderers?)\s*:\s*([^\n\r<]+)/g)) {
|
|
711
|
+
push(collectDelimitedTokens(match[1]));
|
|
712
|
+
}
|
|
713
|
+
return unique(tokens);
|
|
714
|
+
}
|
|
715
|
+
function normalizeScanOptions(value) {
|
|
716
|
+
if (!value) {
|
|
717
|
+
return null;
|
|
718
|
+
}
|
|
719
|
+
const raw = typeof value === 'object' ? value : {};
|
|
720
|
+
if (raw.enabled === false) {
|
|
721
|
+
return null;
|
|
722
|
+
}
|
|
723
|
+
return {
|
|
724
|
+
roots: raw.roots?.length ? [...raw.roots] : defaultScanRoots,
|
|
725
|
+
extensions: new Set((raw.extensions?.length ? raw.extensions : defaultScanExtensions).map(normalizeScanExtension)),
|
|
726
|
+
maxFileSize: raw.maxFileSize ?? defaultScanMaxFileSize
|
|
727
|
+
};
|
|
728
|
+
}
|
|
729
|
+
function scanFile(filePath, extensions, maxFileSize) {
|
|
730
|
+
const extension = normalizeScanExtension(extname(filePath));
|
|
731
|
+
if (!extensions.has(extension)) {
|
|
732
|
+
return [];
|
|
733
|
+
}
|
|
734
|
+
const info = statSyncSafe(filePath);
|
|
735
|
+
if (!info?.isFile() || info.size > maxFileSize) {
|
|
736
|
+
return [];
|
|
737
|
+
}
|
|
738
|
+
return extractFileViewerRendererHintTokens(readFileSync(filePath, 'utf8'));
|
|
739
|
+
}
|
|
740
|
+
function statSyncSafe(filePath) {
|
|
741
|
+
try {
|
|
742
|
+
return existsSync(filePath) ? statSync(filePath) : null;
|
|
743
|
+
}
|
|
744
|
+
catch {
|
|
745
|
+
return null;
|
|
746
|
+
}
|
|
747
|
+
}
|
|
748
|
+
function walkScanRoot(directory, extensions, maxFileSize, output) {
|
|
749
|
+
if (!existsSync(directory)) {
|
|
750
|
+
return;
|
|
751
|
+
}
|
|
752
|
+
for (const entry of readdirSync(directory, { withFileTypes: true })) {
|
|
753
|
+
if (entry.isDirectory()) {
|
|
754
|
+
if (!ignoredScanDirectories.has(entry.name)) {
|
|
755
|
+
walkScanRoot(join(directory, entry.name), extensions, maxFileSize, output);
|
|
756
|
+
}
|
|
757
|
+
continue;
|
|
758
|
+
}
|
|
759
|
+
if (entry.isFile()) {
|
|
760
|
+
output.push(...scanFile(join(directory, entry.name), extensions, maxFileSize));
|
|
761
|
+
}
|
|
762
|
+
}
|
|
763
|
+
}
|
|
764
|
+
export function collectFileViewerRendererScanTokens(projectRoot, scan) {
|
|
765
|
+
const normalized = normalizeScanOptions(scan);
|
|
766
|
+
if (!normalized) {
|
|
767
|
+
return [];
|
|
768
|
+
}
|
|
769
|
+
const tokens = [];
|
|
770
|
+
normalized.roots.forEach((root) => {
|
|
771
|
+
walkScanRoot(isAbsolute(root) ? root : resolve(projectRoot, root), normalized.extensions, normalized.maxFileSize, tokens);
|
|
772
|
+
});
|
|
773
|
+
return unique(tokens);
|
|
774
|
+
}
|
|
775
|
+
function resolveManualPreset(preset) {
|
|
776
|
+
return preset && preset !== 'auto' ? preset : null;
|
|
777
|
+
}
|
|
778
|
+
function selectRenderers(options) {
|
|
779
|
+
const preset = resolveManualPreset(options.preset);
|
|
780
|
+
const presetCoveredIds = new Set(preset ? presetRendererIds[preset] : []);
|
|
781
|
+
const selected = new Map();
|
|
782
|
+
const missing = [];
|
|
783
|
+
const requestedTokens = [...(options.renderers || []), ...(options.formats || [])]
|
|
784
|
+
.map(normalizeToken)
|
|
785
|
+
.filter(Boolean);
|
|
786
|
+
requestedTokens.forEach((token) => {
|
|
787
|
+
const descriptor = descriptorsById.get(token) ||
|
|
788
|
+
descriptorsByRendererId.get(token) ||
|
|
789
|
+
descriptorsByFormat.get(token);
|
|
790
|
+
if (descriptor) {
|
|
791
|
+
if (!presetCoveredIds.has(descriptor.id)) {
|
|
792
|
+
selected.set(descriptor.id, descriptor);
|
|
793
|
+
}
|
|
794
|
+
return;
|
|
795
|
+
}
|
|
796
|
+
missing.push({
|
|
797
|
+
format: token,
|
|
798
|
+
note: 'No renderer mapping is registered for this format yet.'
|
|
799
|
+
});
|
|
800
|
+
});
|
|
801
|
+
return { preset, descriptors: [...selected.values()], missing };
|
|
802
|
+
}
|
|
803
|
+
function formatMissingRendererMessage(missing) {
|
|
804
|
+
return [
|
|
805
|
+
'Some requested File Viewer formats do not have standalone renderer packages in this workspace yet:',
|
|
806
|
+
...missing.map((item) => ` - ${item.format}${item.targetPackage ? ` -> ${item.targetPackage}` : ''}: ${item.note}`),
|
|
807
|
+
'Use @file-viewer/preset-all for full compatibility while the remaining renderer lines are extracted, or remove those formats from @file-viewer/vite-plugin.'
|
|
808
|
+
].join('\n');
|
|
809
|
+
}
|
|
810
|
+
function assertMissingRendererPolicy(selection, mode) {
|
|
811
|
+
if (!selection.missing.length || mode === 'ignore') {
|
|
812
|
+
return;
|
|
813
|
+
}
|
|
814
|
+
const message = formatMissingRendererMessage(selection.missing);
|
|
815
|
+
if (mode === 'warn') {
|
|
816
|
+
console.warn(`[file-viewer:vite-plugin]\n${message}`);
|
|
817
|
+
return;
|
|
818
|
+
}
|
|
819
|
+
throw new Error(`[file-viewer:vite-plugin]\n${message}`);
|
|
820
|
+
}
|
|
821
|
+
function expandDescriptorRendererIds(ids) {
|
|
822
|
+
return unique(ids.flatMap((id) => {
|
|
823
|
+
const descriptor = descriptorsById.get(id);
|
|
824
|
+
return descriptor ? [...descriptor.rendererIds] : [id];
|
|
825
|
+
}));
|
|
826
|
+
}
|
|
827
|
+
function renderVirtualModule(selection, formats, autoPresetIds = [], runtimeAssetBase = null, configureFullAssetBase = false) {
|
|
828
|
+
const presetModule = selection.preset ? presetModules[selection.preset] : null;
|
|
829
|
+
const autoPresetModules = autoPresetIds
|
|
830
|
+
.filter((id) => id !== selection.preset)
|
|
831
|
+
.map((id) => presetModules[id]);
|
|
832
|
+
const presetImport = presetModule
|
|
833
|
+
? `import { ${presetModule.exportName} as presetRenderers } from '${presetModule.packageName}';`
|
|
834
|
+
: null;
|
|
835
|
+
const autoPresetImports = autoPresetModules.map((preset, index) => `import { ${preset.exportName} as autoPresetRenderers${index} } from '${preset.packageName}';`);
|
|
836
|
+
const rendererImports = selection.descriptors.map((descriptor, index) => `import { ${descriptor.exportName} as renderer${index} } from '${descriptor.importPath ?? descriptor.packageName}';`);
|
|
837
|
+
const rendererNames = [
|
|
838
|
+
...(presetModule ? ['presetRenderers'] : []),
|
|
839
|
+
...autoPresetModules.map((_preset, index) => `autoPresetRenderers${index}`),
|
|
840
|
+
...selection.descriptors.map((_descriptor, index) => `renderer${index}`)
|
|
841
|
+
];
|
|
842
|
+
const rendererIds = unique([
|
|
843
|
+
...(presetModule ? expandDescriptorRendererIds(presetModule.rendererIds) : []),
|
|
844
|
+
...autoPresetModules.flatMap((preset) => expandDescriptorRendererIds(preset.rendererIds)),
|
|
845
|
+
...selection.descriptors.flatMap((descriptor) => descriptor.rendererIds)
|
|
846
|
+
]);
|
|
847
|
+
const packages = unique([
|
|
848
|
+
...(presetModule ? [presetModule.packageName] : []),
|
|
849
|
+
...autoPresetModules.map((preset) => preset.packageName),
|
|
850
|
+
...selection.descriptors.map((descriptor) => descriptor.packageName)
|
|
851
|
+
]);
|
|
852
|
+
const plan = {
|
|
853
|
+
preset: selection.preset,
|
|
854
|
+
autoPresets: autoPresetModules.map((preset) => preset.id),
|
|
855
|
+
formats,
|
|
856
|
+
rendererIds,
|
|
857
|
+
packages,
|
|
858
|
+
generatedBy: '@file-viewer/vite-plugin'
|
|
859
|
+
};
|
|
860
|
+
const autoRegistrationId = selection.descriptors.length
|
|
861
|
+
? '@file-viewer/vite-plugin:configured'
|
|
862
|
+
: selection.preset && !autoPresetModules.length
|
|
863
|
+
? selection.preset
|
|
864
|
+
: !selection.preset && autoPresetModules.length === 1
|
|
865
|
+
? autoPresetModules[0].id
|
|
866
|
+
: '@file-viewer/vite-plugin:configured';
|
|
867
|
+
const runtimeAssetBaseImport = runtimeAssetBase
|
|
868
|
+
? runtimeAssetBase.kind === 'deployment'
|
|
869
|
+
? `import { resolveFileViewerRuntimeAssetBaseUrl, setDefaultFileViewerAssetBaseUrl } from '@file-viewer/core/assets';`
|
|
870
|
+
: `import { setDefaultFileViewerAssetBaseUrl } from '@file-viewer/core/assets';`
|
|
871
|
+
: null;
|
|
872
|
+
const fullAssetBaseImport = runtimeAssetBase && configureFullAssetBase
|
|
873
|
+
? `import { setDefaultFullAssetBaseUrl } from '@file-viewer/preset-all';`
|
|
874
|
+
: null;
|
|
875
|
+
const autoRegistrationImport = rendererNames.length
|
|
876
|
+
? `import { registerFileViewerAutoRendererPreset } from '@file-viewer/core';`
|
|
877
|
+
: null;
|
|
878
|
+
const runtimeAssetBaseSetup = !runtimeAssetBase
|
|
879
|
+
? []
|
|
880
|
+
: runtimeAssetBase.kind === 'literal'
|
|
881
|
+
? [
|
|
882
|
+
`setDefaultFileViewerAssetBaseUrl(${JSON.stringify(runtimeAssetBase.url)});`,
|
|
883
|
+
...(configureFullAssetBase
|
|
884
|
+
? [`setDefaultFullAssetBaseUrl(${JSON.stringify(runtimeAssetBase.url)});`]
|
|
885
|
+
: []),
|
|
886
|
+
''
|
|
887
|
+
]
|
|
888
|
+
: [
|
|
889
|
+
"const fileViewerDeploymentBaseUrl = typeof document === 'undefined'",
|
|
890
|
+
" ? '/'",
|
|
891
|
+
' : resolveFileViewerRuntimeAssetBaseUrl(document);',
|
|
892
|
+
"const fileViewerRuntimeAssetBaseUrl = typeof document === 'undefined'",
|
|
893
|
+
` ? '/' + ${JSON.stringify(runtimeAssetBase.encodedBaseDir)}`,
|
|
894
|
+
` : new URL(${JSON.stringify(runtimeAssetBase.encodedBaseDir)}, fileViewerDeploymentBaseUrl.endsWith('/') ? fileViewerDeploymentBaseUrl : fileViewerDeploymentBaseUrl + '/').href;`,
|
|
895
|
+
'setDefaultFileViewerAssetBaseUrl(fileViewerRuntimeAssetBaseUrl);',
|
|
896
|
+
...(configureFullAssetBase
|
|
897
|
+
? ['setDefaultFullAssetBaseUrl(fileViewerRuntimeAssetBaseUrl);']
|
|
898
|
+
: []),
|
|
899
|
+
''
|
|
900
|
+
];
|
|
901
|
+
return [
|
|
902
|
+
...[autoRegistrationImport, runtimeAssetBaseImport, fullAssetBaseImport].filter(Boolean),
|
|
903
|
+
...[presetImport].filter(Boolean),
|
|
904
|
+
...autoPresetImports,
|
|
905
|
+
...rendererImports,
|
|
906
|
+
'',
|
|
907
|
+
...runtimeAssetBaseSetup,
|
|
908
|
+
`export const configuredFileViewerRenderers = [${rendererNames.join(', ')}];`,
|
|
909
|
+
`export const fileViewerRendererPlan = ${JSON.stringify(plan, null, 2)};`,
|
|
910
|
+
...(rendererNames.length
|
|
911
|
+
? [`registerFileViewerAutoRendererPreset(configuredFileViewerRenderers, { id: ${JSON.stringify(autoRegistrationId)} });`]
|
|
912
|
+
: []),
|
|
913
|
+
'export default configuredFileViewerRenderers;',
|
|
914
|
+
''
|
|
915
|
+
].join('\n');
|
|
916
|
+
}
|
|
917
|
+
function hasManualChunks(config) {
|
|
918
|
+
const output = config.build?.rollupOptions?.output;
|
|
919
|
+
if (Array.isArray(output)) {
|
|
920
|
+
return output.some((item) => Boolean(item.manualChunks));
|
|
921
|
+
}
|
|
922
|
+
return Boolean(output?.manualChunks);
|
|
923
|
+
}
|
|
924
|
+
function resolveProjectViteMajor(projectRoot) {
|
|
925
|
+
const requireFns = [
|
|
926
|
+
createRequire(resolve(projectRoot, 'package.json')),
|
|
927
|
+
pluginRequire
|
|
928
|
+
];
|
|
929
|
+
for (const requireFn of requireFns) {
|
|
930
|
+
try {
|
|
931
|
+
const packageJsonPath = requireFn.resolve('vite/package.json');
|
|
932
|
+
const version = String(JSON.parse(readFileSync(packageJsonPath, 'utf8')).version || '');
|
|
933
|
+
const major = Number.parseInt(version.split('.')[0] || '', 10);
|
|
934
|
+
if (Number.isInteger(major) && major > 0)
|
|
935
|
+
return major;
|
|
936
|
+
}
|
|
937
|
+
catch {
|
|
938
|
+
// Try the plugin's own Vite installation when the project does not expose one.
|
|
939
|
+
}
|
|
940
|
+
}
|
|
941
|
+
return 7;
|
|
942
|
+
}
|
|
943
|
+
function getManualChunksFunction(config) {
|
|
944
|
+
const output = config.build?.rollupOptions?.output;
|
|
945
|
+
if (Array.isArray(output)) {
|
|
946
|
+
return null;
|
|
947
|
+
}
|
|
948
|
+
return typeof output?.manualChunks === 'function'
|
|
949
|
+
? output.manualChunks
|
|
950
|
+
: null;
|
|
951
|
+
}
|
|
952
|
+
function getNodeModulePackageName(id) {
|
|
953
|
+
const normalized = id.replace(/\\/g, '/');
|
|
954
|
+
const marker = '/node_modules/';
|
|
955
|
+
const index = normalized.lastIndexOf(marker);
|
|
956
|
+
if (index === -1) {
|
|
957
|
+
return null;
|
|
958
|
+
}
|
|
959
|
+
const parts = normalized.slice(index + marker.length).split('/');
|
|
960
|
+
if (!parts[0]) {
|
|
961
|
+
return null;
|
|
962
|
+
}
|
|
963
|
+
return parts[0].startsWith('@')
|
|
964
|
+
? [parts[0], parts[1]].filter(Boolean).join('/')
|
|
965
|
+
: parts[0];
|
|
966
|
+
}
|
|
967
|
+
function getStableInteropChunkName(id) {
|
|
968
|
+
const packageName = getNodeModulePackageName(id);
|
|
969
|
+
if (!packageName) {
|
|
970
|
+
return undefined;
|
|
971
|
+
}
|
|
972
|
+
if (packageName === 'codemirror' ||
|
|
973
|
+
packageName === '@replit/codemirror-vim' ||
|
|
974
|
+
packageName.startsWith('@codemirror/') ||
|
|
975
|
+
packageName.startsWith('@lezer/') ||
|
|
976
|
+
packageName.startsWith('@codesandbox/sandpack') ||
|
|
977
|
+
packageName === '@codesandbox/nodebox' ||
|
|
978
|
+
packageName === '@marijn/find-cluster-break' ||
|
|
979
|
+
packageName === 'crelt' ||
|
|
980
|
+
packageName === 'style-mod' ||
|
|
981
|
+
packageName === 'w3c-keyname') {
|
|
982
|
+
return 'vendor-codemirror';
|
|
983
|
+
}
|
|
984
|
+
return undefined;
|
|
985
|
+
}
|
|
986
|
+
function createStableInteropManualChunks(manualChunks) {
|
|
987
|
+
return (id, meta) => getStableInteropChunkName(id) || manualChunks(id, meta);
|
|
988
|
+
}
|
|
989
|
+
function createRolldownCodeSplittingGroups(selection, autoPresetIds, options) {
|
|
990
|
+
const groups = [];
|
|
991
|
+
if (options.stabilizeInteropChunks !== false) {
|
|
992
|
+
groups.push({
|
|
993
|
+
name: 'vendor-codemirror',
|
|
994
|
+
test: (id) => getStableInteropChunkName(id) === 'vendor-codemirror',
|
|
995
|
+
priority: -10
|
|
996
|
+
});
|
|
997
|
+
}
|
|
998
|
+
if ((options.chunkStrategy || 'renderer') !== 'none') {
|
|
999
|
+
const resolveChunkName = createManualChunks(selection, autoPresetIds);
|
|
1000
|
+
groups.push({
|
|
1001
|
+
name: (id) => resolveChunkName(id) || null,
|
|
1002
|
+
priority: -20
|
|
1003
|
+
});
|
|
1004
|
+
}
|
|
1005
|
+
return groups;
|
|
1006
|
+
}
|
|
1007
|
+
function mergeRolldownCodeSplittingOutput(output, pluginGroups) {
|
|
1008
|
+
const current = output || {};
|
|
1009
|
+
if (current.codeSplitting === false || !pluginGroups.length)
|
|
1010
|
+
return current;
|
|
1011
|
+
const codeSplitting = current.codeSplitting && typeof current.codeSplitting === 'object'
|
|
1012
|
+
? current.codeSplitting
|
|
1013
|
+
: {};
|
|
1014
|
+
const existingGroups = Array.isArray(codeSplitting.groups) ? codeSplitting.groups : [];
|
|
1015
|
+
const existingNames = new Set(existingGroups
|
|
1016
|
+
.map(group => typeof group.name === 'string' ? group.name : null)
|
|
1017
|
+
.filter((name) => Boolean(name)));
|
|
1018
|
+
const groups = [
|
|
1019
|
+
...existingGroups,
|
|
1020
|
+
...pluginGroups.filter(group => typeof group.name !== 'string' || !existingNames.has(group.name))
|
|
1021
|
+
];
|
|
1022
|
+
return {
|
|
1023
|
+
...current,
|
|
1024
|
+
codeSplitting: {
|
|
1025
|
+
...codeSplitting,
|
|
1026
|
+
groups
|
|
1027
|
+
}
|
|
1028
|
+
};
|
|
1029
|
+
}
|
|
1030
|
+
function createVite8ChunkConfig(userConfig, selection, autoPresetIds, options) {
|
|
1031
|
+
const build = userConfig.build;
|
|
1032
|
+
const rolldownOptions = build?.rolldownOptions || {};
|
|
1033
|
+
const groups = createRolldownCodeSplittingGroups(selection, autoPresetIds, options);
|
|
1034
|
+
const currentOutput = rolldownOptions.output;
|
|
1035
|
+
if (!groups.length ||
|
|
1036
|
+
(!Array.isArray(currentOutput) && currentOutput?.codeSplitting === false)) {
|
|
1037
|
+
return {};
|
|
1038
|
+
}
|
|
1039
|
+
const output = Array.isArray(currentOutput)
|
|
1040
|
+
? currentOutput.map(item => mergeRolldownCodeSplittingOutput(item, groups))
|
|
1041
|
+
: mergeRolldownCodeSplittingOutput(currentOutput, groups);
|
|
1042
|
+
return {
|
|
1043
|
+
build: {
|
|
1044
|
+
rolldownOptions: {
|
|
1045
|
+
...rolldownOptions,
|
|
1046
|
+
output
|
|
1047
|
+
}
|
|
1048
|
+
}
|
|
1049
|
+
};
|
|
1050
|
+
}
|
|
1051
|
+
function createOptimizeDepsExclude(config) {
|
|
1052
|
+
return unique([
|
|
1053
|
+
...(config.optimizeDeps?.exclude || []),
|
|
1054
|
+
...fileViewerOptimizationExcludedPackages
|
|
1055
|
+
]);
|
|
1056
|
+
}
|
|
1057
|
+
function createOptimizeDepsInclude(config, exclude, anchorPackages) {
|
|
1058
|
+
const excluded = new Set(exclude);
|
|
1059
|
+
return unique([
|
|
1060
|
+
...(config.optimizeDeps?.include || []),
|
|
1061
|
+
...cjsInteropPackages.filter((packageName) => !excluded.has(packageName) && Boolean(resolvePackageJson(packageName, anchorPackages)))
|
|
1062
|
+
]);
|
|
1063
|
+
}
|
|
1064
|
+
function createManualChunks(selection, autoPresetIds = []) {
|
|
1065
|
+
const packageToChunk = new Map();
|
|
1066
|
+
const presetIds = unique([
|
|
1067
|
+
...(selection.preset ? [selection.preset] : []),
|
|
1068
|
+
...autoPresetIds
|
|
1069
|
+
]);
|
|
1070
|
+
presetIds.forEach((presetId) => {
|
|
1071
|
+
const presetModule = presetModules[presetId];
|
|
1072
|
+
packageToChunk.set(presetModule.packageName, presetModule.chunkName);
|
|
1073
|
+
presetModule.rendererIds
|
|
1074
|
+
.map((id) => descriptorsById.get(id))
|
|
1075
|
+
.filter((descriptor) => Boolean(descriptor))
|
|
1076
|
+
.forEach((descriptor) => {
|
|
1077
|
+
packageToChunk.set(descriptor.packageName, descriptor.chunkName);
|
|
1078
|
+
});
|
|
1079
|
+
});
|
|
1080
|
+
selection.descriptors.forEach((descriptor) => {
|
|
1081
|
+
packageToChunk.set(descriptor.packageName, descriptor.chunkName);
|
|
1082
|
+
});
|
|
1083
|
+
return (id) => {
|
|
1084
|
+
const normalized = id.replace(/\\/g, '/');
|
|
1085
|
+
if (normalized.endsWith('/dist/vendor/pdfjs/legacy/build/pdf.worker.mjs')) {
|
|
1086
|
+
return undefined;
|
|
1087
|
+
}
|
|
1088
|
+
for (const [packageName, chunkName] of packageToChunk) {
|
|
1089
|
+
if (normalized.includes(`/node_modules/${packageName}/`) ||
|
|
1090
|
+
normalized.includes(`/node_modules/.pnpm/${packageName.replace('/', '+')}@`)) {
|
|
1091
|
+
return chunkName;
|
|
1092
|
+
}
|
|
1093
|
+
}
|
|
1094
|
+
return undefined;
|
|
1095
|
+
};
|
|
1096
|
+
}
|
|
1097
|
+
function projectRequire() {
|
|
1098
|
+
return createRequire(resolve(process.cwd(), 'package.json'));
|
|
1099
|
+
}
|
|
1100
|
+
function findPackageJsonFromEntry(entry) {
|
|
1101
|
+
let current = dirname(entry);
|
|
1102
|
+
while (current && current !== dirname(current)) {
|
|
1103
|
+
const candidate = join(current, 'package.json');
|
|
1104
|
+
if (existsSync(candidate)) {
|
|
1105
|
+
return candidate;
|
|
1106
|
+
}
|
|
1107
|
+
current = dirname(current);
|
|
1108
|
+
}
|
|
1109
|
+
return null;
|
|
1110
|
+
}
|
|
1111
|
+
function tryResolvePackageJson(packageName, requireFn) {
|
|
1112
|
+
try {
|
|
1113
|
+
return requireFn.resolve(`${packageName}/package.json`);
|
|
1114
|
+
}
|
|
1115
|
+
catch {
|
|
1116
|
+
try {
|
|
1117
|
+
const entry = requireFn.resolve(packageName);
|
|
1118
|
+
return findPackageJsonFromEntry(entry);
|
|
1119
|
+
}
|
|
1120
|
+
catch {
|
|
1121
|
+
return null;
|
|
1122
|
+
}
|
|
1123
|
+
}
|
|
1124
|
+
}
|
|
1125
|
+
function collectWorkspacePackageJsons(root) {
|
|
1126
|
+
const packageJsons = new Map();
|
|
1127
|
+
const ignoredDirectoryNames = new Set(['node_modules', 'dist', 'vendor', '.git']);
|
|
1128
|
+
const scanRoots = ['packages', 'apps'].map((item) => join(root, item));
|
|
1129
|
+
const visit = (directory, depth) => {
|
|
1130
|
+
if (depth < 0 || !existsSync(directory)) {
|
|
1131
|
+
return;
|
|
1132
|
+
}
|
|
1133
|
+
const packageJsonPath = join(directory, 'package.json');
|
|
1134
|
+
if (existsSync(packageJsonPath)) {
|
|
1135
|
+
try {
|
|
1136
|
+
const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf8'));
|
|
1137
|
+
if (packageJson.name) {
|
|
1138
|
+
packageJsons.set(packageJson.name, packageJsonPath);
|
|
1139
|
+
}
|
|
1140
|
+
}
|
|
1141
|
+
catch {
|
|
1142
|
+
// Ignore malformed package.json files in unrelated workspace folders.
|
|
1143
|
+
}
|
|
1144
|
+
}
|
|
1145
|
+
for (const entry of readdirSync(directory)) {
|
|
1146
|
+
if (ignoredDirectoryNames.has(entry)) {
|
|
1147
|
+
continue;
|
|
1148
|
+
}
|
|
1149
|
+
const candidate = join(directory, entry);
|
|
1150
|
+
if (statSync(candidate).isDirectory()) {
|
|
1151
|
+
visit(candidate, depth - 1);
|
|
1152
|
+
}
|
|
1153
|
+
}
|
|
1154
|
+
};
|
|
1155
|
+
scanRoots.forEach((scanRoot) => visit(scanRoot, 4));
|
|
1156
|
+
return packageJsons;
|
|
1157
|
+
}
|
|
1158
|
+
function resolveWorkspacePackageJson(packageName) {
|
|
1159
|
+
const root = process.cwd();
|
|
1160
|
+
if (!workspacePackageJsonCache || workspacePackageJsonCache.root !== root) {
|
|
1161
|
+
workspacePackageJsonCache = {
|
|
1162
|
+
root,
|
|
1163
|
+
packages: collectWorkspacePackageJsons(root)
|
|
1164
|
+
};
|
|
1165
|
+
}
|
|
1166
|
+
return workspacePackageJsonCache.packages.get(packageName) || null;
|
|
1167
|
+
}
|
|
1168
|
+
function resolvePackageJson(packageName, anchorPackages = []) {
|
|
1169
|
+
const rootRequireFns = [projectRequire(), pluginRequire];
|
|
1170
|
+
const requireFns = [...rootRequireFns];
|
|
1171
|
+
const effectiveAnchorPackages = unique([
|
|
1172
|
+
...Object.values(presetModules).map((preset) => preset.packageName),
|
|
1173
|
+
...anchorPackages
|
|
1174
|
+
]);
|
|
1175
|
+
const anchorPackageJsons = new Set();
|
|
1176
|
+
let discoveredAnchor = true;
|
|
1177
|
+
while (discoveredAnchor) {
|
|
1178
|
+
discoveredAnchor = false;
|
|
1179
|
+
for (const anchorPackage of effectiveAnchorPackages) {
|
|
1180
|
+
for (const requireFn of [...requireFns]) {
|
|
1181
|
+
const anchorPackageJson = tryResolvePackageJson(anchorPackage, requireFn) ||
|
|
1182
|
+
resolveWorkspacePackageJson(anchorPackage);
|
|
1183
|
+
if (anchorPackageJson && !anchorPackageJsons.has(anchorPackageJson)) {
|
|
1184
|
+
anchorPackageJsons.add(anchorPackageJson);
|
|
1185
|
+
requireFns.push(createRequire(anchorPackageJson));
|
|
1186
|
+
discoveredAnchor = true;
|
|
1187
|
+
}
|
|
1188
|
+
}
|
|
1189
|
+
}
|
|
1190
|
+
}
|
|
1191
|
+
const preferredAnchorPackageJsons = unique(anchorPackages
|
|
1192
|
+
.map((anchorPackage) => requireFns
|
|
1193
|
+
.map((requireFn) => tryResolvePackageJson(anchorPackage, requireFn))
|
|
1194
|
+
.find(Boolean) || resolveWorkspacePackageJson(anchorPackage))
|
|
1195
|
+
.filter((packageJson) => Boolean(packageJson)));
|
|
1196
|
+
const targetRequireFns = [
|
|
1197
|
+
...preferredAnchorPackageJsons.map((packageJson) => createRequire(packageJson)),
|
|
1198
|
+
...requireFns
|
|
1199
|
+
];
|
|
1200
|
+
for (const requireFn of targetRequireFns) {
|
|
1201
|
+
const packageJson = tryResolvePackageJson(packageName, requireFn);
|
|
1202
|
+
if (packageJson) {
|
|
1203
|
+
return packageJson;
|
|
1204
|
+
}
|
|
1205
|
+
}
|
|
1206
|
+
return resolveWorkspacePackageJson(packageName);
|
|
1207
|
+
}
|
|
1208
|
+
function hasExplicitRendererSelection(options) {
|
|
1209
|
+
return Boolean(resolveManualPreset(options.preset) ||
|
|
1210
|
+
options.formats?.length ||
|
|
1211
|
+
options.renderers?.length ||
|
|
1212
|
+
options.scan);
|
|
1213
|
+
}
|
|
1214
|
+
function shouldAutoDiscoverPresets(options) {
|
|
1215
|
+
if (Array.isArray(options.autoPresets)) {
|
|
1216
|
+
return true;
|
|
1217
|
+
}
|
|
1218
|
+
if (typeof options.autoPresets === 'boolean') {
|
|
1219
|
+
return options.autoPresets;
|
|
1220
|
+
}
|
|
1221
|
+
return options.preset === 'auto' || !hasExplicitRendererSelection(options);
|
|
1222
|
+
}
|
|
1223
|
+
function resolveAutoPresetIds(options) {
|
|
1224
|
+
if (!shouldAutoDiscoverPresets(options)) {
|
|
1225
|
+
return [];
|
|
1226
|
+
}
|
|
1227
|
+
const candidates = Array.isArray(options.autoPresets)
|
|
1228
|
+
? options.autoPresets
|
|
1229
|
+
: Object.keys(presetModules);
|
|
1230
|
+
const installed = unique(candidates).filter((presetId) => Boolean(resolvePackageJson(presetModules[presetId].packageName)));
|
|
1231
|
+
return installed.includes('all') ? ['all'] : installed;
|
|
1232
|
+
}
|
|
1233
|
+
function collectSelectedPackages(selection, autoPresetIds = []) {
|
|
1234
|
+
const presetModule = selection.preset ? presetModules[selection.preset] : null;
|
|
1235
|
+
return unique([
|
|
1236
|
+
...(presetModule ? [presetModule.packageName] : []),
|
|
1237
|
+
...autoPresetIds.map((presetId) => presetModules[presetId].packageName),
|
|
1238
|
+
...selection.descriptors.map((descriptor) => descriptor.packageName)
|
|
1239
|
+
]);
|
|
1240
|
+
}
|
|
1241
|
+
function collectDependencyAnchorPackages(selection, autoPresetIds = []) {
|
|
1242
|
+
const presetIds = unique([
|
|
1243
|
+
...(selection.preset ? [selection.preset] : []),
|
|
1244
|
+
...autoPresetIds
|
|
1245
|
+
]);
|
|
1246
|
+
return unique([
|
|
1247
|
+
...collectSelectedPackages(selection, autoPresetIds),
|
|
1248
|
+
...presetIds.flatMap((presetId) => {
|
|
1249
|
+
const packageJsonPath = resolvePackageJson(presetModules[presetId].packageName);
|
|
1250
|
+
if (!packageJsonPath) {
|
|
1251
|
+
return [];
|
|
1252
|
+
}
|
|
1253
|
+
try {
|
|
1254
|
+
const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf8'));
|
|
1255
|
+
return Object.keys({
|
|
1256
|
+
...(packageJson.dependencies || {}),
|
|
1257
|
+
...(packageJson.optionalDependencies || {})
|
|
1258
|
+
}).filter(packageName => packageName.startsWith('@file-viewer/capability-'));
|
|
1259
|
+
}
|
|
1260
|
+
catch {
|
|
1261
|
+
return [];
|
|
1262
|
+
}
|
|
1263
|
+
}),
|
|
1264
|
+
...presetIds.flatMap((presetId) => presetModules[presetId].rendererIds
|
|
1265
|
+
.map((rendererId) => descriptorsById.get(rendererId)?.packageName)
|
|
1266
|
+
.filter((packageName) => Boolean(packageName))),
|
|
1267
|
+
...selection.descriptors.map((descriptor) => descriptor.packageName)
|
|
1268
|
+
]);
|
|
1269
|
+
}
|
|
1270
|
+
function resolvePackageRoot(packageName, anchorPackages = []) {
|
|
1271
|
+
const packageJson = resolvePackageJson(packageName, anchorPackages);
|
|
1272
|
+
return packageJson ? dirname(packageJson) : null;
|
|
1273
|
+
}
|
|
1274
|
+
function readPackageVersion(packageRoot) {
|
|
1275
|
+
if (!packageRoot) {
|
|
1276
|
+
return null;
|
|
1277
|
+
}
|
|
1278
|
+
try {
|
|
1279
|
+
const packageJson = JSON.parse(readFileSync(join(packageRoot, 'package.json'), 'utf8'));
|
|
1280
|
+
return packageJson.version || null;
|
|
1281
|
+
}
|
|
1282
|
+
catch {
|
|
1283
|
+
return null;
|
|
1284
|
+
}
|
|
1285
|
+
}
|
|
1286
|
+
function assertOwnedPackageVersion(packageName, packageRoot, ownerPackageName, anchorPackages = []) {
|
|
1287
|
+
if (!packageRoot) {
|
|
1288
|
+
return null;
|
|
1289
|
+
}
|
|
1290
|
+
const ownerPackageJsonPath = resolvePackageJson(ownerPackageName, anchorPackages);
|
|
1291
|
+
if (!ownerPackageJsonPath) {
|
|
1292
|
+
return readPackageVersion(packageRoot);
|
|
1293
|
+
}
|
|
1294
|
+
const ownerPackageJson = JSON.parse(readFileSync(ownerPackageJsonPath, 'utf8'));
|
|
1295
|
+
const configuredVersion = ownerPackageJson.dependencies?.[packageName];
|
|
1296
|
+
const expectedVersion = configuredVersion?.startsWith('workspace:')
|
|
1297
|
+
? configuredVersion.slice('workspace:'.length)
|
|
1298
|
+
: configuredVersion;
|
|
1299
|
+
const actualVersion = readPackageVersion(packageRoot);
|
|
1300
|
+
if (expectedVersion &&
|
|
1301
|
+
/^\d+\.\d+\.\d+(?:[-+][0-9A-Za-z.-]+)?$/.test(expectedVersion) &&
|
|
1302
|
+
actualVersion !== expectedVersion) {
|
|
1303
|
+
throw new Error(`[file-viewer:vite-plugin] ${ownerPackageName} requires ${packageName}@${expectedVersion}, ` +
|
|
1304
|
+
`but renderer assets resolved from ${packageName}@${actualVersion || 'unknown'} (${packageRoot}).`);
|
|
1305
|
+
}
|
|
1306
|
+
return actualVersion;
|
|
1307
|
+
}
|
|
1308
|
+
function resolvePackageEntry(packageName, anchorPackages = []) {
|
|
1309
|
+
const packageJsonPath = resolvePackageJson(packageName, anchorPackages);
|
|
1310
|
+
if (!packageJsonPath) {
|
|
1311
|
+
return null;
|
|
1312
|
+
}
|
|
1313
|
+
const packageRoot = dirname(packageJsonPath);
|
|
1314
|
+
const anchorPackageJson = anchorPackages
|
|
1315
|
+
.map((anchorPackage) => resolvePackageJson(anchorPackage))
|
|
1316
|
+
.find(Boolean);
|
|
1317
|
+
const requireFns = [
|
|
1318
|
+
projectRequire(),
|
|
1319
|
+
pluginRequire,
|
|
1320
|
+
...(anchorPackageJson ? [createRequire(anchorPackageJson)] : [])
|
|
1321
|
+
];
|
|
1322
|
+
try {
|
|
1323
|
+
const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf8'));
|
|
1324
|
+
const exportSubpath = packageJson.name && packageName.startsWith(`${packageJson.name}/`)
|
|
1325
|
+
? `.${packageName.slice(packageJson.name.length)}`
|
|
1326
|
+
: null;
|
|
1327
|
+
if (exportSubpath) {
|
|
1328
|
+
const exportedEntry = readPackageExportEntry(packageJson.exports?.[exportSubpath]);
|
|
1329
|
+
if (exportedEntry) {
|
|
1330
|
+
const entry = resolve(packageRoot, exportedEntry);
|
|
1331
|
+
if (existsSync(entry) && statSync(entry).isFile()) {
|
|
1332
|
+
return entry;
|
|
1333
|
+
}
|
|
1334
|
+
}
|
|
1335
|
+
for (const requireFn of requireFns) {
|
|
1336
|
+
try {
|
|
1337
|
+
return requireFn.resolve(packageName);
|
|
1338
|
+
}
|
|
1339
|
+
catch {
|
|
1340
|
+
// Continue probing alternate anchors.
|
|
1341
|
+
}
|
|
1342
|
+
}
|
|
1343
|
+
return null;
|
|
1344
|
+
}
|
|
1345
|
+
const candidates = unique([
|
|
1346
|
+
packageJson.module,
|
|
1347
|
+
packageJson.main,
|
|
1348
|
+
'index.js'
|
|
1349
|
+
].filter((value) => Boolean(value)));
|
|
1350
|
+
for (const candidate of candidates) {
|
|
1351
|
+
const entry = resolve(packageRoot, candidate);
|
|
1352
|
+
if (existsSync(entry) && statSync(entry).isFile()) {
|
|
1353
|
+
return entry;
|
|
1354
|
+
}
|
|
1355
|
+
}
|
|
1356
|
+
}
|
|
1357
|
+
catch {
|
|
1358
|
+
// Fall back to Node resolution below.
|
|
1359
|
+
}
|
|
1360
|
+
for (const requireFn of requireFns) {
|
|
1361
|
+
try {
|
|
1362
|
+
return requireFn.resolve(packageName);
|
|
1363
|
+
}
|
|
1364
|
+
catch {
|
|
1365
|
+
// Continue probing alternate anchors.
|
|
1366
|
+
}
|
|
1367
|
+
}
|
|
1368
|
+
return null;
|
|
1369
|
+
}
|
|
1370
|
+
function resolvePackageFile(packageName, relativePath, anchorPackages = []) {
|
|
1371
|
+
const packageRoot = resolvePackageRoot(packageName, anchorPackages);
|
|
1372
|
+
if (!packageRoot) {
|
|
1373
|
+
return null;
|
|
1374
|
+
}
|
|
1375
|
+
const entry = resolve(packageRoot, relativePath);
|
|
1376
|
+
return existsSync(entry) && statSync(entry).isFile() ? entry : null;
|
|
1377
|
+
}
|
|
1378
|
+
function readPackageExportEntry(value) {
|
|
1379
|
+
if (typeof value === 'string') {
|
|
1380
|
+
return value;
|
|
1381
|
+
}
|
|
1382
|
+
if (!value || typeof value !== 'object') {
|
|
1383
|
+
return null;
|
|
1384
|
+
}
|
|
1385
|
+
const record = value;
|
|
1386
|
+
return readPackageExportEntry(record.import) ||
|
|
1387
|
+
readPackageExportEntry(record.default) ||
|
|
1388
|
+
readPackageExportEntry(record.require);
|
|
1389
|
+
}
|
|
1390
|
+
function resolvePackageExportEntry(packageName, exportPath, anchorPackages = []) {
|
|
1391
|
+
const packageJsonPath = resolvePackageJson(packageName, anchorPackages);
|
|
1392
|
+
if (!packageJsonPath) {
|
|
1393
|
+
return null;
|
|
1394
|
+
}
|
|
1395
|
+
try {
|
|
1396
|
+
const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf8'));
|
|
1397
|
+
const exportEntry = readPackageExportEntry(packageJson.exports?.[exportPath]);
|
|
1398
|
+
if (!exportEntry) {
|
|
1399
|
+
return null;
|
|
1400
|
+
}
|
|
1401
|
+
const entry = resolve(dirname(packageJsonPath), exportEntry);
|
|
1402
|
+
return existsSync(entry) && statSync(entry).isFile() ? entry : null;
|
|
1403
|
+
}
|
|
1404
|
+
catch {
|
|
1405
|
+
return null;
|
|
1406
|
+
}
|
|
1407
|
+
}
|
|
1408
|
+
function normalizeViteAlias(alias) {
|
|
1409
|
+
if (!alias) {
|
|
1410
|
+
return [];
|
|
1411
|
+
}
|
|
1412
|
+
if (Array.isArray(alias)) {
|
|
1413
|
+
return [...alias];
|
|
1414
|
+
}
|
|
1415
|
+
return Object.entries(alias).map(([find, replacement]) => ({ find, replacement }));
|
|
1416
|
+
}
|
|
1417
|
+
function escapeRegExp(value) {
|
|
1418
|
+
return value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
1419
|
+
}
|
|
1420
|
+
function createExactImportAlias(find, replacement) {
|
|
1421
|
+
return {
|
|
1422
|
+
find: new RegExp(`^${escapeRegExp(find)}$`),
|
|
1423
|
+
replacement
|
|
1424
|
+
};
|
|
1425
|
+
}
|
|
1426
|
+
function createFileViewerResolveAliases(anchorPackages) {
|
|
1427
|
+
const packageNames = unique([
|
|
1428
|
+
'@file-viewer/core',
|
|
1429
|
+
...anchorPackages,
|
|
1430
|
+
...cjsInteropPackages
|
|
1431
|
+
]);
|
|
1432
|
+
const aliases = [];
|
|
1433
|
+
const coreAssetsEntry = resolvePackageExportEntry('@file-viewer/core', './assets', anchorPackages);
|
|
1434
|
+
if (coreAssetsEntry) {
|
|
1435
|
+
aliases.push(createExactImportAlias('@file-viewer/core/assets', coreAssetsEntry));
|
|
1436
|
+
}
|
|
1437
|
+
const jszipBrowserEntry = resolvePackageFile('jszip', 'dist/jszip.js', anchorPackages);
|
|
1438
|
+
if (jszipBrowserEntry) {
|
|
1439
|
+
aliases.push(createExactImportAlias('jszip/dist/jszip', jszipBrowserEntry));
|
|
1440
|
+
}
|
|
1441
|
+
aliases.push(...packageNames
|
|
1442
|
+
.map((packageName) => {
|
|
1443
|
+
const entry = resolvePackageEntry(packageName, anchorPackages);
|
|
1444
|
+
return entry ? createExactImportAlias(packageName, entry) : null;
|
|
1445
|
+
})
|
|
1446
|
+
.filter((alias) => Boolean(alias)));
|
|
1447
|
+
return aliases;
|
|
1448
|
+
}
|
|
1449
|
+
async function copyFileIfPresent(from, to) {
|
|
1450
|
+
if (!from || !existsSync(from)) {
|
|
1451
|
+
return false;
|
|
1452
|
+
}
|
|
1453
|
+
const info = await stat(from);
|
|
1454
|
+
if (!info.isFile()) {
|
|
1455
|
+
return false;
|
|
1456
|
+
}
|
|
1457
|
+
await mkdir(dirname(to), { recursive: true });
|
|
1458
|
+
await copyFile(from, to);
|
|
1459
|
+
return true;
|
|
1460
|
+
}
|
|
1461
|
+
async function copyDirectoryIfPresent(from, to) {
|
|
1462
|
+
if (!from || !existsSync(from)) {
|
|
1463
|
+
return false;
|
|
1464
|
+
}
|
|
1465
|
+
const info = await stat(from);
|
|
1466
|
+
if (!info.isDirectory()) {
|
|
1467
|
+
return false;
|
|
1468
|
+
}
|
|
1469
|
+
await rm(to, { recursive: true, force: true });
|
|
1470
|
+
await mkdir(dirname(to), { recursive: true });
|
|
1471
|
+
await cp(from, to, { recursive: true, force: true });
|
|
1472
|
+
return true;
|
|
1473
|
+
}
|
|
1474
|
+
async function copyVersionedCadRuntimeDirectoryIfPresent(from, to, runtimeVersion) {
|
|
1475
|
+
if (!from || !existsSync(from)) {
|
|
1476
|
+
return false;
|
|
1477
|
+
}
|
|
1478
|
+
if (!runtimeVersion || !/^\d+\.\d+\.\d+(?:[-+][0-9A-Za-z.-]+)?$/.test(runtimeVersion)) {
|
|
1479
|
+
throw new Error(`[file-viewer:vite-plugin] Cannot publish CAD runtime assets with invalid version ${JSON.stringify(runtimeVersion)}.`);
|
|
1480
|
+
}
|
|
1481
|
+
const copied = await copyDirectoryIfPresent(from, to);
|
|
1482
|
+
if (!copied) {
|
|
1483
|
+
return false;
|
|
1484
|
+
}
|
|
1485
|
+
const versionedTarget = join(to, runtimeVersion);
|
|
1486
|
+
return copyDirectoryIfPresent(from, versionedTarget);
|
|
1487
|
+
}
|
|
1488
|
+
async function copyPdfCjkFontAssets(from, to) {
|
|
1489
|
+
if (!from) {
|
|
1490
|
+
return false;
|
|
1491
|
+
}
|
|
1492
|
+
const files = join(from, 'files');
|
|
1493
|
+
const stylesheet = join(from, 'wght.css');
|
|
1494
|
+
const license = join(from, 'LICENSE');
|
|
1495
|
+
if (![files, stylesheet, license].every(existsSync) || !statSync(files).isDirectory()) {
|
|
1496
|
+
return false;
|
|
1497
|
+
}
|
|
1498
|
+
await rm(to, { recursive: true, force: true });
|
|
1499
|
+
await mkdir(to, { recursive: true });
|
|
1500
|
+
await cp(files, join(to, 'files'), { recursive: true, force: true });
|
|
1501
|
+
await copyFile(stylesheet, join(to, 'noto-sans-sc.css'));
|
|
1502
|
+
await copyFile(license, join(to, 'OFL-1.1.txt'));
|
|
1503
|
+
return true;
|
|
1504
|
+
}
|
|
1505
|
+
function hasPdfCjkFontAssets(root, stylesheet, license) {
|
|
1506
|
+
if (!root) {
|
|
1507
|
+
return false;
|
|
1508
|
+
}
|
|
1509
|
+
const files = join(root, 'files');
|
|
1510
|
+
try {
|
|
1511
|
+
return (existsSync(join(root, stylesheet)) &&
|
|
1512
|
+
existsSync(join(root, license)) &&
|
|
1513
|
+
statSync(files).isDirectory() &&
|
|
1514
|
+
readdirSync(files, { withFileTypes: true }).some((entry) => entry.isFile() && entry.name.endsWith('.woff2')));
|
|
1515
|
+
}
|
|
1516
|
+
catch {
|
|
1517
|
+
return false;
|
|
1518
|
+
}
|
|
1519
|
+
}
|
|
1520
|
+
async function copyKnownRendererAssets(targetRoot, rendererIds) {
|
|
1521
|
+
const selected = new Set(rendererIds);
|
|
1522
|
+
const results = [];
|
|
1523
|
+
const push = async (rendererId, id, to, copyAction, reason, source, required) => {
|
|
1524
|
+
if (!selected.has(rendererId)) {
|
|
1525
|
+
return;
|
|
1526
|
+
}
|
|
1527
|
+
const copied = await copyAction();
|
|
1528
|
+
results.push({
|
|
1529
|
+
rendererId,
|
|
1530
|
+
id,
|
|
1531
|
+
to,
|
|
1532
|
+
copied,
|
|
1533
|
+
reason: copied ? undefined : reason || 'source asset not found',
|
|
1534
|
+
required,
|
|
1535
|
+
...source,
|
|
1536
|
+
});
|
|
1537
|
+
};
|
|
1538
|
+
const rendererPdfRoot = resolvePackageRoot('@file-viewer/renderer-pdf');
|
|
1539
|
+
const stagedPdfRoot = rendererPdfRoot
|
|
1540
|
+
? join(rendererPdfRoot, 'dist/vendor/pdfjs')
|
|
1541
|
+
: null;
|
|
1542
|
+
const stagedPdfProvenancePath = stagedPdfRoot
|
|
1543
|
+
? join(stagedPdfRoot, 'provenance.json')
|
|
1544
|
+
: null;
|
|
1545
|
+
let stagedPdfVersion = null;
|
|
1546
|
+
if (stagedPdfProvenancePath && existsSync(stagedPdfProvenancePath)) {
|
|
1547
|
+
try {
|
|
1548
|
+
const provenance = JSON.parse(readFileSync(stagedPdfProvenancePath, 'utf8'));
|
|
1549
|
+
if (provenance.packageName === 'pdfjs-dist' && provenance.version) {
|
|
1550
|
+
stagedPdfVersion = provenance.version;
|
|
1551
|
+
}
|
|
1552
|
+
}
|
|
1553
|
+
catch {
|
|
1554
|
+
stagedPdfVersion = null;
|
|
1555
|
+
}
|
|
1556
|
+
}
|
|
1557
|
+
const hasStagedPdfAssets = Boolean(stagedPdfRoot &&
|
|
1558
|
+
stagedPdfVersion &&
|
|
1559
|
+
existsSync(join(stagedPdfRoot, 'legacy/build/pdf.worker.mjs')) &&
|
|
1560
|
+
existsSync(join(stagedPdfRoot, 'cmaps')) &&
|
|
1561
|
+
existsSync(join(stagedPdfRoot, 'wasm')) &&
|
|
1562
|
+
existsSync(join(stagedPdfRoot, 'standard_fonts')));
|
|
1563
|
+
const dependencyPdfRoot = hasStagedPdfAssets
|
|
1564
|
+
? null
|
|
1565
|
+
: resolvePackageRoot('pdfjs-dist', ['@file-viewer/renderer-pdf']);
|
|
1566
|
+
const pdfRoot = hasStagedPdfAssets ? stagedPdfRoot : dependencyPdfRoot;
|
|
1567
|
+
const pdfVersion = hasStagedPdfAssets
|
|
1568
|
+
? stagedPdfVersion
|
|
1569
|
+
: assertOwnedPackageVersion('pdfjs-dist', dependencyPdfRoot, '@file-viewer/renderer-pdf');
|
|
1570
|
+
const pdfSource = pdfRoot
|
|
1571
|
+
? { sourcePackage: 'pdfjs-dist', sourceVersion: pdfVersion || undefined }
|
|
1572
|
+
: undefined;
|
|
1573
|
+
await push('pdf', 'pdf-worker', join(targetRoot, 'vendor/pdf/pdf.worker.mjs'), () => copyFileIfPresent(pdfRoot ? join(pdfRoot, 'legacy/build/pdf.worker.mjs') : null, join(targetRoot, 'vendor/pdf/pdf.worker.mjs')), undefined, pdfSource);
|
|
1574
|
+
await push('pdf', 'pdf-cmaps', join(targetRoot, 'vendor/pdf/cmaps'), () => copyDirectoryIfPresent(pdfRoot ? join(pdfRoot, 'cmaps') : null, join(targetRoot, 'vendor/pdf/cmaps')), undefined, pdfSource);
|
|
1575
|
+
await push('pdf', 'pdf-wasm', join(targetRoot, 'vendor/pdf/wasm'), () => copyDirectoryIfPresent(pdfRoot ? join(pdfRoot, 'wasm') : null, join(targetRoot, 'vendor/pdf/wasm')), undefined, pdfSource);
|
|
1576
|
+
await push('pdf', 'pdf-standard-fonts', join(targetRoot, 'vendor/pdf/standard_fonts'), () => copyDirectoryIfPresent(pdfRoot ? join(pdfRoot, 'standard_fonts') : null, join(targetRoot, 'vendor/pdf/standard_fonts')), undefined, pdfSource);
|
|
1577
|
+
const stagedPdfCjkFontRoot = rendererPdfRoot
|
|
1578
|
+
? join(rendererPdfRoot, 'dist/vendor/noto-sans-sc')
|
|
1579
|
+
: null;
|
|
1580
|
+
const standardAssetsRoot = resolvePackageRoot('@file-viewer/assets-standard');
|
|
1581
|
+
const standardPdfCjkFontRoot = standardAssetsRoot
|
|
1582
|
+
? join(standardAssetsRoot, 'viewer/vendor/pdf/fonts')
|
|
1583
|
+
: null;
|
|
1584
|
+
const dependencyPdfCjkFontRoot = resolvePackageRoot('@fontsource-variable/noto-sans-sc', [
|
|
1585
|
+
'@file-viewer/renderer-pdf'
|
|
1586
|
+
]);
|
|
1587
|
+
const pdfCjkFontTarget = join(targetRoot, 'vendor/pdf/fonts');
|
|
1588
|
+
// The PDF renderer owns the runtime font dependency so direct renderer installs retain
|
|
1589
|
+
// CJK fallback support. The standard profile pack is only a pre-staged copy source.
|
|
1590
|
+
// A missing source means an incomplete install and must not silently drop the fallback.
|
|
1591
|
+
const hasStandardPdfCjkFont = hasPdfCjkFontAssets(standardPdfCjkFontRoot, 'noto-sans-sc.css', 'OFL-1.1.txt');
|
|
1592
|
+
const hasStagedPdfCjkFont = hasPdfCjkFontAssets(stagedPdfCjkFontRoot, 'wght.css', 'LICENSE');
|
|
1593
|
+
const hasDependencyPdfCjkFont = hasPdfCjkFontAssets(dependencyPdfCjkFontRoot, 'wght.css', 'LICENSE');
|
|
1594
|
+
const pdfCjkFontSourceAvailable = hasStandardPdfCjkFont || hasStagedPdfCjkFont || hasDependencyPdfCjkFont;
|
|
1595
|
+
await push('pdf', 'pdf-cjk-font-fallback', pdfCjkFontTarget, async () => {
|
|
1596
|
+
if (hasStandardPdfCjkFont && standardPdfCjkFontRoot) {
|
|
1597
|
+
return copyDirectoryIfPresent(standardPdfCjkFontRoot, pdfCjkFontTarget);
|
|
1598
|
+
}
|
|
1599
|
+
if (hasStagedPdfCjkFont && stagedPdfCjkFontRoot) {
|
|
1600
|
+
return copyPdfCjkFontAssets(stagedPdfCjkFontRoot, pdfCjkFontTarget);
|
|
1601
|
+
}
|
|
1602
|
+
return copyPdfCjkFontAssets(dependencyPdfCjkFontRoot, pdfCjkFontTarget);
|
|
1603
|
+
}, pdfCjkFontSourceAvailable
|
|
1604
|
+
? undefined
|
|
1605
|
+
: `repair @file-viewer/renderer-pdf and its @fontsource-variable/noto-sans-sc dependency`, undefined, true);
|
|
1606
|
+
const pptxRoot = resolvePackageRoot('@file-viewer/pptx', [
|
|
1607
|
+
'@file-viewer/renderer-pptx',
|
|
1608
|
+
'@file-viewer/renderer-presentation'
|
|
1609
|
+
]);
|
|
1610
|
+
await push('office-presentation', 'pptx-worker', join(targetRoot, 'vendor/pptx/pptx.worker.js'), () => copyFileIfPresent(pptxRoot ? join(pptxRoot, 'dist/worker/pptx.worker.js') : null, join(targetRoot, 'vendor/pptx/pptx.worker.js')));
|
|
1611
|
+
const pptRoot = resolvePackageRoot('@file-viewer/ppt', [
|
|
1612
|
+
'@file-viewer/renderer-ppt',
|
|
1613
|
+
'@file-viewer/renderer-presentation'
|
|
1614
|
+
]);
|
|
1615
|
+
const pptVersion = readPackageVersion(pptRoot);
|
|
1616
|
+
const pptSource = pptRoot
|
|
1617
|
+
? { sourcePackage: '@file-viewer/ppt', sourceVersion: pptVersion || undefined }
|
|
1618
|
+
: undefined;
|
|
1619
|
+
for (const [id, filename] of [
|
|
1620
|
+
['ppt-module', 'index.mjs'],
|
|
1621
|
+
['ppt-worker', 'worker.mjs'],
|
|
1622
|
+
['ppt-frame-cache', 'frame-cache.mjs'],
|
|
1623
|
+
['ppt-wasm', 'ppt-native.wasm'],
|
|
1624
|
+
['ppt-cjk-font', 'ppt-font-cjk.otf'],
|
|
1625
|
+
['ppt-manifest', 'manifest.json'],
|
|
1626
|
+
['ppt-package', 'package.json'],
|
|
1627
|
+
['ppt-license', 'LICENSE'],
|
|
1628
|
+
['ppt-notice', 'NOTICE']
|
|
1629
|
+
]) {
|
|
1630
|
+
await push('office-presentation-binary', id, join(targetRoot, `vendor/ppt/${filename}`), () => copyFileIfPresent(pptRoot ? join(pptRoot, filename) : null, join(targetRoot, `vendor/ppt/${filename}`)), undefined, pptSource);
|
|
1631
|
+
}
|
|
1632
|
+
const docxRoot = resolvePackageRoot('@file-viewer/docx', ['@file-viewer/renderer-word']);
|
|
1633
|
+
await push('office-word-openxml', 'docx-worker', join(targetRoot, 'vendor/docx/docx.worker.js'), () => copyFileIfPresent(docxRoot ? join(docxRoot, 'dist/docx-preview.worker.js') : null, join(targetRoot, 'vendor/docx/docx.worker.js')));
|
|
1634
|
+
await push('office-word-openxml', 'docx-worker-jszip', join(targetRoot, 'vendor/docx/jszip.min.js'), () => copyFileIfPresent(docxRoot ? join(docxRoot, 'dist/jszip.min.js') : null, join(targetRoot, 'vendor/docx/jszip.min.js')));
|
|
1635
|
+
const spreadsheetRoot = resolvePackageRoot('@file-viewer/renderer-spreadsheet', [
|
|
1636
|
+
'@file-viewer/renderer-spreadsheet',
|
|
1637
|
+
'@file-viewer/preset-office',
|
|
1638
|
+
'@file-viewer/preset-all'
|
|
1639
|
+
]);
|
|
1640
|
+
const spreadsheetVersion = readPackageVersion(spreadsheetRoot);
|
|
1641
|
+
await push('spreadsheet-openxml', 'spreadsheet-worker', join(targetRoot, 'vendor/xlsx/sheet.worker.js'), () => copyFileIfPresent(spreadsheetRoot ? join(spreadsheetRoot, 'dist/worker/sheet.worker.js') : null, join(targetRoot, 'vendor/xlsx/sheet.worker.js')), undefined, spreadsheetRoot
|
|
1642
|
+
? {
|
|
1643
|
+
sourcePackage: '@file-viewer/renderer-spreadsheet',
|
|
1644
|
+
sourceVersion: spreadsheetVersion || undefined
|
|
1645
|
+
}
|
|
1646
|
+
: undefined);
|
|
1647
|
+
const cadDependencyAnchors = ['@file-viewer/renderer-cad'];
|
|
1648
|
+
const cadRoot = resolvePackageRoot('@flyfish-dev/cad-viewer', cadDependencyAnchors);
|
|
1649
|
+
const cadRuntimeVersion = assertOwnedPackageVersion('@flyfish-dev/cad-viewer', cadRoot, '@file-viewer/renderer-cad', cadDependencyAnchors);
|
|
1650
|
+
await push('cad', 'cad-wasm-directory', join(targetRoot, 'wasm/cad'), () => copyVersionedCadRuntimeDirectoryIfPresent(cadRoot ? join(cadRoot, 'dist/wasm') : null, join(targetRoot, 'wasm/cad'), cadRuntimeVersion), undefined, cadRoot
|
|
1651
|
+
? {
|
|
1652
|
+
sourcePackage: '@flyfish-dev/cad-viewer',
|
|
1653
|
+
sourceVersion: cadRuntimeVersion || undefined
|
|
1654
|
+
}
|
|
1655
|
+
: undefined);
|
|
1656
|
+
const modelDependencyAnchors = [
|
|
1657
|
+
'@file-viewer/renderer-3d',
|
|
1658
|
+
'@file-viewer/geometry-engine'
|
|
1659
|
+
];
|
|
1660
|
+
const occtRoot = resolvePackageRoot('occt-import-js', modelDependencyAnchors);
|
|
1661
|
+
const geometryEngineRoot = resolvePackageRoot('@file-viewer/geometry-engine', [
|
|
1662
|
+
'@file-viewer/renderer-3d'
|
|
1663
|
+
]);
|
|
1664
|
+
const occtVersion = assertOwnedPackageVersion('occt-import-js', occtRoot, '@file-viewer/geometry-engine', modelDependencyAnchors);
|
|
1665
|
+
const occtSource = occtRoot
|
|
1666
|
+
? { sourcePackage: 'occt-import-js', sourceVersion: occtVersion || undefined }
|
|
1667
|
+
: undefined;
|
|
1668
|
+
await push('model', 'model-occt-worker', join(targetRoot, 'wasm/model/occt-worker.js'), () => copyFileIfPresent(geometryEngineRoot ? join(geometryEngineRoot, 'assets/occt-worker.js') : null, join(targetRoot, 'wasm/model/occt-worker.js')));
|
|
1669
|
+
for (const [id, filename] of [
|
|
1670
|
+
['model-occt-runtime', 'occt-import-js.js'],
|
|
1671
|
+
['model-occt-wasm', 'occt-import-js.wasm'],
|
|
1672
|
+
['model-occt-license', 'license.occt.txt'],
|
|
1673
|
+
['model-occt-import-license', 'license.occt-import-js.txt']
|
|
1674
|
+
]) {
|
|
1675
|
+
const targetFilename = filename.startsWith('license.')
|
|
1676
|
+
? filename.replace(/^license\./, 'LICENSE.')
|
|
1677
|
+
: filename;
|
|
1678
|
+
await push('model', id, join(targetRoot, `wasm/model/${targetFilename}`), () => copyFileIfPresent(occtRoot ? join(occtRoot, `dist/${filename}`) : null, join(targetRoot, `wasm/model/${targetFilename}`)), undefined, occtSource);
|
|
1679
|
+
}
|
|
1680
|
+
const typstCompilerRoot = resolvePackageRoot('@myriaddreamin/typst-ts-web-compiler', [
|
|
1681
|
+
'@file-viewer/renderer-typst'
|
|
1682
|
+
]);
|
|
1683
|
+
const typstRendererRoot = resolvePackageRoot('@myriaddreamin/typst-ts-renderer', [
|
|
1684
|
+
'@file-viewer/renderer-typst'
|
|
1685
|
+
]);
|
|
1686
|
+
const typstRendererPackageRoot = resolvePackageRoot('@file-viewer/renderer-typst', [
|
|
1687
|
+
'@file-viewer/renderer-typst'
|
|
1688
|
+
]);
|
|
1689
|
+
await push('typst', 'typst-compiler-wasm', join(targetRoot, 'wasm/typst/typst_ts_web_compiler_bg.wasm'), () => copyFileIfPresent(typstCompilerRoot ? join(typstCompilerRoot, 'pkg/typst_ts_web_compiler_bg.wasm') : null, join(targetRoot, 'wasm/typst/typst_ts_web_compiler_bg.wasm')));
|
|
1690
|
+
await push('typst', 'typst-renderer-wasm', join(targetRoot, 'wasm/typst/typst_ts_renderer_bg.wasm'), () => copyFileIfPresent(typstRendererRoot ? join(typstRendererRoot, 'pkg/typst_ts_renderer_bg.wasm') : null, join(targetRoot, 'wasm/typst/typst_ts_renderer_bg.wasm')));
|
|
1691
|
+
await push('typst', 'typst-font-assets', join(targetRoot, 'wasm/typst/fonts'), () => copyDirectoryIfPresent(typstRendererPackageRoot ? join(typstRendererPackageRoot, 'assets/fonts') : null, join(targetRoot, 'wasm/typst/fonts')));
|
|
1692
|
+
const archiveRoot = resolvePackageRoot('libarchive.js', ['@file-viewer/renderer-archive']);
|
|
1693
|
+
await push('archive', 'libarchive-worker', join(targetRoot, 'vendor/libarchive/worker-bundle.js'), () => copyFileIfPresent(archiveRoot ? join(archiveRoot, 'dist/worker-bundle.js') : null, join(targetRoot, 'vendor/libarchive/worker-bundle.js')));
|
|
1694
|
+
await push('archive', 'libarchive-wasm', join(targetRoot, 'vendor/libarchive/libarchive.wasm'), () => copyFileIfPresent(archiveRoot ? join(archiveRoot, 'dist/libarchive.wasm') : null, join(targetRoot, 'vendor/libarchive/libarchive.wasm')));
|
|
1695
|
+
const chmRoot = resolvePackageRoot('@file-viewer/renderer-chm', ['@file-viewer/renderer-chm']);
|
|
1696
|
+
const chmSource = chmRoot
|
|
1697
|
+
? { sourcePackage: '@file-viewer/renderer-chm', sourceVersion: readPackageVersion(chmRoot) || undefined }
|
|
1698
|
+
: undefined;
|
|
1699
|
+
for (const [id, sourceName, targetName] of [
|
|
1700
|
+
['chm-worker', 'dist/chm.worker.js', 'chm.worker.js'],
|
|
1701
|
+
['chm-wasm-module', 'dist/chm_wasm.js', 'chm_wasm.js'],
|
|
1702
|
+
['chm-wasm', 'dist/chm_wasm_bg.wasm', 'chm_wasm_bg.wasm'],
|
|
1703
|
+
['chm-license', 'LICENSE', 'LICENSE'],
|
|
1704
|
+
['chm-third-party-notices', 'THIRD_PARTY_NOTICES.md', 'THIRD_PARTY_NOTICES.md'],
|
|
1705
|
+
['chm-rust-notice', 'rust/NOTICE.md', 'RUST_NOTICE.md'],
|
|
1706
|
+
['chm-rust-third-party-licenses', 'rust/THIRD_PARTY_LICENSES.md', 'RUST_THIRD_PARTY_LICENSES.md']
|
|
1707
|
+
]) {
|
|
1708
|
+
await push('chm', id, join(targetRoot, `vendor/chm/${targetName}`), () => copyFileIfPresent(chmRoot ? join(chmRoot, sourceName) : null, join(targetRoot, `vendor/chm/${targetName}`)), undefined, chmSource);
|
|
1709
|
+
}
|
|
1710
|
+
const sqlJsRoot = resolvePackageRoot('sql.js', ['@file-viewer/renderer-data']);
|
|
1711
|
+
const designRendererRoot = resolvePackageRoot('@file-viewer/renderer-design');
|
|
1712
|
+
const introspectWasmRoot = resolvePackageRoot('@paged-media/introspect-wasm', [
|
|
1713
|
+
'@file-viewer/renderer-design'
|
|
1714
|
+
]);
|
|
1715
|
+
const introspectWasmVersion = assertOwnedPackageVersion('@paged-media/introspect-wasm', introspectWasmRoot, '@file-viewer/renderer-design');
|
|
1716
|
+
const introspectWasmSource = introspectWasmRoot
|
|
1717
|
+
? {
|
|
1718
|
+
sourcePackage: '@paged-media/introspect-wasm',
|
|
1719
|
+
sourceVersion: introspectWasmVersion || undefined
|
|
1720
|
+
}
|
|
1721
|
+
: undefined;
|
|
1722
|
+
await push('illustrator-pdf-design', 'illustrator-pgf-worker', join(targetRoot, 'vendor/design/illustrator-pgf.worker.js'), () => copyFileIfPresent(designRendererRoot ? join(designRendererRoot, 'dist/illustrator-pgf.worker.js') : null, join(targetRoot, 'vendor/design/illustrator-pgf.worker.js')));
|
|
1723
|
+
await push('photoshop-design', 'photoshop-design-worker', join(targetRoot, 'vendor/design/photoshop.worker.js'), () => copyFileIfPresent(designRendererRoot ? join(designRendererRoot, 'dist/photoshop.worker.js') : null, join(targetRoot, 'vendor/design/photoshop.worker.js')));
|
|
1724
|
+
await push('photoshop-resource-design', 'photoshop-resource-worker', join(targetRoot, 'vendor/design/adobe-resource.worker.js'), () => copyFileIfPresent(designRendererRoot ? join(designRendererRoot, 'dist/adobe-resource.worker.js') : null, join(targetRoot, 'vendor/design/adobe-resource.worker.js')));
|
|
1725
|
+
await push('adobe-palette-design', 'adobe-palette-container-worker', join(targetRoot, 'vendor/design/adobe-container.worker.js'), () => copyFileIfPresent(designRendererRoot ? join(designRendererRoot, 'dist/adobe-container.worker.js') : null, join(targetRoot, 'vendor/design/adobe-container.worker.js')));
|
|
1726
|
+
await push('indesign-exchange-design', 'indesign-exchange-container-worker', join(targetRoot, 'vendor/design/adobe-container.worker.js'), () => copyFileIfPresent(designRendererRoot ? join(designRendererRoot, 'dist/adobe-container.worker.js') : null, join(targetRoot, 'vendor/design/adobe-container.worker.js')));
|
|
1727
|
+
await push('adobe-animate-xfl-design', 'adobe-animate-xfl-container-worker', join(targetRoot, 'vendor/design/adobe-container.worker.js'), () => copyFileIfPresent(designRendererRoot ? join(designRendererRoot, 'dist/adobe-container.worker.js') : null, join(targetRoot, 'vendor/design/adobe-container.worker.js')));
|
|
1728
|
+
await push('adobe-xd-design', 'adobe-xd-container-worker', join(targetRoot, 'vendor/design/adobe-container.worker.js'), () => copyFileIfPresent(designRendererRoot ? join(designRendererRoot, 'dist/adobe-container.worker.js') : null, join(targetRoot, 'vendor/design/adobe-container.worker.js')));
|
|
1729
|
+
await push('indesign-native-design', 'indesign-native-container-worker', join(targetRoot, 'vendor/design/adobe-container.worker.js'), () => copyFileIfPresent(designRendererRoot ? join(designRendererRoot, 'dist/adobe-container.worker.js') : null, join(targetRoot, 'vendor/design/adobe-container.worker.js')));
|
|
1730
|
+
await push('postscript-design', 'postscript-design-worker', join(targetRoot, 'vendor/design/postscript.worker.js'), () => copyFileIfPresent(designRendererRoot ? join(designRendererRoot, 'dist/postscript.worker.js') : null, join(targetRoot, 'vendor/design/postscript.worker.js')));
|
|
1731
|
+
await push('postscript-design', 'postscript-design-wasm', join(targetRoot, 'vendor/design/stet_wasm_bg.wasm'), () => copyFileIfPresent(designRendererRoot ? join(designRendererRoot, 'runtime/postscript/stet_wasm_bg.wasm') : null, join(targetRoot, 'vendor/design/stet_wasm_bg.wasm')));
|
|
1732
|
+
const postscriptLicenses = [
|
|
1733
|
+
['postscript-design-license-stet-apache', 'Stet-Apache-2.0.txt', 'LICENSE.stet-Apache-2.0.txt'],
|
|
1734
|
+
['postscript-design-license-stet-mit', 'Stet-MIT.txt', 'LICENSE.stet-MIT.txt'],
|
|
1735
|
+
['postscript-design-license-carlito-ofl', 'Carlito-OFL-1.1.txt', 'LICENSE.Carlito-OFL-1.1.txt'],
|
|
1736
|
+
['postscript-design-license-tinos-ofl', 'Tinos-OFL-1.1.txt', 'LICENSE.Tinos-OFL-1.1.txt'],
|
|
1737
|
+
['postscript-design-license-cousine-ofl', 'Cousine-OFL-1.1.txt', 'LICENSE.Cousine-OFL-1.1.txt'],
|
|
1738
|
+
['postscript-design-license-noto-symbols-ofl', 'NotoSansSymbols2-OFL-1.1.txt', 'LICENSE.NotoSansSymbols2-OFL-1.1.txt']
|
|
1739
|
+
];
|
|
1740
|
+
for (const [assetId, sourceName, targetName] of postscriptLicenses) {
|
|
1741
|
+
await push('postscript-design', assetId, join(targetRoot, 'vendor/design', targetName), () => copyFileIfPresent(designRendererRoot ? join(designRendererRoot, 'LICENSES', sourceName) : null, join(targetRoot, 'vendor/design', targetName)));
|
|
1742
|
+
}
|
|
1743
|
+
await push('indesign-idml-design', 'indesign-idml-worker', join(targetRoot, 'vendor/design/idml.worker.js'), () => copyFileIfPresent(designRendererRoot ? join(designRendererRoot, 'dist/idml.worker.js') : null, join(targetRoot, 'vendor/design/idml.worker.js')));
|
|
1744
|
+
await push('indesign-idml-design', 'indesign-idml-wasm', join(targetRoot, 'vendor/design/paged_introspect_wasm_bg.wasm'), () => copyFileIfPresent(introspectWasmRoot
|
|
1745
|
+
? join(introspectWasmRoot, 'paged_introspect_wasm_bg.wasm')
|
|
1746
|
+
: null, join(targetRoot, 'vendor/design/paged_introspect_wasm_bg.wasm')), undefined, introspectWasmSource);
|
|
1747
|
+
await push('indesign-idml-design', 'indesign-idml-license', join(targetRoot, 'vendor/design/LICENSE.introspect-wasm-MPL-2.0.txt'), () => copyFileIfPresent(designRendererRoot ? join(designRendererRoot, 'LICENSES/MPL-2.0.txt') : null, join(targetRoot, 'vendor/design/LICENSE.introspect-wasm-MPL-2.0.txt')));
|
|
1748
|
+
await push('data-asset', 'data-sql-wasm', join(targetRoot, 'wasm/data/sql-wasm.wasm'), () => copyFileIfPresent(sqlJsRoot ? join(sqlJsRoot, 'dist/sql-wasm.wasm') : null, join(targetRoot, 'wasm/data/sql-wasm.wasm')));
|
|
1749
|
+
await mkdir(targetRoot, { recursive: true });
|
|
1750
|
+
await writeFile(join(targetRoot, 'flyfish-viewer-assets.json'), `${JSON.stringify({
|
|
1751
|
+
schemaVersion: 1,
|
|
1752
|
+
generatedBy: '@file-viewer/vite-plugin',
|
|
1753
|
+
rendererIds,
|
|
1754
|
+
copiedAt: new Date().toISOString(),
|
|
1755
|
+
assets: results
|
|
1756
|
+
}, null, 2)}\n`);
|
|
1757
|
+
return results;
|
|
1758
|
+
}
|
|
1759
|
+
const independentlyOwnedAssetRendererIds = new Map([
|
|
1760
|
+
['archive', '@file-viewer/assets-standard'],
|
|
1761
|
+
['chm', '@file-viewer/assets-chm'],
|
|
1762
|
+
['pdf', '@file-viewer/assets-standard'],
|
|
1763
|
+
['office-word-openxml', '@file-viewer/assets-standard'],
|
|
1764
|
+
['office-presentation', '@file-viewer/assets-standard'],
|
|
1765
|
+
['spreadsheet-openxml', '@file-viewer/assets-standard'],
|
|
1766
|
+
['cad', '@file-viewer/assets-cad'],
|
|
1767
|
+
['typst', '@file-viewer/assets-typst'],
|
|
1768
|
+
['model', '@file-viewer/assets-model'],
|
|
1769
|
+
['apple-pages', '@file-viewer/assets-iwork'],
|
|
1770
|
+
['apple-numbers', '@file-viewer/assets-iwork'],
|
|
1771
|
+
['apple-keynote', '@file-viewer/assets-iwork'],
|
|
1772
|
+
['office-presentation-binary', '@file-viewer/assets-ppt'],
|
|
1773
|
+
['office-hangul', '@file-viewer/assets-hangul'],
|
|
1774
|
+
['office-wordperfect', '@file-viewer/assets-wordperfect'],
|
|
1775
|
+
['data-asset', '@file-viewer/assets-data']
|
|
1776
|
+
]);
|
|
1777
|
+
function resolveInstalledCapabilityAssetSources(installedAssetPackages, anchorPackages) {
|
|
1778
|
+
return installedAssetPackages.map((packageName) => {
|
|
1779
|
+
if (packageName === 'file-viewer-copy-assets') {
|
|
1780
|
+
throw new Error('[file-viewer:vite-plugin] The v2 aggregate asset carrier is forbidden in a v3 capability plan.');
|
|
1781
|
+
}
|
|
1782
|
+
const packageRoot = resolvePackageRoot(packageName, anchorPackages);
|
|
1783
|
+
if (!packageRoot)
|
|
1784
|
+
throw new Error(`[file-viewer:vite-plugin] Could not resolve installed asset owner ${packageName}.`);
|
|
1785
|
+
const packageVersion = readPackageVersion(packageRoot);
|
|
1786
|
+
if (!packageVersion)
|
|
1787
|
+
throw new Error(`[file-viewer:vite-plugin] Could not read ${packageName} version.`);
|
|
1788
|
+
const payloadRoot = join(packageRoot, 'viewer');
|
|
1789
|
+
const manifestPath = [
|
|
1790
|
+
join(payloadRoot, 'file-viewer-asset-pack.json'),
|
|
1791
|
+
join(payloadRoot, 'flyfish-viewer-assets.json')
|
|
1792
|
+
].find(candidate => existsSync(candidate) && statSync(candidate).isFile());
|
|
1793
|
+
if (!manifestPath)
|
|
1794
|
+
throw new Error(`[file-viewer:vite-plugin] ${packageName} has no staged capability asset manifest.`);
|
|
1795
|
+
const manifest = JSON.parse(readFileSync(manifestPath, 'utf8'));
|
|
1796
|
+
if (manifest.schemaVersion !== 1 || !Array.isArray(manifest.rendererAssetManifests) ||
|
|
1797
|
+
manifest.packageName !== packageName || manifest.packageVersion !== packageVersion) {
|
|
1798
|
+
throw new Error(`[file-viewer:vite-plugin] ${packageName}@${packageVersion} has an invalid or stale asset manifest.`);
|
|
1799
|
+
}
|
|
1800
|
+
return { packageName, packageRoot, packageVersion, payloadRoot, manifest };
|
|
1801
|
+
});
|
|
1802
|
+
}
|
|
1803
|
+
async function copyAssetPathWithoutConflicts(sourceRoot, targetRoot, relativePath) {
|
|
1804
|
+
const normalized = relativePath.replace(/\\/g, '/').replace(/^\/+/, '');
|
|
1805
|
+
const source = resolve(sourceRoot, ...normalized.split('/'));
|
|
1806
|
+
const destination = resolve(targetRoot, ...normalized.split('/'));
|
|
1807
|
+
if (!isPathWithin(sourceRoot, source) || !isPathWithin(targetRoot, destination)) {
|
|
1808
|
+
throw new Error(`[file-viewer:vite-plugin] Asset path escapes its package or output root: ${relativePath}.`);
|
|
1809
|
+
}
|
|
1810
|
+
const sourceInfo = await lstat(source);
|
|
1811
|
+
if (sourceInfo.isSymbolicLink())
|
|
1812
|
+
throw new Error(`[file-viewer:vite-plugin] Asset source is a symbolic link: ${source}.`);
|
|
1813
|
+
if (sourceInfo.isDirectory()) {
|
|
1814
|
+
await mkdir(destination, { recursive: true });
|
|
1815
|
+
for (const entry of await readdir(source, { withFileTypes: true })) {
|
|
1816
|
+
if (entry.isSymbolicLink())
|
|
1817
|
+
throw new Error(`[file-viewer:vite-plugin] Asset source is a symbolic link: ${join(source, entry.name)}.`);
|
|
1818
|
+
await copyAssetPathWithoutConflicts(sourceRoot, targetRoot, `${normalized}/${entry.name}`);
|
|
1819
|
+
}
|
|
1820
|
+
return;
|
|
1821
|
+
}
|
|
1822
|
+
if (!sourceInfo.isFile())
|
|
1823
|
+
throw new Error(`[file-viewer:vite-plugin] Asset source is not a regular file: ${source}.`);
|
|
1824
|
+
await mkdir(dirname(destination), { recursive: true });
|
|
1825
|
+
if (existsSync(destination)) {
|
|
1826
|
+
const destinationInfo = await lstat(destination);
|
|
1827
|
+
if (destinationInfo.isSymbolicLink() || !destinationInfo.isFile()) {
|
|
1828
|
+
throw new Error(`[file-viewer:vite-plugin] Refusing unsafe asset destination ${destination}.`);
|
|
1829
|
+
}
|
|
1830
|
+
const [sourceContent, destinationContent] = await Promise.all([readFile(source), readFile(destination)]);
|
|
1831
|
+
if (!sourceContent.equals(destinationContent)) {
|
|
1832
|
+
throw new Error(`[file-viewer:vite-plugin] Asset owners conflict at ${normalized}.`);
|
|
1833
|
+
}
|
|
1834
|
+
return;
|
|
1835
|
+
}
|
|
1836
|
+
await copyFile(source, destination);
|
|
1837
|
+
}
|
|
1838
|
+
async function copyInstalledCapabilityAssetPacks(targetRoot, rendererIds, installedAssetPackages, anchorPackages) {
|
|
1839
|
+
const selected = new Set(rendererIds);
|
|
1840
|
+
const sources = resolveInstalledCapabilityAssetSources(installedAssetPackages, anchorPackages);
|
|
1841
|
+
const rendererOwners = new Map();
|
|
1842
|
+
const results = [];
|
|
1843
|
+
await mkdir(targetRoot, { recursive: true });
|
|
1844
|
+
for (const source of sources) {
|
|
1845
|
+
for (const rendererManifest of source.manifest.rendererAssetManifests || []) {
|
|
1846
|
+
if (!selected.has(rendererManifest.rendererId))
|
|
1847
|
+
continue;
|
|
1848
|
+
const existing = rendererOwners.get(rendererManifest.rendererId);
|
|
1849
|
+
if (existing) {
|
|
1850
|
+
throw new Error(`[file-viewer:vite-plugin] Renderer asset group ${rendererManifest.rendererId} is owned by both ` +
|
|
1851
|
+
`${existing.packageName} and ${source.packageName}.`);
|
|
1852
|
+
}
|
|
1853
|
+
rendererOwners.set(rendererManifest.rendererId, {
|
|
1854
|
+
packageName: source.packageName,
|
|
1855
|
+
manifest: rendererManifest
|
|
1856
|
+
});
|
|
1857
|
+
for (const asset of rendererManifest.assets || []) {
|
|
1858
|
+
if (asset.target !== 'public' || !asset.defaultPath)
|
|
1859
|
+
continue;
|
|
1860
|
+
const destination = resolve(targetRoot, ...asset.defaultPath.replace(/\\/g, '/').replace(/^\/+/, '').split('/'));
|
|
1861
|
+
try {
|
|
1862
|
+
await copyAssetPathWithoutConflicts(source.payloadRoot, targetRoot, asset.defaultPath);
|
|
1863
|
+
results.push({
|
|
1864
|
+
rendererId: asset.rendererId,
|
|
1865
|
+
id: asset.id,
|
|
1866
|
+
to: destination,
|
|
1867
|
+
copied: true,
|
|
1868
|
+
required: asset.required,
|
|
1869
|
+
sourcePackage: source.packageName,
|
|
1870
|
+
sourceVersion: source.packageVersion
|
|
1871
|
+
});
|
|
1872
|
+
}
|
|
1873
|
+
catch (error) {
|
|
1874
|
+
results.push({
|
|
1875
|
+
rendererId: asset.rendererId,
|
|
1876
|
+
id: asset.id,
|
|
1877
|
+
to: destination,
|
|
1878
|
+
copied: false,
|
|
1879
|
+
required: asset.required,
|
|
1880
|
+
reason: error.message,
|
|
1881
|
+
sourcePackage: source.packageName,
|
|
1882
|
+
sourceVersion: source.packageVersion
|
|
1883
|
+
});
|
|
1884
|
+
}
|
|
1885
|
+
}
|
|
1886
|
+
}
|
|
1887
|
+
}
|
|
1888
|
+
const manifests = [...rendererOwners]
|
|
1889
|
+
.sort(([left], [right]) => left.localeCompare(right))
|
|
1890
|
+
.map(([, value]) => value.manifest);
|
|
1891
|
+
await writeFile(join(targetRoot, 'flyfish-viewer-assets.json'), `${JSON.stringify({
|
|
1892
|
+
schemaVersion: 1,
|
|
1893
|
+
generatedBy: '@file-viewer/vite-plugin',
|
|
1894
|
+
rendererAssetManifests: manifests
|
|
1895
|
+
}, null, 2)}\n`);
|
|
1896
|
+
await writeFile(join(targetRoot, 'flyfish-viewer-manifest.json'), `${JSON.stringify({
|
|
1897
|
+
schemaVersion: 1,
|
|
1898
|
+
kind: 'file-viewer-capability-assets',
|
|
1899
|
+
owners: sources.map(source => ({ packageName: source.packageName, packageVersion: source.packageVersion }))
|
|
1900
|
+
.sort((left, right) => left.packageName.localeCompare(right.packageName))
|
|
1901
|
+
}, null, 2)}\n`);
|
|
1902
|
+
return { results, rendererIds: [...rendererOwners.keys()].sort() };
|
|
1903
|
+
}
|
|
1904
|
+
function matchesBundledAssetKind(kind, info) {
|
|
1905
|
+
return kind === 'directory' || kind === 'wasm-directory'
|
|
1906
|
+
? info.isDirectory()
|
|
1907
|
+
: info.isFile();
|
|
1908
|
+
}
|
|
1909
|
+
function isBundledFullAssetPayload(payloadRoot) {
|
|
1910
|
+
return Boolean(payloadRoot &&
|
|
1911
|
+
existsSync(payloadRoot) &&
|
|
1912
|
+
statSync(payloadRoot).isDirectory() &&
|
|
1913
|
+
existsSync(join(payloadRoot, 'flyfish-viewer-assets.json')));
|
|
1914
|
+
}
|
|
1915
|
+
function resolveBundledFullAssetSource(installedFullPackages) {
|
|
1916
|
+
const copyAssetsPackageRoot = resolvePackageRoot('file-viewer-copy-assets', installedFullPackages);
|
|
1917
|
+
const copyAssetsPayloadRoot = copyAssetsPackageRoot
|
|
1918
|
+
? join(copyAssetsPackageRoot, 'viewer')
|
|
1919
|
+
: null;
|
|
1920
|
+
if (copyAssetsPackageRoot && copyAssetsPayloadRoot && isBundledFullAssetPayload(copyAssetsPayloadRoot)) {
|
|
1921
|
+
installedFullPackages.forEach((ownerPackageName) => {
|
|
1922
|
+
assertOwnedPackageVersion('file-viewer-copy-assets', copyAssetsPackageRoot, ownerPackageName);
|
|
1923
|
+
});
|
|
1924
|
+
const sourceVersion = readPackageVersion(copyAssetsPackageRoot);
|
|
1925
|
+
if (sourceVersion) {
|
|
1926
|
+
return {
|
|
1927
|
+
packageName: 'file-viewer-copy-assets',
|
|
1928
|
+
packageRoot: copyAssetsPackageRoot,
|
|
1929
|
+
payloadRoot: copyAssetsPayloadRoot,
|
|
1930
|
+
sourceVersion
|
|
1931
|
+
};
|
|
1932
|
+
}
|
|
1933
|
+
}
|
|
1934
|
+
if (installedFullPackages.includes('@file-viewer/web-full')) {
|
|
1935
|
+
const webFullPackageRoot = resolvePackageRoot('@file-viewer/web-full', installedFullPackages);
|
|
1936
|
+
const webFullPayloadRoot = webFullPackageRoot
|
|
1937
|
+
? join(webFullPackageRoot, 'dist')
|
|
1938
|
+
: null;
|
|
1939
|
+
const sourceVersion = readPackageVersion(webFullPackageRoot);
|
|
1940
|
+
if (webFullPackageRoot &&
|
|
1941
|
+
webFullPayloadRoot &&
|
|
1942
|
+
sourceVersion &&
|
|
1943
|
+
isBundledFullAssetPayload(webFullPayloadRoot)) {
|
|
1944
|
+
return {
|
|
1945
|
+
packageName: '@file-viewer/web-full',
|
|
1946
|
+
packageRoot: webFullPackageRoot,
|
|
1947
|
+
payloadRoot: webFullPayloadRoot,
|
|
1948
|
+
sourceVersion
|
|
1949
|
+
};
|
|
1950
|
+
}
|
|
1951
|
+
}
|
|
1952
|
+
// Source workspaces may not have staged file-viewer-copy-assets/viewer yet.
|
|
1953
|
+
// @file-viewer/web keeps the same tracked payload for local development.
|
|
1954
|
+
const webPackageRoot = resolvePackageRoot('@file-viewer/web', installedFullPackages);
|
|
1955
|
+
const webPayloadRoot = webPackageRoot ? join(webPackageRoot, 'viewer') : null;
|
|
1956
|
+
const sourceVersion = readPackageVersion(webPackageRoot);
|
|
1957
|
+
if (webPackageRoot &&
|
|
1958
|
+
webPayloadRoot &&
|
|
1959
|
+
sourceVersion &&
|
|
1960
|
+
isBundledFullAssetPayload(webPayloadRoot)) {
|
|
1961
|
+
return {
|
|
1962
|
+
packageName: '@file-viewer/web',
|
|
1963
|
+
packageRoot: webPackageRoot,
|
|
1964
|
+
payloadRoot: webPayloadRoot,
|
|
1965
|
+
sourceVersion
|
|
1966
|
+
};
|
|
1967
|
+
}
|
|
1968
|
+
return null;
|
|
1969
|
+
}
|
|
1970
|
+
function assertBundledFullAssetSourceVersion(source, installedFullPackages) {
|
|
1971
|
+
const payloadManifestPath = join(source.payloadRoot, 'flyfish-viewer-manifest.json');
|
|
1972
|
+
if (!existsSync(payloadManifestPath)) {
|
|
1973
|
+
throw new Error(`[file-viewer:vite-plugin] Missing version manifest in ${source.packageName} payload: ${payloadManifestPath}.`);
|
|
1974
|
+
}
|
|
1975
|
+
const payloadManifest = JSON.parse(readFileSync(payloadManifestPath, 'utf8'));
|
|
1976
|
+
if (!payloadManifest.version || payloadManifest.version !== source.sourceVersion) {
|
|
1977
|
+
throw new Error(`[file-viewer:vite-plugin] ${source.packageName}@${source.sourceVersion} contains ` +
|
|
1978
|
+
`viewer assets for ${payloadManifest.version || 'an unknown version'}.`);
|
|
1979
|
+
}
|
|
1980
|
+
installedFullPackages.forEach((packageName) => {
|
|
1981
|
+
const packageRoot = resolvePackageRoot(packageName, installedFullPackages);
|
|
1982
|
+
const packageVersion = readPackageVersion(packageRoot);
|
|
1983
|
+
if (packageVersion && packageVersion !== payloadManifest.version) {
|
|
1984
|
+
throw new Error(`[file-viewer:vite-plugin] ${packageName}@${packageVersion} cannot use ` +
|
|
1985
|
+
`${source.packageName} viewer assets at ${payloadManifest.version}.`);
|
|
1986
|
+
}
|
|
1987
|
+
});
|
|
1988
|
+
}
|
|
1989
|
+
async function copyBundledFullRendererAssets(targetRoot, rendererIds, installedFullPackages) {
|
|
1990
|
+
const source = resolveBundledFullAssetSource(installedFullPackages);
|
|
1991
|
+
if (!source) {
|
|
1992
|
+
return null;
|
|
1993
|
+
}
|
|
1994
|
+
assertBundledFullAssetSourceVersion(source, installedFullPackages);
|
|
1995
|
+
const sourceManifestPath = join(source.payloadRoot, 'flyfish-viewer-assets.json');
|
|
1996
|
+
const manifest = JSON.parse(readFileSync(sourceManifestPath, 'utf8'));
|
|
1997
|
+
if (manifest.schemaVersion !== 1 || !Array.isArray(manifest.rendererAssetManifests)) {
|
|
1998
|
+
throw new Error(`[file-viewer:vite-plugin] Unsupported full asset manifest in ${sourceManifestPath}.`);
|
|
1999
|
+
}
|
|
2000
|
+
await mkdir(targetRoot, { recursive: true });
|
|
2001
|
+
await cp(source.payloadRoot, targetRoot, { recursive: true, force: true });
|
|
2002
|
+
const results = [];
|
|
2003
|
+
for (const asset of manifest.rendererAssetManifests.flatMap((rendererManifest) => rendererManifest.assets)) {
|
|
2004
|
+
if (asset.target !== 'public' || !asset.defaultPath) {
|
|
2005
|
+
continue;
|
|
2006
|
+
}
|
|
2007
|
+
const relativePath = asset.defaultPath.replace(/\\/g, '/').replace(/^\/+/, '');
|
|
2008
|
+
const destination = resolve(targetRoot, ...relativePath.split('/'));
|
|
2009
|
+
let copied = false;
|
|
2010
|
+
let reason;
|
|
2011
|
+
if (!isPathWithin(targetRoot, destination)) {
|
|
2012
|
+
reason = 'asset manifest path escapes the copy target';
|
|
2013
|
+
}
|
|
2014
|
+
else {
|
|
2015
|
+
try {
|
|
2016
|
+
copied = matchesBundledAssetKind(asset.kind, await stat(destination));
|
|
2017
|
+
if (!copied) {
|
|
2018
|
+
reason = `copied path does not match asset kind ${asset.kind}`;
|
|
2019
|
+
}
|
|
2020
|
+
}
|
|
2021
|
+
catch {
|
|
2022
|
+
reason = 'bundled full asset not found after copy';
|
|
2023
|
+
}
|
|
2024
|
+
}
|
|
2025
|
+
results.push({
|
|
2026
|
+
rendererId: asset.rendererId,
|
|
2027
|
+
id: asset.id,
|
|
2028
|
+
to: destination,
|
|
2029
|
+
copied,
|
|
2030
|
+
required: asset.required,
|
|
2031
|
+
reason,
|
|
2032
|
+
sourcePackage: source.packageName,
|
|
2033
|
+
sourceVersion: source.sourceVersion
|
|
2034
|
+
});
|
|
2035
|
+
}
|
|
2036
|
+
await writeFile(join(targetRoot, 'flyfish-viewer-assets.json'), `${JSON.stringify({
|
|
2037
|
+
...manifest,
|
|
2038
|
+
generatedBy: '@file-viewer/vite-plugin',
|
|
2039
|
+
copiedAt: new Date().toISOString(),
|
|
2040
|
+
rendererIds,
|
|
2041
|
+
assets: results
|
|
2042
|
+
}, null, 2)}\n`);
|
|
2043
|
+
return results;
|
|
2044
|
+
}
|
|
2045
|
+
async function copyRendererAssets(target, rendererIds) {
|
|
2046
|
+
if (target.installedFullPackages.length) {
|
|
2047
|
+
const bundledResults = await copyBundledFullRendererAssets(target.targetRoot, rendererIds, target.installedFullPackages);
|
|
2048
|
+
if (bundledResults) {
|
|
2049
|
+
return bundledResults;
|
|
2050
|
+
}
|
|
2051
|
+
}
|
|
2052
|
+
if (target.installedAssetPackages.length) {
|
|
2053
|
+
const bundled = await copyInstalledCapabilityAssetPacks(target.targetRoot, rendererIds, target.installedAssetPackages, target.installedFullPackages);
|
|
2054
|
+
const covered = new Set(bundled.rendererIds);
|
|
2055
|
+
for (const rendererId of rendererIds) {
|
|
2056
|
+
const requiredOwner = independentlyOwnedAssetRendererIds.get(rendererId);
|
|
2057
|
+
if (requiredOwner && !covered.has(rendererId)) {
|
|
2058
|
+
bundled.results.push({
|
|
2059
|
+
rendererId,
|
|
2060
|
+
id: 'missing-independent-asset-owner',
|
|
2061
|
+
to: target.targetRoot,
|
|
2062
|
+
copied: false,
|
|
2063
|
+
// Specialist offline payloads stay opt-in; warn instead of failing the build.
|
|
2064
|
+
required: false,
|
|
2065
|
+
reason: `install ${requiredOwner} for this capability`
|
|
2066
|
+
});
|
|
2067
|
+
}
|
|
2068
|
+
}
|
|
2069
|
+
return bundled.results;
|
|
2070
|
+
}
|
|
2071
|
+
const results = await copyKnownRendererAssets(target.targetRoot, rendererIds);
|
|
2072
|
+
if (target.installedFullPackages.length) {
|
|
2073
|
+
results.push({
|
|
2074
|
+
rendererId: 'full',
|
|
2075
|
+
id: 'full-asset-payload',
|
|
2076
|
+
to: target.targetRoot,
|
|
2077
|
+
copied: false,
|
|
2078
|
+
required: true,
|
|
2079
|
+
reason: 'no version-matched full viewer payload was found in file-viewer-copy-assets, @file-viewer/web-full, or @file-viewer/web'
|
|
2080
|
+
});
|
|
2081
|
+
}
|
|
2082
|
+
return results;
|
|
2083
|
+
}
|
|
2084
|
+
function copyOptions(value) {
|
|
2085
|
+
return typeof value === 'object' ? value : {};
|
|
2086
|
+
}
|
|
2087
|
+
function findNearestProjectPackageJson(projectRoot) {
|
|
2088
|
+
let current = resolve(projectRoot);
|
|
2089
|
+
while (true) {
|
|
2090
|
+
const packageJsonPath = join(current, 'package.json');
|
|
2091
|
+
if (existsSync(packageJsonPath) && statSyncSafe(packageJsonPath)?.isFile()) {
|
|
2092
|
+
return packageJsonPath;
|
|
2093
|
+
}
|
|
2094
|
+
const parent = dirname(current);
|
|
2095
|
+
if (parent === current) {
|
|
2096
|
+
return null;
|
|
2097
|
+
}
|
|
2098
|
+
current = parent;
|
|
2099
|
+
}
|
|
2100
|
+
}
|
|
2101
|
+
function resolveInstalledFullPackages(projectRoot) {
|
|
2102
|
+
let packageJsonPath = findNearestProjectPackageJson(projectRoot);
|
|
2103
|
+
const lightPackages = fileViewerFullPackages.map(packageName => packageName.replace(/-full$/, ''));
|
|
2104
|
+
const projectPackageRequire = createRequire(join(resolve(projectRoot), 'package.json'));
|
|
2105
|
+
try {
|
|
2106
|
+
while (packageJsonPath) {
|
|
2107
|
+
const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf8'));
|
|
2108
|
+
const declaredPackages = new Set([
|
|
2109
|
+
...Object.keys(packageJson.dependencies || {}),
|
|
2110
|
+
...Object.keys(packageJson.devDependencies || {}),
|
|
2111
|
+
...Object.keys(packageJson.optionalDependencies || {}),
|
|
2112
|
+
...Object.keys(packageJson.peerDependencies || {})
|
|
2113
|
+
]);
|
|
2114
|
+
const declaresRuntime = [...declaredPackages].some(packageName => fileViewerFullPackages.some(fullPackage => fullPackage === packageName) ||
|
|
2115
|
+
lightPackages.includes(packageName) ||
|
|
2116
|
+
packageName.startsWith('@file-viewer/preset-') ||
|
|
2117
|
+
packageName.startsWith('@file-viewer/renderer-'));
|
|
2118
|
+
if (declaresRuntime) {
|
|
2119
|
+
return fileViewerFullPackages.filter(packageName => declaredPackages.has(packageName) &&
|
|
2120
|
+
Boolean(tryResolvePackageJson(packageName, projectPackageRequire)));
|
|
2121
|
+
}
|
|
2122
|
+
// Vite roots can contain a metadata-only package.json while runtime
|
|
2123
|
+
// dependencies live in an ancestor. A nearer light runtime is a boundary.
|
|
2124
|
+
const directory = dirname(packageJsonPath);
|
|
2125
|
+
const parent = dirname(directory);
|
|
2126
|
+
packageJsonPath = parent === directory ? null : findNearestProjectPackageJson(parent);
|
|
2127
|
+
}
|
|
2128
|
+
}
|
|
2129
|
+
catch {
|
|
2130
|
+
return [];
|
|
2131
|
+
}
|
|
2132
|
+
return [];
|
|
2133
|
+
}
|
|
2134
|
+
function resolveInstalledAssetPackages(projectRoot) {
|
|
2135
|
+
const packageJsonPath = findNearestProjectPackageJson(projectRoot);
|
|
2136
|
+
if (!packageJsonPath)
|
|
2137
|
+
return [];
|
|
2138
|
+
try {
|
|
2139
|
+
const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf8'));
|
|
2140
|
+
const declared = unique([
|
|
2141
|
+
...Object.keys(packageJson.dependencies || {}),
|
|
2142
|
+
...Object.keys(packageJson.devDependencies || {}),
|
|
2143
|
+
...Object.keys(packageJson.optionalDependencies || {})
|
|
2144
|
+
]).filter(packageName => packageName.startsWith('@file-viewer/assets-'));
|
|
2145
|
+
const require = createRequire(packageJsonPath);
|
|
2146
|
+
const resolved = declared.filter(packageName => Boolean(tryResolvePackageJson(packageName, require)));
|
|
2147
|
+
return unique(resolved).sort();
|
|
2148
|
+
}
|
|
2149
|
+
catch {
|
|
2150
|
+
return [];
|
|
2151
|
+
}
|
|
2152
|
+
}
|
|
2153
|
+
function normalizeCopyAssetsBaseDir(value) {
|
|
2154
|
+
const normalized = value.trim().replace(/\\/g, '/');
|
|
2155
|
+
if (!normalized) {
|
|
2156
|
+
return '';
|
|
2157
|
+
}
|
|
2158
|
+
if (normalized.startsWith('/') ||
|
|
2159
|
+
isAbsolute(value) ||
|
|
2160
|
+
/^[A-Za-z]:\//.test(normalized) ||
|
|
2161
|
+
normalized.includes('\0')) {
|
|
2162
|
+
throw new Error(`[file-viewer:vite-plugin] copyAssets.baseDir must be a relative directory, received ${JSON.stringify(value)}.`);
|
|
2163
|
+
}
|
|
2164
|
+
const segments = normalized.split('/').filter(Boolean);
|
|
2165
|
+
const decodedSegments = [];
|
|
2166
|
+
for (const segment of segments) {
|
|
2167
|
+
let decodedSegment = segment;
|
|
2168
|
+
try {
|
|
2169
|
+
decodedSegment = decodeURIComponent(segment);
|
|
2170
|
+
}
|
|
2171
|
+
catch {
|
|
2172
|
+
throw new Error(`[file-viewer:vite-plugin] copyAssets.baseDir contains invalid URL encoding: ${JSON.stringify(value)}.`);
|
|
2173
|
+
}
|
|
2174
|
+
if (decodedSegment === '.' ||
|
|
2175
|
+
decodedSegment === '..' ||
|
|
2176
|
+
decodedSegment.includes('/') ||
|
|
2177
|
+
decodedSegment.includes('\\') ||
|
|
2178
|
+
decodedSegment.includes('\0')) {
|
|
2179
|
+
throw new Error(`[file-viewer:vite-plugin] copyAssets.baseDir cannot escape its output directory: ${JSON.stringify(value)}.`);
|
|
2180
|
+
}
|
|
2181
|
+
decodedSegments.push(decodedSegment);
|
|
2182
|
+
}
|
|
2183
|
+
return decodedSegments.join('/');
|
|
2184
|
+
}
|
|
2185
|
+
function isPathWithin(parent, candidate) {
|
|
2186
|
+
const relativePath = relative(parent, candidate);
|
|
2187
|
+
return relativePath === '' || (relativePath !== '..' &&
|
|
2188
|
+
!relativePath.startsWith(`..${sep}`) &&
|
|
2189
|
+
!isAbsolute(relativePath));
|
|
2190
|
+
}
|
|
2191
|
+
function resolveOutputRoot(value, fallback, projectRoot) {
|
|
2192
|
+
const output = value || fallback;
|
|
2193
|
+
return isAbsolute(output) ? resolve(output) : resolve(projectRoot, output);
|
|
2194
|
+
}
|
|
2195
|
+
/**
|
|
2196
|
+
* Resolves the exact directory used by copyAssets without running a Vite build.
|
|
2197
|
+
* This is exported so integrations can validate their deployment contract.
|
|
2198
|
+
*/
|
|
2199
|
+
export function resolveFileViewerCopyAssetsTarget(mode, value = true, config = {}) {
|
|
2200
|
+
const projectRoot = resolve(config.projectRoot || process.cwd());
|
|
2201
|
+
const options = copyOptions(value);
|
|
2202
|
+
const installedFullPackages = resolveInstalledFullPackages(projectRoot);
|
|
2203
|
+
const installedAssetPackages = resolveInstalledAssetPackages(projectRoot);
|
|
2204
|
+
const baseDir = normalizeCopyAssetsBaseDir(typeof options.baseDir === 'string'
|
|
2205
|
+
? options.baseDir
|
|
2206
|
+
: installedFullPackages.length
|
|
2207
|
+
? 'file-viewer'
|
|
2208
|
+
: '');
|
|
2209
|
+
const outputRoot = resolveOutputRoot(mode === 'dev' ? options.publicDir : options.outDir, mode === 'dev' ? config.publicDir || 'public' : config.outDir || 'dist', projectRoot);
|
|
2210
|
+
const targetRoot = baseDir
|
|
2211
|
+
? resolve(outputRoot, ...baseDir.split('/'))
|
|
2212
|
+
: outputRoot;
|
|
2213
|
+
if (!isPathWithin(outputRoot, targetRoot)) {
|
|
2214
|
+
throw new Error(`[file-viewer:vite-plugin] Refusing to copy assets outside ${outputRoot}: ${targetRoot}.`);
|
|
2215
|
+
}
|
|
2216
|
+
return {
|
|
2217
|
+
mode,
|
|
2218
|
+
outputRoot,
|
|
2219
|
+
targetRoot,
|
|
2220
|
+
baseDir,
|
|
2221
|
+
installedFullPackages: [...installedFullPackages],
|
|
2222
|
+
installedAssetPackages
|
|
2223
|
+
};
|
|
2224
|
+
}
|
|
2225
|
+
function normalizeViteDevBasePath(base) {
|
|
2226
|
+
let pathname = base;
|
|
2227
|
+
if (/^[A-Za-z][A-Za-z\d+.-]*:\/\//.test(base)) {
|
|
2228
|
+
try {
|
|
2229
|
+
pathname = new URL(base).pathname;
|
|
2230
|
+
}
|
|
2231
|
+
catch {
|
|
2232
|
+
return '/';
|
|
2233
|
+
}
|
|
2234
|
+
}
|
|
2235
|
+
if (!pathname.startsWith('/')) {
|
|
2236
|
+
return '/';
|
|
2237
|
+
}
|
|
2238
|
+
return pathname.endsWith('/') ? pathname : `${pathname}/`;
|
|
2239
|
+
}
|
|
2240
|
+
function resolveViteFullAssetBase(base, baseDir) {
|
|
2241
|
+
const encodedBaseDir = baseDir
|
|
2242
|
+
.split('/')
|
|
2243
|
+
.filter(Boolean)
|
|
2244
|
+
.map((segment) => encodeURIComponent(segment))
|
|
2245
|
+
.join('/');
|
|
2246
|
+
const encodedBaseDirWithSlash = encodedBaseDir ? `${encodedBaseDir}/` : '';
|
|
2247
|
+
const resolvedBase = base === undefined ? '/' : base.trim();
|
|
2248
|
+
const isAbsoluteBase = resolvedBase.startsWith('/') || /^[A-Za-z][A-Za-z\d+.-]*:\/\//.test(resolvedBase);
|
|
2249
|
+
if (!isAbsoluteBase) {
|
|
2250
|
+
return { kind: 'deployment', encodedBaseDir: encodedBaseDirWithSlash };
|
|
2251
|
+
}
|
|
2252
|
+
const normalizedBase = resolvedBase.endsWith('/') ? resolvedBase : `${resolvedBase}/`;
|
|
2253
|
+
return { kind: 'literal', url: `${normalizedBase}${encodedBaseDirWithSlash}` };
|
|
2254
|
+
}
|
|
2255
|
+
function resolveDevAssetRequestPath(targetRoot, baseDir, requestPathname, viteBasePath) {
|
|
2256
|
+
let requestRelativePath;
|
|
2257
|
+
try {
|
|
2258
|
+
// Depending on the Vite major and middleware ordering, configureServer can
|
|
2259
|
+
// observe either the original base-prefixed URL or the pathname after
|
|
2260
|
+
// Vite's base middleware has stripped it. Accept both shapes, then keep the
|
|
2261
|
+
// strict viewer-asset allowlist and target-root boundary checks below.
|
|
2262
|
+
const encodedRelativePath = viteBasePath === '/' || requestPathname.startsWith(viteBasePath)
|
|
2263
|
+
? requestPathname.slice(viteBasePath === '/' ? 1 : viteBasePath.length)
|
|
2264
|
+
: requestPathname.replace(/^\/+/, '');
|
|
2265
|
+
requestRelativePath = decodeURIComponent(encodedRelativePath);
|
|
2266
|
+
}
|
|
2267
|
+
catch {
|
|
2268
|
+
return null;
|
|
2269
|
+
}
|
|
2270
|
+
requestRelativePath = requestRelativePath.replace(/\\/g, '/');
|
|
2271
|
+
if (requestRelativePath.includes('\0')) {
|
|
2272
|
+
return null;
|
|
2273
|
+
}
|
|
2274
|
+
const basePrefix = baseDir ? `${baseDir}/` : '';
|
|
2275
|
+
if (basePrefix && !requestRelativePath.startsWith(basePrefix)) {
|
|
2276
|
+
return null;
|
|
2277
|
+
}
|
|
2278
|
+
const assetRelativePath = requestRelativePath.slice(basePrefix.length);
|
|
2279
|
+
const isViewerManifest = assetRelativePath === 'flyfish-viewer-assets.json' ||
|
|
2280
|
+
assetRelativePath === 'flyfish-viewer-manifest.json';
|
|
2281
|
+
if (!isViewerManifest &&
|
|
2282
|
+
!assetRelativePath.startsWith('vendor/') &&
|
|
2283
|
+
!assetRelativePath.startsWith('wasm/')) {
|
|
2284
|
+
return null;
|
|
2285
|
+
}
|
|
2286
|
+
const assetPath = resolve(targetRoot, ...assetRelativePath.split('/'));
|
|
2287
|
+
return isPathWithin(targetRoot, assetPath) ? assetPath : null;
|
|
2288
|
+
}
|
|
2289
|
+
function collectAssetRendererIds(selection, autoPresetIds = [], includeFullPreset = false) {
|
|
2290
|
+
if (includeFullPreset) {
|
|
2291
|
+
return expandDescriptorRendererIds(presetModules.all.rendererIds);
|
|
2292
|
+
}
|
|
2293
|
+
const presetIds = [
|
|
2294
|
+
...(selection.preset ? expandDescriptorRendererIds(presetModules[selection.preset].rendererIds) : []),
|
|
2295
|
+
...autoPresetIds.flatMap((presetId) => expandDescriptorRendererIds(presetModules[presetId].rendererIds))
|
|
2296
|
+
];
|
|
2297
|
+
return unique([
|
|
2298
|
+
...presetIds,
|
|
2299
|
+
...selection.descriptors.flatMap((descriptor) => descriptor.rendererIds)
|
|
2300
|
+
]);
|
|
2301
|
+
}
|
|
2302
|
+
const defaultRequiredAssetRendererIds = [
|
|
2303
|
+
'pdf',
|
|
2304
|
+
'office-word-openxml',
|
|
2305
|
+
'office-presentation-binary',
|
|
2306
|
+
'office-presentation',
|
|
2307
|
+
'archive',
|
|
2308
|
+
'cad',
|
|
2309
|
+
'typst'
|
|
2310
|
+
];
|
|
2311
|
+
function isRequiredAssetResult(result) {
|
|
2312
|
+
return result.required ?? defaultRequiredAssetRendererIds.includes(result.rendererId);
|
|
2313
|
+
}
|
|
2314
|
+
function reportAssetCopy(results, targetRoot, mode) {
|
|
2315
|
+
const failedRequired = results.filter((result) => !result.copied && isRequiredAssetResult(result));
|
|
2316
|
+
const missingOptional = results.filter((result) => !result.copied && !isRequiredAssetResult(result));
|
|
2317
|
+
if (!results.length) {
|
|
2318
|
+
return;
|
|
2319
|
+
}
|
|
2320
|
+
const summary = `[file-viewer:vite-plugin] Copied ${results.filter((result) => result.copied).length}/${results.length} renderer assets to ${targetRoot}`;
|
|
2321
|
+
console.log(summary);
|
|
2322
|
+
if (missingOptional.length) {
|
|
2323
|
+
const optionalDetails = missingOptional
|
|
2324
|
+
.map((result) => ` - ${result.rendererId}:${result.id} -> ${result.to} (${result.reason || 'source asset not found'})`)
|
|
2325
|
+
.join('\n');
|
|
2326
|
+
console.warn(`[file-viewer:vite-plugin] Skipped optional offline assets; install the owning package to self-host them:\n${optionalDetails}`);
|
|
2327
|
+
}
|
|
2328
|
+
if (!failedRequired.length || mode === 'ignore') {
|
|
2329
|
+
return;
|
|
2330
|
+
}
|
|
2331
|
+
const details = failedRequired
|
|
2332
|
+
.map((result) => ` - ${result.rendererId}:${result.id} -> ${result.to} (${result.reason})`)
|
|
2333
|
+
.join('\n');
|
|
2334
|
+
if (mode === 'warn') {
|
|
2335
|
+
console.warn(`${summary}\nMissing required assets:\n${details}`);
|
|
2336
|
+
return;
|
|
2337
|
+
}
|
|
2338
|
+
throw new Error(`${summary}\nMissing required assets:\n${details}`);
|
|
2339
|
+
}
|
|
2340
|
+
export function fileViewerRenderers(options = {}) {
|
|
2341
|
+
const moduleId = options.moduleId || virtualModuleId;
|
|
2342
|
+
const resolvedModuleId = `\0${moduleId}`;
|
|
2343
|
+
const injectedModulePath = moduleId.startsWith('/') ? moduleId : `/${moduleId}`;
|
|
2344
|
+
const missingMode = options.missingRenderer || 'error';
|
|
2345
|
+
const explicitFormats = [...(options.formats || []), ...(options.renderers || [])]
|
|
2346
|
+
.map(normalizeToken)
|
|
2347
|
+
.filter(Boolean);
|
|
2348
|
+
let scanFormats = [];
|
|
2349
|
+
let requestedFormats = unique([...explicitFormats, ...scanFormats]);
|
|
2350
|
+
let selection = selectRenderers({
|
|
2351
|
+
...options,
|
|
2352
|
+
formats: [...(options.formats || []), ...scanFormats]
|
|
2353
|
+
});
|
|
2354
|
+
let autoPresetIds = resolveAutoPresetIds(options);
|
|
2355
|
+
let resolvedConfig = null;
|
|
2356
|
+
let installedFullPackages = [];
|
|
2357
|
+
let runtimeAssetBase = null;
|
|
2358
|
+
const refreshSelection = (projectRoot) => {
|
|
2359
|
+
if (projectRoot) {
|
|
2360
|
+
scanFormats = collectFileViewerRendererScanTokens(projectRoot, options.scan);
|
|
2361
|
+
}
|
|
2362
|
+
requestedFormats = unique([...explicitFormats, ...scanFormats]);
|
|
2363
|
+
selection = selectRenderers({
|
|
2364
|
+
...options,
|
|
2365
|
+
formats: [...(options.formats || []), ...scanFormats]
|
|
2366
|
+
});
|
|
2367
|
+
autoPresetIds = resolveAutoPresetIds(options);
|
|
2368
|
+
};
|
|
2369
|
+
const refreshFullAssetRuntime = (projectRoot, viteBase) => {
|
|
2370
|
+
if (!options.copyAssets) {
|
|
2371
|
+
installedFullPackages = [];
|
|
2372
|
+
runtimeAssetBase = null;
|
|
2373
|
+
return;
|
|
2374
|
+
}
|
|
2375
|
+
const target = resolveFileViewerCopyAssetsTarget('dev', options.copyAssets, {
|
|
2376
|
+
projectRoot
|
|
2377
|
+
});
|
|
2378
|
+
installedFullPackages = target.installedFullPackages;
|
|
2379
|
+
runtimeAssetBase = resolveViteFullAssetBase(viteBase, target.baseDir);
|
|
2380
|
+
};
|
|
2381
|
+
const hasConfiguredRenderers = () => Boolean(selection.preset || selection.descriptors.length || autoPresetIds.length);
|
|
2382
|
+
return {
|
|
2383
|
+
name: 'file-viewer-renderers',
|
|
2384
|
+
enforce: 'pre',
|
|
2385
|
+
config(userConfig) {
|
|
2386
|
+
const projectRoot = resolve(process.cwd(), userConfig.root || '.');
|
|
2387
|
+
refreshSelection(projectRoot);
|
|
2388
|
+
refreshFullAssetRuntime(projectRoot, userConfig.base);
|
|
2389
|
+
const dependencyAnchorPackages = collectDependencyAnchorPackages(selection, installedFullPackages.length ? unique([...autoPresetIds, 'all']) : autoPresetIds);
|
|
2390
|
+
const resolvedDependencyAnchorPackages = runtimeAssetBase
|
|
2391
|
+
? unique([
|
|
2392
|
+
...dependencyAnchorPackages,
|
|
2393
|
+
'@file-viewer/core',
|
|
2394
|
+
...installedFullPackages,
|
|
2395
|
+
...(installedFullPackages.length ? ['@file-viewer/preset-all'] : [])
|
|
2396
|
+
])
|
|
2397
|
+
: dependencyAnchorPackages;
|
|
2398
|
+
const optimizeDepsExclude = createOptimizeDepsExclude(userConfig);
|
|
2399
|
+
const manualChunksFunction = getManualChunksFunction(userConfig);
|
|
2400
|
+
const nextConfig = {
|
|
2401
|
+
optimizeDeps: {
|
|
2402
|
+
exclude: optimizeDepsExclude,
|
|
2403
|
+
include: createOptimizeDepsInclude(userConfig, optimizeDepsExclude, resolvedDependencyAnchorPackages)
|
|
2404
|
+
},
|
|
2405
|
+
resolve: {
|
|
2406
|
+
alias: [
|
|
2407
|
+
...normalizeViteAlias(userConfig.resolve?.alias),
|
|
2408
|
+
...createFileViewerResolveAliases(resolvedDependencyAnchorPackages)
|
|
2409
|
+
]
|
|
2410
|
+
}
|
|
2411
|
+
};
|
|
2412
|
+
if (resolveProjectViteMajor(projectRoot) >= 8) {
|
|
2413
|
+
return {
|
|
2414
|
+
...nextConfig,
|
|
2415
|
+
...createVite8ChunkConfig(userConfig, selection, autoPresetIds, options)
|
|
2416
|
+
};
|
|
2417
|
+
}
|
|
2418
|
+
if (manualChunksFunction && options.stabilizeInteropChunks !== false) {
|
|
2419
|
+
return {
|
|
2420
|
+
...nextConfig,
|
|
2421
|
+
build: {
|
|
2422
|
+
rollupOptions: {
|
|
2423
|
+
output: {
|
|
2424
|
+
manualChunks: createStableInteropManualChunks(manualChunksFunction)
|
|
2425
|
+
}
|
|
2426
|
+
}
|
|
2427
|
+
}
|
|
2428
|
+
};
|
|
2429
|
+
}
|
|
2430
|
+
if ((options.chunkStrategy || 'renderer') === 'none' || hasManualChunks(userConfig)) {
|
|
2431
|
+
return nextConfig;
|
|
2432
|
+
}
|
|
2433
|
+
return {
|
|
2434
|
+
...nextConfig,
|
|
2435
|
+
build: {
|
|
2436
|
+
rollupOptions: {
|
|
2437
|
+
output: {
|
|
2438
|
+
manualChunks: createManualChunks(selection, autoPresetIds)
|
|
2439
|
+
}
|
|
2440
|
+
}
|
|
2441
|
+
}
|
|
2442
|
+
};
|
|
2443
|
+
},
|
|
2444
|
+
configResolved(config) {
|
|
2445
|
+
resolvedConfig = config;
|
|
2446
|
+
refreshSelection(config.root);
|
|
2447
|
+
refreshFullAssetRuntime(config.root, config.base);
|
|
2448
|
+
},
|
|
2449
|
+
buildStart() {
|
|
2450
|
+
assertMissingRendererPolicy(selection, missingMode);
|
|
2451
|
+
const packages = collectSelectedPackages(selection, autoPresetIds);
|
|
2452
|
+
const missingPackages = packages.filter((packageName) => !resolvePackageJson(packageName));
|
|
2453
|
+
if (missingPackages.length && missingMode !== 'ignore') {
|
|
2454
|
+
const message = `Missing File Viewer preset/renderer package(s): ${missingPackages.join(', ')}. Install them or remove the matching preset/formats from @file-viewer/vite-plugin.`;
|
|
2455
|
+
if (missingMode === 'warn') {
|
|
2456
|
+
console.warn(`[file-viewer:vite-plugin] ${message}`);
|
|
2457
|
+
}
|
|
2458
|
+
else {
|
|
2459
|
+
throw new Error(`[file-viewer:vite-plugin] ${message}`);
|
|
2460
|
+
}
|
|
2461
|
+
}
|
|
2462
|
+
},
|
|
2463
|
+
async configureServer(server) {
|
|
2464
|
+
if (!options.copyAssets || copyOptions(options.copyAssets).mode === 'build') {
|
|
2465
|
+
return;
|
|
2466
|
+
}
|
|
2467
|
+
const copyTarget = resolveFileViewerCopyAssetsTarget('dev', options.copyAssets, {
|
|
2468
|
+
projectRoot: resolvedConfig?.root,
|
|
2469
|
+
publicDir: resolvedConfig?.publicDir || 'public',
|
|
2470
|
+
outDir: resolvedConfig?.build.outDir || 'dist'
|
|
2471
|
+
});
|
|
2472
|
+
const { targetRoot } = copyTarget;
|
|
2473
|
+
const results = await copyRendererAssets(copyTarget, collectAssetRendererIds(selection, autoPresetIds, copyTarget.installedFullPackages.length > 0));
|
|
2474
|
+
reportAssetCopy(results, targetRoot, missingMode);
|
|
2475
|
+
const viteBasePath = normalizeViteDevBasePath(resolvedConfig?.base || '/');
|
|
2476
|
+
if (server?.middlewares?.use) {
|
|
2477
|
+
const realTargetRoot = await realpath(targetRoot).catch(() => targetRoot);
|
|
2478
|
+
server.middlewares.use(async function fileViewerAssetMiddleware(request, response, next) {
|
|
2479
|
+
const requestUrl = request.url || '';
|
|
2480
|
+
const queryIndex = requestUrl.indexOf('?');
|
|
2481
|
+
const pathname = queryIndex >= 0 ? requestUrl.slice(0, queryIndex) : requestUrl;
|
|
2482
|
+
const assetPath = resolveDevAssetRequestPath(targetRoot, copyTarget.baseDir, pathname, viteBasePath);
|
|
2483
|
+
if (assetPath) {
|
|
2484
|
+
try {
|
|
2485
|
+
const resolvedAssetPath = await realpath(assetPath);
|
|
2486
|
+
if (isPathWithin(realTargetRoot, resolvedAssetPath)) {
|
|
2487
|
+
const info = await stat(resolvedAssetPath);
|
|
2488
|
+
if (info.isFile()) {
|
|
2489
|
+
const contentTypes = {
|
|
2490
|
+
'.avif': 'image/avif',
|
|
2491
|
+
'.bcmap': 'application/octet-stream',
|
|
2492
|
+
'.css': 'text/css; charset=utf-8',
|
|
2493
|
+
'.gif': 'image/gif',
|
|
2494
|
+
'.ico': 'image/x-icon',
|
|
2495
|
+
'.jpeg': 'image/jpeg',
|
|
2496
|
+
'.jpg': 'image/jpeg',
|
|
2497
|
+
'.js': 'text/javascript; charset=utf-8',
|
|
2498
|
+
'.json': 'application/json; charset=utf-8',
|
|
2499
|
+
'.map': 'application/json; charset=utf-8',
|
|
2500
|
+
'.md': 'text/markdown; charset=utf-8',
|
|
2501
|
+
'.mjs': 'text/javascript; charset=utf-8',
|
|
2502
|
+
'.otf': 'font/otf',
|
|
2503
|
+
'.pfb': 'application/x-font-type1',
|
|
2504
|
+
'.png': 'image/png',
|
|
2505
|
+
'.svg': 'image/svg+xml',
|
|
2506
|
+
'.ttf': 'font/ttf',
|
|
2507
|
+
'.txt': 'text/plain; charset=utf-8',
|
|
2508
|
+
'.wasm': 'application/wasm',
|
|
2509
|
+
'.webp': 'image/webp',
|
|
2510
|
+
'.woff': 'font/woff',
|
|
2511
|
+
'.woff2': 'font/woff2',
|
|
2512
|
+
'.xml': 'application/xml; charset=utf-8'
|
|
2513
|
+
};
|
|
2514
|
+
response.statusCode = 200;
|
|
2515
|
+
response.setHeader('Content-Type', contentTypes[extname(resolvedAssetPath).toLowerCase()] || 'application/octet-stream');
|
|
2516
|
+
if (request.method === 'HEAD') {
|
|
2517
|
+
response.end();
|
|
2518
|
+
}
|
|
2519
|
+
else {
|
|
2520
|
+
response.end(await readFile(resolvedAssetPath));
|
|
2521
|
+
}
|
|
2522
|
+
return;
|
|
2523
|
+
}
|
|
2524
|
+
}
|
|
2525
|
+
}
|
|
2526
|
+
catch {
|
|
2527
|
+
// Let Vite return its normal 404/fallback response.
|
|
2528
|
+
}
|
|
2529
|
+
}
|
|
2530
|
+
next();
|
|
2531
|
+
});
|
|
2532
|
+
}
|
|
2533
|
+
},
|
|
2534
|
+
transformIndexHtml: {
|
|
2535
|
+
order: 'pre',
|
|
2536
|
+
handler() {
|
|
2537
|
+
if (options.inject === false || (!hasConfiguredRenderers() && !runtimeAssetBase)) {
|
|
2538
|
+
return undefined;
|
|
2539
|
+
}
|
|
2540
|
+
return [
|
|
2541
|
+
{
|
|
2542
|
+
tag: 'script',
|
|
2543
|
+
attrs: { type: 'module', src: injectedModulePath },
|
|
2544
|
+
injectTo: 'head'
|
|
2545
|
+
}
|
|
2546
|
+
];
|
|
2547
|
+
}
|
|
2548
|
+
},
|
|
2549
|
+
handleHotUpdate(context) {
|
|
2550
|
+
if (!options.scan || !resolvedConfig) {
|
|
2551
|
+
return undefined;
|
|
2552
|
+
}
|
|
2553
|
+
const previous = requestedFormats.join(',');
|
|
2554
|
+
refreshSelection(resolvedConfig.root);
|
|
2555
|
+
if (requestedFormats.join(',') === previous) {
|
|
2556
|
+
return undefined;
|
|
2557
|
+
}
|
|
2558
|
+
const modules = [
|
|
2559
|
+
context.server.moduleGraph.getModuleById(resolvedModuleId),
|
|
2560
|
+
context.server.moduleGraph.getModuleById(resolvedVirtualModuleId)
|
|
2561
|
+
].filter(Boolean);
|
|
2562
|
+
modules.forEach((module) => {
|
|
2563
|
+
if (module) {
|
|
2564
|
+
context.server.moduleGraph.invalidateModule(module);
|
|
2565
|
+
}
|
|
2566
|
+
});
|
|
2567
|
+
context.server.ws.send({
|
|
2568
|
+
type: 'full-reload'
|
|
2569
|
+
});
|
|
2570
|
+
return [];
|
|
2571
|
+
},
|
|
2572
|
+
async closeBundle() {
|
|
2573
|
+
if (resolvedConfig?.command === 'serve' || !options.copyAssets || copyOptions(options.copyAssets).mode === 'dev') {
|
|
2574
|
+
return;
|
|
2575
|
+
}
|
|
2576
|
+
const copyTarget = resolveFileViewerCopyAssetsTarget('build', options.copyAssets, {
|
|
2577
|
+
projectRoot: resolvedConfig?.root,
|
|
2578
|
+
publicDir: resolvedConfig?.publicDir || 'public',
|
|
2579
|
+
outDir: resolvedConfig?.build.outDir || 'dist'
|
|
2580
|
+
});
|
|
2581
|
+
const { targetRoot } = copyTarget;
|
|
2582
|
+
const results = await copyRendererAssets(copyTarget, collectAssetRendererIds(selection, autoPresetIds, copyTarget.installedFullPackages.length > 0));
|
|
2583
|
+
reportAssetCopy(results, targetRoot, missingMode);
|
|
2584
|
+
},
|
|
2585
|
+
resolveId(id, importer) {
|
|
2586
|
+
if (id === '@file-viewer/ppt' &&
|
|
2587
|
+
options.copyAssets &&
|
|
2588
|
+
installedFullPackages.length > 0 &&
|
|
2589
|
+
isPresentationRendererImporter(importer)) {
|
|
2590
|
+
return resolvedPackagedPptFallbackModuleId;
|
|
2591
|
+
}
|
|
2592
|
+
if (id === moduleId || id === virtualModuleId || id === injectedModulePath) {
|
|
2593
|
+
return id === virtualModuleId ? resolvedVirtualModuleId : resolvedModuleId;
|
|
2594
|
+
}
|
|
2595
|
+
return undefined;
|
|
2596
|
+
},
|
|
2597
|
+
load(id) {
|
|
2598
|
+
if (id === resolvedPackagedPptFallbackModuleId) {
|
|
2599
|
+
return `
|
|
2600
|
+
export async function createPptViewer() {
|
|
2601
|
+
throw new Error('Packaged PPT runtime URL was not initialized.')
|
|
2602
|
+
}
|
|
2603
|
+
`;
|
|
2604
|
+
}
|
|
2605
|
+
if (id === resolvedModuleId || id === resolvedVirtualModuleId) {
|
|
2606
|
+
return renderVirtualModule(selection, requestedFormats, autoPresetIds, runtimeAssetBase, installedFullPackages.length > 0);
|
|
2607
|
+
}
|
|
2608
|
+
return undefined;
|
|
2609
|
+
}
|
|
2610
|
+
};
|
|
2611
|
+
}
|
|
2612
|
+
export function createFileViewerManualChunks(options = {}) {
|
|
2613
|
+
return createManualChunks(selectRenderers(options), resolveAutoPresetIds(options));
|
|
2614
|
+
}
|
|
2615
|
+
export function resolveFileViewerRendererSelection(options = {}, projectRoot = process.cwd()) {
|
|
2616
|
+
const scanFormats = collectFileViewerRendererScanTokens(projectRoot, options.scan);
|
|
2617
|
+
const requestedFormats = unique([
|
|
2618
|
+
...(options.formats || []),
|
|
2619
|
+
...(options.renderers || []),
|
|
2620
|
+
...scanFormats
|
|
2621
|
+
].map(normalizeToken).filter(Boolean));
|
|
2622
|
+
const selection = selectRenderers({
|
|
2623
|
+
...options,
|
|
2624
|
+
formats: [...(options.formats || []), ...scanFormats]
|
|
2625
|
+
});
|
|
2626
|
+
const presetModule = selection.preset ? presetModules[selection.preset] : null;
|
|
2627
|
+
const autoPresetIds = resolveAutoPresetIds(options);
|
|
2628
|
+
const autoPresetModules = autoPresetIds.map((presetId) => presetModules[presetId]);
|
|
2629
|
+
const packages = collectSelectedPackages(selection, autoPresetIds);
|
|
2630
|
+
return {
|
|
2631
|
+
preset: selection.preset,
|
|
2632
|
+
presetPackage: presetModule?.packageName ?? null,
|
|
2633
|
+
autoPresets: autoPresetModules.map((preset) => preset.id),
|
|
2634
|
+
autoPresetPackages: autoPresetModules.map((preset) => preset.packageName),
|
|
2635
|
+
formats: requestedFormats,
|
|
2636
|
+
packages,
|
|
2637
|
+
rendererIds: unique([
|
|
2638
|
+
...(presetModule ? expandDescriptorRendererIds(presetModule.rendererIds) : []),
|
|
2639
|
+
...autoPresetModules.flatMap((preset) => expandDescriptorRendererIds(preset.rendererIds)),
|
|
2640
|
+
...selection.descriptors.flatMap((descriptor) => descriptor.rendererIds)
|
|
2641
|
+
]),
|
|
2642
|
+
renderers: selection.descriptors.map((descriptor) => ({
|
|
2643
|
+
id: descriptor.id,
|
|
2644
|
+
packageName: descriptor.packageName,
|
|
2645
|
+
formats: [...descriptor.formats],
|
|
2646
|
+
rendererIds: [...descriptor.rendererIds],
|
|
2647
|
+
chunkName: descriptor.chunkName
|
|
2648
|
+
})),
|
|
2649
|
+
missing: selection.missing
|
|
2650
|
+
};
|
|
2651
|
+
}
|
|
2652
|
+
export default fileViewerRenderers;
|