@file-viewer/vite-plugin 2.1.1 → 2.1.3

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 CHANGED
@@ -1,19 +1,36 @@
1
1
  # @file-viewer/vite-plugin
2
2
 
3
- Vite plugin for Flyfish File Viewer on-demand renderer assembly. It generates `virtual:file-viewer-renderers` from the formats your application declares, imports only the matching renderer packages, and provides renderer-oriented chunk planning plus offline worker/WASM/font asset copying. The extension mapping is verified against the full `@file-viewer/core` format matrix in repository gates, so new formats cannot silently drift away from automatic assembly.
3
+ Vite plugin for Flyfish File Viewer on-demand renderer assembly. It can auto-discover installed `@file-viewer/preset-*` packages and inject them into the page, 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
- ## Install
5
+ ## Fastest Start
6
+
7
+ The fastest path is a standard component package, one preset, and one Vite plugin registration. The plugin auto-discovers installed `@file-viewer/preset-*` packages, so application code does not hand-write renderer imports and the plugin does not need `preset:'office'`. Installing the npm package alone does not make Vite run the plugin; register it once in `vite.config.ts`:
6
8
 
7
9
  ```bash
8
- pnpm add @file-viewer/vue3 @file-viewer/vite-plugin @file-viewer/renderer-pdf
10
+ pnpm add @file-viewer/vue3 @file-viewer/preset-office
11
+ pnpm add -D @file-viewer/vite-plugin
12
+ ```
13
+
14
+ ```ts
15
+ import { defineConfig } from 'vite'
16
+ import { fileViewerRenderers } from '@file-viewer/vite-plugin'
17
+
18
+ export default defineConfig({
19
+ plugins: [
20
+ fileViewerRenderers({
21
+ copyAssets: true
22
+ })
23
+ ]
24
+ })
9
25
  ```
10
26
 
11
- Install additional renderer packages when you need more formats, such as `@file-viewer/renderer-word`, `@file-viewer/renderer-ofd`, `@file-viewer/renderer-presentation`, `@file-viewer/renderer-cad`, `@file-viewer/renderer-drawing`, `@file-viewer/renderer-3d`, `@file-viewer/renderer-data`, `@file-viewer/renderer-eda`, `@file-viewer/renderer-typst`, `@file-viewer/renderer-archive`, or `@file-viewer/renderer-text`.
27
+ 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.
12
28
 
13
- When you want one package for a common product shape, install a preset:
29
+ Heavy users that want the fastest full-capability setup can install the full preset and keep the same Vite config:
14
30
 
15
31
  ```bash
16
- pnpm add @file-viewer/vue3 @file-viewer/vite-plugin @file-viewer/preset-office
32
+ pnpm add @file-viewer/vue3 @file-viewer/preset-all
33
+ pnpm add -D @file-viewer/vite-plugin
17
34
  ```
18
35
 
19
36
  Available presets:
@@ -23,8 +40,20 @@ Available presets:
23
40
  - `@file-viewer/preset-engineering`: CAD, 3D, drawing, XMind, Geo, Typst, Archive, Data, and EDA.
24
41
  - `@file-viewer/preset-all`: the complete official demo format matrix.
25
42
 
43
+ Install individual renderer packages only for strict cuts, such as `@file-viewer/renderer-pdf`, `@file-viewer/renderer-word`, `@file-viewer/renderer-ofd`, `@file-viewer/renderer-presentation`, `@file-viewer/renderer-cad`, `@file-viewer/renderer-drawing`, `@file-viewer/renderer-3d`, `@file-viewer/renderer-data`, `@file-viewer/renderer-eda`, `@file-viewer/renderer-typst`, `@file-viewer/renderer-archive`, or `@file-viewer/renderer-text`, then use `formats` to generate exact imports.
44
+
26
45
  ## vite.config.ts
27
46
 
47
+ Prefer preset auto assembly for normal products. With no explicit `preset` option, or only `copyAssets:true`, the plugin auto-discovers installed `@file-viewer/preset-*` packages:
48
+
49
+ ```ts
50
+ fileViewerRenderers({
51
+ copyAssets: true
52
+ })
53
+ ```
54
+
55
+ Use customization options only when you need source scanning, single-format cuts, or manual registry control:
56
+
28
57
  ```ts
29
58
  import { defineConfig } from 'vite'
30
59
  import { fileViewerRenderers } from '@file-viewer/vite-plugin'
@@ -41,15 +70,60 @@ export default defineConfig({
41
70
  })
42
71
  ```
43
72
 
44
- Or use one preset package:
73
+ `inject` is enabled by default. The plugin injects `virtual:file-viewer-renderers` into Vite HTML entrypoints, preset imports register themselves in core, and framework components consume them through `autoRenderers`.
74
+
75
+ ```ts
76
+ const options = {
77
+ // Defaults to true; set false when a product needs total manual control.
78
+ autoRenderers: true
79
+ }
80
+ ```
81
+
82
+ ### Customization Options
83
+
84
+ | Option | Description |
85
+ | --- | --- |
86
+ | `copyAssets` | `true` or `{ publicDir, outDir, mode }`; copies matched renderer Worker, WASM, font, and vendor assets |
87
+ | `preset` | `'auto' | 'lite' | 'office' | 'engineering' | 'all'`; with no explicit formats, installed presets are discovered automatically |
88
+ | `autoPresets` | `true` or a preset list; useful with `scan:true` when installed presets should stay active |
89
+ | `formats` | File extensions or format tokens, for example `['pdf', 'docx', 'dwg']` |
90
+ | `renderers` | Renderer ids, for example `['pdf', 'word', 'cad']` |
91
+ | `scan` | `true` or `{ roots, extensions, maxFileSize }`; scans source hints and merges formats |
92
+ | `inject` | Defaults to `true`; set `false` to import `virtual:file-viewer-renderers` manually |
93
+ | `chunkStrategy` | `'renderer' | 'none'`; controls renderer-level chunk grouping |
94
+ | `missingRenderer` | `'error' | 'warn' | 'ignore'`; controls notices for planned renderer mappings |
95
+
96
+ For strict registry control, disable injection and pass the virtual module explicitly:
45
97
 
46
98
  ```ts
47
99
  fileViewerRenderers({
48
- preset: 'office',
100
+ formats: ['pdf'],
101
+ inject: false,
49
102
  copyAssets: true
50
103
  })
51
104
  ```
52
105
 
106
+ ```ts
107
+ import { configuredFileViewerRenderers } from 'virtual:file-viewer-renderers'
108
+
109
+ const options = {
110
+ rendererMode: 'replace',
111
+ renderers: configuredFileViewerRenderers
112
+ }
113
+ ```
114
+
115
+ You can also use `preset: 'auto'` to discover installed preset packages. When `preset-all` is installed, it wins to avoid importing narrower presets twice. Note: when `scan:true` is enabled, use `preset:'auto'` or `autoPresets:true` explicitly; otherwise the plugin treats source hints as the explicit renderer selection and skips zero-config preset discovery.
116
+
117
+ ```ts
118
+ fileViewerRenderers({
119
+ preset: 'auto',
120
+ scan: true,
121
+ formats: ['pdf'],
122
+ copyAssets: true,
123
+ chunkStrategy: 'renderer'
124
+ })
125
+ ```
126
+
53
127
  `scan: true` inspects common source folders for lightweight hints and merges them with `formats`:
54
128
 
55
129
  ```ts
@@ -62,21 +136,13 @@ export const fileViewerFormats = ['pdf', 'docx', 'xlsx']
62
136
 
63
137
  This is useful when upload accept lists, sample matrices, or attachment allow-lists already live in source code: dev and production builds can generate the renderer assembly module without a second hand-written import list.
64
138
 
65
- ## Application Code
139
+ ## Missing Renderer Guidance
66
140
 
67
- ```ts
68
- import FileViewer from '@file-viewer/vue3'
69
- import { configuredFileViewerRenderers } from 'virtual:file-viewer-renderers'
70
-
71
- const options = {
72
- rendererMode: 'replace',
73
- renderers: configuredFileViewerRenderers
74
- }
75
- ```
141
+ When a file extension is in the supported matrix but the current project has not assembled its renderer, core now shows an install-oriented “renderer assembly required” state with the recommended preset / renderer package. For example, `.pdf` points to `@file-viewer/preset-office` or `@file-viewer/renderer-pdf`. Only truly unknown extensions show an unsupported-format state.
76
142
 
77
143
  ## Current Boundary
78
144
 
79
- 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 also copies the Typst compiler / renderer WASM files and the `wasm/typst/fonts/` default-font directory. `preset: 'lite' | 'office' | 'engineering' | 'all'` imports the matching `@file-viewer/preset-*` package; when `formats` are also present, the plugin adds extra renderers outside the preset.
145
+ 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 also copies the Typst compiler / renderer WASM files and the `wasm/typst/fonts/` default-font directory. `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.
80
146
 
81
147
  ## Documentation
82
148
 
package/README.md CHANGED
@@ -1,19 +1,36 @@
1
1
  # @file-viewer/vite-plugin
2
2
 
3
- Flyfish File Viewer 的 Vite 按需 renderer 自动装配插件。它根据业务声明的文件格式生成 `virtual:file-viewer-renderers`,只 import 命中的 renderer 包,并提供 chunk 分组和离线 worker/WASM/字体资源复制能力。插件的扩展名映射会在仓库门禁中对照 `@file-viewer/core` 的完整格式矩阵验证,避免新增格式后自动装配能力漂移。
3
+ Flyfish File Viewer 的 Vite 按需 renderer 自动装配插件。它可以自动发现已安装的 `@file-viewer/preset-*` 包并注入到页面,让 Vue、React、Svelte、jQuery 和 Vanilla JS 组件无需手动传 `renderers` 就获得对应预览能力;也可以根据业务声明的文件格式生成 `virtual:file-viewer-renderers`,只 import 命中的 renderer 包,并提供 chunk 分组和离线 worker/WASM/字体资源复制能力。
4
4
 
5
- ## 安装
5
+ ## 最快开始
6
+
7
+ 最快接入路径是“标准组件包 + 一个 preset + 注册一次 Vite 插件”。插件会自动发现当前项目已安装的 `@file-viewer/preset-*`,无需手写 renderer import,也无需给插件显式写 `preset:'office'`。注意:只安装 npm 包不会让 Vite 自动运行插件,仍需要在 `vite.config.ts` 中注册一次:
6
8
 
7
9
  ```bash
8
- pnpm add @file-viewer/vue3 @file-viewer/vite-plugin @file-viewer/renderer-pdf
10
+ pnpm add @file-viewer/vue3 @file-viewer/preset-office
11
+ pnpm add -D @file-viewer/vite-plugin
12
+ ```
13
+
14
+ ```ts
15
+ import { defineConfig } from 'vite'
16
+ import { fileViewerRenderers } from '@file-viewer/vite-plugin'
17
+
18
+ export default defineConfig({
19
+ plugins: [
20
+ fileViewerRenderers({
21
+ copyAssets: true
22
+ })
23
+ ]
24
+ })
9
25
  ```
10
26
 
11
- 需要更多格式时安装对应 renderer 包,例如 `@file-viewer/renderer-word`、`@file-viewer/renderer-ofd`、`@file-viewer/renderer-presentation`、`@file-viewer/renderer-cad`、`@file-viewer/renderer-drawing`、`@file-viewer/renderer-3d`、`@file-viewer/renderer-data`、`@file-viewer/renderer-eda`、`@file-viewer/renderer-typst`、`@file-viewer/renderer-archive`、`@file-viewer/renderer-text`。
27
+ 组件默认 `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` 即可获得对应能力。
12
28
 
13
- 如果你希望用一个包完成常见场景装配,可以安装 preset
29
+ 重度用户需要最快拥有全部预览能力时,直接安装全量 preset,Vite 配置保持不变:
14
30
 
15
31
  ```bash
16
- pnpm add @file-viewer/vue3 @file-viewer/vite-plugin @file-viewer/preset-office
32
+ pnpm add @file-viewer/vue3 @file-viewer/preset-all
33
+ pnpm add -D @file-viewer/vite-plugin
17
34
  ```
18
35
 
19
36
  可选 preset:
@@ -23,8 +40,20 @@ pnpm add @file-viewer/vue3 @file-viewer/vite-plugin @file-viewer/preset-office
23
40
  - `@file-viewer/preset-engineering`: CAD、3D、绘图、XMind、Geo、Typst、Archive、Data、EDA。
24
41
  - `@file-viewer/preset-all`: 官方 demo 完整格式矩阵。
25
42
 
43
+ 如果只需要极少数格式,也可以安装对应 renderer 包,例如 `@file-viewer/renderer-pdf`、`@file-viewer/renderer-word`、`@file-viewer/renderer-ofd`、`@file-viewer/renderer-presentation`、`@file-viewer/renderer-cad`、`@file-viewer/renderer-drawing`、`@file-viewer/renderer-3d`、`@file-viewer/renderer-data`、`@file-viewer/renderer-eda`、`@file-viewer/renderer-typst`、`@file-viewer/renderer-archive`、`@file-viewer/renderer-text`,再通过 `formats` 做精确裁剪。
44
+
26
45
  ## vite.config.ts
27
46
 
47
+ 推荐默认使用 preset 自动装配。无参或只传 `copyAssets:true` 时,插件会自动发现已安装的 `@file-viewer/preset-*`,无需写 `preset:'office'`:
48
+
49
+ ```ts
50
+ fileViewerRenderers({
51
+ copyAssets: true
52
+ })
53
+ ```
54
+
55
+ 只有在需要源码扫描、单格式裁剪、或手动 registry 管理时,再使用自定义能力:
56
+
28
57
  ```ts
29
58
  import { defineConfig } from 'vite'
30
59
  import { fileViewerRenderers } from '@file-viewer/vite-plugin'
@@ -41,15 +70,60 @@ export default defineConfig({
41
70
  })
42
71
  ```
43
72
 
44
- 或者使用 preset 一包装配:
73
+ `inject` 默认开启,插件会把 `virtual:file-viewer-renderers` 注入 Vite HTML 入口,preset 导入后会自动注册到 core。常规业务只需要安装组件包和对应 preset,组件会通过 `autoRenderers` 默认读取这些能力。
74
+
75
+ ```ts
76
+ const options = {
77
+ // 默认 true;需要完全手动控制时设为 false。
78
+ autoRenderers: true
79
+ }
80
+ ```
81
+
82
+ ### 可定制能力
83
+
84
+ | 选项 | 说明 |
85
+ | --- | --- |
86
+ | `copyAssets` | `true` 或 `{ publicDir, outDir, mode }`,复制匹配 renderer 的 Worker、WASM、字体和 vendor 资源 |
87
+ | `preset` | `'auto' | 'lite' | 'office' | 'engineering' | 'all'`;默认无显式格式时自动发现已安装 preset |
88
+ | `autoPresets` | `true` 或 preset 列表;常用于 `scan:true` 时继续自动激活已安装 preset |
89
+ | `formats` | 文件扩展名或格式 token,例如 `['pdf', 'docx', 'dwg']` |
90
+ | `renderers` | renderer id,例如 `['pdf', 'word', 'cad']` |
91
+ | `scan` | `true` 或 `{ roots, extensions, maxFileSize }`,扫描源码 hint 并合并格式 |
92
+ | `inject` | 默认 `true`;设为 `false` 后手动导入 `virtual:file-viewer-renderers` |
93
+ | `chunkStrategy` | `'renderer' | 'none'`,控制是否注入 renderer 级 chunk 分组 |
94
+ | `missingRenderer` | `'error' | 'warn' | 'ignore'`,控制尚未提取的 renderer 映射提示方式 |
95
+
96
+ 如果你需要严格控制 registry,可以关闭注入并手动传入:
45
97
 
46
98
  ```ts
47
99
  fileViewerRenderers({
48
- preset: 'office',
100
+ formats: ['pdf'],
101
+ inject: false,
49
102
  copyAssets: true
50
103
  })
51
104
  ```
52
105
 
106
+ ```ts
107
+ import { configuredFileViewerRenderers } from 'virtual:file-viewer-renderers'
108
+
109
+ const options = {
110
+ rendererMode: 'replace',
111
+ renderers: configuredFileViewerRenderers
112
+ }
113
+ ```
114
+
115
+ 也可以使用 `preset: 'auto'` 发现项目中已安装的 preset 包;当 `preset-all` 存在时会优先使用它,避免重复导入其它 preset。注意:如果同时开启 `scan:true`,请显式使用 `preset:'auto'` 或 `autoPresets:true`,否则插件会以源码 hint 为准,不再做“无配置 preset 自动发现”。
116
+
117
+ ```ts
118
+ fileViewerRenderers({
119
+ preset: 'auto',
120
+ scan: true,
121
+ formats: ['pdf'],
122
+ copyAssets: true,
123
+ chunkStrategy: 'renderer'
124
+ })
125
+ ```
126
+
53
127
  `scan: true` 会扫描常见源码目录里的轻量 hint,并把它们合并到 `formats`:
54
128
 
55
129
  ```ts
@@ -62,21 +136,13 @@ export const fileViewerFormats = ['pdf', 'docx', 'xlsx']
62
136
 
63
137
  这适合业务把上传入口、示例矩阵或附件白名单维护在源码中时使用:开发和构建阶段插件会自动生成 renderer 装配模块,少写一份手工 import 清单。
64
138
 
65
- ## 业务代码
139
+ ## 缺失 renderer 提示
66
140
 
67
- ```ts
68
- import FileViewer from '@file-viewer/vue3'
69
- import { configuredFileViewerRenderers } from 'virtual:file-viewer-renderers'
70
-
71
- const options = {
72
- rendererMode: 'replace',
73
- renderers: configuredFileViewerRenderers
74
- }
75
- ```
141
+ 如果用户打开的是支持矩阵内的格式,但项目没有安装或装配对应 renderer,core 会显示“需要装配预览能力”,并提示推荐安装的 preset / renderer 包,例如 `.pdf` 会引导安装 `@file-viewer/preset-office` 或 `@file-viewer/renderer-pdf`。只有真正不在支持矩阵中的扩展名才显示“不支持在线预览”。
76
142
 
77
143
  ## 当前边界
78
144
 
79
- 当前插件会为已经拆出的 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` 时会同时复制 Typst compiler / renderer WASM 与 `wasm/typst/fonts/` 默认字体目录。`preset: 'lite' | 'office' | 'engineering' | 'all'` 会导入对应 `@file-viewer/preset-*` 包;如果同时声明 `formats`,插件会在 preset 之外补充额外 renderer。
145
+ 当前插件会为已经拆出的 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` 时会同时复制 Typst compiler / renderer WASM 与 `wasm/typst/fonts/` 默认字体目录。`preset: 'auto' | 'lite' | 'office' | 'engineering' | 'all'` 会导入对应 `@file-viewer/preset-*` 包;如果同时声明 `formats`,插件会在 preset 之外补充额外 renderer。
80
146
 
81
147
  ## 文档
82
148
 
package/client.d.ts CHANGED
@@ -9,6 +9,7 @@ declare module 'virtual:file-viewer-renderers' {
9
9
 
10
10
  export interface ConfiguredFileViewerRendererPlan {
11
11
  preset: string | null;
12
+ autoPresets: string[];
12
13
  formats: string[];
13
14
  rendererIds: string[];
14
15
  packages: string[];
package/dist/index.d.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  import type { Plugin } from 'vite';
2
2
  export type FileViewerVitePreset = 'all' | 'lite' | 'office' | 'engineering';
3
+ export type FileViewerVitePresetMode = FileViewerVitePreset | 'auto';
3
4
  export type FileViewerMissingRendererMode = 'error' | 'warn' | 'ignore';
4
5
  export type FileViewerChunkStrategy = 'renderer' | 'none';
5
6
  export interface FileViewerRendererScanOptions {
@@ -45,10 +46,23 @@ export interface FileViewerRenderersPluginOptions {
45
46
  */
46
47
  renderers?: readonly string[];
47
48
  /**
48
- * Presets import their dedicated @file-viewer/preset-* package. Add
49
- * `formats` / `renderers` when you need to extend a preset with extra lines.
49
+ * Presets import their dedicated @file-viewer/preset-* package. Use `auto`
50
+ * to discover installed preset packages, and add `formats` / `renderers`
51
+ * when you need to extend a preset with extra lines.
50
52
  */
51
- preset?: FileViewerVitePreset;
53
+ preset?: FileViewerVitePresetMode;
54
+ /**
55
+ * Auto-discovers installed `@file-viewer/preset-*` packages and registers
56
+ * them globally for framework components. Defaults to true only when no
57
+ * explicit preset/formats/renderers are configured, or when `preset: 'auto'`.
58
+ */
59
+ autoPresets?: boolean | readonly FileViewerVitePreset[];
60
+ /**
61
+ * Injects the virtual renderer module into Vite HTML entrypoints so
62
+ * framework components can consume auto-registered renderers without
63
+ * application code importing `virtual:file-viewer-renderers`.
64
+ */
65
+ inject?: boolean;
52
66
  /**
53
67
  * Virtual module id consumed by application code.
54
68
  */
@@ -85,6 +99,8 @@ export declare function createFileViewerManualChunks(options?: FileViewerRendere
85
99
  export declare function resolveFileViewerRendererSelection(options?: FileViewerRenderersPluginOptions, projectRoot?: string): {
86
100
  preset: FileViewerVitePreset | null;
87
101
  presetPackage: string | null;
102
+ autoPresets: FileViewerVitePreset[];
103
+ autoPresetPackages: string[];
88
104
  formats: string[];
89
105
  packages: string[];
90
106
  rendererIds: string[];
package/dist/index.js CHANGED
@@ -557,8 +557,11 @@ export function collectFileViewerRendererScanTokens(projectRoot, scan) {
557
557
  });
558
558
  return unique(tokens);
559
559
  }
560
+ function resolveManualPreset(preset) {
561
+ return preset && preset !== 'auto' ? preset : null;
562
+ }
560
563
  function selectRenderers(options) {
561
- const preset = options.preset ?? null;
564
+ const preset = resolveManualPreset(options.preset);
562
565
  const presetCoveredIds = new Set(preset ? presetRendererIds[preset] : []);
563
566
  const selected = new Map();
564
567
  const missing = [];
@@ -606,37 +609,55 @@ function expandDescriptorRendererIds(ids) {
606
609
  return descriptor ? [...descriptor.rendererIds] : [id];
607
610
  }));
608
611
  }
609
- function renderVirtualModule(selection, formats) {
612
+ function renderVirtualModule(selection, formats, autoPresetIds = []) {
610
613
  const presetModule = selection.preset ? presetModules[selection.preset] : null;
614
+ const autoPresetModules = autoPresetIds
615
+ .filter((id) => id !== selection.preset)
616
+ .map((id) => presetModules[id]);
611
617
  const presetImport = presetModule
612
618
  ? `import { ${presetModule.exportName} as presetRenderers } from '${presetModule.packageName}';`
613
619
  : null;
620
+ const autoPresetImports = autoPresetModules.map((preset, index) => `import { ${preset.exportName} as autoPresetRenderers${index} } from '${preset.packageName}';`);
614
621
  const rendererImports = selection.descriptors.map((descriptor, index) => `import { ${descriptor.exportName} as renderer${index} } from '${descriptor.packageName}';`);
615
622
  const rendererNames = [
616
623
  ...(presetModule ? ['presetRenderers'] : []),
624
+ ...autoPresetModules.map((_preset, index) => `autoPresetRenderers${index}`),
617
625
  ...selection.descriptors.map((_descriptor, index) => `renderer${index}`)
618
626
  ];
619
627
  const rendererIds = unique([
620
628
  ...(presetModule ? expandDescriptorRendererIds(presetModule.rendererIds) : []),
629
+ ...autoPresetModules.flatMap((preset) => expandDescriptorRendererIds(preset.rendererIds)),
621
630
  ...selection.descriptors.flatMap((descriptor) => descriptor.rendererIds)
622
631
  ]);
623
632
  const packages = unique([
624
633
  ...(presetModule ? [presetModule.packageName] : []),
634
+ ...autoPresetModules.map((preset) => preset.packageName),
625
635
  ...selection.descriptors.map((descriptor) => descriptor.packageName)
626
636
  ]);
627
637
  const plan = {
628
638
  preset: selection.preset,
639
+ autoPresets: autoPresetModules.map((preset) => preset.id),
629
640
  formats,
630
641
  rendererIds,
631
642
  packages,
632
643
  generatedBy: '@file-viewer/vite-plugin'
633
644
  };
645
+ const autoRegistrationId = selection.descriptors.length
646
+ ? '@file-viewer/vite-plugin:configured'
647
+ : selection.preset && !autoPresetModules.length
648
+ ? selection.preset
649
+ : !selection.preset && autoPresetModules.length === 1
650
+ ? autoPresetModules[0].id
651
+ : '@file-viewer/vite-plugin:configured';
634
652
  return [
653
+ `import { registerFileViewerAutoRendererPreset } from '@file-viewer/core';`,
635
654
  ...[presetImport].filter(Boolean),
655
+ ...autoPresetImports,
636
656
  ...rendererImports,
637
657
  '',
638
658
  `export const configuredFileViewerRenderers = [${rendererNames.join(', ')}];`,
639
659
  `export const fileViewerRendererPlan = ${JSON.stringify(plan, null, 2)};`,
660
+ `registerFileViewerAutoRendererPreset(configuredFileViewerRenderers, { id: ${JSON.stringify(autoRegistrationId)} });`,
640
661
  'export default configuredFileViewerRenderers;',
641
662
  ''
642
663
  ].join('\n');
@@ -648,10 +669,14 @@ function hasManualChunks(config) {
648
669
  }
649
670
  return Boolean(output?.manualChunks);
650
671
  }
651
- function createManualChunks(selection) {
672
+ function createManualChunks(selection, autoPresetIds = []) {
652
673
  const packageToChunk = new Map();
653
- if (selection.preset) {
654
- const presetModule = presetModules[selection.preset];
674
+ const presetIds = unique([
675
+ ...(selection.preset ? [selection.preset] : []),
676
+ ...autoPresetIds
677
+ ]);
678
+ presetIds.forEach((presetId) => {
679
+ const presetModule = presetModules[presetId];
655
680
  packageToChunk.set(presetModule.packageName, presetModule.chunkName);
656
681
  presetModule.rendererIds
657
682
  .map((id) => descriptorsById.get(id))
@@ -659,7 +684,7 @@ function createManualChunks(selection) {
659
684
  .forEach((descriptor) => {
660
685
  packageToChunk.set(descriptor.packageName, descriptor.chunkName);
661
686
  });
662
- }
687
+ });
663
688
  selection.descriptors.forEach((descriptor) => {
664
689
  packageToChunk.set(descriptor.packageName, descriptor.chunkName);
665
690
  });
@@ -763,6 +788,39 @@ function resolvePackageJson(packageName, anchorPackages = []) {
763
788
  }
764
789
  return resolveWorkspacePackageJson(packageName);
765
790
  }
791
+ function hasExplicitRendererSelection(options) {
792
+ return Boolean(resolveManualPreset(options.preset) ||
793
+ options.formats?.length ||
794
+ options.renderers?.length ||
795
+ options.scan);
796
+ }
797
+ function shouldAutoDiscoverPresets(options) {
798
+ if (Array.isArray(options.autoPresets)) {
799
+ return true;
800
+ }
801
+ if (typeof options.autoPresets === 'boolean') {
802
+ return options.autoPresets;
803
+ }
804
+ return options.preset === 'auto' || !hasExplicitRendererSelection(options);
805
+ }
806
+ function resolveAutoPresetIds(options) {
807
+ if (!shouldAutoDiscoverPresets(options)) {
808
+ return [];
809
+ }
810
+ const candidates = Array.isArray(options.autoPresets)
811
+ ? options.autoPresets
812
+ : Object.keys(presetModules);
813
+ const installed = unique(candidates).filter((presetId) => Boolean(resolvePackageJson(presetModules[presetId].packageName)));
814
+ return installed.includes('all') ? ['all'] : installed;
815
+ }
816
+ function collectSelectedPackages(selection, autoPresetIds = []) {
817
+ const presetModule = selection.preset ? presetModules[selection.preset] : null;
818
+ return unique([
819
+ ...(presetModule ? [presetModule.packageName] : []),
820
+ ...autoPresetIds.map((presetId) => presetModules[presetId].packageName),
821
+ ...selection.descriptors.map((descriptor) => descriptor.packageName)
822
+ ]);
823
+ }
766
824
  function resolvePackageRoot(packageName, anchorPackages = []) {
767
825
  const packageJson = resolvePackageJson(packageName, anchorPackages);
768
826
  return packageJson ? dirname(packageJson) : null;
@@ -849,10 +907,11 @@ function resolveTargetDir(value, fallback) {
849
907
  function copyOptions(value) {
850
908
  return typeof value === 'object' ? value : {};
851
909
  }
852
- function collectAssetRendererIds(selection) {
853
- const presetIds = selection.preset
854
- ? expandDescriptorRendererIds(presetModules[selection.preset].rendererIds)
855
- : [];
910
+ function collectAssetRendererIds(selection, autoPresetIds = []) {
911
+ const presetIds = [
912
+ ...(selection.preset ? expandDescriptorRendererIds(presetModules[selection.preset].rendererIds) : []),
913
+ ...autoPresetIds.flatMap((presetId) => expandDescriptorRendererIds(presetModules[presetId].rendererIds))
914
+ ];
856
915
  return unique([
857
916
  ...presetIds,
858
917
  ...selection.descriptors.flatMap((descriptor) => descriptor.rendererIds)
@@ -890,6 +949,7 @@ export function fileViewerRenderers(options = {}) {
890
949
  ...options,
891
950
  formats: [...(options.formats || []), ...scanFormats]
892
951
  });
952
+ let autoPresetIds = resolveAutoPresetIds(options);
893
953
  let resolvedConfig = null;
894
954
  const refreshSelection = (projectRoot) => {
895
955
  if (projectRoot) {
@@ -900,7 +960,9 @@ export function fileViewerRenderers(options = {}) {
900
960
  ...options,
901
961
  formats: [...(options.formats || []), ...scanFormats]
902
962
  });
963
+ autoPresetIds = resolveAutoPresetIds(options);
903
964
  };
965
+ const hasConfiguredRenderers = () => Boolean(selection.preset || selection.descriptors.length || autoPresetIds.length);
904
966
  return {
905
967
  name: 'file-viewer-renderers',
906
968
  enforce: 'pre',
@@ -914,7 +976,7 @@ export function fileViewerRenderers(options = {}) {
914
976
  build: {
915
977
  rollupOptions: {
916
978
  output: {
917
- manualChunks: createManualChunks(selection)
979
+ manualChunks: createManualChunks(selection, autoPresetIds)
918
980
  }
919
981
  }
920
982
  }
@@ -926,10 +988,7 @@ export function fileViewerRenderers(options = {}) {
926
988
  },
927
989
  buildStart() {
928
990
  assertMissingRendererPolicy(selection, missingMode);
929
- const packages = unique([
930
- ...(selection.preset ? [presetModules[selection.preset].packageName] : []),
931
- ...selection.descriptors.map((descriptor) => descriptor.packageName)
932
- ]);
991
+ const packages = collectSelectedPackages(selection, autoPresetIds);
933
992
  const missingPackages = packages.filter((packageName) => !resolvePackageJson(packageName));
934
993
  if (missingPackages.length && missingMode !== 'ignore') {
935
994
  const message = `Missing File Viewer preset/renderer package(s): ${missingPackages.join(', ')}. Install them or remove the matching preset/formats from @file-viewer/vite-plugin.`;
@@ -946,9 +1005,22 @@ export function fileViewerRenderers(options = {}) {
946
1005
  return;
947
1006
  }
948
1007
  const targetRoot = resolveTargetDir(copyOptions(options.copyAssets).publicDir, resolvedConfig?.publicDir || 'public');
949
- const results = await copyKnownRendererAssets(targetRoot, collectAssetRendererIds(selection));
1008
+ const results = await copyKnownRendererAssets(targetRoot, collectAssetRendererIds(selection, autoPresetIds));
950
1009
  reportAssetCopy(results, targetRoot, missingMode);
951
1010
  },
1011
+ transformIndexHtml() {
1012
+ if (options.inject === false || !hasConfiguredRenderers()) {
1013
+ return undefined;
1014
+ }
1015
+ return [
1016
+ {
1017
+ tag: 'script',
1018
+ attrs: { type: 'module' },
1019
+ children: `import ${JSON.stringify(moduleId)};`,
1020
+ injectTo: 'head'
1021
+ }
1022
+ ];
1023
+ },
952
1024
  handleHotUpdate(context) {
953
1025
  if (!options.scan || !resolvedConfig) {
954
1026
  return undefined;
@@ -978,7 +1050,7 @@ export function fileViewerRenderers(options = {}) {
978
1050
  }
979
1051
  const outDir = resolvedConfig?.build.outDir || 'dist';
980
1052
  const targetRoot = resolveTargetDir(copyOptions(options.copyAssets).outDir, outDir);
981
- const results = await copyKnownRendererAssets(targetRoot, collectAssetRendererIds(selection));
1053
+ const results = await copyKnownRendererAssets(targetRoot, collectAssetRendererIds(selection, autoPresetIds));
982
1054
  reportAssetCopy(results, targetRoot, missingMode);
983
1055
  },
984
1056
  resolveId(id) {
@@ -989,14 +1061,14 @@ export function fileViewerRenderers(options = {}) {
989
1061
  },
990
1062
  load(id) {
991
1063
  if (id === resolvedModuleId || id === resolvedVirtualModuleId) {
992
- return renderVirtualModule(selection, requestedFormats);
1064
+ return renderVirtualModule(selection, requestedFormats, autoPresetIds);
993
1065
  }
994
1066
  return undefined;
995
1067
  }
996
1068
  };
997
1069
  }
998
1070
  export function createFileViewerManualChunks(options = {}) {
999
- return createManualChunks(selectRenderers(options));
1071
+ return createManualChunks(selectRenderers(options), resolveAutoPresetIds(options));
1000
1072
  }
1001
1073
  export function resolveFileViewerRendererSelection(options = {}, projectRoot = process.cwd()) {
1002
1074
  const scanFormats = collectFileViewerRendererScanTokens(projectRoot, options.scan);
@@ -1010,17 +1082,19 @@ export function resolveFileViewerRendererSelection(options = {}, projectRoot = p
1010
1082
  formats: [...(options.formats || []), ...scanFormats]
1011
1083
  });
1012
1084
  const presetModule = selection.preset ? presetModules[selection.preset] : null;
1013
- const packages = unique([
1014
- ...(presetModule ? [presetModule.packageName] : []),
1015
- ...selection.descriptors.map((descriptor) => descriptor.packageName)
1016
- ]);
1085
+ const autoPresetIds = resolveAutoPresetIds(options);
1086
+ const autoPresetModules = autoPresetIds.map((presetId) => presetModules[presetId]);
1087
+ const packages = collectSelectedPackages(selection, autoPresetIds);
1017
1088
  return {
1018
1089
  preset: selection.preset,
1019
1090
  presetPackage: presetModule?.packageName ?? null,
1091
+ autoPresets: autoPresetModules.map((preset) => preset.id),
1092
+ autoPresetPackages: autoPresetModules.map((preset) => preset.packageName),
1020
1093
  formats: requestedFormats,
1021
1094
  packages,
1022
1095
  rendererIds: unique([
1023
1096
  ...(presetModule ? expandDescriptorRendererIds(presetModule.rendererIds) : []),
1097
+ ...autoPresetModules.flatMap((preset) => expandDescriptorRendererIds(preset.rendererIds)),
1024
1098
  ...selection.descriptors.flatMap((descriptor) => descriptor.rendererIds)
1025
1099
  ]),
1026
1100
  renderers: selection.descriptors.map((descriptor) => ({
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@file-viewer/vite-plugin",
3
- "version": "2.1.1",
3
+ "version": "2.1.3",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "description": "Vite plugin for Flyfish File Viewer on-demand renderer assembly, chunk planning, and offline asset deployment.",