@file-viewer/vite-plugin 2.1.29 → 2.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.en.md +13 -9
- package/README.md +13 -9
- package/dist/index.d.ts +28 -0
- package/dist/index.js +575 -76
- package/package.json +1 -1
package/README.en.md
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
# @file-viewer/vite-plugin
|
|
2
2
|
|
|
3
|
-
Vite plugin for Flyfish File Viewer on-demand renderer assembly. It can auto-discover installed `@file-viewer/preset-*`
|
|
3
|
+
Vite plugin for Flyfish File Viewer on-demand renderer assembly. It can auto-discover installed `@file-viewer/preset-*` and `@file-viewer/*-full` packages, so Vue, React, Svelte, jQuery, and Vanilla JS components receive matching preview capability without application code passing `renderers` manually. It can also generate `virtual:file-viewer-renderers` from declared formats, import only matching renderer packages, and provide renderer-oriented chunk planning plus offline worker/WASM/font asset copying.
|
|
4
4
|
|
|
5
5
|
## Fastest Start
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
For complete format support, the fastest path is one full package and one Vite plugin registration. Full packages already include `preset-all`; do not install another preset. `copyAssets:true` matches the installed full package and publishes its Worker, WASM, font, and vendor files under `file-viewer/` at the deployment base (`/file-viewer/` for a root deployment) in both dev and build:
|
|
8
8
|
|
|
9
9
|
```bash
|
|
10
|
-
pnpm add @file-viewer/vue3
|
|
10
|
+
pnpm add @file-viewer/vue3-full
|
|
11
11
|
pnpm add -D @file-viewer/vite-plugin
|
|
12
12
|
```
|
|
13
13
|
|
|
@@ -24,15 +24,17 @@ export default defineConfig({
|
|
|
24
24
|
})
|
|
25
25
|
```
|
|
26
26
|
|
|
27
|
-
|
|
27
|
+
Installing a full package without publishing these assets leaves PDF Worker, CAD/Typst/Archive WASM, and other formats without runtime files. That is partial support, not a complete setup.
|
|
28
28
|
|
|
29
|
-
|
|
29
|
+
For a smaller install, use a standard component with one preset and keep the same Vite config. The plugin auto-discovers installed presets, so application code does not hand-write renderer imports and the plugin does not need `preset:'office'`:
|
|
30
30
|
|
|
31
31
|
```bash
|
|
32
|
-
pnpm add @file-viewer/vue3 @file-viewer/preset-
|
|
32
|
+
pnpm add @file-viewer/vue3 @file-viewer/preset-office
|
|
33
33
|
pnpm add -D @file-viewer/vite-plugin
|
|
34
34
|
```
|
|
35
35
|
|
|
36
|
+
Components keep `autoRenderers:true` by default, so `@file-viewer/vue3`, `@file-viewer/react`, `@file-viewer/web`, `@file-viewer/svelte`, `@file-viewer/jquery`, `@file-viewer/vue2.7`, and `@file-viewer/vue2.6` automatically consume the injected preset / renderer registry.
|
|
37
|
+
|
|
36
38
|
Available presets:
|
|
37
39
|
|
|
38
40
|
- `@file-viewer/preset-lite`: text, Markdown, code, image, audio, and video.
|
|
@@ -44,7 +46,7 @@ Install individual renderer packages only for strict cuts, such as `@file-viewer
|
|
|
44
46
|
|
|
45
47
|
## vite.config.ts
|
|
46
48
|
|
|
47
|
-
Prefer preset auto assembly for normal products. With
|
|
49
|
+
Prefer full/preset auto assembly for normal products. With only `copyAssets:true`, the plugin auto-discovers installed `@file-viewer/*-full` or `@file-viewer/preset-*` packages:
|
|
48
50
|
|
|
49
51
|
```ts
|
|
50
52
|
fileViewerRenderers({
|
|
@@ -83,7 +85,7 @@ const options = {
|
|
|
83
85
|
|
|
84
86
|
| Option | Description |
|
|
85
87
|
| --- | --- |
|
|
86
|
-
| `copyAssets` | `true` or `{ publicDir, outDir, mode }`; copies
|
|
88
|
+
| `copyAssets` | `true` or `{ publicDir, outDir, mode, baseDir }`; copies matching Worker, WASM, font, and vendor assets. Installed full packages default to `<deployment-base>/file-viewer/`, which is required for complete full support; standard packages/presets keep the existing root behavior |
|
|
87
89
|
| `preset` | `'auto' | 'lite' | 'office' | 'engineering' | 'all'`; with no explicit formats, installed presets are discovered automatically |
|
|
88
90
|
| `autoPresets` | `true` or a preset list; useful with `scan:true` when installed presets should stay active |
|
|
89
91
|
| `formats` | File extensions or format tokens, for example `['pdf', 'docx', 'dwg']` |
|
|
@@ -96,6 +98,8 @@ const options = {
|
|
|
96
98
|
|
|
97
99
|
When host apps split `node_modules` by package name, circular dependencies between `@codemirror/*`, `@lezer/*`, and Sandpack can show up in production as `codemirror-view.* Cannot access ... before initialization`. The plugin wraps existing `manualChunks` functions by default, stabilizes only those known interop chunks, and preserves the rest of the app's custom grouping. Set `stabilizeInteropChunks:false` only when the host build needs total control.
|
|
98
100
|
|
|
101
|
+
`copyAssets.baseDir` overrides automatic placement. It must be relative and cannot contain `..`; an empty string explicitly selects the root. The plugin now aligns the shared runtime asset base for standard packages, presets, and full packages; full packages also keep `setDefaultFullAssetBaseUrl()` synchronized. Only integrations that set `inject:false` and do not import the virtual module must call `setDefaultFileViewerAssetBaseUrl()` themselves (plus `setDefaultFullAssetBaseUrl()` for a full package). With Vite `base:'/app/'`, full-package dev URLs start with `/app/file-viewer/...`, while production files remain under `outDir/file-viewer/`.
|
|
102
|
+
|
|
99
103
|
For strict registry control, disable injection and pass the virtual module explicitly:
|
|
100
104
|
|
|
101
105
|
```ts
|
|
@@ -145,7 +149,7 @@ When a file extension is in the supported matrix but the current project has not
|
|
|
145
149
|
|
|
146
150
|
## Current Boundary
|
|
147
151
|
|
|
148
|
-
The plugin currently generates imports for extracted renderer packages: Word, Spreadsheet, PDF, OFD, Presentation, CAD, Draw.io/Excalidraw/Mermaid/PlantUML, 3D, Data, EDA, Typst, archives, email, EPUB, code/Markdown/Patch/Git Bundle, image, media, XMind, and Geo. Declare them explicitly with `formats`, or let `scan: true` discover source hints automatically; core-supported extensions such as `.zipx`, `.cbz`, `.tiff`, `.mjs`, `.gv`, `.patch`, `.bundle`, `.mermaid`, `.puml`, and `.mpeg` also resolve to their renderer packages. With `copyAssets:true`, the plugin
|
|
152
|
+
The plugin currently generates imports for extracted renderer packages: Word, Spreadsheet, PDF, OFD, Presentation, CAD, Draw.io/Excalidraw/Mermaid/PlantUML, 3D, Data, EDA, Typst, archives, email, EPUB, code/Markdown/Patch/Git Bundle, image, media, XMind, and Geo. Declare them explicitly with `formats`, or let `scan: true` discover source hints automatically; core-supported extensions such as `.zipx`, `.cbz`, `.tiff`, `.mjs`, `.gv`, `.patch`, `.bundle`, `.mermaid`, `.puml`, and `.mpeg` also resolve to their renderer packages. With `copyAssets:true`, the plugin detects installed capability packages. Full packages copy matching assets into dev `publicDir/file-viewer/` and production `outDir/file-viewer/`; standard packages/presets keep the existing root placement, including the Typst compiler / renderer WASM files and default fonts. `preset: 'auto' | 'lite' | 'office' | 'engineering' | 'all'` imports matching `@file-viewer/preset-*` packages; when `formats` are also present, the plugin adds extra renderers outside the preset.
|
|
149
153
|
|
|
150
154
|
## Documentation
|
|
151
155
|
|
package/README.md
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
# @file-viewer/vite-plugin
|
|
2
2
|
|
|
3
|
-
Flyfish File Viewer 的 Vite 按需 renderer 自动装配插件。它可以自动发现已安装的 `@file-viewer/preset-*`
|
|
3
|
+
Flyfish File Viewer 的 Vite 按需 renderer 自动装配插件。它可以自动发现已安装的 `@file-viewer/preset-*` 和 `@file-viewer/*-full` 包,让 Vue、React、Svelte、jQuery 和 Vanilla JS 组件无需手动传 `renderers` 就获得对应预览能力;也可以根据业务声明的文件格式生成 `virtual:file-viewer-renderers`,只 import 命中的 renderer 包,并提供 chunk 分组和离线 worker/WASM/字体资源复制能力。
|
|
4
4
|
|
|
5
5
|
## 最快开始
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
需要完整格式支持时,最快路径是“full 包 + 注册一次 Vite 插件”。full 已内置 `preset-all`,不要再安装 preset;`copyAssets:true` 会在开发和构建时自动匹配 full 包,并把 Worker、WASM、字体和 vendor 文件发布到部署基址下的 `file-viewer/`(根部署即 `/file-viewer/`):
|
|
8
8
|
|
|
9
9
|
```bash
|
|
10
|
-
pnpm add @file-viewer/vue3
|
|
10
|
+
pnpm add @file-viewer/vue3-full
|
|
11
11
|
pnpm add -D @file-viewer/vite-plugin
|
|
12
12
|
```
|
|
13
13
|
|
|
@@ -24,15 +24,17 @@ export default defineConfig({
|
|
|
24
24
|
})
|
|
25
25
|
```
|
|
26
26
|
|
|
27
|
-
|
|
27
|
+
只安装 full 包而不启用资源复制,PDF Worker、CAD/Typst/Archive WASM 等格式会缺少运行文件,只能获得部分格式支持。
|
|
28
28
|
|
|
29
|
-
|
|
29
|
+
需要更小体积时,改用“标准组件包 + 一个 preset”,Vite 配置保持不变。插件会自动发现已安装的 preset,无需手写 renderer import,也无需显式写 `preset:'office'`:
|
|
30
30
|
|
|
31
31
|
```bash
|
|
32
|
-
pnpm add @file-viewer/vue3 @file-viewer/preset-
|
|
32
|
+
pnpm add @file-viewer/vue3 @file-viewer/preset-office
|
|
33
33
|
pnpm add -D @file-viewer/vite-plugin
|
|
34
34
|
```
|
|
35
35
|
|
|
36
|
+
组件默认 `autoRenderers:true`,会读取 Vite 插件注入的 preset / renderer registry。常规业务代码只要使用 `@file-viewer/vue3`、`@file-viewer/react`、`@file-viewer/web`、`@file-viewer/svelte`、`@file-viewer/jquery`、`@file-viewer/vue2.7` 或 `@file-viewer/vue2.6` 即可获得对应能力。
|
|
37
|
+
|
|
36
38
|
可选 preset:
|
|
37
39
|
|
|
38
40
|
- `@file-viewer/preset-lite`: 文本、Markdown、代码、图片、音频、视频。
|
|
@@ -44,7 +46,7 @@ pnpm add -D @file-viewer/vite-plugin
|
|
|
44
46
|
|
|
45
47
|
## vite.config.ts
|
|
46
48
|
|
|
47
|
-
推荐默认使用 preset
|
|
49
|
+
推荐默认使用 full/preset 自动装配。只传 `copyAssets:true` 时,插件会自动发现已安装的 `@file-viewer/*-full` 或 `@file-viewer/preset-*`,无需写 `preset:'all'`:
|
|
48
50
|
|
|
49
51
|
```ts
|
|
50
52
|
fileViewerRenderers({
|
|
@@ -83,7 +85,7 @@ const options = {
|
|
|
83
85
|
|
|
84
86
|
| 选项 | 说明 |
|
|
85
87
|
| --- | --- |
|
|
86
|
-
| `copyAssets` | `true` 或 `{ publicDir, outDir, mode }
|
|
88
|
+
| `copyAssets` | `true` 或 `{ publicDir, outDir, mode, baseDir }`;复制匹配的 Worker、WASM、字体和 vendor 资源。检测到 full 时默认发布到 `<部署基址>/file-viewer/`,这是 full 完整格式支持的必需项;标准包/preset 保持原有根目录行为 |
|
|
87
89
|
| `preset` | `'auto' | 'lite' | 'office' | 'engineering' | 'all'`;默认无显式格式时自动发现已安装 preset |
|
|
88
90
|
| `autoPresets` | `true` 或 preset 列表;常用于 `scan:true` 时继续自动激活已安装 preset |
|
|
89
91
|
| `formats` | 文件扩展名或格式 token,例如 `['pdf', 'docx', 'dwg']` |
|
|
@@ -96,6 +98,8 @@ const options = {
|
|
|
96
98
|
|
|
97
99
|
如果宿主项目按包名拆分 `node_modules`,`@codemirror/*`、`@lezer/*` 和 Sandpack 之间的循环依赖可能在生产构建中表现为 `codemirror-view.* Cannot access ... before initialization`。插件默认会包裹已有的 `manualChunks` 函数,只稳定这些已知互操作 chunk,保留其它自定义分组;确实需要完全接管时可设置 `stabilizeInteropChunks:false`。
|
|
98
100
|
|
|
101
|
+
`copyAssets.baseDir` 可以覆盖自动目录:必须是相对路径,不能包含 `..`;传空字符串表示显式复制到根目录。插件会为标准包、preset 和 full 包同步统一运行时资源根;full 包仍同时同步 `setDefaultFullAssetBaseUrl()`。只有设置 `inject:false` 且不手动导入虚拟模块时,业务才需要调用 `setDefaultFileViewerAssetBaseUrl()`(full 包同时调用 `setDefaultFullAssetBaseUrl()`)。Vite 配置了 `base:'/app/'` 时,full 包开发 URL 为 `/app/file-viewer/...`,构建文件仍位于 `outDir/file-viewer/`。
|
|
102
|
+
|
|
99
103
|
如果你需要严格控制 registry,可以关闭注入并手动传入:
|
|
100
104
|
|
|
101
105
|
```ts
|
|
@@ -145,7 +149,7 @@ export const fileViewerFormats = ['pdf', 'docx', 'xlsx']
|
|
|
145
149
|
|
|
146
150
|
## 当前边界
|
|
147
151
|
|
|
148
|
-
当前插件会为已经拆出的 renderer 包生成导入:Word、Spreadsheet、PDF、OFD、Presentation、CAD、Draw.io/Excalidraw/Mermaid/PlantUML、3D、Data、EDA、Typst、压缩包、邮件、EPUB、代码/Markdown/Patch/Git Bundle、图片、媒体、XMind 和 Geo。可以通过 `formats` 显式声明,也可以通过 `scan: true` 从源码 hint 自动发现;`.zipx`、`.cbz`、`.tiff`、`.mjs`、`.gv`、`.patch`、`.bundle`、`.mermaid`、`.puml`、`.mpeg` 等 core 支持的扩展也会映射到对应 renderer。开启 `copyAssets:true`
|
|
152
|
+
当前插件会为已经拆出的 renderer 包生成导入:Word、Spreadsheet、PDF、OFD、Presentation、CAD、Draw.io/Excalidraw/Mermaid/PlantUML、3D、Data、EDA、Typst、压缩包、邮件、EPUB、代码/Markdown/Patch/Git Bundle、图片、媒体、XMind 和 Geo。可以通过 `formats` 显式声明,也可以通过 `scan: true` 从源码 hint 自动发现;`.zipx`、`.cbz`、`.tiff`、`.mjs`、`.gv`、`.patch`、`.bundle`、`.mermaid`、`.puml`、`.mpeg` 等 core 支持的扩展也会映射到对应 renderer。开启 `copyAssets:true` 时会识别已安装能力;full 包把匹配资源复制到开发 `publicDir/file-viewer/` 与构建 `outDir/file-viewer/`,标准包/preset 维持根目录行为,包括 Typst compiler / renderer WASM 与默认字体目录。`preset: 'auto' | 'lite' | 'office' | 'engineering' | 'all'` 会导入对应 `@file-viewer/preset-*` 包;如果同时声明 `formats`,插件会在 preset 之外补充额外 renderer。
|
|
149
153
|
|
|
150
154
|
## 文档
|
|
151
155
|
|
package/dist/index.d.ts
CHANGED
|
@@ -31,6 +31,14 @@ export interface FileViewerCopyAssetsOptions {
|
|
|
31
31
|
* Directory used after production build. Defaults to build.outDir.
|
|
32
32
|
*/
|
|
33
33
|
outDir?: string;
|
|
34
|
+
/**
|
|
35
|
+
* Directory below publicDir/outDir where assets are published. When omitted,
|
|
36
|
+
* projects with an installed @file-viewer/*-full package use `file-viewer`;
|
|
37
|
+
* other projects keep the existing output-root layout. Use an empty string
|
|
38
|
+
* to explicitly publish at the output root. The injected runtime module
|
|
39
|
+
* keeps every renderer's default asset base aligned with this directory.
|
|
40
|
+
*/
|
|
41
|
+
baseDir?: string;
|
|
34
42
|
/**
|
|
35
43
|
* Copy during dev server startup, build closeBundle, or both.
|
|
36
44
|
*/
|
|
@@ -100,6 +108,26 @@ interface MissingRendererNotice {
|
|
|
100
108
|
}
|
|
101
109
|
export declare function extractFileViewerRendererHintTokens(source: string): string[];
|
|
102
110
|
export declare function collectFileViewerRendererScanTokens(projectRoot: string, scan: FileViewerRenderersPluginOptions['scan']): string[];
|
|
111
|
+
export interface FileViewerCopyAssetsTargetConfig {
|
|
112
|
+
/** Vite project root. Defaults to process.cwd(). */
|
|
113
|
+
projectRoot?: string;
|
|
114
|
+
/** Resolved Vite publicDir. Defaults to `public`. */
|
|
115
|
+
publicDir?: string;
|
|
116
|
+
/** Resolved Vite build.outDir. Defaults to `dist`. */
|
|
117
|
+
outDir?: string;
|
|
118
|
+
}
|
|
119
|
+
export interface FileViewerCopyAssetsTarget {
|
|
120
|
+
mode: 'dev' | 'build';
|
|
121
|
+
outputRoot: string;
|
|
122
|
+
targetRoot: string;
|
|
123
|
+
baseDir: string;
|
|
124
|
+
installedFullPackages: string[];
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Resolves the exact directory used by copyAssets without running a Vite build.
|
|
128
|
+
* This is exported so integrations can validate their deployment contract.
|
|
129
|
+
*/
|
|
130
|
+
export declare function resolveFileViewerCopyAssetsTarget(mode: 'dev' | 'build', value?: true | FileViewerCopyAssetsOptions, config?: FileViewerCopyAssetsTargetConfig): FileViewerCopyAssetsTarget;
|
|
103
131
|
export declare function fileViewerRenderers(options?: FileViewerRenderersPluginOptions): Plugin;
|
|
104
132
|
export declare function createFileViewerManualChunks(options?: FileViewerRenderersPluginOptions): (id: string) => string | undefined;
|
|
105
133
|
export declare function resolveFileViewerRendererSelection(options?: FileViewerRenderersPluginOptions, projectRoot?: string): {
|
package/dist/index.js
CHANGED
|
@@ -1,9 +1,19 @@
|
|
|
1
1
|
import { existsSync, readdirSync, readFileSync, statSync } from 'node:fs';
|
|
2
|
-
import { copyFile, cp, mkdir, readFile, rm, stat, writeFile } from 'node:fs/promises';
|
|
2
|
+
import { copyFile, cp, mkdir, readFile, realpath, rm, stat, writeFile } from 'node:fs/promises';
|
|
3
3
|
import { createRequire } from 'node:module';
|
|
4
|
-
import { dirname, extname, isAbsolute, join, resolve, sep } from 'node:path';
|
|
4
|
+
import { dirname, extname, isAbsolute, join, relative, resolve, sep } from 'node:path';
|
|
5
5
|
const virtualModuleId = 'virtual:file-viewer-renderers';
|
|
6
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
|
+
};
|
|
7
17
|
const pluginRequire = createRequire(import.meta.url);
|
|
8
18
|
let workspacePackageJsonCache = null;
|
|
9
19
|
const rendererModules = [
|
|
@@ -43,8 +53,17 @@ const rendererModules = [
|
|
|
43
53
|
id: 'presentation',
|
|
44
54
|
packageName: '@file-viewer/renderer-presentation',
|
|
45
55
|
exportName: 'presentationRenderer',
|
|
46
|
-
formats: [
|
|
47
|
-
|
|
56
|
+
formats: [
|
|
57
|
+
'presentation',
|
|
58
|
+
'ppt',
|
|
59
|
+
'pptx',
|
|
60
|
+
'pptm',
|
|
61
|
+
'potx',
|
|
62
|
+
'potm',
|
|
63
|
+
'ppsx',
|
|
64
|
+
'ppsm'
|
|
65
|
+
],
|
|
66
|
+
rendererIds: ['office-presentation-binary', 'office-presentation'],
|
|
48
67
|
chunkName: 'file-viewer-presentation'
|
|
49
68
|
},
|
|
50
69
|
{
|
|
@@ -384,27 +403,32 @@ const presetModules = {
|
|
|
384
403
|
chunkName: 'file-viewer-preset-engineering'
|
|
385
404
|
}
|
|
386
405
|
};
|
|
406
|
+
const fileViewerFullPackages = [
|
|
407
|
+
'@file-viewer/react-full',
|
|
408
|
+
'@file-viewer/react-legacy-full',
|
|
409
|
+
'@file-viewer/vue3-full',
|
|
410
|
+
'@file-viewer/vue2.7-full',
|
|
411
|
+
'@file-viewer/vue2.6-full',
|
|
412
|
+
'@file-viewer/web-full',
|
|
413
|
+
'@file-viewer/jquery-full',
|
|
414
|
+
'@file-viewer/svelte-full'
|
|
415
|
+
];
|
|
387
416
|
// Vite dep optimization rewrites import.meta.url into node_modules/.vite/deps
|
|
388
417
|
// and can trigger full-preset dev-server re-optimization reloads. Keep File
|
|
389
418
|
// Viewer packages out of dep optimization while still optimizing their
|
|
390
419
|
// CommonJS/UMD helper dependencies below.
|
|
391
420
|
const fileViewerOptimizationExcludedPackages = [
|
|
392
421
|
'@file-viewer/core',
|
|
422
|
+
'@file-viewer/ppt',
|
|
393
423
|
'@file-viewer/pptx',
|
|
394
424
|
...rendererModules.map((descriptor) => descriptor.packageName),
|
|
395
425
|
...Object.values(presetModules).map((preset) => preset.packageName),
|
|
396
|
-
|
|
397
|
-
'@file-viewer/react-legacy-full',
|
|
398
|
-
'@file-viewer/vue3-full',
|
|
399
|
-
'@file-viewer/vue2.7-full',
|
|
400
|
-
'@file-viewer/vue2.6-full',
|
|
401
|
-
'@file-viewer/web-full',
|
|
402
|
-
'@file-viewer/jquery-full',
|
|
403
|
-
'@file-viewer/svelte-full'
|
|
426
|
+
...fileViewerFullPackages
|
|
404
427
|
];
|
|
405
428
|
const cjsInteropPackages = [
|
|
406
429
|
'@file-viewer/docx',
|
|
407
430
|
'@xmldom/xmldom',
|
|
431
|
+
'occt-import-js',
|
|
408
432
|
'jszip'
|
|
409
433
|
];
|
|
410
434
|
const defaultScanRoots = ['src', 'app', 'pages', 'components'];
|
|
@@ -453,6 +477,7 @@ const mimeFormatHints = {
|
|
|
453
477
|
'application/vnd.rar': ['rar'],
|
|
454
478
|
'text/markdown': ['md'],
|
|
455
479
|
'text/csv': ['csv'],
|
|
480
|
+
'text/tab-separated-values': ['tsv'],
|
|
456
481
|
'text/html': ['html'],
|
|
457
482
|
'text/css': ['css'],
|
|
458
483
|
'text/plain': ['txt'],
|
|
@@ -632,7 +657,7 @@ function expandDescriptorRendererIds(ids) {
|
|
|
632
657
|
return descriptor ? [...descriptor.rendererIds] : [id];
|
|
633
658
|
}));
|
|
634
659
|
}
|
|
635
|
-
function renderVirtualModule(selection, formats, autoPresetIds = []) {
|
|
660
|
+
function renderVirtualModule(selection, formats, autoPresetIds = [], runtimeAssetBase = null, configureFullAssetBase = false) {
|
|
636
661
|
const presetModule = selection.preset ? presetModules[selection.preset] : null;
|
|
637
662
|
const autoPresetModules = autoPresetIds
|
|
638
663
|
.filter((id) => id !== selection.preset)
|
|
@@ -672,15 +697,52 @@ function renderVirtualModule(selection, formats, autoPresetIds = []) {
|
|
|
672
697
|
: !selection.preset && autoPresetModules.length === 1
|
|
673
698
|
? autoPresetModules[0].id
|
|
674
699
|
: '@file-viewer/vite-plugin:configured';
|
|
700
|
+
const runtimeAssetBaseImport = runtimeAssetBase
|
|
701
|
+
? runtimeAssetBase.kind === 'deployment'
|
|
702
|
+
? `import { resolveFileViewerRuntimeAssetBaseUrl, setDefaultFileViewerAssetBaseUrl } from '@file-viewer/core/assets';`
|
|
703
|
+
: `import { setDefaultFileViewerAssetBaseUrl } from '@file-viewer/core/assets';`
|
|
704
|
+
: null;
|
|
705
|
+
const fullAssetBaseImport = runtimeAssetBase && configureFullAssetBase
|
|
706
|
+
? `import { setDefaultFullAssetBaseUrl } from '@file-viewer/preset-all';`
|
|
707
|
+
: null;
|
|
708
|
+
const autoRegistrationImport = rendererNames.length
|
|
709
|
+
? `import { registerFileViewerAutoRendererPreset } from '@file-viewer/core';`
|
|
710
|
+
: null;
|
|
711
|
+
const runtimeAssetBaseSetup = !runtimeAssetBase
|
|
712
|
+
? []
|
|
713
|
+
: runtimeAssetBase.kind === 'literal'
|
|
714
|
+
? [
|
|
715
|
+
`setDefaultFileViewerAssetBaseUrl(${JSON.stringify(runtimeAssetBase.url)});`,
|
|
716
|
+
...(configureFullAssetBase
|
|
717
|
+
? [`setDefaultFullAssetBaseUrl(${JSON.stringify(runtimeAssetBase.url)});`]
|
|
718
|
+
: []),
|
|
719
|
+
''
|
|
720
|
+
]
|
|
721
|
+
: [
|
|
722
|
+
"const fileViewerDeploymentBaseUrl = typeof document === 'undefined'",
|
|
723
|
+
" ? '/'",
|
|
724
|
+
' : resolveFileViewerRuntimeAssetBaseUrl(document);',
|
|
725
|
+
"const fileViewerRuntimeAssetBaseUrl = typeof document === 'undefined'",
|
|
726
|
+
` ? '/' + ${JSON.stringify(runtimeAssetBase.encodedBaseDir)}`,
|
|
727
|
+
` : new URL(${JSON.stringify(runtimeAssetBase.encodedBaseDir)}, fileViewerDeploymentBaseUrl.endsWith('/') ? fileViewerDeploymentBaseUrl : fileViewerDeploymentBaseUrl + '/').href;`,
|
|
728
|
+
'setDefaultFileViewerAssetBaseUrl(fileViewerRuntimeAssetBaseUrl);',
|
|
729
|
+
...(configureFullAssetBase
|
|
730
|
+
? ['setDefaultFullAssetBaseUrl(fileViewerRuntimeAssetBaseUrl);']
|
|
731
|
+
: []),
|
|
732
|
+
''
|
|
733
|
+
];
|
|
675
734
|
return [
|
|
676
|
-
|
|
735
|
+
...[autoRegistrationImport, runtimeAssetBaseImport, fullAssetBaseImport].filter(Boolean),
|
|
677
736
|
...[presetImport].filter(Boolean),
|
|
678
737
|
...autoPresetImports,
|
|
679
738
|
...rendererImports,
|
|
680
739
|
'',
|
|
740
|
+
...runtimeAssetBaseSetup,
|
|
681
741
|
`export const configuredFileViewerRenderers = [${rendererNames.join(', ')}];`,
|
|
682
742
|
`export const fileViewerRendererPlan = ${JSON.stringify(plan, null, 2)};`,
|
|
683
|
-
|
|
743
|
+
...(rendererNames.length
|
|
744
|
+
? [`registerFileViewerAutoRendererPreset(configuredFileViewerRenderers, { id: ${JSON.stringify(autoRegistrationId)} });`]
|
|
745
|
+
: []),
|
|
684
746
|
'export default configuredFileViewerRenderers;',
|
|
685
747
|
''
|
|
686
748
|
].join('\n');
|
|
@@ -954,16 +1016,19 @@ function readPackageVersion(packageRoot) {
|
|
|
954
1016
|
return null;
|
|
955
1017
|
}
|
|
956
1018
|
}
|
|
957
|
-
function assertOwnedPackageVersion(packageName, packageRoot, ownerPackageName) {
|
|
1019
|
+
function assertOwnedPackageVersion(packageName, packageRoot, ownerPackageName, anchorPackages = []) {
|
|
958
1020
|
if (!packageRoot) {
|
|
959
1021
|
return null;
|
|
960
1022
|
}
|
|
961
|
-
const ownerPackageJsonPath = resolvePackageJson(ownerPackageName);
|
|
1023
|
+
const ownerPackageJsonPath = resolvePackageJson(ownerPackageName, anchorPackages);
|
|
962
1024
|
if (!ownerPackageJsonPath) {
|
|
963
1025
|
return readPackageVersion(packageRoot);
|
|
964
1026
|
}
|
|
965
1027
|
const ownerPackageJson = JSON.parse(readFileSync(ownerPackageJsonPath, 'utf8'));
|
|
966
|
-
const
|
|
1028
|
+
const configuredVersion = ownerPackageJson.dependencies?.[packageName];
|
|
1029
|
+
const expectedVersion = configuredVersion?.startsWith('workspace:')
|
|
1030
|
+
? configuredVersion.slice('workspace:'.length)
|
|
1031
|
+
: configuredVersion;
|
|
967
1032
|
const actualVersion = readPackageVersion(packageRoot);
|
|
968
1033
|
if (expectedVersion &&
|
|
969
1034
|
/^\d+\.\d+\.\d+(?:[-+][0-9A-Za-z.-]+)?$/.test(expectedVersion) &&
|
|
@@ -1167,11 +1232,65 @@ async function copyKnownRendererAssets(targetRoot, rendererIds) {
|
|
|
1167
1232
|
await push('pdf', 'pdf-cjk-font-fallback', join(targetRoot, 'vendor/pdf/fonts'), () => copyPdfCjkFontAssets(pdfCjkFontRoot, join(targetRoot, 'vendor/pdf/fonts')));
|
|
1168
1233
|
const pptxRoot = resolvePackageRoot('@file-viewer/pptx', ['@file-viewer/renderer-presentation']);
|
|
1169
1234
|
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')));
|
|
1235
|
+
const pptRoot = resolvePackageRoot('@file-viewer/ppt', ['@file-viewer/renderer-presentation']);
|
|
1236
|
+
const pptVersion = readPackageVersion(pptRoot);
|
|
1237
|
+
const pptSource = pptRoot
|
|
1238
|
+
? { sourcePackage: '@file-viewer/ppt', sourceVersion: pptVersion || undefined }
|
|
1239
|
+
: undefined;
|
|
1240
|
+
for (const [id, filename] of [
|
|
1241
|
+
['ppt-module', 'index.mjs'],
|
|
1242
|
+
['ppt-worker', 'worker.mjs'],
|
|
1243
|
+
['ppt-frame-cache', 'frame-cache.mjs'],
|
|
1244
|
+
['ppt-wasm', 'ppt-native.wasm'],
|
|
1245
|
+
['ppt-cjk-font', 'ppt-font-cjk.otf'],
|
|
1246
|
+
['ppt-manifest', 'manifest.json'],
|
|
1247
|
+
['ppt-package', 'package.json'],
|
|
1248
|
+
['ppt-license', 'LICENSE'],
|
|
1249
|
+
['ppt-notice', 'NOTICE']
|
|
1250
|
+
]) {
|
|
1251
|
+
await push('office-presentation-binary', id, join(targetRoot, `vendor/ppt/${filename}`), () => copyFileIfPresent(pptRoot ? join(pptRoot, filename) : null, join(targetRoot, `vendor/ppt/${filename}`)), undefined, pptSource);
|
|
1252
|
+
}
|
|
1170
1253
|
const docxRoot = resolvePackageRoot('@file-viewer/docx', ['@file-viewer/renderer-word']);
|
|
1171
1254
|
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')));
|
|
1172
1255
|
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')));
|
|
1256
|
+
const spreadsheetRoot = resolvePackageRoot('@file-viewer/renderer-spreadsheet', [
|
|
1257
|
+
'@file-viewer/renderer-spreadsheet',
|
|
1258
|
+
'@file-viewer/preset-office',
|
|
1259
|
+
'@file-viewer/preset-all'
|
|
1260
|
+
]);
|
|
1261
|
+
const spreadsheetVersion = readPackageVersion(spreadsheetRoot);
|
|
1262
|
+
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
|
|
1263
|
+
? {
|
|
1264
|
+
sourcePackage: '@file-viewer/renderer-spreadsheet',
|
|
1265
|
+
sourceVersion: spreadsheetVersion || undefined
|
|
1266
|
+
}
|
|
1267
|
+
: undefined);
|
|
1173
1268
|
const cadRoot = resolvePackageRoot('@flyfish-dev/cad-viewer', ['@file-viewer/renderer-cad']);
|
|
1174
1269
|
await push('cad', 'cad-wasm-directory', join(targetRoot, 'wasm/cad'), () => copyDirectoryIfPresent(cadRoot ? join(cadRoot, 'dist/wasm') : null, join(targetRoot, 'wasm/cad')));
|
|
1270
|
+
const modelDependencyAnchors = [
|
|
1271
|
+
'@file-viewer/renderer-3d',
|
|
1272
|
+
'@file-viewer/geometry-engine'
|
|
1273
|
+
];
|
|
1274
|
+
const occtRoot = resolvePackageRoot('occt-import-js', modelDependencyAnchors);
|
|
1275
|
+
const geometryEngineRoot = resolvePackageRoot('@file-viewer/geometry-engine', [
|
|
1276
|
+
'@file-viewer/renderer-3d'
|
|
1277
|
+
]);
|
|
1278
|
+
const occtVersion = assertOwnedPackageVersion('occt-import-js', occtRoot, '@file-viewer/geometry-engine', modelDependencyAnchors);
|
|
1279
|
+
const occtSource = occtRoot
|
|
1280
|
+
? { sourcePackage: 'occt-import-js', sourceVersion: occtVersion || undefined }
|
|
1281
|
+
: undefined;
|
|
1282
|
+
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')));
|
|
1283
|
+
for (const [id, filename] of [
|
|
1284
|
+
['model-occt-runtime', 'occt-import-js.js'],
|
|
1285
|
+
['model-occt-wasm', 'occt-import-js.wasm'],
|
|
1286
|
+
['model-occt-license', 'license.occt.txt'],
|
|
1287
|
+
['model-occt-import-license', 'license.occt-import-js.txt']
|
|
1288
|
+
]) {
|
|
1289
|
+
const targetFilename = filename.startsWith('license.')
|
|
1290
|
+
? filename.replace(/^license\./, 'LICENSE.')
|
|
1291
|
+
: filename;
|
|
1292
|
+
await push('model', id, join(targetRoot, `wasm/model/${targetFilename}`), () => copyFileIfPresent(occtRoot ? join(occtRoot, `dist/${filename}`) : null, join(targetRoot, `wasm/model/${targetFilename}`)), undefined, occtSource);
|
|
1293
|
+
}
|
|
1175
1294
|
const typstCompilerRoot = resolvePackageRoot('@myriaddreamin/typst-ts-web-compiler', [
|
|
1176
1295
|
'@file-viewer/renderer-typst'
|
|
1177
1296
|
]);
|
|
@@ -1199,14 +1318,343 @@ async function copyKnownRendererAssets(targetRoot, rendererIds) {
|
|
|
1199
1318
|
}, null, 2)}\n`);
|
|
1200
1319
|
return results;
|
|
1201
1320
|
}
|
|
1202
|
-
function
|
|
1203
|
-
|
|
1204
|
-
|
|
1321
|
+
function matchesBundledAssetKind(kind, info) {
|
|
1322
|
+
return kind === 'directory' || kind === 'wasm-directory'
|
|
1323
|
+
? info.isDirectory()
|
|
1324
|
+
: info.isFile();
|
|
1325
|
+
}
|
|
1326
|
+
function isBundledFullAssetPayload(payloadRoot) {
|
|
1327
|
+
return Boolean(payloadRoot &&
|
|
1328
|
+
existsSync(payloadRoot) &&
|
|
1329
|
+
statSync(payloadRoot).isDirectory() &&
|
|
1330
|
+
existsSync(join(payloadRoot, 'flyfish-viewer-assets.json')));
|
|
1331
|
+
}
|
|
1332
|
+
function resolveBundledFullAssetSource(installedFullPackages) {
|
|
1333
|
+
const copyAssetsPackageRoot = resolvePackageRoot('file-viewer-copy-assets', installedFullPackages);
|
|
1334
|
+
const copyAssetsPayloadRoot = copyAssetsPackageRoot
|
|
1335
|
+
? join(copyAssetsPackageRoot, 'viewer')
|
|
1336
|
+
: null;
|
|
1337
|
+
if (copyAssetsPackageRoot && copyAssetsPayloadRoot && isBundledFullAssetPayload(copyAssetsPayloadRoot)) {
|
|
1338
|
+
installedFullPackages.forEach((ownerPackageName) => {
|
|
1339
|
+
assertOwnedPackageVersion('file-viewer-copy-assets', copyAssetsPackageRoot, ownerPackageName);
|
|
1340
|
+
});
|
|
1341
|
+
const sourceVersion = readPackageVersion(copyAssetsPackageRoot);
|
|
1342
|
+
if (sourceVersion) {
|
|
1343
|
+
return {
|
|
1344
|
+
packageName: 'file-viewer-copy-assets',
|
|
1345
|
+
packageRoot: copyAssetsPackageRoot,
|
|
1346
|
+
payloadRoot: copyAssetsPayloadRoot,
|
|
1347
|
+
sourceVersion
|
|
1348
|
+
};
|
|
1349
|
+
}
|
|
1350
|
+
}
|
|
1351
|
+
if (installedFullPackages.includes('@file-viewer/web-full')) {
|
|
1352
|
+
const webFullPackageRoot = resolvePackageRoot('@file-viewer/web-full', installedFullPackages);
|
|
1353
|
+
const webFullPayloadRoot = webFullPackageRoot
|
|
1354
|
+
? join(webFullPackageRoot, 'dist')
|
|
1355
|
+
: null;
|
|
1356
|
+
const sourceVersion = readPackageVersion(webFullPackageRoot);
|
|
1357
|
+
if (webFullPackageRoot &&
|
|
1358
|
+
webFullPayloadRoot &&
|
|
1359
|
+
sourceVersion &&
|
|
1360
|
+
isBundledFullAssetPayload(webFullPayloadRoot)) {
|
|
1361
|
+
return {
|
|
1362
|
+
packageName: '@file-viewer/web-full',
|
|
1363
|
+
packageRoot: webFullPackageRoot,
|
|
1364
|
+
payloadRoot: webFullPayloadRoot,
|
|
1365
|
+
sourceVersion
|
|
1366
|
+
};
|
|
1367
|
+
}
|
|
1368
|
+
}
|
|
1369
|
+
// Source workspaces may not have staged file-viewer-copy-assets/viewer yet.
|
|
1370
|
+
// @file-viewer/web keeps the same tracked payload for local development.
|
|
1371
|
+
const webPackageRoot = resolvePackageRoot('@file-viewer/web', installedFullPackages);
|
|
1372
|
+
const webPayloadRoot = webPackageRoot ? join(webPackageRoot, 'viewer') : null;
|
|
1373
|
+
const sourceVersion = readPackageVersion(webPackageRoot);
|
|
1374
|
+
if (webPackageRoot &&
|
|
1375
|
+
webPayloadRoot &&
|
|
1376
|
+
sourceVersion &&
|
|
1377
|
+
isBundledFullAssetPayload(webPayloadRoot)) {
|
|
1378
|
+
return {
|
|
1379
|
+
packageName: '@file-viewer/web',
|
|
1380
|
+
packageRoot: webPackageRoot,
|
|
1381
|
+
payloadRoot: webPayloadRoot,
|
|
1382
|
+
sourceVersion
|
|
1383
|
+
};
|
|
1384
|
+
}
|
|
1385
|
+
return null;
|
|
1386
|
+
}
|
|
1387
|
+
function assertBundledFullAssetSourceVersion(source, installedFullPackages) {
|
|
1388
|
+
const payloadManifestPath = join(source.payloadRoot, 'flyfish-viewer-manifest.json');
|
|
1389
|
+
if (!existsSync(payloadManifestPath)) {
|
|
1390
|
+
throw new Error(`[file-viewer:vite-plugin] Missing version manifest in ${source.packageName} payload: ${payloadManifestPath}.`);
|
|
1391
|
+
}
|
|
1392
|
+
const payloadManifest = JSON.parse(readFileSync(payloadManifestPath, 'utf8'));
|
|
1393
|
+
if (!payloadManifest.version || payloadManifest.version !== source.sourceVersion) {
|
|
1394
|
+
throw new Error(`[file-viewer:vite-plugin] ${source.packageName}@${source.sourceVersion} contains ` +
|
|
1395
|
+
`viewer assets for ${payloadManifest.version || 'an unknown version'}.`);
|
|
1396
|
+
}
|
|
1397
|
+
installedFullPackages.forEach((packageName) => {
|
|
1398
|
+
const packageRoot = resolvePackageRoot(packageName, installedFullPackages);
|
|
1399
|
+
const packageVersion = readPackageVersion(packageRoot);
|
|
1400
|
+
if (packageVersion && packageVersion !== payloadManifest.version) {
|
|
1401
|
+
throw new Error(`[file-viewer:vite-plugin] ${packageName}@${packageVersion} cannot use ` +
|
|
1402
|
+
`${source.packageName} viewer assets at ${payloadManifest.version}.`);
|
|
1403
|
+
}
|
|
1404
|
+
});
|
|
1405
|
+
}
|
|
1406
|
+
async function copyBundledFullRendererAssets(targetRoot, rendererIds, installedFullPackages) {
|
|
1407
|
+
const source = resolveBundledFullAssetSource(installedFullPackages);
|
|
1408
|
+
if (!source) {
|
|
1409
|
+
return null;
|
|
1410
|
+
}
|
|
1411
|
+
assertBundledFullAssetSourceVersion(source, installedFullPackages);
|
|
1412
|
+
const sourceManifestPath = join(source.payloadRoot, 'flyfish-viewer-assets.json');
|
|
1413
|
+
const manifest = JSON.parse(readFileSync(sourceManifestPath, 'utf8'));
|
|
1414
|
+
if (manifest.schemaVersion !== 1 || !Array.isArray(manifest.rendererAssetManifests)) {
|
|
1415
|
+
throw new Error(`[file-viewer:vite-plugin] Unsupported full asset manifest in ${sourceManifestPath}.`);
|
|
1416
|
+
}
|
|
1417
|
+
await mkdir(targetRoot, { recursive: true });
|
|
1418
|
+
await cp(source.payloadRoot, targetRoot, { recursive: true, force: true });
|
|
1419
|
+
const results = [];
|
|
1420
|
+
for (const asset of manifest.rendererAssetManifests.flatMap((rendererManifest) => rendererManifest.assets)) {
|
|
1421
|
+
if (asset.target !== 'public' || !asset.defaultPath) {
|
|
1422
|
+
continue;
|
|
1423
|
+
}
|
|
1424
|
+
const relativePath = asset.defaultPath.replace(/\\/g, '/').replace(/^\/+/, '');
|
|
1425
|
+
const destination = resolve(targetRoot, ...relativePath.split('/'));
|
|
1426
|
+
let copied = false;
|
|
1427
|
+
let reason;
|
|
1428
|
+
if (!isPathWithin(targetRoot, destination)) {
|
|
1429
|
+
reason = 'asset manifest path escapes the copy target';
|
|
1430
|
+
}
|
|
1431
|
+
else {
|
|
1432
|
+
try {
|
|
1433
|
+
copied = matchesBundledAssetKind(asset.kind, await stat(destination));
|
|
1434
|
+
if (!copied) {
|
|
1435
|
+
reason = `copied path does not match asset kind ${asset.kind}`;
|
|
1436
|
+
}
|
|
1437
|
+
}
|
|
1438
|
+
catch {
|
|
1439
|
+
reason = 'bundled full asset not found after copy';
|
|
1440
|
+
}
|
|
1441
|
+
}
|
|
1442
|
+
results.push({
|
|
1443
|
+
rendererId: asset.rendererId,
|
|
1444
|
+
id: asset.id,
|
|
1445
|
+
to: destination,
|
|
1446
|
+
copied,
|
|
1447
|
+
required: asset.required,
|
|
1448
|
+
reason,
|
|
1449
|
+
sourcePackage: source.packageName,
|
|
1450
|
+
sourceVersion: source.sourceVersion
|
|
1451
|
+
});
|
|
1452
|
+
}
|
|
1453
|
+
await writeFile(join(targetRoot, 'flyfish-viewer-assets.json'), `${JSON.stringify({
|
|
1454
|
+
...manifest,
|
|
1455
|
+
generatedBy: '@file-viewer/vite-plugin',
|
|
1456
|
+
copiedAt: new Date().toISOString(),
|
|
1457
|
+
rendererIds,
|
|
1458
|
+
assets: results
|
|
1459
|
+
}, null, 2)}\n`);
|
|
1460
|
+
return results;
|
|
1461
|
+
}
|
|
1462
|
+
async function copyRendererAssets(target, rendererIds) {
|
|
1463
|
+
if (target.installedFullPackages.length) {
|
|
1464
|
+
const bundledResults = await copyBundledFullRendererAssets(target.targetRoot, rendererIds, target.installedFullPackages);
|
|
1465
|
+
if (bundledResults) {
|
|
1466
|
+
return bundledResults;
|
|
1467
|
+
}
|
|
1468
|
+
}
|
|
1469
|
+
const results = await copyKnownRendererAssets(target.targetRoot, rendererIds);
|
|
1470
|
+
if (target.installedFullPackages.length) {
|
|
1471
|
+
results.push({
|
|
1472
|
+
rendererId: 'full',
|
|
1473
|
+
id: 'full-asset-payload',
|
|
1474
|
+
to: target.targetRoot,
|
|
1475
|
+
copied: false,
|
|
1476
|
+
required: true,
|
|
1477
|
+
reason: 'no version-matched full viewer payload was found in file-viewer-copy-assets, @file-viewer/web-full, or @file-viewer/web'
|
|
1478
|
+
});
|
|
1479
|
+
}
|
|
1480
|
+
return results;
|
|
1205
1481
|
}
|
|
1206
1482
|
function copyOptions(value) {
|
|
1207
1483
|
return typeof value === 'object' ? value : {};
|
|
1208
1484
|
}
|
|
1209
|
-
function
|
|
1485
|
+
function findNearestProjectPackageJson(projectRoot) {
|
|
1486
|
+
let current = resolve(projectRoot);
|
|
1487
|
+
while (true) {
|
|
1488
|
+
const packageJsonPath = join(current, 'package.json');
|
|
1489
|
+
if (existsSync(packageJsonPath) && statSyncSafe(packageJsonPath)?.isFile()) {
|
|
1490
|
+
return packageJsonPath;
|
|
1491
|
+
}
|
|
1492
|
+
const parent = dirname(current);
|
|
1493
|
+
if (parent === current) {
|
|
1494
|
+
return null;
|
|
1495
|
+
}
|
|
1496
|
+
current = parent;
|
|
1497
|
+
}
|
|
1498
|
+
}
|
|
1499
|
+
function resolveInstalledFullPackages(projectRoot) {
|
|
1500
|
+
const packageJsonPath = findNearestProjectPackageJson(projectRoot);
|
|
1501
|
+
if (!packageJsonPath) {
|
|
1502
|
+
return [];
|
|
1503
|
+
}
|
|
1504
|
+
try {
|
|
1505
|
+
const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf8'));
|
|
1506
|
+
const declaredPackages = new Set([
|
|
1507
|
+
...Object.keys(packageJson.dependencies || {}),
|
|
1508
|
+
...Object.keys(packageJson.devDependencies || {}),
|
|
1509
|
+
...Object.keys(packageJson.optionalDependencies || {}),
|
|
1510
|
+
...Object.keys(packageJson.peerDependencies || {})
|
|
1511
|
+
]);
|
|
1512
|
+
const projectPackageRequire = createRequire(packageJsonPath);
|
|
1513
|
+
return fileViewerFullPackages.filter((packageName) => declaredPackages.has(packageName) &&
|
|
1514
|
+
Boolean(tryResolvePackageJson(packageName, projectPackageRequire)));
|
|
1515
|
+
}
|
|
1516
|
+
catch {
|
|
1517
|
+
return [];
|
|
1518
|
+
}
|
|
1519
|
+
}
|
|
1520
|
+
function normalizeCopyAssetsBaseDir(value) {
|
|
1521
|
+
const normalized = value.trim().replace(/\\/g, '/');
|
|
1522
|
+
if (!normalized) {
|
|
1523
|
+
return '';
|
|
1524
|
+
}
|
|
1525
|
+
if (normalized.startsWith('/') ||
|
|
1526
|
+
isAbsolute(value) ||
|
|
1527
|
+
/^[A-Za-z]:\//.test(normalized) ||
|
|
1528
|
+
normalized.includes('\0')) {
|
|
1529
|
+
throw new Error(`[file-viewer:vite-plugin] copyAssets.baseDir must be a relative directory, received ${JSON.stringify(value)}.`);
|
|
1530
|
+
}
|
|
1531
|
+
const segments = normalized.split('/').filter(Boolean);
|
|
1532
|
+
const decodedSegments = [];
|
|
1533
|
+
for (const segment of segments) {
|
|
1534
|
+
let decodedSegment = segment;
|
|
1535
|
+
try {
|
|
1536
|
+
decodedSegment = decodeURIComponent(segment);
|
|
1537
|
+
}
|
|
1538
|
+
catch {
|
|
1539
|
+
throw new Error(`[file-viewer:vite-plugin] copyAssets.baseDir contains invalid URL encoding: ${JSON.stringify(value)}.`);
|
|
1540
|
+
}
|
|
1541
|
+
if (decodedSegment === '.' ||
|
|
1542
|
+
decodedSegment === '..' ||
|
|
1543
|
+
decodedSegment.includes('/') ||
|
|
1544
|
+
decodedSegment.includes('\\') ||
|
|
1545
|
+
decodedSegment.includes('\0')) {
|
|
1546
|
+
throw new Error(`[file-viewer:vite-plugin] copyAssets.baseDir cannot escape its output directory: ${JSON.stringify(value)}.`);
|
|
1547
|
+
}
|
|
1548
|
+
decodedSegments.push(decodedSegment);
|
|
1549
|
+
}
|
|
1550
|
+
return decodedSegments.join('/');
|
|
1551
|
+
}
|
|
1552
|
+
function isPathWithin(parent, candidate) {
|
|
1553
|
+
const relativePath = relative(parent, candidate);
|
|
1554
|
+
return relativePath === '' || (relativePath !== '..' &&
|
|
1555
|
+
!relativePath.startsWith(`..${sep}`) &&
|
|
1556
|
+
!isAbsolute(relativePath));
|
|
1557
|
+
}
|
|
1558
|
+
function resolveOutputRoot(value, fallback, projectRoot) {
|
|
1559
|
+
const output = value || fallback;
|
|
1560
|
+
return isAbsolute(output) ? resolve(output) : resolve(projectRoot, output);
|
|
1561
|
+
}
|
|
1562
|
+
/**
|
|
1563
|
+
* Resolves the exact directory used by copyAssets without running a Vite build.
|
|
1564
|
+
* This is exported so integrations can validate their deployment contract.
|
|
1565
|
+
*/
|
|
1566
|
+
export function resolveFileViewerCopyAssetsTarget(mode, value = true, config = {}) {
|
|
1567
|
+
const projectRoot = resolve(config.projectRoot || process.cwd());
|
|
1568
|
+
const options = copyOptions(value);
|
|
1569
|
+
const installedFullPackages = resolveInstalledFullPackages(projectRoot);
|
|
1570
|
+
const baseDir = normalizeCopyAssetsBaseDir(typeof options.baseDir === 'string'
|
|
1571
|
+
? options.baseDir
|
|
1572
|
+
: installedFullPackages.length
|
|
1573
|
+
? 'file-viewer'
|
|
1574
|
+
: '');
|
|
1575
|
+
const outputRoot = resolveOutputRoot(mode === 'dev' ? options.publicDir : options.outDir, mode === 'dev' ? config.publicDir || 'public' : config.outDir || 'dist', projectRoot);
|
|
1576
|
+
const targetRoot = baseDir
|
|
1577
|
+
? resolve(outputRoot, ...baseDir.split('/'))
|
|
1578
|
+
: outputRoot;
|
|
1579
|
+
if (!isPathWithin(outputRoot, targetRoot)) {
|
|
1580
|
+
throw new Error(`[file-viewer:vite-plugin] Refusing to copy assets outside ${outputRoot}: ${targetRoot}.`);
|
|
1581
|
+
}
|
|
1582
|
+
return {
|
|
1583
|
+
mode,
|
|
1584
|
+
outputRoot,
|
|
1585
|
+
targetRoot,
|
|
1586
|
+
baseDir,
|
|
1587
|
+
installedFullPackages: [...installedFullPackages]
|
|
1588
|
+
};
|
|
1589
|
+
}
|
|
1590
|
+
function normalizeViteDevBasePath(base) {
|
|
1591
|
+
let pathname = base;
|
|
1592
|
+
if (/^[A-Za-z][A-Za-z\d+.-]*:\/\//.test(base)) {
|
|
1593
|
+
try {
|
|
1594
|
+
pathname = new URL(base).pathname;
|
|
1595
|
+
}
|
|
1596
|
+
catch {
|
|
1597
|
+
return '/';
|
|
1598
|
+
}
|
|
1599
|
+
}
|
|
1600
|
+
if (!pathname.startsWith('/')) {
|
|
1601
|
+
return '/';
|
|
1602
|
+
}
|
|
1603
|
+
return pathname.endsWith('/') ? pathname : `${pathname}/`;
|
|
1604
|
+
}
|
|
1605
|
+
function resolveViteFullAssetBase(base, baseDir) {
|
|
1606
|
+
const encodedBaseDir = baseDir
|
|
1607
|
+
.split('/')
|
|
1608
|
+
.filter(Boolean)
|
|
1609
|
+
.map((segment) => encodeURIComponent(segment))
|
|
1610
|
+
.join('/');
|
|
1611
|
+
const encodedBaseDirWithSlash = encodedBaseDir ? `${encodedBaseDir}/` : '';
|
|
1612
|
+
const resolvedBase = base === undefined ? '/' : base.trim();
|
|
1613
|
+
const isAbsoluteBase = resolvedBase.startsWith('/') || /^[A-Za-z][A-Za-z\d+.-]*:\/\//.test(resolvedBase);
|
|
1614
|
+
if (!isAbsoluteBase) {
|
|
1615
|
+
return { kind: 'deployment', encodedBaseDir: encodedBaseDirWithSlash };
|
|
1616
|
+
}
|
|
1617
|
+
const normalizedBase = resolvedBase.endsWith('/') ? resolvedBase : `${resolvedBase}/`;
|
|
1618
|
+
return { kind: 'literal', url: `${normalizedBase}${encodedBaseDirWithSlash}` };
|
|
1619
|
+
}
|
|
1620
|
+
function resolveDevAssetRequestPath(targetRoot, baseDir, requestPathname, viteBasePath) {
|
|
1621
|
+
let requestRelativePath;
|
|
1622
|
+
try {
|
|
1623
|
+
// Depending on the Vite major and middleware ordering, configureServer can
|
|
1624
|
+
// observe either the original base-prefixed URL or the pathname after
|
|
1625
|
+
// Vite's base middleware has stripped it. Accept both shapes, then keep the
|
|
1626
|
+
// strict viewer-asset allowlist and target-root boundary checks below.
|
|
1627
|
+
const encodedRelativePath = viteBasePath === '/' || requestPathname.startsWith(viteBasePath)
|
|
1628
|
+
? requestPathname.slice(viteBasePath === '/' ? 1 : viteBasePath.length)
|
|
1629
|
+
: requestPathname.replace(/^\/+/, '');
|
|
1630
|
+
requestRelativePath = decodeURIComponent(encodedRelativePath);
|
|
1631
|
+
}
|
|
1632
|
+
catch {
|
|
1633
|
+
return null;
|
|
1634
|
+
}
|
|
1635
|
+
requestRelativePath = requestRelativePath.replace(/\\/g, '/');
|
|
1636
|
+
if (requestRelativePath.includes('\0')) {
|
|
1637
|
+
return null;
|
|
1638
|
+
}
|
|
1639
|
+
const basePrefix = baseDir ? `${baseDir}/` : '';
|
|
1640
|
+
if (basePrefix && !requestRelativePath.startsWith(basePrefix)) {
|
|
1641
|
+
return null;
|
|
1642
|
+
}
|
|
1643
|
+
const assetRelativePath = requestRelativePath.slice(basePrefix.length);
|
|
1644
|
+
const isViewerManifest = assetRelativePath === 'flyfish-viewer-assets.json' ||
|
|
1645
|
+
assetRelativePath === 'flyfish-viewer-manifest.json';
|
|
1646
|
+
if (!isViewerManifest &&
|
|
1647
|
+
!assetRelativePath.startsWith('vendor/') &&
|
|
1648
|
+
!assetRelativePath.startsWith('wasm/')) {
|
|
1649
|
+
return null;
|
|
1650
|
+
}
|
|
1651
|
+
const assetPath = resolve(targetRoot, ...assetRelativePath.split('/'));
|
|
1652
|
+
return isPathWithin(targetRoot, assetPath) ? assetPath : null;
|
|
1653
|
+
}
|
|
1654
|
+
function collectAssetRendererIds(selection, autoPresetIds = [], includeFullPreset = false) {
|
|
1655
|
+
if (includeFullPreset) {
|
|
1656
|
+
return expandDescriptorRendererIds(presetModules.all.rendererIds);
|
|
1657
|
+
}
|
|
1210
1658
|
const presetIds = [
|
|
1211
1659
|
...(selection.preset ? expandDescriptorRendererIds(presetModules[selection.preset].rendererIds) : []),
|
|
1212
1660
|
...autoPresetIds.flatMap((presetId) => expandDescriptorRendererIds(presetModules[presetId].rendererIds))
|
|
@@ -1217,14 +1665,15 @@ function collectAssetRendererIds(selection, autoPresetIds = []) {
|
|
|
1217
1665
|
]);
|
|
1218
1666
|
}
|
|
1219
1667
|
function reportAssetCopy(results, targetRoot, mode) {
|
|
1220
|
-
const failedRequired = results.filter((result) => !result.copied && [
|
|
1668
|
+
const failedRequired = results.filter((result) => !result.copied && (result.required ?? [
|
|
1221
1669
|
'pdf',
|
|
1222
1670
|
'office-word-openxml',
|
|
1671
|
+
'office-presentation-binary',
|
|
1223
1672
|
'office-presentation',
|
|
1224
1673
|
'archive',
|
|
1225
1674
|
'cad',
|
|
1226
1675
|
'typst'
|
|
1227
|
-
].includes(result.rendererId));
|
|
1676
|
+
].includes(result.rendererId)));
|
|
1228
1677
|
if (!results.length) {
|
|
1229
1678
|
return;
|
|
1230
1679
|
}
|
|
@@ -1258,6 +1707,8 @@ export function fileViewerRenderers(options = {}) {
|
|
|
1258
1707
|
});
|
|
1259
1708
|
let autoPresetIds = resolveAutoPresetIds(options);
|
|
1260
1709
|
let resolvedConfig = null;
|
|
1710
|
+
let installedFullPackages = [];
|
|
1711
|
+
let runtimeAssetBase = null;
|
|
1261
1712
|
const refreshSelection = (projectRoot) => {
|
|
1262
1713
|
if (projectRoot) {
|
|
1263
1714
|
scanFormats = collectFileViewerRendererScanTokens(projectRoot, options.scan);
|
|
@@ -1269,6 +1720,18 @@ export function fileViewerRenderers(options = {}) {
|
|
|
1269
1720
|
});
|
|
1270
1721
|
autoPresetIds = resolveAutoPresetIds(options);
|
|
1271
1722
|
};
|
|
1723
|
+
const refreshFullAssetRuntime = (projectRoot, viteBase) => {
|
|
1724
|
+
if (!options.copyAssets) {
|
|
1725
|
+
installedFullPackages = [];
|
|
1726
|
+
runtimeAssetBase = null;
|
|
1727
|
+
return;
|
|
1728
|
+
}
|
|
1729
|
+
const target = resolveFileViewerCopyAssetsTarget('dev', options.copyAssets, {
|
|
1730
|
+
projectRoot
|
|
1731
|
+
});
|
|
1732
|
+
installedFullPackages = target.installedFullPackages;
|
|
1733
|
+
runtimeAssetBase = resolveViteFullAssetBase(viteBase, target.baseDir);
|
|
1734
|
+
};
|
|
1272
1735
|
const hasConfiguredRenderers = () => Boolean(selection.preset || selection.descriptors.length || autoPresetIds.length);
|
|
1273
1736
|
return {
|
|
1274
1737
|
name: 'file-viewer-renderers',
|
|
@@ -1276,19 +1739,27 @@ export function fileViewerRenderers(options = {}) {
|
|
|
1276
1739
|
config(userConfig) {
|
|
1277
1740
|
const projectRoot = resolve(process.cwd(), userConfig.root || '.');
|
|
1278
1741
|
refreshSelection(projectRoot);
|
|
1279
|
-
|
|
1742
|
+
refreshFullAssetRuntime(projectRoot, userConfig.base);
|
|
1280
1743
|
const dependencyAnchorPackages = collectDependencyAnchorPackages(selection, autoPresetIds);
|
|
1744
|
+
const resolvedDependencyAnchorPackages = runtimeAssetBase
|
|
1745
|
+
? unique([
|
|
1746
|
+
...dependencyAnchorPackages,
|
|
1747
|
+
'@file-viewer/core',
|
|
1748
|
+
...installedFullPackages,
|
|
1749
|
+
...(installedFullPackages.length ? ['@file-viewer/preset-all'] : [])
|
|
1750
|
+
])
|
|
1751
|
+
: dependencyAnchorPackages;
|
|
1281
1752
|
const optimizeDepsExclude = createOptimizeDepsExclude(userConfig);
|
|
1282
1753
|
const manualChunksFunction = getManualChunksFunction(userConfig);
|
|
1283
1754
|
const nextConfig = {
|
|
1284
1755
|
optimizeDeps: {
|
|
1285
1756
|
exclude: optimizeDepsExclude,
|
|
1286
|
-
include: createOptimizeDepsInclude(userConfig, optimizeDepsExclude,
|
|
1757
|
+
include: createOptimizeDepsInclude(userConfig, optimizeDepsExclude, resolvedDependencyAnchorPackages)
|
|
1287
1758
|
},
|
|
1288
1759
|
resolve: {
|
|
1289
1760
|
alias: [
|
|
1290
1761
|
...normalizeViteAlias(userConfig.resolve?.alias),
|
|
1291
|
-
...createFileViewerResolveAliases(
|
|
1762
|
+
...createFileViewerResolveAliases(resolvedDependencyAnchorPackages)
|
|
1292
1763
|
]
|
|
1293
1764
|
}
|
|
1294
1765
|
};
|
|
@@ -1321,6 +1792,7 @@ export function fileViewerRenderers(options = {}) {
|
|
|
1321
1792
|
configResolved(config) {
|
|
1322
1793
|
resolvedConfig = config;
|
|
1323
1794
|
refreshSelection(config.root);
|
|
1795
|
+
refreshFullAssetRuntime(config.root, config.base);
|
|
1324
1796
|
},
|
|
1325
1797
|
buildStart() {
|
|
1326
1798
|
assertMissingRendererPolicy(selection, missingMode);
|
|
@@ -1340,58 +1812,68 @@ export function fileViewerRenderers(options = {}) {
|
|
|
1340
1812
|
if (!options.copyAssets || copyOptions(options.copyAssets).mode === 'build') {
|
|
1341
1813
|
return;
|
|
1342
1814
|
}
|
|
1343
|
-
const
|
|
1344
|
-
|
|
1815
|
+
const copyTarget = resolveFileViewerCopyAssetsTarget('dev', options.copyAssets, {
|
|
1816
|
+
projectRoot: resolvedConfig?.root,
|
|
1817
|
+
publicDir: resolvedConfig?.publicDir || 'public',
|
|
1818
|
+
outDir: resolvedConfig?.build.outDir || 'dist'
|
|
1819
|
+
});
|
|
1820
|
+
const { targetRoot } = copyTarget;
|
|
1821
|
+
const results = await copyRendererAssets(copyTarget, collectAssetRendererIds(selection, autoPresetIds, copyTarget.installedFullPackages.length > 0));
|
|
1345
1822
|
reportAssetCopy(results, targetRoot, missingMode);
|
|
1346
|
-
const
|
|
1347
|
-
if (
|
|
1348
|
-
const
|
|
1349
|
-
server.middlewares.use(async (request, response, next)
|
|
1823
|
+
const viteBasePath = normalizeViteDevBasePath(resolvedConfig?.base || '/');
|
|
1824
|
+
if (server?.middlewares?.use) {
|
|
1825
|
+
const realTargetRoot = await realpath(targetRoot).catch(() => targetRoot);
|
|
1826
|
+
server.middlewares.use(async function fileViewerAssetMiddleware(request, response, next) {
|
|
1350
1827
|
const requestUrl = request.url || '';
|
|
1351
1828
|
const queryIndex = requestUrl.indexOf('?');
|
|
1352
1829
|
const pathname = queryIndex >= 0 ? requestUrl.slice(0, queryIndex) : requestUrl;
|
|
1353
|
-
|
|
1354
|
-
|
|
1830
|
+
const assetPath = resolveDevAssetRequestPath(targetRoot, copyTarget.baseDir, pathname, viteBasePath);
|
|
1831
|
+
if (assetPath) {
|
|
1355
1832
|
try {
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1833
|
+
const resolvedAssetPath = await realpath(assetPath);
|
|
1834
|
+
if (isPathWithin(realTargetRoot, resolvedAssetPath)) {
|
|
1835
|
+
const info = await stat(resolvedAssetPath);
|
|
1836
|
+
if (info.isFile()) {
|
|
1837
|
+
const contentTypes = {
|
|
1838
|
+
'.avif': 'image/avif',
|
|
1839
|
+
'.bcmap': 'application/octet-stream',
|
|
1840
|
+
'.css': 'text/css; charset=utf-8',
|
|
1841
|
+
'.gif': 'image/gif',
|
|
1842
|
+
'.ico': 'image/x-icon',
|
|
1843
|
+
'.jpeg': 'image/jpeg',
|
|
1844
|
+
'.jpg': 'image/jpeg',
|
|
1845
|
+
'.js': 'text/javascript; charset=utf-8',
|
|
1846
|
+
'.json': 'application/json; charset=utf-8',
|
|
1847
|
+
'.map': 'application/json; charset=utf-8',
|
|
1848
|
+
'.md': 'text/markdown; charset=utf-8',
|
|
1849
|
+
'.mjs': 'text/javascript; charset=utf-8',
|
|
1850
|
+
'.otf': 'font/otf',
|
|
1851
|
+
'.pfb': 'application/x-font-type1',
|
|
1852
|
+
'.png': 'image/png',
|
|
1853
|
+
'.svg': 'image/svg+xml',
|
|
1854
|
+
'.ttf': 'font/ttf',
|
|
1855
|
+
'.txt': 'text/plain; charset=utf-8',
|
|
1856
|
+
'.wasm': 'application/wasm',
|
|
1857
|
+
'.webp': 'image/webp',
|
|
1858
|
+
'.woff': 'font/woff',
|
|
1859
|
+
'.woff2': 'font/woff2',
|
|
1860
|
+
'.xml': 'application/xml; charset=utf-8'
|
|
1861
|
+
};
|
|
1862
|
+
response.statusCode = 200;
|
|
1863
|
+
response.setHeader('Content-Type', contentTypes[extname(resolvedAssetPath).toLowerCase()] || 'application/octet-stream');
|
|
1864
|
+
if (request.method === 'HEAD') {
|
|
1865
|
+
response.end();
|
|
1388
1866
|
}
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1867
|
+
else {
|
|
1868
|
+
response.end(await readFile(resolvedAssetPath));
|
|
1869
|
+
}
|
|
1870
|
+
return;
|
|
1392
1871
|
}
|
|
1393
1872
|
}
|
|
1394
1873
|
}
|
|
1874
|
+
catch {
|
|
1875
|
+
// Let Vite return its normal 404/fallback response.
|
|
1876
|
+
}
|
|
1395
1877
|
}
|
|
1396
1878
|
next();
|
|
1397
1879
|
});
|
|
@@ -1400,7 +1882,7 @@ export function fileViewerRenderers(options = {}) {
|
|
|
1400
1882
|
transformIndexHtml: {
|
|
1401
1883
|
order: 'pre',
|
|
1402
1884
|
handler() {
|
|
1403
|
-
if (options.inject === false || !hasConfiguredRenderers()) {
|
|
1885
|
+
if (options.inject === false || (!hasConfiguredRenderers() && !runtimeAssetBase)) {
|
|
1404
1886
|
return undefined;
|
|
1405
1887
|
}
|
|
1406
1888
|
return [
|
|
@@ -1439,20 +1921,37 @@ export function fileViewerRenderers(options = {}) {
|
|
|
1439
1921
|
if (!options.copyAssets || copyOptions(options.copyAssets).mode === 'dev') {
|
|
1440
1922
|
return;
|
|
1441
1923
|
}
|
|
1442
|
-
const
|
|
1443
|
-
|
|
1444
|
-
|
|
1924
|
+
const copyTarget = resolveFileViewerCopyAssetsTarget('build', options.copyAssets, {
|
|
1925
|
+
projectRoot: resolvedConfig?.root,
|
|
1926
|
+
publicDir: resolvedConfig?.publicDir || 'public',
|
|
1927
|
+
outDir: resolvedConfig?.build.outDir || 'dist'
|
|
1928
|
+
});
|
|
1929
|
+
const { targetRoot } = copyTarget;
|
|
1930
|
+
const results = await copyRendererAssets(copyTarget, collectAssetRendererIds(selection, autoPresetIds, copyTarget.installedFullPackages.length > 0));
|
|
1445
1931
|
reportAssetCopy(results, targetRoot, missingMode);
|
|
1446
1932
|
},
|
|
1447
|
-
resolveId(id) {
|
|
1933
|
+
resolveId(id, importer) {
|
|
1934
|
+
if (id === '@file-viewer/ppt' &&
|
|
1935
|
+
options.copyAssets &&
|
|
1936
|
+
installedFullPackages.length > 0 &&
|
|
1937
|
+
isPresentationRendererImporter(importer)) {
|
|
1938
|
+
return resolvedPackagedPptFallbackModuleId;
|
|
1939
|
+
}
|
|
1448
1940
|
if (id === moduleId || id === virtualModuleId || id === injectedModulePath) {
|
|
1449
1941
|
return id === virtualModuleId ? resolvedVirtualModuleId : resolvedModuleId;
|
|
1450
1942
|
}
|
|
1451
1943
|
return undefined;
|
|
1452
1944
|
},
|
|
1453
1945
|
load(id) {
|
|
1946
|
+
if (id === resolvedPackagedPptFallbackModuleId) {
|
|
1947
|
+
return `
|
|
1948
|
+
export async function createPptViewer() {
|
|
1949
|
+
throw new Error('Packaged PPT runtime URL was not initialized.')
|
|
1950
|
+
}
|
|
1951
|
+
`;
|
|
1952
|
+
}
|
|
1454
1953
|
if (id === resolvedModuleId || id === resolvedVirtualModuleId) {
|
|
1455
|
-
return renderVirtualModule(selection, requestedFormats, autoPresetIds);
|
|
1954
|
+
return renderVirtualModule(selection, requestedFormats, autoPresetIds, runtimeAssetBase, installedFullPackages.length > 0);
|
|
1456
1955
|
}
|
|
1457
1956
|
return undefined;
|
|
1458
1957
|
}
|
package/package.json
CHANGED