@file-viewer/ppt 0.2.0 → 0.3.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/NOTICE CHANGED
@@ -25,8 +25,9 @@ capability, source-delivery rights, or readable parser/renderer source.
25
25
 
26
26
  Commercial licensing: https://dev.flyfish.group/shop
27
27
 
28
- The native engine embeds deterministic fallback fonts. Their copyright notices
29
- and full font licenses are appended to this NOTICE in the published package.
28
+ The package ships deterministic fallback font resources separately from the
29
+ native engine. Their copyright notices and full font licenses are appended to
30
+ this NOTICE in the published package.
30
31
 
31
32
  THIRD-PARTY FONT NOTICES
32
33
 
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,80 +58,211 @@ 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.0/worker.mjs', location.origin),
197
+ wasmUrl: new URL('/vendor/file-viewer/ppt/0.3.0/ppt-native.wasm', location.origin),
198
+ fontUrl: new URL('/vendor/file-viewer/ppt/0.3.0/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
 
@@ -159,20 +297,26 @@ Purchase a commercial license from the
159
297
  安装 Microsoft Office、LibreOffice、浏览器插件,也不依赖服务端格式转换。
160
298
 
161
299
  产品适用于文件预览平台、档案与知识管理系统、企业内网、SaaS 产品,以及仍需
162
- 稳定支持传统 PowerPoint 文档的 Web 应用。
300
+ 稳定支持传统 PowerPoint 文档的 Web 应用。面向视口的运行架构既适合普通文档,
301
+ 也适合包含大量页面的演示文稿。
163
302
 
164
303
  ### 产品特点
165
304
 
166
305
  - **原生理解 `.ppt`**:直接读取复合文件、持久化记录、文字、绘图和图片结构。
167
306
  - **专业幻灯片还原**:支持页面尺寸、母版、背景、配色、文字格式、可调节
168
- OfficeArt 形状、填充、渐变、受限的传统 3D 挤出、组合对象、图片、旋转变换
169
- 和图层顺序。
170
- - **原生 WASM Canvas 链路**:解析、布局、光栅化和公网水印合成全部在同一个
171
- WebAssembly 引擎内完成;JavaScript 只将最终 RGBA 画面提交给 Canvas。
307
+ OfficeArt 形状、填充、渐变、组合对象、图片、旋转变换、图层顺序,以及兼容的
308
+ 传统 3D 效果子集。
309
+ - **响应式 Worker 链路**:浏览器能力允许时,默认通过 Module Worker、
310
+ WebAssembly OffscreenCanvas 完成解析和光栅化,避免占用主 UI 线程。
311
+ - **大文档虚拟滚动**:仅主动渲染视口和预加载区页面;不可见页面延迟释放 Canvas
312
+ 图形缓冲,不随总页数持续堆积。
313
+ - **有界页面缓存**:可将最终、带原生强制水印的 PNG 页面保存到 IndexedDB LRU,
314
+ 并设置总容量、条目数和单页容量上限;页面数据明确不使用 `localStorage`。
315
+ - **独立 CJK 字体资源**:CJK 回退字体与 WASM 引擎分开加载和完整性校验,可使用
316
+ 浏览器或 CDN 长期缓存,减少重复下载和引擎体积。
172
317
  - **文档本地处理**:公网运行时不要求将文档上传到第三方转换服务。
173
- - **引擎完整性校验**:执行前自动校验原生 WASM 的精确 SHA-256。
174
- - **易于集成**:提供 ESM、TypeScript 类型,无 JavaScript 运行时依赖;既可
175
- 挂载完整预览器,也可单独渲染指定页。
318
+ - **易于集成**:提供 ESM、TypeScript 类型且无 JavaScript 运行时依赖,既可挂载
319
+ 完整预览器,也可按需渲染指定页。
176
320
 
177
321
  ### 格式范围
178
322
 
@@ -185,76 +329,149 @@ Purchase a commercial license from the
185
329
  npm install @file-viewer/ppt
186
330
  ```
187
331
 
188
- ### 快速开始
189
-
190
- ```html
191
- <input id="ppt-file" type="file" accept=".ppt,application/vnd.ms-powerpoint">
192
- <div id="ppt-viewer"></div>
193
- ```
332
+ ### 快速开始:虚拟化完整预览
194
333
 
195
334
  ```js
196
335
  import { createPptViewer } from '@file-viewer/ppt';
197
336
 
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;
337
+ const viewer = await createPptViewer({
338
+ worker: 'auto',
339
+ cache: {
340
+ enabled: true,
341
+ maxBytes: 256 * 1024 * 1024,
342
+ maxEntries: 200,
343
+ maxEntryBytes: 32 * 1024 * 1024
344
+ }
345
+ });
204
346
 
205
- await viewer.mount('#ppt-viewer', await file.arrayBuffer(), {
347
+ const response = await fetch('/documents/presentation.ppt');
348
+ const mounted = await viewer.mount(
349
+ '#ppt-viewer',
350
+ await response.arrayBuffer(),
351
+ {
206
352
  scale: 1,
207
- pixelRatio: window.devicePixelRatio
208
- });
209
- });
353
+ pixelRatio: window.devicePixelRatio,
354
+ virtualize: true,
355
+ rootMargin: '150% 0px',
356
+ releaseDelayMs: 1200
357
+ }
358
+ );
359
+
360
+ console.log(viewer.mode); // "worker" 或 "direct"
361
+ console.log(await mounted.cacheStats());
362
+
363
+ // 预览不再使用时:
364
+ await mounted.close();
365
+ await viewer.close();
210
366
  ```
211
367
 
212
- `mount()` 会为每一页创建 Canvas 并渐进渲染。公网水印版不需要 license 文件,
213
- 也不限制正常 HTTP/HTTPS origin。
368
+ `worker: 'auto'` `virtualize: true` 均为默认值。支持 Module Worker 与
369
+ OffscreenCanvas 的浏览器会把解析与渲染放到 Worker;否则自动使用兼容的直接
370
+ 渲染模式。完整预览会创建稳定的页面容器,仅渲染视口附近内容,并在页面离开
371
+ 预加载区后释放其光栅资源。
214
372
 
215
- ### 单页渲染
373
+ IndexedDB 可用时,再次浏览已释放页面可优先恢复最终水印 PNG。浏览器禁用
374
+ IndexedDB、隐私模式限制存储或缓存被配额机制清理时,不影响原生重新渲染。该
375
+ IndexedDB 缓存用于 Worker 模式;直接模式会在页面再次进入视口时重新渲染。
216
376
 
217
- ```js
218
- const response = await fetch('/documents/presentation.ppt');
219
- const pptDocument = viewer.open(await response.arrayBuffer());
377
+ 超大文件可在创建 viewer 时设置 `transferInputOwnership: true`,把完整
378
+ `ArrayBuffer` 的所有权直接转移给 Worker,避免主线程额外复制。该缓冲区随后会
379
+ detach,仅应在业务不再读取原缓冲区时启用。
220
380
 
381
+ ### 单页渲染与异步生命周期
382
+
383
+ ```js
384
+ const pptDocument = await viewer.open(await response.arrayBuffer());
221
385
  const canvas = document.querySelector('canvas');
222
- pptDocument.renderSlide(0, canvas, { scale: 1.25 });
223
386
 
224
- console.log(pptDocument.slideCount, pptDocument.width, pptDocument.height);
225
- pptDocument.close();
387
+ const result = await pptDocument.renderSlide(0, canvas, { scale: 1.25 });
388
+ console.log(result.source); // Worker 模式为 "native" 或 "indexeddb"
389
+
390
+ await pptDocument.releaseSlide(0);
391
+ console.log(await pptDocument.cacheStats());
392
+ await pptDocument.close();
393
+ await viewer.close();
226
394
  ```
227
395
 
228
- 文档不再使用时请调用 `close()`,以便立即释放原生内存。
396
+ Worker 与直接模式采用相同的异步 API。文档、完整挂载预览或运行时不再使用时,
397
+ 请 `await close()`,以便及时释放原生内存、Worker 和图形资源。
229
398
 
230
399
  ### 核心 API
231
400
 
232
401
  | API | 用途 |
233
402
  | --- | --- |
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()` | 返回包与版本信息 |
403
+ | `createPptViewer(options)` / `loadPptViewer(options)` | 加载并校验运行资源,返回 Worker 或直接模式 |
404
+ | `viewer.mount(target, input, options)` | 挂载完整、支持虚拟滚动的 Canvas 预览 |
405
+ | `viewer.open(input)` | 异步打开 `.ppt` 并返回不透明文档句柄 |
406
+ | `document.renderSlide(index, canvas, options)` | 异步渲染或恢复指定页最终画面 |
407
+ | `document.releaseSlide(index)` | 释放指定页当前光栅资源 |
408
+ | `cacheStats()` | 在文档、挂载对象或运行时级别读取缓存统计 |
409
+ | `close()` | 在对应生命周期边界释放资源 |
410
+ | `getPptPackageManifest()` | 返回包、资源、版本和能力信息 |
240
411
 
241
412
  所有公开 API 均提供 TypeScript 类型。解析后的文档模型、记录、HTML、SVG、
242
413
  绘图指令流和无水印画面均不属于公开 API。
243
414
 
244
- ### 浏览器与部署要求
415
+ ### 虚拟滚动与页面缓存
416
+
417
+ 默认仅保留视口及 `150% 0px` 预加载区;页面离开该区域 1200ms 后会被缓存并
418
+ 释放。IndexedDB LRU 默认总容量上限为 256MiB、最多 200 页、单页编码 PNG
419
+ 最多 32MiB,均可通过 `cache` 选项调整。
420
+
421
+ IndexedDB 缓存用于 Worker 模式,并且只是性能加速层;它只保存最终水印 PNG,
422
+ 不保存源 `.ppt` 文件或中间文档
423
+ 数据;不可用或被浏览器清理时会安全退化为重新渲染。同步、字符串化且容量有限的
424
+ `localStorage` 不用于页面缓存。
425
+
426
+ ### 静态资源与部署
427
+
428
+ 静态部署需完整保留以下资源:
429
+
430
+ ```text
431
+ index.mjs
432
+ worker.mjs
433
+ frame-cache.mjs
434
+ ppt-native.wasm
435
+ ppt-font-cjk.otf
436
+ manifest.json
437
+ ```
438
+
439
+ 默认地址相对 `index.mjs` 解析。使用打包工具或 CDN 改变目录时,请通过
440
+ `workerUrl`、`wasmUrl`、`fontUrl` 指定实际地址。为获得最广泛的浏览器兼容性,
441
+ 建议 `worker.mjs` 与 `frame-cache.mjs` 保持同源;WASM 或字体使用独立 CDN
442
+ 时,需要正确配置 CORS 和 `connect-src`。
443
+
444
+ 推荐 MIME:`.mjs` 使用 `text/javascript; charset=utf-8`,`.wasm` 使用
445
+ `application/wasm`,`.otf` 使用 `font/otf`,`.ppt` 使用
446
+ `application/vnd.ms-powerpoint`。
447
+
448
+ 将资源发布在版本化或内容寻址目录(如 `/vendor/file-viewer/ppt/0.3.0/`)后,
449
+ 可配置:
450
+
451
+ ```http
452
+ Cache-Control: public, max-age=31536000, immutable
453
+ ```
454
+
455
+ 不要为可能替换内容的非版本化地址设置 `immutable`。`ppt-font-cjk.otf` 是渲染器
456
+ 资源而不是 CSS `@font-face` 字体;它会独立加载和校验,因此可在不同 PPT 文档及
457
+ 多次访问之间复用浏览器/CDN 缓存。
458
+
459
+ 同源部署的基础 CSP 需要允许包模块、Module Worker、资源请求和 WebAssembly;
460
+ 部分浏览器要求在 `script-src` 中加入 `'wasm-unsafe-eval'`。若字体或 WASM 使用
461
+ 独立 CDN,还需将该域名加入 `connect-src`。默认 Worker 架构不要求
462
+ `SharedArrayBuffer`、跨域隔离或 Blob Worker。
245
463
 
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
464
+ ### 浏览器兼容性
252
465
 
253
- ### 兼容性说明
466
+ - 基础要求:ES Modules、WebAssembly、Web Crypto、`fetch` 和 Canvas 2D。
467
+ - Worker 模式还需要 Module Worker 与 OffscreenCanvas Canvas 转移能力;
468
+ `worker: 'auto'` 会在不支持时回退到直接模式。
469
+ - 虚拟滚动使用 IntersectionObserver;不可用时预览器仍会通过兼容路径工作。
470
+ - IndexedDB 是可选加速能力,不可用只影响页面再次访问速度,不影响渲染正确性。
254
471
 
255
472
  传统 PPT 可能包含宏、ActiveX、OLE、链接媒体或依赖桌面宿主的行为,浏览器无法
256
- 执行这些能力;预览器会把它们作为不可执行内容安全处理。原始字体不在内置回退
257
- 字体集时,会使用确定性的字体替代。
473
+ 执行这些能力;预览器会把它们作为不可执行内容处理。原始字体不可用时可能使用
474
+ 兼容字体替代。
258
475
 
259
476
  ### 版本与授权
260
477