@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/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;