@file-viewer/ppt 0.2.0 → 0.3.1

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.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # @file-viewer/ppt
2
2
 
3
- > Professional browser preview for PowerPoint 97–2003 (`.ppt`), powered by native WebAssembly and Canvas.
3
+ > Professional, browser-native preview for PowerPoint 97–2003 (`.ppt`).
4
4
 
5
5
  [![npm version](https://img.shields.io/npm/v/%40file-viewer%2Fppt.svg)](https://www.npmjs.com/package/@file-viewer/ppt)
6
6
  [![format](https://img.shields.io/badge/format-PowerPoint%2097--2003-c43e1c.svg)](#format-scope)
@@ -15,11 +15,12 @@
15
15
  `@file-viewer/ppt` is Flyfish's independently developed preview engine for the
16
16
  PowerPoint 97–2003 binary (`.ppt`) format. It reconstructs slides directly in a
17
17
  modern browser without Microsoft Office, LibreOffice, browser plug-ins, or a
18
- server-side conversion service.
18
+ server-side document conversion service.
19
19
 
20
20
  The product is designed for document platforms, archives, knowledge systems,
21
21
  intranets, SaaS applications, and web products that still need dependable
22
- access to traditional PowerPoint files.
22
+ access to traditional PowerPoint files. Its viewport-first runtime is equally
23
+ suitable for ordinary presentations and very large decks.
23
24
 
24
25
  ### Product highlights
25
26
 
@@ -27,17 +28,23 @@ access to traditional PowerPoint files.
27
28
  persist-record, text, drawing, and picture structures directly.
28
29
  - **Professional slide reconstruction** — Handles slide size, masters,
29
30
  backgrounds, color schemes, text formatting, adjustable OfficeArt shapes,
30
- fills, gradients, bounded legacy 3-D extrusion, grouped objects, pictures,
31
- transforms, and layer order.
32
- - **Native WASM Canvas pipeline** — Parsing, layout, rasterization, and public
33
- watermark composition run in one WebAssembly engine. JavaScript presents the
34
- engine's final RGBA frames with Canvas.
31
+ fills, gradients, grouped objects, pictures, transforms, layer order, and a
32
+ compatible subset of traditional 3-D effects.
33
+ - **Responsive worker pipeline** — Uses a module Worker, WebAssembly, and
34
+ OffscreenCanvas by default in capable browsers, keeping document parsing and
35
+ slide rasterization away from the main UI thread.
36
+ - **Large-deck virtualization** — Keeps only the viewport and an overscan window
37
+ actively rendered. Hidden Canvas backing stores are released after a short
38
+ delay instead of accumulating for the entire presentation.
39
+ - **Bounded frame cache** — Optionally stores only final, native-watermarked PNG
40
+ frames in an IndexedDB LRU. It has explicit byte, entry, and per-frame limits;
41
+ slide frames are never stored in `localStorage`.
42
+ - **Independent CJK font asset** — Loads the CJK fallback font as a separate,
43
+ integrity-verified resource that can use a long-lived browser or CDN cache.
35
44
  - **Local document processing** — The public runtime does not require documents
36
45
  to be uploaded to a conversion service.
37
- - **Verified engine asset** — The loader validates the exact native WASM
38
- SHA-256 before execution.
39
- - **Straightforward integration** — ESM, TypeScript declarations, no runtime
40
- JavaScript dependencies, and support for both complete-viewer mounting and
46
+ - **Straightforward integration** — ESM, TypeScript declarations, no JavaScript
47
+ runtime dependencies, and APIs for both complete-viewer mounting and
41
48
  individual-slide rendering.
42
49
 
43
50
  ### Format scope
@@ -51,97 +58,230 @@ This package previews PowerPoint 97–2003 binary `.ppt` files. For XML-based
51
58
  npm install @file-viewer/ppt
52
59
  ```
53
60
 
54
- ### Quick start
55
-
56
- ```html
57
- <input id="ppt-file" type="file" accept=".ppt,application/vnd.ms-powerpoint">
58
- <div id="ppt-viewer"></div>
59
- ```
61
+ ### Quick start: virtualized full presentation
60
62
 
61
63
  ```js
62
64
  import { createPptViewer } from '@file-viewer/ppt';
63
65
 
64
- const viewer = await createPptViewer();
65
- const input = document.querySelector('#ppt-file');
66
-
67
- input.addEventListener('change', async () => {
68
- const file = input.files?.[0];
69
- if (!file) return;
66
+ const viewer = await createPptViewer({
67
+ worker: 'auto',
68
+ cache: {
69
+ enabled: true,
70
+ maxBytes: 256 * 1024 * 1024,
71
+ maxEntries: 200,
72
+ maxEntryBytes: 32 * 1024 * 1024
73
+ }
74
+ });
70
75
 
71
- await viewer.mount('#ppt-viewer', await file.arrayBuffer(), {
76
+ const response = await fetch('/documents/presentation.ppt');
77
+ const mounted = await viewer.mount(
78
+ '#ppt-viewer',
79
+ await response.arrayBuffer(),
80
+ {
72
81
  scale: 1,
73
- pixelRatio: window.devicePixelRatio
74
- });
75
- });
82
+ pixelRatio: window.devicePixelRatio,
83
+ virtualize: true,
84
+ rootMargin: '150% 0px',
85
+ releaseDelayMs: 1200
86
+ }
87
+ );
88
+
89
+ console.log(viewer.mode); // "worker" or "direct"
90
+ console.log(await mounted.cacheStats());
91
+
92
+ // When this mounted preview is no longer needed:
93
+ await mounted.close();
94
+ await viewer.close();
76
95
  ```
77
96
 
78
- `mount()` creates one Canvas per slide and renders progressively. No license
79
- file or origin registration is required for the public watermarked edition.
97
+ `worker: 'auto'` is the default. It selects the module Worker path when Worker,
98
+ OffscreenCanvas, and URL-based assets are available, and otherwise uses the
99
+ compatible direct renderer. Set `worker: true` when worker rendering is a hard
100
+ deployment requirement, or `worker: false` for explicit direct mode.
101
+
102
+ `virtualize: true` is also the default. The viewer creates stable page shells,
103
+ renders pages near the viewport, and releases hidden raster backing stores.
104
+ In worker mode, when IndexedDB is available, revisiting a released page can
105
+ restore its final watermarked PNG before a native rerender is needed. Cache
106
+ failure or browser quota eviction never prevents the document from rendering;
107
+ direct mode simply rerenders a released page.
108
+
109
+ For very large files, set `transferInputOwnership: true` when constructing the
110
+ viewer to transfer a full input `ArrayBuffer` without an additional main-thread
111
+ copy. The supplied buffer is detached, so enable this only when the application
112
+ will not read it again.
80
113
 
81
114
  ### Render one slide
82
115
 
83
116
  ```js
117
+ import { createPptViewer } from '@file-viewer/ppt';
118
+
119
+ const viewer = await createPptViewer();
84
120
  const response = await fetch('/documents/presentation.ppt');
85
- const pptDocument = viewer.open(await response.arrayBuffer());
121
+ const pptDocument = await viewer.open(await response.arrayBuffer());
86
122
 
87
123
  const canvas = document.querySelector('canvas');
88
- pptDocument.renderSlide(0, canvas, { scale: 1.25 });
124
+ const result = await pptDocument.renderSlide(0, canvas, { scale: 1.25 });
89
125
 
90
126
  console.log(pptDocument.slideCount, pptDocument.width, pptDocument.height);
91
- pptDocument.close();
127
+ console.log(result.source); // "native" or "indexeddb" in worker mode
128
+
129
+ await pptDocument.releaseSlide(0);
130
+ console.log(await pptDocument.cacheStats());
131
+ await pptDocument.close();
132
+ await viewer.close();
92
133
  ```
93
134
 
94
- Close documents when they are no longer needed so their native memory can be
95
- released immediately.
135
+ The API is asynchronous in both worker and direct modes, so application code
136
+ does not need separate lifecycle branches. Close a mounted viewer, document,
137
+ or runtime when it is no longer needed so associated native and graphics
138
+ resources can be released promptly.
96
139
 
97
140
  ### Core API
98
141
 
99
142
  | API | Purpose |
100
143
  | --- | --- |
101
- | `createPptViewer()` / `loadPptViewer()` | Loads and verifies the native viewer engine |
102
- | `viewer.mount(target, input, options)` | Renders the complete presentation into Canvas elements |
103
- | `viewer.open(input)` | Opens a `.ppt` document and returns an opaque document handle |
104
- | `document.renderSlide(index, canvas, options)` | Renders one final RGBA slide frame to Canvas |
105
- | `document.close()` | Releases native document memory |
106
- | `getPptPackageManifest()` | Returns package and edition metadata |
144
+ | `createPptViewer(options)` / `loadPptViewer(options)` | Loads and verifies the runtime assets; returns worker or direct mode |
145
+ | `viewer.mount(target, input, options)` | Mounts a complete, virtualized Canvas presentation |
146
+ | `viewer.open(input)` | Asynchronously opens a `.ppt` and returns an opaque document handle |
147
+ | `document.renderSlide(index, canvas, options)` | Asynchronously renders or restores one final slide frame |
148
+ | `document.releaseSlide(index)` | Releases a slide's active raster resources |
149
+ | `document.cacheStats()` / `mounted.cacheStats()` / `viewer.cacheStats()` | Returns current bounded-cache counters |
150
+ | `document.close()` / `mounted.close()` / `viewer.close()` | Releases resources at the corresponding lifecycle boundary |
151
+ | `getPptPackageManifest()` | Returns package, asset, edition, and capability metadata |
107
152
 
108
153
  All public APIs include TypeScript declarations. Parsed document models,
109
154
  records, HTML, SVG, drawing command streams, and unwatermarked frames are not
110
155
  part of the public API.
111
156
 
112
- ### Browser and deployment requirements
157
+ ### Virtualization and worker frame-cache options
158
+
159
+ The relevant defaults are:
160
+
161
+ | Option | Default | Meaning |
162
+ | --- | --- | --- |
163
+ | `virtualize` | `true` | Render the viewport and overscan window instead of retaining every page |
164
+ | `rootMargin` | `150% 0px` | IntersectionObserver overscan around the scroll viewport |
165
+ | `releaseDelayMs` | `1200` | Grace period before a hidden page is persisted and released |
166
+ | `cache.enabled` | `true` | Use IndexedDB when available |
167
+ | `cache.maxBytes` | `256 MiB` | Total final-frame cache budget |
168
+ | `cache.maxEntries` | `200` | Maximum cached slide frames |
169
+ | `cache.maxEntryBytes` | `32 MiB` | Maximum encoded PNG size for one frame |
170
+
171
+ The IndexedDB cache operates in worker mode and is a performance layer, not
172
+ document storage: it contains only final
173
+ watermarked PNG frames, does not retain source `.ppt` bytes, and degrades safely
174
+ when private browsing, storage policy, or quota makes IndexedDB unavailable.
175
+ Synchronous string-based `localStorage` is intentionally not used for frame
176
+ data.
177
+
178
+ ### Runtime assets
179
+
180
+ Static deployments must preserve the following package assets:
181
+
182
+ ```text
183
+ index.mjs
184
+ worker.mjs
185
+ frame-cache.mjs
186
+ ppt-native.wasm
187
+ ppt-font-cjk.otf
188
+ manifest.json
189
+ ```
190
+
191
+ The default locations are resolved relative to `index.mjs`. If a bundler or CDN
192
+ moves assets, configure them explicitly:
113
193
 
114
- - A current browser with ES modules, WebAssembly, Web Crypto, `fetch`, and Canvas 2D
115
- - Static hosting or a bundler that emits `ppt-native.wasm` beside `index.mjs`
116
- - `application/wasm` MIME type for `.wasm` assets
117
- - CSP permission to load the package's own module and WASM asset, including
118
- `'wasm-unsafe-eval'` where required by the browser
119
- - Normal HTTP or HTTPS hosting; the public edition does not restrict origin
194
+ ```js
195
+ const viewer = await createPptViewer({
196
+ workerUrl: new URL('/vendor/file-viewer/ppt/0.3.1/worker.mjs', location.origin),
197
+ wasmUrl: new URL('/vendor/file-viewer/ppt/0.3.1/ppt-native.wasm', location.origin),
198
+ fontUrl: new URL('/vendor/file-viewer/ppt/0.3.1/ppt-font-cjk.otf', location.origin)
199
+ });
200
+ ```
201
+
202
+ For the widest browser compatibility, serve `worker.mjs` and
203
+ `frame-cache.mjs` from the application origin. A separate asset origin for the
204
+ WASM or font must provide CORS permission and be allowed by `connect-src`.
205
+
206
+ `ppt-font-cjk.otf` is a renderer resource, not a CSS `@font-face` dependency.
207
+ It is fetched and verified independently from the smaller WASM engine, so a
208
+ browser or CDN can reuse the font response across presentations and application
209
+ visits.
210
+
211
+ ### MIME, cache, and CSP configuration
212
+
213
+ Use these response types:
214
+
215
+ | Extension | `Content-Type` |
216
+ | --- | --- |
217
+ | `.mjs` | `text/javascript; charset=utf-8` |
218
+ | `.wasm` | `application/wasm` |
219
+ | `.otf` | `font/otf` |
220
+ | `.ppt` | `application/vnd.ms-powerpoint` |
221
+
222
+ Place assets under a versioned or content-addressed path before serving them
223
+ with a long immutable cache lifetime:
224
+
225
+ ```http
226
+ Cache-Control: public, max-age=31536000, immutable
227
+ ```
228
+
229
+ Do not apply `immutable` to an unversioned path that may later serve different
230
+ bytes. The runtime verifies the declared size and SHA-256 of both
231
+ `ppt-native.wasm` and `ppt-font-cjk.otf` before use.
232
+
233
+ A same-origin baseline CSP is:
234
+
235
+ ```http
236
+ Content-Security-Policy:
237
+ default-src 'self';
238
+ script-src 'self' 'wasm-unsafe-eval';
239
+ worker-src 'self';
240
+ connect-src 'self';
241
+ font-src 'self';
242
+ img-src 'self' blob:;
243
+ style-src 'self' 'unsafe-inline';
244
+ ```
120
245
 
121
- ### Compatibility notes
246
+ Extend `connect-src` for approved WASM/font CDNs. Some browsers require
247
+ `'wasm-unsafe-eval'` to compile WebAssembly. The default worker architecture
248
+ does not require `SharedArrayBuffer`, cross-origin isolation, or a blob Worker.
249
+
250
+ ### Browser compatibility
251
+
252
+ - A current browser with ES modules, WebAssembly, Web Crypto, `fetch`, and
253
+ Canvas 2D is required.
254
+ - Worker mode additionally requires module Workers and OffscreenCanvas canvas
255
+ transfer. `worker: 'auto'` falls back to direct mode when these capabilities
256
+ are unavailable.
257
+ - Virtual scrolling uses IntersectionObserver. When it is unavailable, the
258
+ viewer remains functional and renders through its compatibility path.
259
+ - IndexedDB is optional. A disabled or unavailable cache affects revisit speed,
260
+ not rendering correctness.
122
261
 
123
262
  Traditional PowerPoint files may contain macros, ActiveX controls, OLE objects,
124
263
  linked media, or host-specific behaviors that browsers cannot execute. These
125
264
  features are treated as non-executable preview content. Font substitution may
126
- be used when an original document font is not available in the viewer's
127
- embedded fallback set.
265
+ be used when a document font is not available to the viewer.
128
266
 
129
267
  ### Editions and licensing
130
268
 
131
269
  | Edition | Permitted use | Watermark | Origin |
132
270
  | --- | --- | --- | --- |
133
- | Public npm edition | Individual personal, non-commercial, non-organizational use | Mandatory `Flyfish Viewer` on every slide | Any normal HTTP/HTTPS origin |
134
- | Commercial edition | Licensed company, organization, customer project, intranet, SaaS, OEM, or production use | Watermark-free build available according to the purchased agreement | According to the commercial agreement |
271
+ | Public npm edition | Any lawful personal, organizational, commercial, production, SaaS, hosted, or customer-facing use | Mandatory `Flyfish Viewer` on every slide | Any normal HTTP/HTTPS origin |
272
+ | Watermark-free edition | Uses covered by a separate written authorization | Watermark-free build according to the purchased agreement | According to the commercial agreement |
135
273
 
136
- **Commercial use requires a purchased license.** Use by or for a company,
137
- organization, government body, school, nonprofit, team, employer, customer, or
138
- client—including internal evaluation—is commercial use.
274
+ The unmodified public runtime can be bundled, self-hosted, and redistributed as
275
+ an integrated dependency, including File Viewer Full, CDN/IIFE, Docker, offline,
276
+ copy-assets, and GitHub Release distributions. A paid authorization is required
277
+ only to remove, replace, hide, or weaken the required watermark, or to receive a
278
+ separate watermark-free build or source delivery.
139
279
 
140
280
  The public npm edition is proprietary software and is **not licensed under
141
281
  Apache-2.0**. Removing, hiding, covering, replacing, or bypassing the required
142
282
  watermark is prohibited. See [LICENSE](./LICENSE) for the binding terms.
143
283
 
144
- Purchase a commercial license from the
284
+ Purchase watermark-free commercial authorization from the
145
285
  [Flyfish Shop](https://dev.flyfish.group/shop).
146
286
 
147
287
  ### Product links
@@ -159,20 +299,26 @@ Purchase a commercial license from the
159
299
  安装 Microsoft Office、LibreOffice、浏览器插件,也不依赖服务端格式转换。
160
300
 
161
301
  产品适用于文件预览平台、档案与知识管理系统、企业内网、SaaS 产品,以及仍需
162
- 稳定支持传统 PowerPoint 文档的 Web 应用。
302
+ 稳定支持传统 PowerPoint 文档的 Web 应用。面向视口的运行架构既适合普通文档,
303
+ 也适合包含大量页面的演示文稿。
163
304
 
164
305
  ### 产品特点
165
306
 
166
307
  - **原生理解 `.ppt`**:直接读取复合文件、持久化记录、文字、绘图和图片结构。
167
308
  - **专业幻灯片还原**:支持页面尺寸、母版、背景、配色、文字格式、可调节
168
- OfficeArt 形状、填充、渐变、受限的传统 3D 挤出、组合对象、图片、旋转变换
169
- 和图层顺序。
170
- - **原生 WASM Canvas 链路**:解析、布局、光栅化和公网水印合成全部在同一个
171
- WebAssembly 引擎内完成;JavaScript 只将最终 RGBA 画面提交给 Canvas。
309
+ OfficeArt 形状、填充、渐变、组合对象、图片、旋转变换、图层顺序,以及兼容的
310
+ 传统 3D 效果子集。
311
+ - **响应式 Worker 链路**:浏览器能力允许时,默认通过 Module Worker、
312
+ WebAssembly OffscreenCanvas 完成解析和光栅化,避免占用主 UI 线程。
313
+ - **大文档虚拟滚动**:仅主动渲染视口和预加载区页面;不可见页面延迟释放 Canvas
314
+ 图形缓冲,不随总页数持续堆积。
315
+ - **有界页面缓存**:可将最终、带原生强制水印的 PNG 页面保存到 IndexedDB LRU,
316
+ 并设置总容量、条目数和单页容量上限;页面数据明确不使用 `localStorage`。
317
+ - **独立 CJK 字体资源**:CJK 回退字体与 WASM 引擎分开加载和完整性校验,可使用
318
+ 浏览器或 CDN 长期缓存,减少重复下载和引擎体积。
172
319
  - **文档本地处理**:公网运行时不要求将文档上传到第三方转换服务。
173
- - **引擎完整性校验**:执行前自动校验原生 WASM 的精确 SHA-256。
174
- - **易于集成**:提供 ESM、TypeScript 类型,无 JavaScript 运行时依赖;既可
175
- 挂载完整预览器,也可单独渲染指定页。
320
+ - **易于集成**:提供 ESM、TypeScript 类型且无 JavaScript 运行时依赖,既可挂载
321
+ 完整预览器,也可按需渲染指定页。
176
322
 
177
323
  ### 格式范围
178
324
 
@@ -185,94 +331,168 @@ Purchase a commercial license from the
185
331
  npm install @file-viewer/ppt
186
332
  ```
187
333
 
188
- ### 快速开始
189
-
190
- ```html
191
- <input id="ppt-file" type="file" accept=".ppt,application/vnd.ms-powerpoint">
192
- <div id="ppt-viewer"></div>
193
- ```
334
+ ### 快速开始:虚拟化完整预览
194
335
 
195
336
  ```js
196
337
  import { createPptViewer } from '@file-viewer/ppt';
197
338
 
198
- const viewer = await createPptViewer();
199
- const input = document.querySelector('#ppt-file');
200
-
201
- input.addEventListener('change', async () => {
202
- const file = input.files?.[0];
203
- if (!file) return;
339
+ const viewer = await createPptViewer({
340
+ worker: 'auto',
341
+ cache: {
342
+ enabled: true,
343
+ maxBytes: 256 * 1024 * 1024,
344
+ maxEntries: 200,
345
+ maxEntryBytes: 32 * 1024 * 1024
346
+ }
347
+ });
204
348
 
205
- await viewer.mount('#ppt-viewer', await file.arrayBuffer(), {
349
+ const response = await fetch('/documents/presentation.ppt');
350
+ const mounted = await viewer.mount(
351
+ '#ppt-viewer',
352
+ await response.arrayBuffer(),
353
+ {
206
354
  scale: 1,
207
- pixelRatio: window.devicePixelRatio
208
- });
209
- });
355
+ pixelRatio: window.devicePixelRatio,
356
+ virtualize: true,
357
+ rootMargin: '150% 0px',
358
+ releaseDelayMs: 1200
359
+ }
360
+ );
361
+
362
+ console.log(viewer.mode); // "worker" 或 "direct"
363
+ console.log(await mounted.cacheStats());
364
+
365
+ // 预览不再使用时:
366
+ await mounted.close();
367
+ await viewer.close();
210
368
  ```
211
369
 
212
- `mount()` 会为每一页创建 Canvas 并渐进渲染。公网水印版不需要 license 文件,
213
- 也不限制正常 HTTP/HTTPS origin。
370
+ `worker: 'auto'` `virtualize: true` 均为默认值。支持 Module Worker 与
371
+ OffscreenCanvas 的浏览器会把解析与渲染放到 Worker;否则自动使用兼容的直接
372
+ 渲染模式。完整预览会创建稳定的页面容器,仅渲染视口附近内容,并在页面离开
373
+ 预加载区后释放其光栅资源。
214
374
 
215
- ### 单页渲染
375
+ IndexedDB 可用时,再次浏览已释放页面可优先恢复最终水印 PNG。浏览器禁用
376
+ IndexedDB、隐私模式限制存储或缓存被配额机制清理时,不影响原生重新渲染。该
377
+ IndexedDB 缓存用于 Worker 模式;直接模式会在页面再次进入视口时重新渲染。
216
378
 
217
- ```js
218
- const response = await fetch('/documents/presentation.ppt');
219
- const pptDocument = viewer.open(await response.arrayBuffer());
379
+ 超大文件可在创建 viewer 时设置 `transferInputOwnership: true`,把完整
380
+ `ArrayBuffer` 的所有权直接转移给 Worker,避免主线程额外复制。该缓冲区随后会
381
+ detach,仅应在业务不再读取原缓冲区时启用。
220
382
 
383
+ ### 单页渲染与异步生命周期
384
+
385
+ ```js
386
+ const pptDocument = await viewer.open(await response.arrayBuffer());
221
387
  const canvas = document.querySelector('canvas');
222
- pptDocument.renderSlide(0, canvas, { scale: 1.25 });
223
388
 
224
- console.log(pptDocument.slideCount, pptDocument.width, pptDocument.height);
225
- pptDocument.close();
389
+ const result = await pptDocument.renderSlide(0, canvas, { scale: 1.25 });
390
+ console.log(result.source); // Worker 模式为 "native" 或 "indexeddb"
391
+
392
+ await pptDocument.releaseSlide(0);
393
+ console.log(await pptDocument.cacheStats());
394
+ await pptDocument.close();
395
+ await viewer.close();
226
396
  ```
227
397
 
228
- 文档不再使用时请调用 `close()`,以便立即释放原生内存。
398
+ Worker 与直接模式采用相同的异步 API。文档、完整挂载预览或运行时不再使用时,
399
+ 请 `await close()`,以便及时释放原生内存、Worker 和图形资源。
229
400
 
230
401
  ### 核心 API
231
402
 
232
403
  | API | 用途 |
233
404
  | --- | --- |
234
- | `createPptViewer()` / `loadPptViewer()` | 加载并校验原生预览引擎 |
235
- | `viewer.mount(target, input, options)` | 将完整演示文稿渲染为 Canvas 列表 |
236
- | `viewer.open(input)` | 打开 `.ppt` 并返回不透明文档句柄 |
237
- | `document.renderSlide(index, canvas, options)` | 将单页最终 RGBA 画面渲染到 Canvas |
238
- | `document.close()` | 释放原生文档内存 |
239
- | `getPptPackageManifest()` | 返回包与版本信息 |
405
+ | `createPptViewer(options)` / `loadPptViewer(options)` | 加载并校验运行资源,返回 Worker 或直接模式 |
406
+ | `viewer.mount(target, input, options)` | 挂载完整、支持虚拟滚动的 Canvas 预览 |
407
+ | `viewer.open(input)` | 异步打开 `.ppt` 并返回不透明文档句柄 |
408
+ | `document.renderSlide(index, canvas, options)` | 异步渲染或恢复指定页最终画面 |
409
+ | `document.releaseSlide(index)` | 释放指定页当前光栅资源 |
410
+ | `cacheStats()` | 在文档、挂载对象或运行时级别读取缓存统计 |
411
+ | `close()` | 在对应生命周期边界释放资源 |
412
+ | `getPptPackageManifest()` | 返回包、资源、版本和能力信息 |
240
413
 
241
414
  所有公开 API 均提供 TypeScript 类型。解析后的文档模型、记录、HTML、SVG、
242
415
  绘图指令流和无水印画面均不属于公开 API。
243
416
 
244
- ### 浏览器与部署要求
417
+ ### 虚拟滚动与页面缓存
418
+
419
+ 默认仅保留视口及 `150% 0px` 预加载区;页面离开该区域 1200ms 后会被缓存并
420
+ 释放。IndexedDB LRU 默认总容量上限为 256MiB、最多 200 页、单页编码 PNG
421
+ 最多 32MiB,均可通过 `cache` 选项调整。
422
+
423
+ IndexedDB 缓存用于 Worker 模式,并且只是性能加速层;它只保存最终水印 PNG,
424
+ 不保存源 `.ppt` 文件或中间文档
425
+ 数据;不可用或被浏览器清理时会安全退化为重新渲染。同步、字符串化且容量有限的
426
+ `localStorage` 不用于页面缓存。
427
+
428
+ ### 静态资源与部署
429
+
430
+ 静态部署需完整保留以下资源:
431
+
432
+ ```text
433
+ index.mjs
434
+ worker.mjs
435
+ frame-cache.mjs
436
+ ppt-native.wasm
437
+ ppt-font-cjk.otf
438
+ manifest.json
439
+ ```
440
+
441
+ 默认地址相对 `index.mjs` 解析。使用打包工具或 CDN 改变目录时,请通过
442
+ `workerUrl`、`wasmUrl`、`fontUrl` 指定实际地址。为获得最广泛的浏览器兼容性,
443
+ 建议 `worker.mjs` 与 `frame-cache.mjs` 保持同源;WASM 或字体使用独立 CDN
444
+ 时,需要正确配置 CORS 和 `connect-src`。
445
+
446
+ 推荐 MIME:`.mjs` 使用 `text/javascript; charset=utf-8`,`.wasm` 使用
447
+ `application/wasm`,`.otf` 使用 `font/otf`,`.ppt` 使用
448
+ `application/vnd.ms-powerpoint`。
449
+
450
+ 将资源发布在版本化或内容寻址目录(如 `/vendor/file-viewer/ppt/0.3.1/`)后,
451
+ 可配置:
452
+
453
+ ```http
454
+ Cache-Control: public, max-age=31536000, immutable
455
+ ```
456
+
457
+ 不要为可能替换内容的非版本化地址设置 `immutable`。`ppt-font-cjk.otf` 是渲染器
458
+ 资源而不是 CSS `@font-face` 字体;它会独立加载和校验,因此可在不同 PPT 文档及
459
+ 多次访问之间复用浏览器/CDN 缓存。
460
+
461
+ 同源部署的基础 CSP 需要允许包模块、Module Worker、资源请求和 WebAssembly;
462
+ 部分浏览器要求在 `script-src` 中加入 `'wasm-unsafe-eval'`。若字体或 WASM 使用
463
+ 独立 CDN,还需将该域名加入 `connect-src`。默认 Worker 架构不要求
464
+ `SharedArrayBuffer`、跨域隔离或 Blob Worker。
245
465
 
246
- - 支持 ES Modules、WebAssembly、Web Crypto、`fetch` 和 Canvas 2D 的现代浏览器
247
- - 能将 `ppt-native.wasm` 与 `index.mjs` 一同发布的静态服务器或打包工具
248
- - 为 `.wasm` 配置 `application/wasm` MIME 类型
249
- - CSP 允许加载包自身的模块和 WASM 资源;浏览器要求时需允许
250
- `'wasm-unsafe-eval'`
251
- - 使用正常 HTTP 或 HTTPS 部署;公网版不限制 origin
466
+ ### 浏览器兼容性
252
467
 
253
- ### 兼容性说明
468
+ - 基础要求:ES Modules、WebAssembly、Web Crypto、`fetch` 和 Canvas 2D。
469
+ - Worker 模式还需要 Module Worker 与 OffscreenCanvas Canvas 转移能力;
470
+ `worker: 'auto'` 会在不支持时回退到直接模式。
471
+ - 虚拟滚动使用 IntersectionObserver;不可用时预览器仍会通过兼容路径工作。
472
+ - IndexedDB 是可选加速能力,不可用只影响页面再次访问速度,不影响渲染正确性。
254
473
 
255
474
  传统 PPT 可能包含宏、ActiveX、OLE、链接媒体或依赖桌面宿主的行为,浏览器无法
256
- 执行这些能力;预览器会把它们作为不可执行内容安全处理。原始字体不在内置回退
257
- 字体集时,会使用确定性的字体替代。
475
+ 执行这些能力;预览器会把它们作为不可执行内容处理。原始字体不可用时可能使用
476
+ 兼容字体替代。
258
477
 
259
478
  ### 版本与授权
260
479
 
261
480
  | 版本 | 允许用途 | 水印 | Origin |
262
481
  | --- | --- | --- | --- |
263
- | 公网 npm 版 | 自然人个人、非商业、非组织用途 | 每页强制显示 `Flyfish Viewer` | 任意正常 HTTP/HTTPS origin |
264
- | 商业版 | 已授权的公司、组织、客户项目、内网、SaaS、OEM 或生产用途 | 按商业协议提供无公网水印构建 | 按商业协议执行 |
482
+ | 公网 npm 版 | 任何合法的个人、组织、商业、生产、SaaS、内网或客户项目用途 | 每页强制显示 `Flyfish Viewer` | 任意正常 HTTP/HTTPS origin |
483
+ | 无水印版 | 书面商业授权覆盖的用途 | 按协议提供无水印构建 | 按商业协议执行 |
265
484
 
266
- **任何商业用途均需购买授权。** 公司、组织、政府、学校、非营利机构、团队、
267
- 雇主、客户或委托项目的使用,包括内部评估,均属于商业用途。
485
+ 未修改的公网运行时可以作为应用依赖打包、自托管和再分发,包括 File Viewer Full、
486
+ CDN/IIFE、Docker、离线包、copy-assets 和 GitHub Release。只有移除、替换、隐藏或
487
+ 弱化强制水印,或取得单独的无水印构建/源码交付时,才需要书面商业授权。
268
488
 
269
489
  公网 npm 版是专有软件,**不适用 Apache-2.0**。禁止删除、隐藏、遮挡、替换或
270
490
  绕过强制水印。具有法律约束力的完整条款见 [LICENSE](./LICENSE)。
271
491
 
272
- 商业授权请前往 [Flyfish 商店](https://dev.flyfish.group/shop)购买。
492
+ 无水印商业授权请前往 [Flyfish 商店](https://dev.flyfish.group/shop)购买。
273
493
 
274
494
  ### 产品链接
275
495
 
276
496
  - [产品文档](https://officejs-doc.pages.dev)
277
- - [商业授权](https://dev.flyfish.group/shop)
497
+ - [无水印商业授权](https://dev.flyfish.group/shop)
278
498
  - [问题反馈](https://github.com/flyfish-dev/office-preview-js/issues)