@coco-vexel/coco-office 0.0.0-stage → 1.0.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.
Files changed (76) hide show
  1. package/LICENSE +202 -0
  2. package/README.md +120 -2
  3. package/THIRD_PARTY_NOTICES.md +1188 -0
  4. package/dist/excel-worker-browser.cjs +6544 -0
  5. package/dist/excel-worker-browser.cjs.map +1 -0
  6. package/dist/excel-worker-browser.d.cts +2 -0
  7. package/dist/excel-worker-browser.d.ts +2 -0
  8. package/dist/excel-worker-browser.js +6523 -0
  9. package/dist/excel-worker-browser.js.map +1 -0
  10. package/dist/excel-worker.cjs +6547 -0
  11. package/dist/excel-worker.cjs.map +1 -0
  12. package/dist/excel-worker.d.cts +2 -0
  13. package/dist/excel-worker.d.ts +2 -0
  14. package/dist/excel-worker.js +6526 -0
  15. package/dist/excel-worker.js.map +1 -0
  16. package/dist/excel.cjs +12523 -0
  17. package/dist/excel.cjs.map +1 -0
  18. package/dist/excel.d.cts +2252 -0
  19. package/dist/excel.d.ts +2252 -0
  20. package/dist/excel.js +12368 -0
  21. package/dist/excel.js.map +1 -0
  22. package/dist/index.cjs +19 -0
  23. package/dist/index.cjs.map +1 -0
  24. package/dist/index.d.cts +2 -0
  25. package/dist/index.d.ts +2 -0
  26. package/dist/index.js +1 -0
  27. package/dist/index.js.map +1 -0
  28. package/dist/kernel-worker-browser.cjs +12304 -0
  29. package/dist/kernel-worker-browser.cjs.map +1 -0
  30. package/dist/kernel-worker-browser.d.cts +2 -0
  31. package/dist/kernel-worker-browser.d.ts +2 -0
  32. package/dist/kernel-worker-browser.js +12283 -0
  33. package/dist/kernel-worker-browser.js.map +1 -0
  34. package/dist/kernel-worker.cjs +12309 -0
  35. package/dist/kernel-worker.cjs.map +1 -0
  36. package/dist/kernel-worker.d.cts +2 -0
  37. package/dist/kernel-worker.d.ts +2 -0
  38. package/dist/kernel-worker.js +12288 -0
  39. package/dist/kernel-worker.js.map +1 -0
  40. package/dist/pack.cjs +459 -0
  41. package/dist/pack.cjs.map +1 -0
  42. package/dist/pack.d.cts +119 -0
  43. package/dist/pack.d.ts +119 -0
  44. package/dist/pack.js +408 -0
  45. package/dist/pack.js.map +1 -0
  46. package/dist/ppt.cjs +7427 -0
  47. package/dist/ppt.cjs.map +1 -0
  48. package/dist/ppt.d.cts +1432 -0
  49. package/dist/ppt.d.ts +1432 -0
  50. package/dist/ppt.js +7355 -0
  51. package/dist/ppt.js.map +1 -0
  52. package/dist/shared.cjs +105 -0
  53. package/dist/shared.cjs.map +1 -0
  54. package/dist/shared.d.cts +31 -0
  55. package/dist/shared.d.ts +31 -0
  56. package/dist/shared.js +81 -0
  57. package/dist/shared.js.map +1 -0
  58. package/dist/types-BVkkdcfh.d.cts +54 -0
  59. package/dist/types-BVkkdcfh.d.ts +54 -0
  60. package/dist/types-C2vQfM-b.d.cts +102 -0
  61. package/dist/types-C2vQfM-b.d.ts +102 -0
  62. package/dist/view-DAkeR0RW.d.ts +1199 -0
  63. package/dist/view-DX2YAG5A.d.cts +1199 -0
  64. package/dist/word-view.cjs +1824 -0
  65. package/dist/word-view.cjs.map +1 -0
  66. package/dist/word-view.d.cts +2 -0
  67. package/dist/word-view.d.ts +2 -0
  68. package/dist/word-view.js +1791 -0
  69. package/dist/word-view.js.map +1 -0
  70. package/dist/word.cjs +14106 -0
  71. package/dist/word.cjs.map +1 -0
  72. package/dist/word.d.cts +3042 -0
  73. package/dist/word.d.ts +3042 -0
  74. package/dist/word.js +14011 -0
  75. package/dist/word.js.map +1 -0
  76. package/package.json +103 -3
@@ -0,0 +1,3042 @@
1
+ import { S as StoryId, P as PackageIndices, L as ListParagraphsOptions, a as ListResult, b as ParagraphInfo, C as CommentInfo, c as CommentId$1, d as ListRevisionsOptions, R as RevisionInfo, e as ListStylesOptions, f as StyleInfo, g as ListTablesOptions, T as TableInfo, h as TableVerbatim, i as ListDrawingsOptions, D as DrawingInfo, I as ImageBytesResult, j as SectionInfo, k as RowHeight, l as TableCellInfo } from './view-DX2YAG5A.cjs';
2
+ export { A as A_NS, B as BookmarkEntry, m as BookmarkLoadError, n as BookmarkLoadErrorCode, o as CHART_NS, p as CommentEntry, q as DEFAULT_PAGINATION, r as DGM_NS, s as DrawingAnchoringMode, t as DrawingKind, u as DrawingPosition, v as DrawingPositionAxis, w as DrawingWrapType, H as HeaderFooterRef, x as HeaderFooterType, y as ListParagraphsFilter, z as ListParagraphsPagination, E as ListParagraphsScope, F as ListParagraphsTextFormat, G as ListStoriesOptions, M as MC_NS, J as PIC_NS, K as PKG_NS, N as PREVIEW_CHAR_LIMIT, O as ParagraphFormat, Q as R_NS, U as RunTextOptions, V as SectionType, W as SplitResult, X as Story, Y as StoryKind, Z as StyleType, _ as TableCellBlockInfo, $ as TableVerbatimImage, a0 as VML_NS, a1 as W14_NS, a2 as WPC_NS, a3 as WPG_NS, a4 as WPS_NS, a5 as WP_NS, a6 as W_NS, a7 as XML_NS, a8 as buildDrawingIndex, a9 as buildIndices, aa as buildParagraphInfo, ab as buildStylesIndex, ac as findStoryFor, ad as getComment, ae as getDrawingById, af as getParagraphByParaId, ag as getParagraphRuns, ah as getParagraphText, ai as getRunText, aj as getStoryParagraphs, ak as getStyleById, al as getTableById, am as getTableVerbatim, an as hasDrawingAncestor, ao as listComments, ap as listDrawings, aq as listParagraphs, ar as listRevisions, as as listSections, at as listStories, au as listStyles, av as listTables, aw as resolveScope, ax as splitRunAt } from './view-DX2YAG5A.cjs';
3
+ import { a as Package } from './types-BVkkdcfh.cjs';
4
+ import { b as SnapshotInfo, C as ChangeLog, S as SnapshotStorageAdapter } from './types-C2vQfM-b.cjs';
5
+
6
+ /**
7
+ * w14:paraId 装载时 normalize —— docs/03 §11.2 / §13.6。
8
+ *
9
+ * 语义:
10
+ * - 扫 Package 里所有 XML part,对缺 `w14:paraId` 的 `<w:p>` 分配随机 8 位十六进制 id
11
+ * - **package 全局唯一**(body / headers / footers / footnotes / endnotes / comments 同集合)
12
+ * - 发生分配的 part 被 markDirty,便于后续 toZip / toFlatOpc 重 serialize
13
+ * - 10 万段落 ≈ 40ms(实测基线,见 bench/xml-stack-worker)
14
+ */
15
+
16
+ interface EnsureParaIdsResult {
17
+ /** 本次新分配的 paraId 数量 */
18
+ added: number;
19
+ /** 扫描到的 <w:p> 总数(含既有 paraId) */
20
+ total: number;
21
+ /** 发生分配的 part path 列表 */
22
+ touchedParts: string[];
23
+ }
24
+ /**
25
+ * 为 Package 内所有缺 w14:paraId 的 <w:p> 分配随机 id(package 全局唯一)。
26
+ *
27
+ * 发生分配的 part 会被 markDirty。
28
+ */
29
+ declare function ensureParaIds(pkg: Package): EnsureParaIdsResult;
30
+
31
+ /**
32
+ * Bookmark 只读查询(docs/03.1 §1.5 / §2,#25)。
33
+ *
34
+ * 基于 `PackageIndices.bookmarkIdx`(#13 建好)做 O(1) 反查,没有任何 fontoxpath
35
+ * 调用。rangeKind 判定走 DOM 遍历(孩子顺序 + 同 `<w:p>` 判断)。
36
+ *
37
+ * 三类 rangeKind(docs/03.1 §1.5):
38
+ * - `'paragraph'` —— start / end 在**同一 `<w:p>`** 中,且 `<w:bookmarkStart>`
39
+ * 之前没有任何内容节点、`<w:bookmarkEnd>` 之后也没有 —— 即书签覆盖整段的"内容区"
40
+ * - `'text'` —— 同一 `<w:p>`,但 start / end 不在段首/段尾(书签仅覆盖段内文本片段)
41
+ * - `'complex'` —— 跨段落、缺 end、start / end parent 不同、或 parent 不是 `<w:p>`
42
+ * (表 cell、body 直子等),core 不简单建模,只标 kind
43
+ *
44
+ * `hidden`:name 以 `_` 开头(如 `_Toc123` / `_GoBack` / `_Hlk12345`)。`listBookmarks`
45
+ * 默认过滤;`getBookmark(name)` 不过滤(调用方已知 name)。
46
+ */
47
+
48
+ type BookmarkName$1 = string;
49
+ interface BookmarkInfo {
50
+ name: BookmarkName$1;
51
+ story: StoryId;
52
+ rangeKind: 'paragraph' | 'text' | 'complex';
53
+ /** rangeKind = 'paragraph' | 'text' 时给(书签所属的段落 paraId,大写 8 hex) */
54
+ paraId?: string;
55
+ /** rangeKind = 'text' 时给(start / end 之间所有 `<w:t>` 的纯文本拼接) */
56
+ text?: string;
57
+ /** name 以 `_` 开头时 true;否则缺字段 */
58
+ hidden?: boolean;
59
+ }
60
+ interface ListBookmarksOptions {
61
+ /** 默认 false。true 时返回所有书签,包括 `_` 开头的隐藏书签 */
62
+ includeHidden?: boolean;
63
+ /**
64
+ * 名字前缀过滤(大小写敏感)。提供时只返回 `name.startsWith(prefix)` 的书签。
65
+ *
66
+ * 配合 `InsertParagraphSpec.bookmark.prefix` 的规则化命名(`{prefix}_{anchorParaId}` /
67
+ * 冲突时 `{prefix}_{anchorParaId}_2` 等)使用,可批量回查"某语义标签下的所有书签"。
68
+ * `_` 开头的隐藏书签若未设置 `includeHidden=true` 仍被过滤(prefix 与 hidden 是
69
+ * 独立轴)。
70
+ */
71
+ prefix?: string;
72
+ }
73
+ declare function listBookmarks(pkg: Package, indices: PackageIndices, opts?: ListBookmarksOptions): BookmarkInfo[];
74
+ declare function getBookmark(pkg: Package, indices: PackageIndices, name: BookmarkName$1): BookmarkInfo | null;
75
+
76
+ type ContextSearchScope = 'body' | 'all';
77
+ interface ContextSearchInclude {
78
+ paragraphs?: boolean;
79
+ tables?: boolean;
80
+ headings?: boolean;
81
+ bookmarks?: 'none' | 'metadata' | 'coveredText';
82
+ comments?: 'none' | 'anchors';
83
+ revisions?: 'none' | 'flag' | 'visibleText';
84
+ headersFooters?: boolean;
85
+ footnotesEndnotes?: boolean;
86
+ }
87
+ interface ContextSearchOptions {
88
+ query: string;
89
+ keywords?: string[];
90
+ scope?: ContextSearchScope;
91
+ include?: ContextSearchInclude;
92
+ context?: {
93
+ before?: number;
94
+ after?: number;
95
+ };
96
+ limit?: number;
97
+ bookmarkFilter?: {
98
+ name?: string;
99
+ prefix?: string;
100
+ includeHidden?: boolean;
101
+ };
102
+ }
103
+ interface ContextSearchResult {
104
+ matches: ContextSearchMatch[];
105
+ truncated?: boolean;
106
+ }
107
+ interface ContextSearchMatch {
108
+ matchId: string;
109
+ score: number;
110
+ reason: 'keyword' | 'bookmark' | 'heading' | 'table' | 'metadata';
111
+ target: ContextSearchTarget;
112
+ text: string;
113
+ highlights?: ContextSearchHighlight[];
114
+ before?: ContextBlock[];
115
+ after?: ContextBlock[];
116
+ headingPath?: string[];
117
+ flags?: {
118
+ hasComments?: boolean;
119
+ hasRevisions?: boolean;
120
+ };
121
+ bookmarks?: ContextBookmark[];
122
+ }
123
+ interface ContextSearchHighlight {
124
+ text: string;
125
+ start: number;
126
+ end: number;
127
+ }
128
+ type ContextSearchTarget = {
129
+ kind: 'paragraph';
130
+ paraId: string;
131
+ story: string;
132
+ } | {
133
+ kind: 'tableCell';
134
+ tableId: string;
135
+ row: number;
136
+ col: number;
137
+ paraId?: string;
138
+ story: string;
139
+ } | {
140
+ kind: 'bookmark';
141
+ bookmarkName: string;
142
+ rangeKind: 'paragraph' | 'text' | 'complex';
143
+ paraId?: string;
144
+ story: string;
145
+ } | {
146
+ kind: 'heading';
147
+ paraId: string;
148
+ story: string;
149
+ };
150
+ interface ContextBlock {
151
+ paraId: string;
152
+ story: string;
153
+ text: string;
154
+ table?: {
155
+ tableId: string;
156
+ row: number;
157
+ col: number;
158
+ };
159
+ }
160
+ interface ContextBookmark {
161
+ name: string;
162
+ rangeKind: 'paragraph' | 'text' | 'complex';
163
+ writable: boolean;
164
+ }
165
+ declare function searchContext(pkg: Package, indices: PackageIndices, options: ContextSearchOptions): ContextSearchResult;
166
+
167
+ /**
168
+ * TOC 域查询(#197)。
169
+ *
170
+ * 识别文档中的 TOC(目录)域:
171
+ * - complex field:`<w:fldChar w:fldCharType="begin">` … `end`,depth 计数跳过嵌套子域
172
+ * - simple field:`<w:fldSimple w:instr="TOC ...">` 单段闭合
173
+ *
174
+ * 只识别域名前缀匹配 `/^TOC\b/i` 的域,PAGEREF / HYPERLINK 等子域不收集。
175
+ *
176
+ * 嵌套处理:depth 计数器跟踪 fldChar 深度;instr 只在 depth=1(最外层)时收集。
177
+ * complex TOC 的 firstParaId/lastParaId 是 begin/end fldChar 所在段;中间段也在区间内。
178
+ */
179
+
180
+ interface TocFieldRange {
181
+ /** 文档顺序索引(0-based) */
182
+ tocIndex: number;
183
+ /** TOC 域第一段的 paraId(complex field = fldChar begin 段;simple field = fldSimple 段)*/
184
+ firstParaId: string;
185
+ /** TOC 域最后一段的 paraId(complex field = fldChar end 段;simple field = firstParaId)*/
186
+ lastParaId: string;
187
+ /**
188
+ * 域指令文本(拼接所有 instrText / fldSimple@w:instr,trim 后)。
189
+ * 示例:`'TOC \\o "1-3" \\h \\z \\u'`
190
+ */
191
+ instr: string;
192
+ }
193
+ declare function listTocFields(pkg: Package): TocFieldRange[];
194
+
195
+ /**
196
+ * change-events —— `WordDocument.on('change', ...)` 的类型定义。
197
+ *
198
+ * 文档变更事件在 `kernel.applyPlan()` 成功后触发,涵盖两条入口:
199
+ * - `doc.plan().apply()` → source = 'plan'
200
+ * - `doc.executeCode(script)` → source = 'script'(脚本内调 `doc.applyPlan`)
201
+ *
202
+ * **不**触发的场景:
203
+ * - 空 plan(`ops.length === 0`)—— kernel 直接返回,不算一次变更
204
+ * - applyPlan 抛错回滚 —— 文档状态未变
205
+ * - 脚本绕过 kernel.applyPlan 直接改 `doc.getPackage()` 的 DOM —— v1 不覆盖,
206
+ * 此类用法被视作"自负其责";后续可加 dirty-watcher,但代价大。
207
+ *
208
+ * Payload 默认只带 `ops` + `result` + `source`,**不**带全文档 —— 全文档输出
209
+ * (toFlatOpc / toZip)在 worker 模式下要 RPC + serialize,10 万段落级别可达数百 ms,
210
+ * 不是"白送"的开销。订阅时通过 `fullDocument: 'flatOpc' | 'zip'` 显式开启,本模块
211
+ * 在派发前由 WordDocument 一次性拉取(多订阅者共享)。
212
+ */
213
+
214
+ /**
215
+ * Kernel 内部的 change event payload —— 走 worker 边界时被 structured-clone,
216
+ * 因此所有字段必须是 plain JSON。
217
+ */
218
+ interface KernelChangeEvent {
219
+ /** 触发本次 apply 的 op 队列(完整传出,便于审计 / 重放) */
220
+ ops: Op[];
221
+ /** kernel.applyPlan 的返回值 */
222
+ result: ApplyResult;
223
+ /**
224
+ * 'plan' = 走 RPC `applyPlan`(`doc.plan().apply()` 路径)
225
+ * 'script' = 走 `doc.applyPlan(...)`(`doc.executeCode(...)` 内部脚本路径)
226
+ *
227
+ * 由触发层(kernel-handlers / script-execute)显式标注;kernel.applyPlan 自己不知道
228
+ * 来源,只接收 `opts.source`。
229
+ */
230
+ source: 'plan' | 'script';
231
+ }
232
+ /**
233
+ * `WordDocument.on('change', handler)` 收到的 payload。比 KernelChangeEvent 多了
234
+ * 可选的全文档字段 —— 是否填充由订阅时的 `fullDocument` 决定。
235
+ */
236
+ interface ChangeEvent extends KernelChangeEvent {
237
+ /** 仅当 `subscribe.fullDocument === 'flatOpc'` 时存在 */
238
+ flatOpc?: string;
239
+ /** 仅当 `subscribe.fullDocument === 'zip'` 时存在 */
240
+ zip?: Uint8Array;
241
+ }
242
+ /** 订阅选项;默认 `fullDocument: 'none'`(只发 metadata,不付全文档输出代价)。 */
243
+ interface ChangeSubscribeOptions {
244
+ /**
245
+ * - `'none'`(默认):payload 只含 `{ ops, result, source }`
246
+ * - `'flatOpc'`:派发前调一次 `toFlatOpc()`,payload.flatOpc 填充 XML 字符串
247
+ * - `'zip'`:派发前调一次 `toZip()`,payload.zip 填充 docx 字节
248
+ *
249
+ * **代价警示**:`'flatOpc'` / `'zip'` 在 worker 模式下要 RPC + structured-clone
250
+ * 整篇文档,大文档一次几百 ms;只在确实要"快照式消费"时启用。多订阅者共享同一次
251
+ * 拉取,因此打开多个 'flatOpc' 订阅不会重复跑。
252
+ */
253
+ fullDocument?: 'none' | 'flatOpc' | 'zip';
254
+ }
255
+ /** 订阅回调;可同步可 async。WordDocument 串行 await 每个订阅者,保证派发顺序与变更顺序一致。 */
256
+ type ChangeListener = (ev: ChangeEvent) => void | Promise<void>;
257
+ /** RPC event 通道里 word change 事件的 `event` 字符串常量。 */
258
+ declare const WORD_CHANGE_EVENT = "word.change";
259
+
260
+ type DomainCacheState = 'empty' | 'ready' | 'dirty';
261
+ type DomainCacheName = 'all' | 'paragraphs' | 'tables';
262
+ interface ParagraphDomainCacheSnapshot {
263
+ state: DomainCacheState;
264
+ listAllBodyReady: boolean;
265
+ cachedParagraphIds: string[];
266
+ dirtyReason?: string;
267
+ buildCount: number;
268
+ }
269
+ interface WordDomainCacheSnapshot {
270
+ revision: number;
271
+ paragraphs: ParagraphDomainCacheSnapshot;
272
+ tables: TableDomainCacheSnapshot;
273
+ }
274
+ interface TableDomainCacheSnapshot {
275
+ state: DomainCacheState;
276
+ cachedProfiles: string[];
277
+ cachedTableIds: string[];
278
+ dirtyReason?: string;
279
+ buildCount: number;
280
+ }
281
+
282
+ /** Kernel.load 的输入 */
283
+ type KernelLoadSource = {
284
+ type: 'zip';
285
+ bytes: Uint8Array;
286
+ } | {
287
+ type: 'flat-opc';
288
+ xml: string;
289
+ };
290
+ interface KernelLoadParams {
291
+ source: KernelLoadSource;
292
+ docId: string;
293
+ }
294
+ /**
295
+ * 装载 / rebuild 进度回调。
296
+ *
297
+ * - load 使用 `'fetch' | 'parse' | 'normalize'`(LoadPhase 对齐)
298
+ * - rebuildFromParts(#22)使用 `'parse' | 'build-indices' | 'done'`
299
+ *
300
+ * 上层 WordDocument.rollback 会把 phase 作为字符串透传,不强制 union 收敛。
301
+ */
302
+ type KernelProgress = (phase: string, pct?: number) => void;
303
+ /**
304
+ * Kernel —— 持有单一 WordDocument 的内部状态。
305
+ *
306
+ * 一个 WordDocument 代理对应一个 Kernel。生命周期由代理控制:load → 多次操作 → dispose。
307
+ */
308
+ declare class Kernel {
309
+ private pkg?;
310
+ private indices?;
311
+ private docId?;
312
+ private initialBytes?;
313
+ private initialFlatOpc?;
314
+ private disposed;
315
+ private readonly domainCache;
316
+ /**
317
+ * change 事件订阅者(applyPlan 成功后 fan-out)。InlineTransport 直接订阅;worker
318
+ * 模式下 worker 内创建 Kernel 时由 worker entry 订阅一个把事件 post 到主线程的
319
+ * 中转 listener(详见 kernel-worker-shared.ts)。
320
+ *
321
+ * 监听器异常被静默吞掉 —— 一个订阅者抛错不该影响其它订阅者,也不该影响 applyPlan
322
+ * 的返回值(applyPlan 已经成功提交,事件只是事后通知)。
323
+ */
324
+ private readonly changeListeners;
325
+ /**
326
+ * applyPlan 互斥链 —— 串行化所有 applyPlan 调用,不论来源(plan / script)。
327
+ *
328
+ * 必要性:applyPlan 内部对 `pkg.parts[*].xmlDom` 做 deepClone(transaction
329
+ * snapshot)+ 同步 mutate + 索引重建。多个 applyPlan 在 microtask 边界穿插
330
+ * 时:
331
+ * - 多份 deepClone 同时占内存(50w 字 doc × 并发数 → WPS WebView OOM)
332
+ * - A 的 dispatch 与 B 的 dispatch 在共享 xmlDom 上交错,paraIdx 错位
333
+ * - A 的回滚 snapshot 包含 B 的 mutation,A 失败回滚会 wipe B 的写
334
+ * - finally 里 buildIndices 互相覆盖
335
+ *
336
+ * 用 promise chain 串行化:每次 applyPlan 等前一个完成才进入 inner。链上
337
+ * resolve 永不 reject —— 把 inner 的成功/失败结果在外层 await 时直接抛给
338
+ * 调用方,链本身只保证"前一个跑完了"。
339
+ */
340
+ private _applyPlanChain;
341
+ load(params: KernelLoadParams, onProgress?: KernelProgress): Promise<void>;
342
+ toZip(): Promise<Uint8Array>;
343
+ toFlatOpc(): Promise<string>;
344
+ /**
345
+ * 段落查询。纯同步,基于当前已装载的 pkg。
346
+ *
347
+ * 所有策略(scope / filter / textFormat / pagination)由入参决定,kernel **不**
348
+ * 做"智能默认"——未传 pagination 时按 `DEFAULT_PAGINATION`(byCount(25,0))返回
349
+ * 第一页;要全量请显式 `{ pagination: { mode: 'all' } }`(docs/03 §9.2)。
350
+ *
351
+ * 纯逻辑实现在 `list-paragraphs.ts`,本方法只做:装载态校验 + pkg 传入 + 错误
352
+ * 包装(validation Error → WordError,附 docId)。
353
+ */
354
+ listParagraphs(opts?: ListParagraphsOptions): ListResult;
355
+ /**
356
+ * 按 paraId 精确取段(#25)。走 paraIdx → O(1) 查找;不存在返回 null。
357
+ * paraId 大小写不敏感(索引 key 是大写 8 hex)。
358
+ */
359
+ getParagraph(paraId: string): ParagraphInfo | null;
360
+ /**
361
+ * 枚举书签(#25)。默认过滤 `_` 开头的隐藏书签(_Toc... / _GoBack / _Hlk...),
362
+ * `opts.includeHidden=true` 可拿到全部。返回顺序遵循 bookmarkIdx 的迭代序 ——
363
+ * JS Map 按插入序,装载期从上到下、逐 part 逐 `<w:bookmarkStart>` 收集。
364
+ */
365
+ listBookmarks(opts?: ListBookmarksOptions): BookmarkInfo[];
366
+ /**
367
+ * 按 name 精确取书签(#25)。走 bookmarkIdx;不存在返回 null。
368
+ * 不做 hidden 过滤 —— 调用方已知 name,通常就是来找隐藏书签的。
369
+ */
370
+ getBookmark(name: BookmarkName$1): BookmarkInfo | null;
371
+ /**
372
+ * 枚举批注(#26)。走 commentIdx,按 Map 插入序(= 装载期 part 顺序 + w:id 升序)
373
+ * 返回。主体缺失或无锚点的 entry 被跳过 —— 调用方看到的都是"可用"的批注。
374
+ */
375
+ listComments(): CommentInfo[];
376
+ /**
377
+ * 按 id 取批注(#26)。不存在或主体缺失返回 null 。
378
+ */
379
+ getComment(id: CommentId$1): CommentInfo | null;
380
+ /**
381
+ * 枚举修订(#26 + #33,Tier 1)。只覆盖 `<w:ins>` / `<w:del>` 标签级修订。
382
+ *
383
+ * **#33 加强**:扫到 `<w:rPrChange>` / `<w:pPrChange>` / `sectPrChange` /
384
+ * `numberingChange` / `moveFrom` / `moveTo` 等 Tier 2 属性级修订 → 抛
385
+ * `UNSUPPORTED_OOXML_FEATURE`(以前是默默忽略)。读写共用守护,与
386
+ * `acceptRevisions` / `rejectRevisions` 行为一致。
387
+ *
388
+ * scope 与 `listParagraphs` 一致:默认 'body',可传 'all' 或 `StoryId[]`。
389
+ */
390
+ listRevisions(opts?: ListRevisionsOptions): RevisionInfo[];
391
+ getRevision(revId: string, opts?: ListRevisionsOptions): RevisionInfo | null;
392
+ searchContext(opts: ContextSearchOptions): ContextSearchResult;
393
+ /** 列出 styles.xml 中的样式,可按 type 过滤。styles.xml 不存在时返回空数组。 */
394
+ listStyles(opts?: ListStylesOptions): StyleInfo[];
395
+ /** 按 styleId 精确查找,O(1)。不存在返回 null。 */
396
+ getStyle(styleId: string): StyleInfo | null;
397
+ /** 枚举表格,默认只返回主文档 body 的顶层表格。*/
398
+ listTables(opts?: ListTablesOptions): TableInfo[];
399
+ /** 按 tableId 精确取单个表格,O(1)。不存在返回 null。 */
400
+ getTable(tableId: string): TableInfo | null;
401
+ /**
402
+ * 按 tableId verbatim 取一张表的 OOXML 子树 + 格内图字节
403
+ * (task-20260616-table-content-driven,供跨文档搬表 insertTableFrom)。
404
+ * 不存在返回 null。
405
+ */
406
+ getTableVerbatim(tableId: string): TableVerbatim | null;
407
+ /** 枚举 drawing 对象,默认只返回主文档 body 内的 drawing。*/
408
+ listDrawings(opts?: ListDrawingsOptions): DrawingInfo[];
409
+ /** 按 drawingId 精确取单个 drawing,O(1)。不存在返回 null。 */
410
+ getDrawing(drawingId: string): DrawingInfo | null;
411
+ /**
412
+ * 读取 drawingId 对应 picture 的原始图片字节(task-insert-image)。
413
+ * drawingId 不存在 / 非 picture / media 找不到 → 返回 null(不抛)。
414
+ */
415
+ getImageBytes(drawingId: string): ImageBytesResult | null;
416
+ /** 枚举主 body 的所有节(#211)。doc-order 排序。*/
417
+ listSections(): SectionInfo[];
418
+ /** 枚举主 body 的所有 TOC 域(#197)。doc-order 排序。*/
419
+ listTocFields(): TocFieldRange[];
420
+ /**
421
+ * 执行 WordPlan 提交的 op 队列(docs/03.1 §3.2)。
422
+ *
423
+ * **#27 作用域**:本方法只承担 **Plan 容器 + ApplyResult 结构 + 错误状态机**。
424
+ * 真正的 op executor 由后续 PR 分别落地(见 `plan.ts` 顶部注释)。因此本版本:
425
+ * - ops 为空 → 返回 `EMPTY_APPLY_RESULT`(WordPlanImpl 侧通常已拦,这里兜底)
426
+ * - ops 非空 → 抛 `UNSUPPORTED_OOXML_FEATURE`,message 指向待落地的 issue
427
+ *
428
+ * 注意:事务原子性(#16 runTransaction)+ 索引同步 + trackChanges 包装,都在首个
429
+ * executor(#28)落地时接入。本 PR 不引入 executor registry,避免为空抽象付代价;
430
+ * #28 直接在这里改成 switch(op.type) 即可。
431
+ */
432
+ /**
433
+ * 执行 Plan op 队列(docs/03.1 §3.2)。
434
+ *
435
+ * 流程:
436
+ * 1. 预扫 affected parts(每个 op 触达的 part path)
437
+ * 2. `runTransaction` 包裹 dispatch 循环 —— 任一 op throw → 全回滚
438
+ * 3. 成功后重建三索引(paraIdx / bookmarkIdx / commentIdx)—— executor 可能
439
+ * 增删元素,最简单的保真方式是 buildIndices 一次性重跑
440
+ *
441
+ * 返回 Promise 因 runTransaction 是 async;#27 的 sync 签名承诺在 RPC 层
442
+ * (handler `await` + `transport.call` 自带 await)对调用方完全透明。
443
+ */
444
+ applyPlan(params: ApplyPlanParams, opts?: {
445
+ source?: 'plan' | 'script';
446
+ }): Promise<ApplyResult>;
447
+ validatePlan(params: ApplyPlanParams): Promise<PlanValidationResult>;
448
+ private _applyPlanInner;
449
+ /**
450
+ * 订阅 applyPlan 成功事件。返回取消订阅函数。
451
+ *
452
+ * 监听器同步触发(在 applyPlan 内部 fan-out),抛错被吞掉(不影响其它订阅者
453
+ * 与 applyPlan 返回)。要做 async 工作请在监听器内自行 catch 并 fire-and-forget。
454
+ */
455
+ onChange(listener: (ev: KernelChangeEvent) => void): () => void;
456
+ private emitChange;
457
+ /**
458
+ * 序列化当前 pkg 为 snapshot 用的 parts 数组。
459
+ * 优化:
460
+ * - dirty=false 且有 _originalBytes → 直接复用原始字节(零 serialize,Uint8Array 引用共享)
461
+ * - dirty=true 的 XML part → slimdom serialize
462
+ * - 二进制 part → 用 bytes / _originalBytes
463
+ */
464
+ serializeParts(): SnapshotPartEntry[];
465
+ /**
466
+ * 从 snapshot 的 parts 数组重建 pkg + 三索引。
467
+ *
468
+ * 覆盖原 pkg:调用方应在 rollback 前确保 dispose/ 清理 transient 状态(如 changelog)。
469
+ * 重建后 ensureParaIds + buildIndices 再跑一次,保证索引准确(docs/03.2 §10)。
470
+ *
471
+ * onProgress 分阶段上报(docs/03.2 §6):
472
+ * - `'parse'` 每个 part 被 parse 完成时,pct 0→100
473
+ * - `'build-indices'` buildIndices 开始前,pct 0
474
+ * - `'done'` 全部完成,pct 100
475
+ */
476
+ rebuildFromParts(parts: readonly SnapshotPartEntry[], onProgress?: KernelProgress): void;
477
+ dispose(): void;
478
+ /** @internal */
479
+ getDocId(): string | undefined;
480
+ /** @internal */
481
+ getPackage(): Package | undefined;
482
+ /** @internal */
483
+ getIndices(): PackageIndices | undefined;
484
+ /** @internal */
485
+ getInitialBytes(): Uint8Array | undefined;
486
+ /** @internal */
487
+ getInitialFlatOpc(): string | undefined;
488
+ /** @internal */
489
+ isDisposed(): boolean;
490
+ /** @internal */
491
+ debugCacheSnapshot(): WordDomainCacheSnapshot;
492
+ /** @internal */
493
+ debugInvalidateCache(domain?: DomainCacheName, reason?: string): void;
494
+ private assertLoaded;
495
+ private assertNotDisposed;
496
+ }
497
+ /** Kernel.serializeParts / rebuildFromParts 的 entry 形态(与 SnapshotPayload.parts 一致) */
498
+ interface SnapshotPartEntry {
499
+ path: string;
500
+ contentType: string;
501
+ bytes: Uint8Array;
502
+ }
503
+
504
+ type KernelMethod = 'load' | 'toZip' | 'toFlatOpc' | 'dispose' | 'serializeParts' | 'rebuildFromParts' | 'paragraphs.list' | 'paragraphs.get' | 'bookmarks.list' | 'bookmarks.get' | 'comments.list' | 'comments.get' | 'context.search' | 'revisions.list' | 'revisions.get' | 'styles.list' | 'styles.get' | 'tables.list' | 'tables.get' | 'tables.getVerbatim' | 'drawings.list' | 'drawings.get' | 'drawings.getImageBytes' | 'validatePlan' | 'sections.list' | 'tocFields.list' | 'applyPlan';
505
+
506
+ /**
507
+ * Transport —— WordDocument(主线程代理)与 Kernel 之间的分发抽象。
508
+ *
509
+ * 两种实现:
510
+ * - `InlineTransport`:kernel 跑在主线程,call 直接委托到 kernelHandlers
511
+ * - `WorkerTransport`(worker-transport.ts):kernel 跑在 Worker,call 通过 postMessage
512
+ * 编码成 RPC 消息,等待 response
513
+ *
514
+ * Transport 对外形态相同 → WordDocument 不需感知模式。
515
+ */
516
+
517
+ interface Transport {
518
+ /** 调用 kernel 方法;onProgress 用于流式进度(装载等) */
519
+ call<T>(method: KernelMethod, args: unknown[], onProgress?: KernelProgress): Promise<T>;
520
+ /**
521
+ * 在 kernel 同上下文执行一段用户脚本(04.2 §六)。与 `call` 平级,**不**进
522
+ * `KernelMethod` 联合 —— `KernelMethod` 表"数据 API",脚本执行是另一类能力。
523
+ *
524
+ * @param code 用户 JS 源码;函数体形态(允许顶层 await / return)
525
+ * @param args 传给脚本的参数,经 structured clone 过 worker 边界
526
+ * @param timeoutMs 超时毫秒数;0 = 不超时
527
+ * @param signal 可选 AbortSignal(#151):
528
+ * - WorkerTransport:abort 触发 → terminate worker + reload 路径
529
+ * (复用 #144 timeout reload 实施;pending RPC reject 为 \`WORKER_RELOADED\`)
530
+ * - InlineTransport:abort 触发 → race 拒绝(主线程立即返回,但脚本
531
+ * 仍在主线程后台跑直到自然结束 —— inline 无 worker 可 terminate)
532
+ * @returns 脚本顶层 return 的值(structured-cloneable)
533
+ * @throws 语法错误 / 脚本运行错 / 超时 / abort
534
+ */
535
+ executeScript(code: string, args: Record<string, unknown> | undefined, timeoutMs: number, signal?: AbortSignal): Promise<unknown>;
536
+ /** 释放底层资源(worker 模式下 terminate worker) */
537
+ dispose(): Promise<void>;
538
+ /**
539
+ * 可选:订阅 reload 完成事件。Worker 模式下每次 crash + reload 成功后触发;
540
+ * InlineTransport 不触发(inline 无 reload 语义)。返回取消订阅函数。
541
+ *
542
+ * 主要用途(#23):SnapshotApi 订阅此事件,在 worker reload 完成后重建内存态
543
+ * (nextId / changelog)——worker reload 会丢失主线程侧的自增栈,需要从 adapter
544
+ * 重读已持久化快照重建 nextId。详见 docs/03.2 §9.1。
545
+ *
546
+ * Listener 可返回 Promise;transport 会串行 await 每个 listener 完成后再 flush
547
+ * reload 期间排队的 RPC,避免 queued 的 take() 在 nextId 重建前执行。
548
+ */
549
+ onReload?(listener: () => void | Promise<void>): () => void;
550
+ /**
551
+ * 订阅 kernel 推出的 change 事件(applyPlan 成功后触发,涵盖 plan / script 两条入口)。
552
+ * 返回取消订阅函数。
553
+ *
554
+ * - InlineTransport:直接转发 kernel.onChange
555
+ * - WorkerTransport:监听 RpcEvent('word.change'),fan-out 给本地订阅者
556
+ *
557
+ * payload 是 `KernelChangeEvent`(精简版,不含全文档);WordDocument 上层根据订阅
558
+ * 选项再决定是否拉取 toFlatOpc / toZip。监听器同步触发,抛错被吞掉。
559
+ */
560
+ onChange(listener: (ev: KernelChangeEvent) => void): () => void;
561
+ }
562
+ /** Inline:kernel 直接在主线程 */
563
+ declare class InlineTransport implements Transport {
564
+ readonly kernel: Kernel;
565
+ constructor();
566
+ call<T>(method: KernelMethod, args: unknown[], onProgress?: KernelProgress): Promise<T>;
567
+ executeScript(code: string, args: Record<string, unknown> | undefined, timeoutMs: number, signal?: AbortSignal): Promise<unknown>;
568
+ dispose(): Promise<void>;
569
+ onChange(listener: (ev: KernelChangeEvent) => void): () => void;
570
+ }
571
+
572
+ /**
573
+ * WordError —— Word core 的统一错误模型(docs/03.1 §4)。
574
+ *
575
+ * 所有面向消费方的错误都用 WordError 抛出。`code` 枚举覆盖装载期 / 查询 / 变更前置 / Plan 状态
576
+ * 四大类。`docId` 由 core 自动填充(WordDocument 内捕获底层错误后重抛时注入),方便日志
577
+ * 与多文档场景定位。
578
+ */
579
+ type WordErrorCode = 'PACKAGE_CORRUPT' | 'PACKAGE_UNSUPPORTED_FORMAT' | 'BOOKMARK_NAME_DUPLICATE_ON_LOAD' | 'BOOKMARK_NAME_EMPTY_ON_LOAD' | 'WORKER_CREATION_FAILED' | 'WORKER_RELOADED' | 'PARA_NOT_FOUND' | 'BOOKMARK_NOT_FOUND' | 'COMMENT_NOT_FOUND' | 'REVISION_NOT_FOUND' | 'TABLE_NOT_FOUND' | 'DRAWING_NOT_FOUND' | 'TEXT_NOT_FOUND_IN_PARA' | 'BOOKMARK_NAME_EXISTS' | 'BOOKMARK_NAME_INVALID' | 'ANCHOR_CONFLICT' | 'UNSUPPORTED_OOXML_FEATURE' | 'INVALID_ARGUMENT' | 'PLAN_ALREADY_APPLIED' | 'PLAN_EMPTY' | 'CONTENT_LOST';
580
+ declare class WordError extends Error {
581
+ readonly code: WordErrorCode;
582
+ readonly docId: string;
583
+ readonly details: Record<string, unknown>;
584
+ constructor(code: WordErrorCode, message: string, docId: string, details?: Record<string, unknown>);
585
+ }
586
+
587
+ /**
588
+ * SDT (Structured Document Tag, Content Control) XML 构建器 —— #188 表格域化。
589
+ *
590
+ * 设计:
591
+ * - 三种子类型: Plain Text / Date Picker / Rich Text
592
+ * - 输出 inline SDT (作 <w:r> 兄弟出现在 <w:p> 内), 段落 pPr 由调用方保留
593
+ * - SDT id 由调用方传入 (典型: hash 输入对象保证幂等), 避免 builder 维护全局状态
594
+ * - rPr 可由调用方拷贝原 run 的 rPr 传入, 保留字体 / 颜色 / 字号等字符属性
595
+ *
596
+ * SDT id 取值: OOXML 规定 32-bit signed integer; Word 加载时容错并按需重分配,
597
+ * 调用方不必严格保证全局唯一, hash 取值即可。
598
+ *
599
+ * 参考: ECMA-376 §17.5 Structured Document Tags。
600
+ */
601
+ /**
602
+ * SDT 配置 (JSON-serializable, 可走 plan op RPC)。
603
+ *
604
+ * `rPr` 字符属性透传不在 spec 内 —— DOM Element 不能 JSON 序列化, 由 executor 在
605
+ * 替换时从原 run 直接克隆并传给 `buildInlineSdt` 的 `rPr` 参数。
606
+ */
607
+ interface SdtSpecBase {
608
+ /** UI 显示名 (Word "Click here..." 上方的提示标签) */
609
+ alias: string;
610
+ /**
611
+ * 程序匹配 tag (后续模板填充阶段按 tag 定位 SDT)。
612
+ * 缺省时按 `alias` trim + 空白转 `_`。
613
+ */
614
+ tag?: string;
615
+ /** 占位提示文本; 缺省 `"请输入" + alias` */
616
+ placeholderText?: string;
617
+ }
618
+ interface PlainTextSdtSpec extends SdtSpecBase {
619
+ kind: 'text';
620
+ }
621
+ interface DateSdtSpec extends SdtSpecBase {
622
+ kind: 'date';
623
+ /** 日期格式 (e.g. "yyyy-M-d"), 缺省 "yyyy-M-d" */
624
+ dateFormat?: string;
625
+ /** Locale, 缺省 "zh-CN" */
626
+ locale?: string;
627
+ }
628
+ interface RichTextSdtSpec extends SdtSpecBase {
629
+ kind: 'richText';
630
+ }
631
+ type SdtSpec = PlainTextSdtSpec | DateSdtSpec | RichTextSdtSpec;
632
+ /**
633
+ * 构建一个 inline SDT 元素 (`<w:sdt>`), 用于段落内 run 替换场景。
634
+ *
635
+ * 结构:
636
+ * <w:sdt>
637
+ * <w:sdtPr>
638
+ * (rPr?)
639
+ * <w:alias w:val="..."/>
640
+ * <w:tag w:val="..."/>
641
+ * <w:id w:val="..."/>
642
+ * <w:placeholder><w:docPart w:val="DefaultPlaceholder_-1854013440"/></w:placeholder>
643
+ * <w:showingPlcHdr/>
644
+ * (类型标记: <w:text/> | <w:date.../> | <w:richText/>)
645
+ * </w:sdtPr>
646
+ * <w:sdtContent>
647
+ * <w:r>(rPr?)<w:t xml:space="preserve">placeholderText</w:t></w:r>
648
+ * </w:sdtContent>
649
+ * </w:sdt>
650
+ *
651
+ * @param doc owner Document (来自 paragraph.ownerDocument)
652
+ * @param spec SDT 配置 (JSON-serializable)
653
+ * @param id 32-bit 整数 ID; 推荐用 hashSdtId(tableId, row, col, alias) 算
654
+ * @param rPr 可选, 从原 run 克隆的 `<w:rPr>` —— 字符属性透传, 同时挂到
655
+ * sdtPr 与 sdtContent 内 placeholder run 上
656
+ */
657
+ declare function buildInlineSdt(doc: Document, spec: SdtSpec, id: number, rPr?: Element): Element;
658
+ /**
659
+ * 由 (tableId, row, col, alias) 算 SDT id (djb2 hash → 32-bit signed)。
660
+ *
661
+ * 幂等性保证: 同一组输入永远产出同一 id, 重跑骨架化不会因 id 变化制造无意义 diff。
662
+ */
663
+ declare function hashSdtId(tableId: string, row: number, col: number, alias: string): number;
664
+
665
+ /**
666
+ * WordPlan —— 变更 builder + apply 机制(docs/03.1 §3,#27)。
667
+ *
668
+ * 职责(本 PR):
669
+ * - 11 个链式 builder 方法 `return this`,**不返回 op 句柄**;每个方法只把 op
670
+ * push 进内部队列,错误集中到 `apply()` 抛(契约 §4.2)
671
+ * - `apply()` 状态机:
672
+ * - 二次 apply → `PLAN_ALREADY_APPLIED`
673
+ * - 空 plan → console.warn 不抛(契约默认语义;严格模式留未来)
674
+ * - 非空 plan → transport RPC 到 kernel 的 `applyPlan`
675
+ * - 多 plan 并存独立,不共享状态(每次 `doc.plan()` 新实例)
676
+ *
677
+ * **不含**任何 op 的真正执行 —— executor 一 PR 一张,#28 起陆续落地:
678
+ * - #28: replaceParagraph / replaceTextInParagraph
679
+ * - #29: insertParagraphBefore/After / deleteParagraph
680
+ * - #34: createBookmark / deleteBookmark
681
+ * - #35: addComment / deleteComment
682
+ * - #31/#32: acceptRevisions / rejectRevisions
683
+ *
684
+ * 当前 kernel 侧 `applyPlan` 对任何非空 ops 直接抛 `UNSUPPORTED_OOXML_FEATURE`。
685
+ */
686
+
687
+ type ParaId = string;
688
+ type BookmarkName = string;
689
+ type CommentId = number;
690
+ type RevisionId = string;
691
+ /** 段落级定位 */
692
+ interface ParagraphRange {
693
+ paraId: ParaId;
694
+ }
695
+ /** 段落内关键词定位 */
696
+ interface TextRange$1 {
697
+ paraId: ParaId;
698
+ text: string;
699
+ /** 默认 'first' */
700
+ scope?: 'first' | 'all';
701
+ }
702
+ type Range = ParagraphRange | TextRange$1;
703
+ type RevisionScope = {
704
+ scope: 'all';
705
+ } | {
706
+ scope: 'paragraph';
707
+ paraId: ParaId;
708
+ } | {
709
+ scope: 'revision';
710
+ revId: RevisionId;
711
+ };
712
+ interface ParagraphDirectFormat {
713
+ alignment?: 'left' | 'center' | 'right' | 'both' | 'distribute';
714
+ outlineLevel?: number;
715
+ pageBreakBefore?: boolean;
716
+ indent?: {
717
+ left?: number;
718
+ right?: number;
719
+ /**
720
+ * Positive value writes first-line indent; negative value writes hanging indent.
721
+ */
722
+ firstLine?: number;
723
+ };
724
+ spacing?: {
725
+ before?: number;
726
+ after?: number;
727
+ line?: number;
728
+ lineRule?: 'auto' | 'exact' | 'atLeast';
729
+ };
730
+ }
731
+ interface TableCellDirectFormat {
732
+ shading?: {
733
+ /** 6-digit hex fill color without '#', or 'auto'. */
734
+ fill?: string;
735
+ /** 6-digit hex foreground color without '#', or 'auto'. */
736
+ color?: string;
737
+ /** OOXML shading pattern. Defaults to 'clear' when only fill is provided. */
738
+ val?: string;
739
+ };
740
+ verticalAlignment?: 'top' | 'center' | 'bottom' | 'both';
741
+ /** Cell width in twips, written as tcW type='dxa'. */
742
+ width?: number;
743
+ }
744
+ interface InsertParagraphSpec {
745
+ text: string;
746
+ /** 'inherit'(默认)继承 anchor 的 `<w:pPr>`;字符串为 styleId */
747
+ style?: 'inherit' | string;
748
+ /**
749
+ * 控制新段内容 run 的 `<w:rPr>` 来源。
750
+ *
751
+ * - `'default'`(默认):裸 run,不附加任何 rPr,行为与未传时完全一致。
752
+ * - `'inherit'`:克隆 anchor 段**首个直属 `<w:r>`** 的 `<w:rPr>`(深拷贝 cloneNode(true))
753
+ * 并应用到新段的内容 run。常用于「簇展开」场景:样式写在直接格式(rPr)而非命名样式上。
754
+ * anchor 无直属 run 或首 run 无 rPr 时退化为 `'default'`(不报错)。
755
+ * 与 `color` 共存时:先继承 rPr,再由 color 覆盖/追加 `<w:color>`(color 优先级更高)。
756
+ * 与 `style` 正交:style 管 pPr,runFormat 管 rPr,可独立组合。
757
+ */
758
+ runFormat?: 'inherit' | 'default';
759
+ /**
760
+ * 整段文字的字体颜色,6 位十六进制无 `#`(如 `'0070C0'` 标准蓝)。
761
+ * 留空则继承样式默认色。
762
+ * 颜色作为 run-level `<w:rPr><w:color w:val="..."/></w:rPr>` 写入新段唯一 run。
763
+ */
764
+ color?: string;
765
+ /**
766
+ * 从指定段(任意 `paraId`)克隆 pPr + 首 run rPr 到新段(全文重组场景)。
767
+ *
768
+ * - **优先级最高**:同时传 `style` / `runFormat` 时以 `styleSource` 为准(pPr + rPr 都来自 styleSource)。
769
+ * - pPr:深拷贝 `<w:pPr>`;styleSource 段无 pPr 则新段也不加 pPr(退化,不报错)。
770
+ * - rPr:克隆 styleSource 段**首个直属 `<w:r>`** 的 `<w:rPr>`;无直属 run 或首 run 无 rPr 则退化裸 run(不报错)。
771
+ * - styleSource 段**不存在**时抛 `PARA_NOT_FOUND`。
772
+ * - styleSource 段自身只读,不被修改。
773
+ * - 与 `color` 共存:先克隆 rPr,再 color 覆盖/追加 `<w:color>`(color 优先,同 #12)。
774
+ * - `styleSource === anchor` 时退化为 `style:'inherit' + runFormat:'inherit'` 效果(#12 兼容)。
775
+ */
776
+ styleSource?: ParaId;
777
+ /**
778
+ * 可选:插入段的同时**原子地**建一个跨段书签,range 涵盖 anchor 段 → 新插段。
779
+ *
780
+ * 调用方只声明命名规则(`prefix`),不传具体名 —— 系统按 `{prefix}_{anchorParaId}`
781
+ * 生成,冲突自动追加 `_2`/`_3` 后缀;实际名通过 `ApplyResult.createdBookmarks[i].name`
782
+ * 回传(同一 entry 的 `range` 给 fromParaId / toParaId)。
783
+ *
784
+ * `prefix` 校验:必须匹配 `^[A-Za-z_][A-Za-z0-9_]*$`(允许 `_` 起头作 Word hidden
785
+ * bookmark);最终名长度受 OOXML 40 字符上限约束,过长抛 `BOOKMARK_NAME_INVALID`。
786
+ *
787
+ * trackChanges=true 时本字段触发 `UNSUPPORTED_OOXML_FEATURE`(与 createBookmark
788
+ * 的现状一致,#31 再统一处理)。
789
+ */
790
+ bookmark?: {
791
+ prefix: string;
792
+ };
793
+ /**
794
+ * 段落大纲级别(Word outline level),写入 `<w:pPr><w:outlineLvl w:val="N"/>`。
795
+ *
796
+ * - 取值 **0–8**(对应 Word「1 级标题…9 级标题」;heading-1→0, heading-2→1, …)。
797
+ * - 省略(`undefined`):不写 outlineLvl,保持 styleSource 克隆来的 pPr 原样。
798
+ * - 0–8:在新段 pPr 写入/覆盖 `<w:outlineLvl>`(显式值优先于 styleSource 克隆来的)。
799
+ * - 越界(< 0 或 > 8):抛 `INVALID_ARGUMENT`。
800
+ */
801
+ outlineLevel?: number;
802
+ /**
803
+ * 段前分页(Word「段前分页」),写入 `<w:pPr><w:pageBreakBefore/>`。
804
+ *
805
+ * - `true`:该段强制从新页起始(比手工 `<w:br type="page"/>` 更鲁棒:绑在段上不随内容漂移)。
806
+ * - 省略(`undefined`)/ `false`:不写该元素(继承样式或默认)。
807
+ */
808
+ pageBreakBefore?: boolean;
809
+ }
810
+ interface PlanOptions {
811
+ /** 默认 false */
812
+ trackChanges?: boolean;
813
+ /** 默认走 `WordDocument.setDefaultAuthor` 配置的值 */
814
+ author?: string;
815
+ /** 默认 `new Date()` */
816
+ date?: Date;
817
+ }
818
+ type Op = {
819
+ type: 'replaceParagraph';
820
+ paraId: ParaId;
821
+ text: string;
822
+ onAnchorConflict: 'error' | 'drop';
823
+ /** 保留段内含图形的 run(w:drawing / w:pict / wps:wsp / v:line / w:object)。
824
+ * 默认 false(现有行为:整段所有 run 全删)。
825
+ * true 时:只删纯文字 run,图形 run 原位保留;新文字 run 插在首个被删文字 run 位置。 */
826
+ keepInlineGraphics?: boolean;
827
+ } | {
828
+ type: 'replaceTextInParagraph';
829
+ paraId: ParaId;
830
+ search: string;
831
+ replacement: string;
832
+ scope: 'first' | 'all';
833
+ } | {
834
+ type: 'formatTextInParagraph';
835
+ paraId: ParaId;
836
+ search: string;
837
+ format: {
838
+ bold?: boolean;
839
+ color?: string;
840
+ italic?: boolean;
841
+ underline?: boolean;
842
+ highlight?: string;
843
+ fontSize?: number;
844
+ fontFamily?: string;
845
+ };
846
+ scope: 'first' | 'all';
847
+ } | {
848
+ type: 'formatParagraph';
849
+ paraId: ParaId;
850
+ format: ParagraphDirectFormat;
851
+ } | {
852
+ type: 'insertParagraphBefore';
853
+ anchorParaId: ParaId;
854
+ spec: InsertParagraphSpec;
855
+ } | {
856
+ type: 'insertParagraphAfter';
857
+ anchorParaId: ParaId;
858
+ spec: InsertParagraphSpec;
859
+ } | {
860
+ type: 'insertParagraphAtBodyStart';
861
+ } | {
862
+ type: 'deleteParagraph';
863
+ paraId: ParaId;
864
+ onAnchorConflict: 'error' | 'drop';
865
+ } | {
866
+ type: 'createBookmark';
867
+ name: BookmarkName;
868
+ range: Range;
869
+ } | {
870
+ type: 'deleteBookmark';
871
+ name: BookmarkName;
872
+ } | {
873
+ type: 'addComment';
874
+ range: Range;
875
+ text: string;
876
+ author?: string;
877
+ /** RPC 友好:按 ISO 8601 字符串序列化;builder 端接 Date,push 前 toISOString */
878
+ date?: string;
879
+ } | {
880
+ type: 'deleteComment';
881
+ commentId: CommentId;
882
+ } | {
883
+ type: 'acceptRevisions';
884
+ scope: RevisionScope;
885
+ } | {
886
+ type: 'rejectRevisions';
887
+ scope: RevisionScope;
888
+ } | {
889
+ type: 'addTableComment';
890
+ tableId: string;
891
+ text: string;
892
+ author?: string;
893
+ /** ISO 8601 字符串 */
894
+ date?: string;
895
+ } | {
896
+ type: 'deleteTable';
897
+ tableId: string;
898
+ onAnchorConflict: 'error' | 'drop';
899
+ } | {
900
+ type: 'replaceTableCellWithSdt';
901
+ tableId: string;
902
+ /** 0-based 行索引(对应 TableInfo.cells 网格的 i)*/
903
+ row: number;
904
+ /** 0-based 列索引(对应 cells[i] 的 j) */
905
+ col: number;
906
+ sdt: SdtSpec;
907
+ onAnchorConflict: 'error' | 'drop';
908
+ } | {
909
+ type: 'deleteTableRow';
910
+ tableId: string;
911
+ /** 0-based 行索引(按删除时刻表格状态计) */
912
+ row: number;
913
+ onAnchorConflict: 'error' | 'drop';
914
+ } | {
915
+ type: 'replaceTableCellText';
916
+ tableId: string;
917
+ /** 0-based 行索引(对应 TableInfo.cells 网格的 i)*/
918
+ row: number;
919
+ /** 0-based 列索引(对应 cells[i] 的 j)*/
920
+ col: number;
921
+ text: string;
922
+ onAnchorConflict: 'error' | 'drop';
923
+ } | {
924
+ type: 'formatTableCell';
925
+ tableId: string;
926
+ /** 0-based row index, matching TableInfo.cellGrid[row][col]. */
927
+ row: number;
928
+ /** 0-based column index, matching TableInfo.cellGrid[row][col]. */
929
+ col: number;
930
+ format: TableCellDirectFormat;
931
+ } | {
932
+ type: 'insertTableCellParagraph';
933
+ tableId: string;
934
+ /** 0-based row index, matching TableInfo.cellGrid[row][col]. */
935
+ row: number;
936
+ /** 0-based column index, matching TableInfo.cellGrid[row][col]. */
937
+ col: number;
938
+ /** Plain text for the new paragraph. */
939
+ text: string;
940
+ /** Insert before the first direct cell content block or after the last one. */
941
+ position: 'start' | 'end';
942
+ } | {
943
+ type: 'replaceDrawingWithPlaceholder';
944
+ drawingId: string;
945
+ } | {
946
+ type: 'deleteDrawing';
947
+ drawingId: string;
948
+ } | {
949
+ type: 'replaceShapeInnerText';
950
+ drawingId: string;
951
+ placeholder: string;
952
+ } | {
953
+ type: 'insertTableRow';
954
+ tableId: string;
955
+ templateRow: number;
956
+ position: number | 'end';
957
+ cellTexts?: string[];
958
+ } | {
959
+ type: 'cloneTableAfter';
960
+ anchorParaId: ParaId;
961
+ sourceTableId: string;
962
+ } | {
963
+ type: 'insertImageAfter';
964
+ anchorParaId: ParaId;
965
+ bytes: Uint8Array;
966
+ contentType: string;
967
+ widthEmu: number;
968
+ heightEmu: number;
969
+ } | {
970
+ type: 'insertTableFrom';
971
+ anchorParaId: ParaId;
972
+ tableXml: string;
973
+ images?: Array<{
974
+ originalRId: string;
975
+ bytes: Uint8Array;
976
+ contentType: string;
977
+ }>;
978
+ styleTblPrXml?: string;
979
+ } | {
980
+ type: 'setTableColumnWidths';
981
+ tableId: string;
982
+ widths: number[];
983
+ } | {
984
+ type: 'setTableRowHeights';
985
+ tableId: string;
986
+ heights: (RowHeight | null)[];
987
+ } | {
988
+ type: 'setUpdateFields';
989
+ enabled: boolean;
990
+ };
991
+ interface ApplyResult {
992
+ /** 插入段落产生的新 paraId,按 op 顺序 */
993
+ insertedParagraphs: Array<{
994
+ opIndex: number;
995
+ anchorParaId: ParaId;
996
+ position: 'before' | 'after';
997
+ newParaId: ParaId;
998
+ }>;
999
+ /**
1000
+ * `insertParagraphAtBodyStart` 在 body 起始合成的空段 paraId,按 op 顺序。
1001
+ * 调用方据此拿到锚点 paraId 做后续重建(与 insertedParagraphs 分开,语义清晰)。
1002
+ */
1003
+ insertedBodyStartParaIds: ParaId[];
1004
+ /** 新建批注分配的 commentId,按 op 顺序 */
1005
+ createdComments: Array<{
1006
+ opIndex: number;
1007
+ commentId: CommentId;
1008
+ }>;
1009
+ /**
1010
+ * 新建书签清单。
1011
+ *
1012
+ * - 显式 `createBookmark` op 产生的:`name` 是调用方传入的;`range` 给段落 ID
1013
+ * (ParagraphRange 时 fromParaId === toParaId,TextRange 同段所以也相等)
1014
+ * - `insertParagraphAfter` 通过 `spec.bookmark` 触发的:`name` 是按规则解析后的实际名
1015
+ * (规则冲突会有 `_2/_3` 后缀);`range.fromParaId` = anchor,`range.toParaId` = newParaId
1016
+ */
1017
+ createdBookmarks: Array<{
1018
+ opIndex: number;
1019
+ name: BookmarkName;
1020
+ range: {
1021
+ fromParaId: ParaId;
1022
+ toParaId: ParaId;
1023
+ };
1024
+ }>;
1025
+ acceptedRevisions: number;
1026
+ rejectedRevisions: number;
1027
+ /**
1028
+ * 实际替换的表格单元格数 (#188 / #204)。
1029
+ *
1030
+ * `replaceTableCellWithSdt` op 在 `onAnchorConflict='drop'` 模式下遇锚点会
1031
+ * **静默跳过**, 该计数只统计真正完成替换的单元格数, 调用方据此报告准确域化数。
1032
+ */
1033
+ replacedTableCells: number;
1034
+ /** Diagnostic timing, present only when the kernel collects apply timing. */
1035
+ debugTiming?: {
1036
+ ops: number;
1037
+ affectedParts: number;
1038
+ collectAffectedPartsMs?: number;
1039
+ collectStoriesMs?: number;
1040
+ collectStoryLookups?: number;
1041
+ collectStoryLookupMs?: number;
1042
+ collectByType?: Array<{
1043
+ type: Op['type'];
1044
+ count: number;
1045
+ ms: number;
1046
+ storyLookups: number;
1047
+ storyLookupMs: number;
1048
+ }>;
1049
+ transactionMs: number;
1050
+ indicesMs: number;
1051
+ totalMs: number;
1052
+ kernelMs?: number;
1053
+ byType: Array<{
1054
+ type: Op['type'];
1055
+ count: number;
1056
+ ms: number;
1057
+ }>;
1058
+ };
1059
+ }
1060
+ interface PlanValidationIssue {
1061
+ code: WordErrorCode;
1062
+ message: string;
1063
+ details?: Record<string, unknown>;
1064
+ }
1065
+ interface PlanValidationItem {
1066
+ opIndex: number;
1067
+ opType: Op['type'];
1068
+ status: 'valid' | 'invalid' | 'unvalidated';
1069
+ issue?: PlanValidationIssue;
1070
+ }
1071
+ interface PlanValidationResult {
1072
+ valid: boolean;
1073
+ items: PlanValidationItem[];
1074
+ }
1075
+ /** 空结果常量(空 plan / 内部初始化用)*/
1076
+ declare const EMPTY_APPLY_RESULT: ApplyResult;
1077
+ interface WordPlan {
1078
+ replaceParagraph(paraId: ParaId, text: string, opts?: {
1079
+ onAnchorConflict?: 'error' | 'drop';
1080
+ keepInlineGraphics?: boolean;
1081
+ }): this;
1082
+ replaceTextInParagraph(paraId: ParaId, search: string, replacement: string, opts?: {
1083
+ scope?: 'first' | 'all';
1084
+ }): this;
1085
+ formatTextInParagraph(paraId: ParaId, search: string, format: {
1086
+ bold?: boolean;
1087
+ color?: string;
1088
+ italic?: boolean;
1089
+ underline?: boolean;
1090
+ highlight?: string;
1091
+ fontSize?: number;
1092
+ fontFamily?: string;
1093
+ }, opts?: {
1094
+ scope?: 'first' | 'all';
1095
+ }): this;
1096
+ formatParagraph(paraId: ParaId, format: ParagraphDirectFormat): this;
1097
+ insertParagraphBefore(anchorParaId: ParaId, spec: InsertParagraphSpec): this;
1098
+ insertParagraphAfter(anchorParaId: ParaId, spec: InsertParagraphSpec): this;
1099
+ /**
1100
+ * 无锚点在 `<w:body>` 起始插一个空段,新 paraId 通过
1101
+ * `ApplyResult.insertedBodyStartParaIds` 回传。
1102
+ *
1103
+ * 用途:body 完全无段落(极简/特殊文档,正文段被骨架删光)时,重建需要一个真实落点锚段。
1104
+ * 与 insertParagraphBefore/After 不同——后者必须有 anchor 段;本 op 不依赖任何已有段。
1105
+ */
1106
+ insertParagraphAtBodyStart(): this;
1107
+ deleteParagraph(paraId: ParaId, opts?: {
1108
+ onAnchorConflict?: 'error' | 'drop';
1109
+ }): this;
1110
+ acceptRevisions(scope: RevisionScope): this;
1111
+ rejectRevisions(scope: RevisionScope): this;
1112
+ createBookmark(spec: {
1113
+ name: BookmarkName;
1114
+ range: Range;
1115
+ }): this;
1116
+ deleteBookmark(name: BookmarkName): this;
1117
+ addComment(spec: {
1118
+ range: Range;
1119
+ text: string;
1120
+ author?: string;
1121
+ date?: Date;
1122
+ }): this;
1123
+ deleteComment(commentId: CommentId): this;
1124
+ /** Resolve and validate supported operation targets without mutating the document. */
1125
+ validate(): Promise<PlanValidationResult>;
1126
+ /**
1127
+ * 给表格挂批注(#186 表格分类与保留决策的"决策理由可追溯"载体)。
1128
+ * 实现上批注挂在表格首单元格的首段落,语义入口走 tableId。
1129
+ */
1130
+ addTableComment(spec: {
1131
+ tableId: string;
1132
+ text: string;
1133
+ author?: string;
1134
+ date?: Date;
1135
+ }): this;
1136
+ /**
1137
+ * 删除整张表格(#186 不保留表格的裁剪入口)。
1138
+ * 表格内段落若含活锚点(书签/批注),按 onAnchorConflict 处理。
1139
+ */
1140
+ deleteTable(tableId: string, opts?: {
1141
+ onAnchorConflict?: 'error' | 'drop';
1142
+ }): this;
1143
+ /**
1144
+ * 把表格指定单元格首段的 runs 替换为 inline SDT (#188 表格域化)。
1145
+ *
1146
+ * - (row, col) 对应 `TableInfo.cells[row][col]` 网格坐标(tr 顺序 × tc 顺序)
1147
+ * - 段落 pPr / 单元格 tcPr / 边框 / 合并关系全部保留
1148
+ * - 原首段 runs 的首 rPr 自动透传到 SDT 内 placeholder run, 字体 / 颜色 / 字号不丢
1149
+ * - 单元格首段含锚点 (书签 / 批注) 时按 onAnchorConflict 处理 ('error' 抛 / 'drop' 跳过)
1150
+ * - 单元格首段不存在或单元格不存在时抛 PARA_NOT_FOUND
1151
+ */
1152
+ replaceTableCellWithSdt(spec: {
1153
+ tableId: string;
1154
+ row: number;
1155
+ col: number;
1156
+ sdt: SdtSpec;
1157
+ onAnchorConflict?: 'error' | 'drop';
1158
+ }): this;
1159
+ /**
1160
+ * 替换表格指定单元格首段的内容为单个纯文字 run(排版回填)。
1161
+ *
1162
+ * - (row, col) 对应 TableInfo.cells[row][col] 网格坐标
1163
+ * - **单元格 tcPr(底纹 shd / 边框 / 对齐 vAlign / 列宽 tcW)完全保留**(只动首段内部)
1164
+ * - 首段 pPr 保留;原首 run 的 rPr(字体/字号/颜色)透传到新文字 run
1165
+ * - 单元格首段含锚点(书签/批注)时按 onAnchorConflict 处理('error' 抛 / 'drop' 跳过不替换)
1166
+ * - 单元格不存在 → TABLE_NOT_FOUND;首段不存在 → PACKAGE_CORRUPT
1167
+ * - trackChanges=true 暂不支持,抛 UNSUPPORTED_OOXML_FEATURE
1168
+ */
1169
+ replaceTableCellText(spec: {
1170
+ tableId: string;
1171
+ row: number;
1172
+ col: number;
1173
+ text: string;
1174
+ onAnchorConflict?: 'error' | 'drop';
1175
+ }): this;
1176
+ formatTableCell(spec: {
1177
+ tableId: string;
1178
+ row: number;
1179
+ col: number;
1180
+ format: TableCellDirectFormat;
1181
+ }): this;
1182
+ insertTableCellParagraph(spec: {
1183
+ tableId: string;
1184
+ row: number;
1185
+ col: number;
1186
+ text: string;
1187
+ position: 'start' | 'end';
1188
+ }): this;
1189
+ /**
1190
+ * 删除表格指定行 (#188 §7.2 行级裁剪)。
1191
+ *
1192
+ * - `row` 是 op 执行时的行索引;同一 plan 内连续删多行时调用方按**降序**传入,
1193
+ * 避免索引漂移(删 row 3 后原 row 4 变成新的 row 3)
1194
+ * - 行内段落含活锚点 (书签 / 批注) 时按 `onAnchorConflict` 处理 ('error' 抛 / 'drop' 跳过)
1195
+ * - 删除最后一行会让表格只剩 tblPr / tblGrid —— Word 允许 0 行表格但显示异常,
1196
+ * 调用方应在外层保证至少留一行(典型场景:可变行数表保留表头 + 1~N 样例行)
1197
+ */
1198
+ deleteTableRow(tableId: string, row: number, opts?: {
1199
+ onAnchorConflict?: 'error' | 'drop';
1200
+ }): this;
1201
+ /**
1202
+ * 把 drawing 的图片内容替换为共享占位图 (#190)。
1203
+ *
1204
+ * - 仅接受 kind = 'picture' 的 drawing;其它 kind(chart / smartArt / shape / textBox /
1205
+ * group / canvas / other)抛 UNSUPPORTED_OOXML_FEATURE,需走 deleteDrawing 或 #192
1206
+ * - **布局完全保持**:wp:inline / wp:anchor、wp:extent、wrap、position、anchorParaId
1207
+ * 都不动,只改 a:blip/@r:embed 指向共享 placeholder
1208
+ * - 同一文档内多次调用幂等:共用一份 word/media/placeholder.png + 单条 image rel
1209
+ * - 替换后若旧 media 在全包无其它引用,自动清理对应 rels 条目 + binary part
1210
+ * (保证「原始图片二进制不出现在输出文档中」的验收条件)
1211
+ * - drawingId 不存在抛 DRAWING_NOT_FOUND
1212
+ * - trackChanges=true 暂不支持,抛 UNSUPPORTED_OOXML_FEATURE
1213
+ */
1214
+ replaceDrawingWithPlaceholder(drawingId: string): this;
1215
+ /**
1216
+ * 删除 drawing(B/C 类裁剪入口)。
1217
+ *
1218
+ * - 不限制 kind,任何 drawing 都可删
1219
+ * - 物理删 w:drawing;承载它的 w:r 若仅含该 drawing 一并删除
1220
+ * - 同样清理孤儿 media / rels(逻辑与 replaceDrawingWithPlaceholder 共享)
1221
+ * - drawingId 不存在抛 DRAWING_NOT_FOUND
1222
+ * - trackChanges=true 暂不支持,抛 UNSUPPORTED_OOXML_FEATURE
1223
+ */
1224
+ deleteDrawing(drawingId: string): this;
1225
+ /**
1226
+ * 把 Shape / TextBox 内部文字替换为统一占位文字 (#210,#192 内容型保留依赖)。
1227
+ *
1228
+ * - 仅接受含 `w:txbxContent` 的 drawing(textBox / shape-with-text)
1229
+ * 其它 kind(picture / chart / smartArt / group / canvas / shape-without-text / other)
1230
+ * 抛 UNSUPPORTED_OOXML_FEATURE,需走 replaceDrawingWithPlaceholder 或 deleteDrawing
1231
+ * - **外壳完全保留**:w:drawing 整个 wp:inline / wp:anchor / wsp:spPr / wp:extent /
1232
+ * wrap / position 一字不动
1233
+ * - 内部 `w:txbxContent` 被重写为**单段单 run** placeholder 文本;原首段
1234
+ * `w:pPr/w:jc` 对齐保留(沿用 innerTextAlign 维度)
1235
+ * - 内部 hyperlink / 嵌套 picture 的 rels 引用按 deleteDrawing 同源清理
1236
+ * - 占位文字走默认 run 样式(v1 不保留原首段 run rPr 字体 / 字号 / 颜色)
1237
+ * - drawingId 不存在抛 DRAWING_NOT_FOUND
1238
+ * - trackChanges=true 暂不支持,抛 UNSUPPORTED_OOXML_FEATURE
1239
+ */
1240
+ replaceShapeInnerText(drawingId: string, placeholder: string): this;
1241
+ /**
1242
+ * 克隆表格某一行作模板,在指定位置插入新行(可变行数表回填)。(#14)
1243
+ *
1244
+ * - `templateRow`:0-based,克隆此行的单元格结构(tcPr 含底纹 shd / 边框 /
1245
+ * 对齐 vAlign / 列宽 tcW + 首段 pPr + 首 run rPr 全保留)
1246
+ * - `position`:插入后新行所在的 0-based 行索引(insert-before 语义);
1247
+ * 传 'end' 追加到末尾。范围 [0, rowCount],rowCount 等价 'end'
1248
+ * - `cellTexts`:可选,新行各列文字(保留各列 rPr)。
1249
+ * - 不传:克隆模板行原样(含模板原文字)
1250
+ * - 传 L 个元素:列 i ∈ [0, min(L,C)) 替换为 cellTexts[i];列 i ∈ [L,C) 清空;多余忽略
1251
+ * - 克隆行内锚点(书签/批注)一律剥离;行内每个 <w:p> 重新分配 paraId
1252
+ * - 表格不存在 / templateRow 越界 / position 越界 → TABLE_NOT_FOUND
1253
+ * - trackChanges=true 暂不支持 → UNSUPPORTED_OOXML_FEATURE
1254
+ */
1255
+ insertTableRow(spec: {
1256
+ tableId: string;
1257
+ templateRow: number;
1258
+ position: number | 'end';
1259
+ cellTexts?: string[];
1260
+ }): this;
1261
+ /**
1262
+ * 把已有表格深克隆一份,插入到指定段落之后(排版重建:模板表克隆到多处)。(#15)
1263
+ *
1264
+ * - `sourceTableId`:克隆哪张表。深克隆整个 `<w:tbl>`(tblPr/tblGrid/所有行/
1265
+ * 单元格 tcPr/pPr/rPr 全保留)。源表自身**只读,不被修改**。
1266
+ * - `anchorParaId`:克隆表插到此段之后(与 insertParagraphAfter 同语义:
1267
+ * 插到 anchor 的下一个兄弟之前)。anchor 应为 body story 直属段落。
1268
+ * - 克隆表内**锚点(书签/批注 5 类)一律剥离**;克隆表内**每个 `<w:p>`
1269
+ * 重新分配 paraId**,保 paraId 全局唯一。
1270
+ * - anchorParaId 不存在 → PARA_NOT_FOUND;sourceTableId 不存在 → TABLE_NOT_FOUND。
1271
+ * - trackChanges=true 暂不支持 → UNSUPPORTED_OOXML_FEATURE。
1272
+ * - v1 不在 ApplyResult 回传新表 tableId;apply 后用 `doc.tables.list()` 按文档顺序定位。
1273
+ */
1274
+ cloneTableAfter(spec: {
1275
+ anchorParaId: ParaId;
1276
+ sourceTableId: string;
1277
+ }): this;
1278
+ /**
1279
+ * 在指定段落之后新插一个段,段内含一个 inline 图片(task-insert-image)。
1280
+ *
1281
+ * - `anchorParaId`:新段插到此段之后(与 insertParagraphAfter 同语义)
1282
+ * - `bytes`:图片二进制(`Uint8Array`,跨端,绝不碰 node fs/Buffer)
1283
+ * - `contentType`:'image/png' | 'image/jpeg' | 'image/gif' | 'image/bmp' | 'image/tiff'
1284
+ * - `widthEmu` / `heightEmu`:wp:extent@cx/cy(EMU 单位,1 英寸 = 914400 EMU)
1285
+ * - anchor 不存在 → `PARA_NOT_FOUND`
1286
+ * - 不支持的 contentType → `UNSUPPORTED_OOXML_FEATURE`
1287
+ * - trackChanges=true → `UNSUPPORTED_OOXML_FEATURE`
1288
+ */
1289
+ insertImageAfter(anchorParaId: ParaId, spec: {
1290
+ bytes: Uint8Array;
1291
+ contentType: string;
1292
+ widthEmu: number;
1293
+ heightEmu: number;
1294
+ }): this;
1295
+ /**
1296
+ * 跨文档 verbatim 搬一张表进当前文档,插到 anchorParaId 段之后
1297
+ * (task-20260616-table-content-driven,"数据表 = 内容块" §13.9)。
1298
+ *
1299
+ * - `anchorParaId`:搬入的表插到此段之后(与 cloneTableAfter 同语义)。
1300
+ * - `tableXml`:源文档 `<w:tbl>` 子树序列化字符串。调用方(typeset,持源 doc)用
1301
+ * `serializeToWellFormedString(tblElement)` 取得;命名空间随子树带入,无需额外声明。
1302
+ * - `images`:格内图预解析字节,按源 `<a:blip @r:embed>` 的**原始 rId** 索引;executor 在
1303
+ * host 新建 media part + image rel + content-type,把 embed 改写成新 rId。缺某 rId → 该
1304
+ * blip embed 清掉 + warn(结构/文字仍保真,仅该格图降级)。
1305
+ * - `styleTblPrXml`:可选,模板数据表 `<w:tblPr>` 序列化串。提供则整体替换搬入表的 tblPr
1306
+ * (tblStyle/边框/tblLook/宽度 → 归一到模板样式,覆盖内容表自带样式)。
1307
+ * - 表内锚点(书签/批注 5 类)一律剥离;每个 `<w:p>` 重分配 paraId(全局唯一)。
1308
+ * - 行/列/值/合并/嵌套表/格内图全部 verbatim 来自 tableXml,executor 不重建/不裁剪/不对位。
1309
+ * - anchor 不存在 → `PARA_NOT_FOUND`;tableXml 非 `<w:tbl>` → `INVALID_ARGUMENT`;
1310
+ * trackChanges=true → `UNSUPPORTED_OOXML_FEATURE`。
1311
+ * - v1 不在 ApplyResult 回传新表 tableId;apply 后用 `doc.tables.list()` 按文档顺序定位。
1312
+ */
1313
+ insertTableFrom(spec: {
1314
+ anchorParaId: ParaId;
1315
+ tableXml: string;
1316
+ images?: Array<{
1317
+ originalRId: string;
1318
+ bytes: Uint8Array;
1319
+ contentType: string;
1320
+ }>;
1321
+ styleTblPrXml?: string;
1322
+ }): this;
1323
+ /**
1324
+ * 设表格列宽:同步更新 `<w:tblGrid>` gridCol w:w **和** 每个单元格 `<w:tcW>`
1325
+ * (task-core-table-grid:merger 保真源表列宽)。
1326
+ *
1327
+ * - `tableId`:目标表格(来自 `tables.list()` 的 tableId)。
1328
+ * - `widths`:新列宽数组(twips,1 twip = 1/20 磅)。长度必须等于该表格的
1329
+ * `colCount`(gridCol 数量)——不等则抛 `INVALID_ARGUMENT`(防止截断/越界)。
1330
+ * - 同步设每个单元格 `<w:tcW w:type="dxa">`(Word 渲染优先 tcW over gridCol):
1331
+ * 合并单元格(gridSpan > 1)的 tcW = 跨列宽之和;vMerge 续行单元格正常处理。
1332
+ * - tableId 不存在 → `TABLE_NOT_FOUND`。
1333
+ * - trackChanges=true → `UNSUPPORTED_OOXML_FEATURE`(暂不支持)。
1334
+ */
1335
+ setTableColumnWidths(spec: {
1336
+ tableId: string;
1337
+ widths: number[];
1338
+ }): this;
1339
+ /**
1340
+ * 设表格行高(task-core-table-rowheight:merger 保真源表行高)。
1341
+ *
1342
+ * - `tableId`:目标表格(来自 `tables.list()` 的 tableId)。
1343
+ * - `heights`:每行行高数组,长度必须等于该表格的 `rowCount`——不等则抛 `INVALID_ARGUMENT`。
1344
+ * - `RowHeight`:在该行 `<w:trPr>` 写入/替换 `<w:trHeight w:val="N" w:hRule="..."/>`。
1345
+ * - `null`:删除该行的 `<w:trHeight>`(即「不指定行高」)。
1346
+ * - `heights[i]` 套到物理第 i 行 `<w:tr>`(与 `TableInfo.rowHeights` 1:1)。
1347
+ * - tableId 不存在 → `TABLE_NOT_FOUND`。
1348
+ * - trackChanges=true → `UNSUPPORTED_OOXML_FEATURE`(暂不支持)。
1349
+ */
1350
+ setTableRowHeights(spec: {
1351
+ tableId: string;
1352
+ heights: (RowHeight | null)[];
1353
+ }): this;
1354
+ /**
1355
+ * 在 settings.xml 写入/更新 `<w:updateFields>`,让含 TOC 域的文档打开时自动更新域。
1356
+ * (task-core-update-fields)
1357
+ *
1358
+ * - `enabled=true`:在 settings.xml 根 `<w:settings>` 写入/更新
1359
+ * `<w:updateFields w:val="true"/>`——Word/WPS 打开文档时自动重生成所有域(TOC/PAGEREF/SEQ 等)。
1360
+ * - `enabled=false`:写 `<w:updateFields w:val="false"/>`(显式禁用,语义更清晰)。
1361
+ * - 幂等:settings.xml 已有 `<w:updateFields>` 则改 `w:val`,不重复插入元素。
1362
+ * - settings.xml 不存在 → 抛 `UNSUPPORTED_OOXML_FEATURE`(后续跟进新建 settings part)。
1363
+ */
1364
+ setUpdateFields(enabled: boolean): this;
1365
+ apply(): Promise<ApplyResult>;
1366
+ /** 只读 op 队列,用于调试 / 日志 / 测试 */
1367
+ readonly ops: ReadonlyArray<Op>;
1368
+ /** apply 是否已被调用过(成功与否都置 true,防止二次 apply)*/
1369
+ readonly applied: boolean;
1370
+ /** Plan 创建时的选项,只读 */
1371
+ readonly options: Readonly<Required<Pick<PlanOptions, 'trackChanges'>> & Omit<PlanOptions, 'trackChanges'>>;
1372
+ }
1373
+ interface WordPlanImplInit {
1374
+ docId: string;
1375
+ transport: Transport;
1376
+ options: PlanOptions;
1377
+ }
1378
+ declare class WordPlanImpl implements WordPlan {
1379
+ private readonly docId;
1380
+ private readonly transport;
1381
+ private readonly _options;
1382
+ private readonly _ops;
1383
+ private _applied;
1384
+ constructor(init: WordPlanImplInit);
1385
+ get ops(): ReadonlyArray<Op>;
1386
+ get applied(): boolean;
1387
+ get options(): Readonly<WordPlan['options']>;
1388
+ replaceParagraph(paraId: ParaId, text: string, opts?: {
1389
+ onAnchorConflict?: 'error' | 'drop';
1390
+ keepInlineGraphics?: boolean;
1391
+ }): this;
1392
+ replaceTextInParagraph(paraId: ParaId, search: string, replacement: string, opts?: {
1393
+ scope?: 'first' | 'all';
1394
+ }): this;
1395
+ formatTextInParagraph(paraId: ParaId, search: string, format: {
1396
+ bold?: boolean;
1397
+ color?: string;
1398
+ italic?: boolean;
1399
+ underline?: boolean;
1400
+ highlight?: string;
1401
+ fontSize?: number;
1402
+ fontFamily?: string;
1403
+ }, opts?: {
1404
+ scope?: 'first' | 'all';
1405
+ }): this;
1406
+ formatParagraph(paraId: ParaId, format: ParagraphDirectFormat): this;
1407
+ insertParagraphBefore(anchorParaId: ParaId, spec: InsertParagraphSpec): this;
1408
+ insertParagraphAfter(anchorParaId: ParaId, spec: InsertParagraphSpec): this;
1409
+ insertParagraphAtBodyStart(): this;
1410
+ deleteParagraph(paraId: ParaId, opts?: {
1411
+ onAnchorConflict?: 'error' | 'drop';
1412
+ }): this;
1413
+ acceptRevisions(scope: RevisionScope): this;
1414
+ rejectRevisions(scope: RevisionScope): this;
1415
+ createBookmark(spec: {
1416
+ name: BookmarkName;
1417
+ range: Range;
1418
+ }): this;
1419
+ deleteBookmark(name: BookmarkName): this;
1420
+ addComment(spec: {
1421
+ range: Range;
1422
+ text: string;
1423
+ author?: string;
1424
+ date?: Date;
1425
+ }): this;
1426
+ deleteComment(commentId: CommentId): this;
1427
+ addTableComment(spec: {
1428
+ tableId: string;
1429
+ text: string;
1430
+ author?: string;
1431
+ date?: Date;
1432
+ }): this;
1433
+ deleteTable(tableId: string, opts?: {
1434
+ onAnchorConflict?: 'error' | 'drop';
1435
+ }): this;
1436
+ replaceTableCellWithSdt(spec: {
1437
+ tableId: string;
1438
+ row: number;
1439
+ col: number;
1440
+ sdt: SdtSpec;
1441
+ onAnchorConflict?: 'error' | 'drop';
1442
+ }): this;
1443
+ deleteTableRow(tableId: string, row: number, opts?: {
1444
+ onAnchorConflict?: 'error' | 'drop';
1445
+ }): this;
1446
+ replaceTableCellText(spec: {
1447
+ tableId: string;
1448
+ row: number;
1449
+ col: number;
1450
+ text: string;
1451
+ onAnchorConflict?: 'error' | 'drop';
1452
+ }): this;
1453
+ formatTableCell(spec: {
1454
+ tableId: string;
1455
+ row: number;
1456
+ col: number;
1457
+ format: TableCellDirectFormat;
1458
+ }): this;
1459
+ insertTableCellParagraph(spec: {
1460
+ tableId: string;
1461
+ row: number;
1462
+ col: number;
1463
+ text: string;
1464
+ position: 'start' | 'end';
1465
+ }): this;
1466
+ replaceDrawingWithPlaceholder(drawingId: string): this;
1467
+ deleteDrawing(drawingId: string): this;
1468
+ replaceShapeInnerText(drawingId: string, placeholder: string): this;
1469
+ insertTableRow(spec: {
1470
+ tableId: string;
1471
+ templateRow: number;
1472
+ position: number | 'end';
1473
+ cellTexts?: string[];
1474
+ }): this;
1475
+ cloneTableAfter(spec: {
1476
+ anchorParaId: ParaId;
1477
+ sourceTableId: string;
1478
+ }): this;
1479
+ insertImageAfter(anchorParaId: ParaId, spec: {
1480
+ bytes: Uint8Array;
1481
+ contentType: string;
1482
+ widthEmu: number;
1483
+ heightEmu: number;
1484
+ }): this;
1485
+ insertTableFrom(spec: {
1486
+ anchorParaId: ParaId;
1487
+ tableXml: string;
1488
+ images?: Array<{
1489
+ originalRId: string;
1490
+ bytes: Uint8Array;
1491
+ contentType: string;
1492
+ }>;
1493
+ styleTblPrXml?: string;
1494
+ }): this;
1495
+ setTableColumnWidths(spec: {
1496
+ tableId: string;
1497
+ widths: number[];
1498
+ }): this;
1499
+ setTableRowHeights(spec: {
1500
+ tableId: string;
1501
+ heights: (RowHeight | null)[];
1502
+ }): this;
1503
+ setUpdateFields(enabled: boolean): this;
1504
+ apply(): Promise<ApplyResult>;
1505
+ validate(): Promise<PlanValidationResult>;
1506
+ private ensureOpen;
1507
+ }
1508
+ /**
1509
+ * `kernel.applyPlan` 接收的结构。`date` 是 ISO 8601 字符串(序列化友好),kernel
1510
+ * 端需要时用 `new Date(str)` 解回。
1511
+ */
1512
+ interface ApplyPlanParams {
1513
+ ops: Op[];
1514
+ options: {
1515
+ trackChanges: boolean;
1516
+ author?: string;
1517
+ date?: string;
1518
+ };
1519
+ }
1520
+
1521
+ interface RangeClassification {
1522
+ kind: 'paragraph' | 'text' | 'complex';
1523
+ /** 'paragraph' / 'text' 命中时,containing `<w:p>` 的 paraId(大写 8 hex) */
1524
+ paraId?: string;
1525
+ /** 'text' 命中时,start/end 之间所有 `<w:t>` 的纯文本拼接 */
1526
+ text?: string;
1527
+ }
1528
+ declare function classifyRange(start: Element | null, end: Element | null): RangeClassification;
1529
+
1530
+ /**
1531
+ * Core-Word 读 API 的 namespace 子对象(#92,docs/03.1 §2)。
1532
+ *
1533
+ * 把 Phase B 原本平铺在 `WordDocument` 上的 7 个读方法按实体聚合为 4 个子 API:
1534
+ *
1535
+ * | 旧(平铺) | 新(namespace) |
1536
+ * |---|---|
1537
+ * | `doc.listParagraphs(opts)` | `doc.paragraphs.list(opts)` |
1538
+ * | `doc.getParagraph(id)` | `doc.paragraphs.get(id)` |
1539
+ * | `doc.listBookmarks(opts)` | `doc.bookmarks.list(opts)` |
1540
+ * | `doc.getBookmark(name)` | `doc.bookmarks.get(name)` |
1541
+ * | `doc.listComments()` | `doc.comments.list()` |
1542
+ * | `doc.getComment(id)` | `doc.comments.get(id)` |
1543
+ * | `doc.listRevisions(opts)` | `doc.revisions.list(opts)` |
1544
+ *
1545
+ * 动机:Phase F 起属性层(`format.*`)+ sections / tables / drawings / styles /
1546
+ * hyperlinks / fields 若继续平铺会让主类表面爆炸。namespace 聚合后新实体扩展只
1547
+ * 需往 `WordDocument` 加一个 `readonly` 字段(见 docs/03.1 §2 的 "未来扩展")。
1548
+ *
1549
+ * 命名规范(docs/03.1 §2.1):
1550
+ * - 子 API 方法用动词短命名 `list` / `get`,不重复实体名
1551
+ * - 过滤/分页选项保留顶层类型名(`ListParagraphsOptions` 不简化)
1552
+ * - 返回值类型名不变
1553
+ *
1554
+ * RPC method name 同步迁移:`paragraphs.list` / `paragraphs.get` / `bookmarks.list`
1555
+ * / `bookmarks.get` / `comments.list` / `comments.get` / `revisions.list`。协议
1556
+ * 版本不 bump —— 这是 method name rename,非协议结构变更。
1557
+ */
1558
+
1559
+ interface ParagraphApi {
1560
+ /**
1561
+ * Lists paragraphs and returns live paragraph handles.
1562
+ */
1563
+ list(opts?: ListParagraphsOptions): Promise<ParagraphList>;
1564
+ /**
1565
+ * Gets one paragraph by `paraId`.
1566
+ *
1567
+ * Returns `null` when the paragraph no longer exists.
1568
+ */
1569
+ get(paraId: string): Promise<Paragraph | null>;
1570
+ }
1571
+ interface ParagraphList {
1572
+ paragraphs: Paragraph[];
1573
+ pagination: ListResult['pagination'];
1574
+ }
1575
+ interface LiveObjectWriteOptions {
1576
+ /**
1577
+ * Enables tracked-change markup for the write operation when supported.
1578
+ */
1579
+ trackChanges?: boolean;
1580
+ /**
1581
+ * Author metadata used by comments and tracked changes.
1582
+ */
1583
+ author?: string;
1584
+ /**
1585
+ * Date metadata used by comments and tracked changes.
1586
+ */
1587
+ date?: Date;
1588
+ }
1589
+ interface ContextApi {
1590
+ /**
1591
+ * Searches local document content and returns actionable context matches.
1592
+ */
1593
+ search(opts: ContextSearchOptions): Promise<ContextSearchResult>;
1594
+ }
1595
+ interface RevisionBulkOptions extends LiveObjectWriteOptions {
1596
+ /**
1597
+ * Bulk revision writes currently target all supported revisions.
1598
+ */
1599
+ scope?: 'all';
1600
+ }
1601
+ interface ParagraphDeleteOptions extends LiveObjectWriteOptions {
1602
+ /**
1603
+ * Controls what happens when deleting the paragraph would affect anchors such
1604
+ * as bookmarks or comments.
1605
+ */
1606
+ onAnchorConflict?: 'error' | 'drop';
1607
+ }
1608
+ interface ParagraphInsertOptions extends LiveObjectWriteOptions {
1609
+ /**
1610
+ * Controls the new paragraph's paragraph/run style source.
1611
+ */
1612
+ style?: 'inherit' | string;
1613
+ /**
1614
+ * Controls whether the new paragraph run inherits the anchor run format.
1615
+ */
1616
+ runFormat?: 'inherit' | 'default';
1617
+ }
1618
+ interface ParagraphReplaceOptions extends LiveObjectWriteOptions {
1619
+ /**
1620
+ * Controls what happens when replacing a paragraph would affect anchors such
1621
+ * as bookmarks or comments.
1622
+ */
1623
+ onAnchorConflict?: 'error' | 'drop';
1624
+ /**
1625
+ * Preserves inline drawings/objects while replacing text runs.
1626
+ */
1627
+ keepInlineGraphics?: boolean;
1628
+ }
1629
+ interface ParagraphInsertImageSpec {
1630
+ /** Image bytes. The SDK accepts browser-safe Uint8Array data. */
1631
+ bytes: Uint8Array;
1632
+ /** Image MIME type, for example `image/png` or `image/jpeg`. */
1633
+ contentType: string;
1634
+ /** Rendered width in EMU. 1 inch = 914400 EMU. */
1635
+ widthEmu: number;
1636
+ /** Rendered height in EMU. 1 inch = 914400 EMU. */
1637
+ heightEmu: number;
1638
+ }
1639
+ interface ParagraphInsertTableSpec {
1640
+ /**
1641
+ * Text matrix used to create a simple Word table. Missing cells in ragged
1642
+ * rows are created as empty cells.
1643
+ */
1644
+ rows: string[][];
1645
+ /** Column widths in twips. Defaults to 2400 twips for each column. */
1646
+ columnWidths?: number[];
1647
+ /** Optional Word table style id, written as `w:tblStyle`. */
1648
+ tableStyleId?: string;
1649
+ }
1650
+ /**
1651
+ * Live handle for one document paragraph.
1652
+ *
1653
+ * Snapshot fields such as `paraId` and `story` come from the read that created
1654
+ * the handle. Methods read or write the current document state.
1655
+ */
1656
+ interface Paragraph extends ParagraphInfo {
1657
+ /** Stable paragraph identifier. */
1658
+ readonly paraId: ParaId;
1659
+ /** Alias of `paraId`, kept for object-style APIs. */
1660
+ readonly id: ParaId;
1661
+ /** Document story that contains this paragraph. */
1662
+ readonly story: ParagraphInfo['story'];
1663
+ /**
1664
+ * Reads the current metadata for this paragraph.
1665
+ */
1666
+ getInfo(opts?: Pick<ListParagraphsOptions, 'includeFormat' | 'textFormat'>): Promise<ParagraphInfo | null>;
1667
+ /**
1668
+ * Reads the current plain text of this paragraph.
1669
+ */
1670
+ getText(): Promise<string | null>;
1671
+ /**
1672
+ * Replaces this paragraph with plain text.
1673
+ */
1674
+ replaceWith(text: string, opts?: ParagraphReplaceOptions): Promise<ApplyResult>;
1675
+ /**
1676
+ * Sets horizontal paragraph alignment.
1677
+ */
1678
+ setAlignment(value: NonNullable<ParagraphDirectFormat['alignment']>, opts?: LiveObjectWriteOptions): Promise<ApplyResult>;
1679
+ /**
1680
+ * Sets paragraph outline level. Values 0-8 correspond to heading levels 1-9.
1681
+ */
1682
+ setOutlineLevel(value: number, opts?: LiveObjectWriteOptions): Promise<ApplyResult>;
1683
+ /**
1684
+ * Sets whether this paragraph starts on a new page.
1685
+ */
1686
+ setPageBreakBefore(value: boolean, opts?: LiveObjectWriteOptions): Promise<ApplyResult>;
1687
+ /**
1688
+ * Sets paragraph indentation in twips.
1689
+ */
1690
+ setIndent(value: NonNullable<ParagraphDirectFormat['indent']>, opts?: LiveObjectWriteOptions): Promise<ApplyResult>;
1691
+ /**
1692
+ * Sets paragraph spacing in twips.
1693
+ */
1694
+ setSpacing(value: NonNullable<ParagraphDirectFormat['spacing']>, opts?: LiveObjectWriteOptions): Promise<ApplyResult>;
1695
+ /**
1696
+ * Inserts a new paragraph before this paragraph.
1697
+ */
1698
+ insertBefore(text: string, opts?: ParagraphInsertOptions): Promise<ApplyResult>;
1699
+ /**
1700
+ * Inserts a new paragraph after this paragraph.
1701
+ */
1702
+ insertAfter(text: string, opts?: ParagraphInsertOptions): Promise<ApplyResult>;
1703
+ /**
1704
+ * Inserts a new inline image paragraph after this paragraph.
1705
+ */
1706
+ insertImageAfter(spec: ParagraphInsertImageSpec, opts?: LiveObjectWriteOptions): Promise<ApplyResult>;
1707
+ /**
1708
+ * Inserts a simple text table after this paragraph.
1709
+ *
1710
+ * For high-fidelity table copy, use `table.getVerbatim()` with
1711
+ * `doc.plan().insertTableFrom(...)`.
1712
+ */
1713
+ insertTableAfter(spec: ParagraphInsertTableSpec, opts?: LiveObjectWriteOptions): Promise<ApplyResult>;
1714
+ /**
1715
+ * Deletes this paragraph from the document.
1716
+ */
1717
+ delete(opts?: ParagraphDeleteOptions): Promise<ApplyResult>;
1718
+ /**
1719
+ * Adds a comment to this whole paragraph.
1720
+ */
1721
+ addComment(text: string, opts?: LiveObjectWriteOptions): Promise<ApplyResult>;
1722
+ /**
1723
+ * Creates a bookmark around this whole paragraph.
1724
+ */
1725
+ createBookmark(name: BookmarkName$1, opts?: LiveObjectWriteOptions): Promise<ApplyResult>;
1726
+ /**
1727
+ * Creates a text range handle by searching inside this paragraph.
1728
+ *
1729
+ * The returned range is lazy: it resolves the search when a range method is
1730
+ * executed.
1731
+ */
1732
+ findText(search: string, opts?: {
1733
+ scope?: 'first' | 'all';
1734
+ }): TextRange;
1735
+ }
1736
+ /**
1737
+ * Live handle for text matched inside one paragraph.
1738
+ */
1739
+ interface TextRange {
1740
+ /**
1741
+ * Replaces the matched text with plain text.
1742
+ */
1743
+ replaceWith(text: string, opts?: LiveObjectWriteOptions): Promise<ApplyResult>;
1744
+ /**
1745
+ * Deletes the matched text.
1746
+ */
1747
+ delete(opts?: LiveObjectWriteOptions): Promise<ApplyResult>;
1748
+ /**
1749
+ * Sets bold formatting on the matched text.
1750
+ */
1751
+ setBold(value: boolean, opts?: LiveObjectWriteOptions): Promise<ApplyResult>;
1752
+ /**
1753
+ * Sets font color on the matched text.
1754
+ */
1755
+ setColor(value: string, opts?: LiveObjectWriteOptions): Promise<ApplyResult>;
1756
+ /**
1757
+ * Sets italic formatting on the matched text.
1758
+ */
1759
+ setItalic(value: boolean, opts?: LiveObjectWriteOptions): Promise<ApplyResult>;
1760
+ /**
1761
+ * Sets single underline on the matched text.
1762
+ */
1763
+ setUnderline(value: boolean, opts?: LiveObjectWriteOptions): Promise<ApplyResult>;
1764
+ /**
1765
+ * Sets Word highlight color on the matched text.
1766
+ */
1767
+ setHighlight(value: string, opts?: LiveObjectWriteOptions): Promise<ApplyResult>;
1768
+ /**
1769
+ * Sets font size in points on the matched text.
1770
+ */
1771
+ setFontSize(value: number, opts?: LiveObjectWriteOptions): Promise<ApplyResult>;
1772
+ /**
1773
+ * Sets font family on the matched text.
1774
+ */
1775
+ setFontFamily(value: string, opts?: LiveObjectWriteOptions): Promise<ApplyResult>;
1776
+ /**
1777
+ * Adds a comment to the matched text.
1778
+ */
1779
+ addComment(text: string, opts?: LiveObjectWriteOptions): Promise<ApplyResult>;
1780
+ /**
1781
+ * Creates a bookmark around the matched text.
1782
+ */
1783
+ createBookmark(name: BookmarkName$1, opts?: LiveObjectWriteOptions): Promise<ApplyResult>;
1784
+ }
1785
+ interface BookmarkApi {
1786
+ /**
1787
+ * Lists bookmarks and returns live bookmark handles.
1788
+ */
1789
+ list(opts?: ListBookmarksOptions): Promise<Bookmark[]>;
1790
+ /**
1791
+ * Gets one bookmark by name.
1792
+ *
1793
+ * Returns `null` when the bookmark no longer exists.
1794
+ */
1795
+ get(name: BookmarkName$1): Promise<Bookmark | null>;
1796
+ }
1797
+ /**
1798
+ * Live handle for one document bookmark.
1799
+ */
1800
+ interface Bookmark extends BookmarkInfo {
1801
+ /** Alias of `name`, kept for object-style APIs. */
1802
+ readonly id: BookmarkName$1;
1803
+ /**
1804
+ * Reads current metadata for this bookmark.
1805
+ */
1806
+ getInfo(): Promise<BookmarkInfo | null>;
1807
+ /**
1808
+ * Reads the current text covered by this bookmark when it can be expressed as
1809
+ * a paragraph or text range.
1810
+ */
1811
+ getText(): Promise<string | null>;
1812
+ /**
1813
+ * Returns the paragraph that contains this bookmark when available.
1814
+ */
1815
+ getParagraph(): Promise<Paragraph | null>;
1816
+ /**
1817
+ * Deletes this bookmark anchor pair.
1818
+ */
1819
+ delete(opts?: LiveObjectWriteOptions): Promise<ApplyResult>;
1820
+ }
1821
+ interface CommentApi {
1822
+ /**
1823
+ * Lists comments and returns live comment handles.
1824
+ */
1825
+ list(): Promise<Comment[]>;
1826
+ /**
1827
+ * Gets one comment by id.
1828
+ *
1829
+ * Returns `null` when the comment no longer exists.
1830
+ */
1831
+ get(id: CommentId$1): Promise<Comment | null>;
1832
+ }
1833
+ /**
1834
+ * Live handle for one document comment.
1835
+ */
1836
+ interface Comment extends CommentInfo {
1837
+ /**
1838
+ * Reads current metadata for this comment.
1839
+ */
1840
+ getInfo(): Promise<CommentInfo | null>;
1841
+ /**
1842
+ * Reads the current comment body text from `comments.xml`.
1843
+ */
1844
+ getText(): Promise<string | null>;
1845
+ /**
1846
+ * Reads the current document text covered by this comment anchor.
1847
+ */
1848
+ getAnchorText(): Promise<string | null>;
1849
+ /**
1850
+ * Returns the paragraph that contains this comment anchor when available.
1851
+ */
1852
+ getParagraph(): Promise<Paragraph | null>;
1853
+ /**
1854
+ * Deletes this comment body and its anchors.
1855
+ */
1856
+ delete(opts?: LiveObjectWriteOptions): Promise<ApplyResult>;
1857
+ }
1858
+ interface RevisionApi {
1859
+ /**
1860
+ * Lists revisions and returns live revision handles.
1861
+ */
1862
+ list(opts?: ListRevisionsOptions): Promise<Revision[]>;
1863
+ /**
1864
+ * Gets one revision by `revId`.
1865
+ *
1866
+ * Returns `null` when the revision no longer exists.
1867
+ */
1868
+ get(revId: RevisionInfo['revId'], opts?: ListRevisionsOptions): Promise<Revision | null>;
1869
+ /**
1870
+ * Accepts all supported revisions.
1871
+ */
1872
+ accept(opts?: RevisionBulkOptions): Promise<ApplyResult>;
1873
+ /**
1874
+ * Rejects all supported revisions.
1875
+ */
1876
+ reject(opts?: RevisionBulkOptions): Promise<ApplyResult>;
1877
+ }
1878
+ /**
1879
+ * Live handle for one document revision.
1880
+ *
1881
+ * `revision.accept/reject` operate on this single revision id. Use
1882
+ * `doc.revisions.accept/reject` for all supported revisions.
1883
+ */
1884
+ interface Revision extends RevisionInfo {
1885
+ /** Stable alias of `revId`, kept for object-style APIs. */
1886
+ readonly id: RevisionInfo['revId'];
1887
+ /**
1888
+ * Reads current metadata for this revision.
1889
+ */
1890
+ getInfo(opts?: ListRevisionsOptions): Promise<RevisionInfo | null>;
1891
+ /**
1892
+ * Reads the revision text when available.
1893
+ */
1894
+ getText(): Promise<string | null>;
1895
+ /**
1896
+ * Returns the paragraph that contains this revision when available.
1897
+ */
1898
+ getParagraph(): Promise<Paragraph | null>;
1899
+ /**
1900
+ * Accepts this revision.
1901
+ */
1902
+ accept(opts?: LiveObjectWriteOptions): Promise<ApplyResult>;
1903
+ /**
1904
+ * Rejects this revision.
1905
+ */
1906
+ reject(opts?: LiveObjectWriteOptions): Promise<ApplyResult>;
1907
+ }
1908
+ interface StylesApi {
1909
+ /**
1910
+ * 列出 styles.xml 中的所有样式(或按 type 过滤)。
1911
+ * styles.xml 不存在时返回空数组。
1912
+ */
1913
+ list(opts?: ListStylesOptions): Promise<StyleInfo[]>;
1914
+ /**
1915
+ * 按 styleId 精确查找,O(1)。
1916
+ * styleId 大小写敏感。不存在时返回 null。
1917
+ */
1918
+ get(styleId: string): Promise<StyleInfo | null>;
1919
+ }
1920
+ interface TablesApi {
1921
+ /**
1922
+ * 枚举文档表格(#185)。
1923
+ * - scope: 'body'(默认)只返回主文档 body 中的表格
1924
+ * - includeNested: false(默认)跳过嵌套在其他表格内的表格
1925
+ */
1926
+ /**
1927
+ * Lists tables in the document and returns live table handles.
1928
+ *
1929
+ * The returned `Table` values contain a snapshot of the table metadata at
1930
+ * list time, and also expose methods that can read fresh state or write back
1931
+ * to the same table.
1932
+ */
1933
+ list(opts?: ListTablesOptions): Promise<Table[]>;
1934
+ /**
1935
+ * 按 tableId 精确取单个表格,O(1)。不存在返回 null。
1936
+ */
1937
+ /**
1938
+ * Gets one table by `tableId`.
1939
+ *
1940
+ * Returns `null` when the table no longer exists.
1941
+ */
1942
+ get(tableId: string): Promise<Table | null>;
1943
+ /**
1944
+ * 按 tableId verbatim 取一张表的 OOXML 子树 + 格内图字节(自包含 payload)。
1945
+ * 供跨文档搬表 `plan.insertTableFrom(...)`("数据表 = 内容块" §13.9)。不存在返回 null。
1946
+ */
1947
+ /**
1948
+ * Exports the raw OOXML subtree and related media for a table.
1949
+ *
1950
+ * This is an advanced API for high-fidelity table copying. Normal table
1951
+ * reads and writes should use `list`, `get`, and the methods on `Table`.
1952
+ */
1953
+ getVerbatim(tableId: string): Promise<TableVerbatim | null>;
1954
+ }
1955
+ interface TableDeleteOptions extends LiveObjectWriteOptions {
1956
+ /**
1957
+ * Controls what happens when deleting the table would affect anchors such as
1958
+ * bookmarks or comments.
1959
+ */
1960
+ onAnchorConflict?: 'error' | 'drop';
1961
+ }
1962
+ interface TableCellWriteOptions extends LiveObjectWriteOptions {
1963
+ /**
1964
+ * Controls what happens when replacing cell text would affect anchors such
1965
+ * as bookmarks or comments.
1966
+ */
1967
+ onAnchorConflict?: 'error' | 'drop';
1968
+ }
1969
+ interface TableRowDeleteOptions extends LiveObjectWriteOptions {
1970
+ /**
1971
+ * Controls what happens when deleting the row would affect anchors such as
1972
+ * bookmarks or comments.
1973
+ */
1974
+ onAnchorConflict?: 'error' | 'drop';
1975
+ }
1976
+ /**
1977
+ * Live handle for one document table.
1978
+ *
1979
+ * A `Table` is both a metadata snapshot and an operation handle:
1980
+ * snapshot fields such as `tableId`, `rowCount`, `colCount`, and `cells` come
1981
+ * from the read that created the handle, while methods such as `getInfo` and
1982
+ * `replaceCellText` read or write the current document state.
1983
+ */
1984
+ interface Table extends TableInfo {
1985
+ /** Stable alias of `tableId`, kept for object-style APIs. */
1986
+ readonly id: string;
1987
+ /**
1988
+ * Creates a live handle for one cell, addressed by zero-based row and column.
1989
+ */
1990
+ cell(row: number, col: number): TableCell;
1991
+ /**
1992
+ * Creates a live handle for one row, addressed by zero-based row index.
1993
+ */
1994
+ row(row: number): TableRow;
1995
+ /**
1996
+ * Creates a live handle for one column, addressed by zero-based column index.
1997
+ */
1998
+ column(col: number): TableColumn;
1999
+ /**
2000
+ * Reads the current metadata for this table.
2001
+ *
2002
+ * Use this after writes when you need fresh row, column, width, height, or
2003
+ * cell information.
2004
+ */
2005
+ getInfo(opts?: ListTablesOptions): Promise<TableInfo | null>;
2006
+ /**
2007
+ * Exports this table as raw OOXML plus related media.
2008
+ *
2009
+ * This is intended for high-fidelity copy/move flows, not routine editing.
2010
+ */
2011
+ getVerbatim(): Promise<TableVerbatim | null>;
2012
+ /**
2013
+ * Reads the current plain text of this table.
2014
+ *
2015
+ * Cell text is joined using tabs between columns and line breaks between
2016
+ * rows.
2017
+ */
2018
+ getText(opts?: ListTablesOptions): Promise<string | null>;
2019
+ /**
2020
+ * Reads the current table cell text as a two-dimensional array.
2021
+ *
2022
+ * Returns `null` when the table no longer exists.
2023
+ */
2024
+ getCells(opts?: ListTablesOptions): Promise<string[][] | null>;
2025
+ /** Adds a comment to the whole table range. */
2026
+ addComment(text: string, opts?: LiveObjectWriteOptions): Promise<ApplyResult>;
2027
+ /** Deletes this table from the document. */
2028
+ delete(opts?: TableDeleteOptions): Promise<ApplyResult>;
2029
+ /**
2030
+ * Replaces the text of one cell, addressed by zero-based row and column.
2031
+ */
2032
+ replaceCellText(row: number, col: number, text: string, opts?: TableCellWriteOptions): Promise<ApplyResult>;
2033
+ /** Deletes one row, addressed by zero-based row index. */
2034
+ deleteRow(row: number, opts?: TableRowDeleteOptions): Promise<ApplyResult>;
2035
+ /**
2036
+ * Inserts one row.
2037
+ *
2038
+ * `templateRow` is the zero-based source row used for row structure.
2039
+ * `position` is the zero-based insertion position, or `'end'`.
2040
+ */
2041
+ insertRow(spec: {
2042
+ templateRow: number;
2043
+ position: number | 'end';
2044
+ cellTexts?: string[];
2045
+ }, opts?: LiveObjectWriteOptions): Promise<ApplyResult>;
2046
+ /**
2047
+ * Sets table grid column widths in twips.
2048
+ *
2049
+ * The array length should match the table column count.
2050
+ */
2051
+ setColumnWidths(widths: number[], opts?: LiveObjectWriteOptions): Promise<ApplyResult>;
2052
+ /**
2053
+ * Sets row heights.
2054
+ *
2055
+ * Pass `null` for a row that should keep its current height.
2056
+ */
2057
+ setRowHeights(heights: (RowHeight | null)[], opts?: LiveObjectWriteOptions): Promise<ApplyResult>;
2058
+ }
2059
+ /**
2060
+ * Live handle for one table cell.
2061
+ */
2062
+ interface TableCell {
2063
+ /** Parent table id. */
2064
+ readonly tableId: string;
2065
+ /** Zero-based row index. */
2066
+ readonly row: number;
2067
+ /** Zero-based column index. */
2068
+ readonly col: number;
2069
+ /**
2070
+ * Reads the current cell metadata.
2071
+ */
2072
+ getInfo(opts?: ListTablesOptions): Promise<TableCellInfo | null>;
2073
+ /**
2074
+ * Reads direct content blocks in this cell, preserving cell content order.
2075
+ */
2076
+ getBlocks(opts?: ListTablesOptions): Promise<TableCellBlock[] | null>;
2077
+ /**
2078
+ * Reads live paragraph handles for direct paragraphs in this cell.
2079
+ */
2080
+ getParagraphs(opts?: ListTablesOptions): Promise<Paragraph[]>;
2081
+ /**
2082
+ * Reads the current plain text of this cell.
2083
+ */
2084
+ getText(opts?: ListTablesOptions): Promise<string | null>;
2085
+ /**
2086
+ * Creates a text range handle by searching inside this cell's paragraphs.
2087
+ */
2088
+ findText(search: string, opts?: {
2089
+ scope?: 'first' | 'all';
2090
+ }): CellTextRange;
2091
+ /**
2092
+ * Replaces this cell with plain text.
2093
+ */
2094
+ replaceWith(text: string, opts?: TableCellWriteOptions): Promise<ApplyResult>;
2095
+ /**
2096
+ * Inserts a new paragraph before the first direct content block in this cell.
2097
+ */
2098
+ insertParagraphAtStart(text: string, opts?: LiveObjectWriteOptions): Promise<ApplyResult>;
2099
+ /**
2100
+ * Inserts a new paragraph after the last direct content block in this cell.
2101
+ */
2102
+ insertParagraphAtEnd(text: string, opts?: LiveObjectWriteOptions): Promise<ApplyResult>;
2103
+ /**
2104
+ * Sets direct cell background shading fill color.
2105
+ */
2106
+ setShading(fill: string, opts?: LiveObjectWriteOptions): Promise<ApplyResult>;
2107
+ /**
2108
+ * Sets direct cell vertical alignment.
2109
+ */
2110
+ setVerticalAlignment(value: NonNullable<TableCellDirectFormat['verticalAlignment']>, opts?: LiveObjectWriteOptions): Promise<ApplyResult>;
2111
+ /**
2112
+ * Sets direct cell width in twips.
2113
+ */
2114
+ setWidth(width: number, opts?: LiveObjectWriteOptions): Promise<ApplyResult>;
2115
+ }
2116
+ type TableCellBlock = {
2117
+ type: 'paragraph';
2118
+ paragraph: Paragraph;
2119
+ paraId: string;
2120
+ text: string;
2121
+ index: number;
2122
+ } | {
2123
+ type: 'drawing';
2124
+ drawing: Drawing | null;
2125
+ drawingId: string;
2126
+ paraId?: string;
2127
+ index: number;
2128
+ } | {
2129
+ type: 'table';
2130
+ table: Table | null;
2131
+ tableId: string;
2132
+ index: number;
2133
+ };
2134
+ /**
2135
+ * Live handle for text matched inside a table cell.
2136
+ */
2137
+ interface CellTextRange {
2138
+ replaceWith(text: string, opts?: LiveObjectWriteOptions): Promise<ApplyResult>;
2139
+ delete(opts?: LiveObjectWriteOptions): Promise<ApplyResult>;
2140
+ setBold(value: boolean, opts?: LiveObjectWriteOptions): Promise<ApplyResult>;
2141
+ setColor(value: string, opts?: LiveObjectWriteOptions): Promise<ApplyResult>;
2142
+ setItalic(value: boolean, opts?: LiveObjectWriteOptions): Promise<ApplyResult>;
2143
+ setUnderline(value: boolean, opts?: LiveObjectWriteOptions): Promise<ApplyResult>;
2144
+ setHighlight(value: string, opts?: LiveObjectWriteOptions): Promise<ApplyResult>;
2145
+ setFontSize(value: number, opts?: LiveObjectWriteOptions): Promise<ApplyResult>;
2146
+ setFontFamily(value: string, opts?: LiveObjectWriteOptions): Promise<ApplyResult>;
2147
+ addComment(text: string, opts?: LiveObjectWriteOptions): Promise<ApplyResult>;
2148
+ createBookmark(name: BookmarkName$1, opts?: LiveObjectWriteOptions): Promise<ApplyResult>;
2149
+ }
2150
+ /**
2151
+ * Live handle for one table row.
2152
+ */
2153
+ interface TableRow {
2154
+ /** Parent table id. */
2155
+ readonly tableId: string;
2156
+ /** Zero-based row index. */
2157
+ readonly index: number;
2158
+ /**
2159
+ * Reads the current cell texts for this row.
2160
+ */
2161
+ getCells(opts?: ListTablesOptions): Promise<string[] | null>;
2162
+ /**
2163
+ * Reads the current plain text of this row.
2164
+ *
2165
+ * Cell text is joined using tabs.
2166
+ */
2167
+ getText(opts?: ListTablesOptions): Promise<string | null>;
2168
+ /**
2169
+ * Deletes this row.
2170
+ */
2171
+ delete(opts?: TableRowDeleteOptions): Promise<ApplyResult>;
2172
+ /**
2173
+ * Inserts a row before this row, using this row as the structural template.
2174
+ */
2175
+ insertBefore(cellTexts?: string[], opts?: LiveObjectWriteOptions): Promise<ApplyResult>;
2176
+ /**
2177
+ * Inserts a row after this row, using this row as the structural template.
2178
+ */
2179
+ insertAfter(cellTexts?: string[], opts?: LiveObjectWriteOptions): Promise<ApplyResult>;
2180
+ /**
2181
+ * Sets the row height. Pass `null` to remove the explicit row height.
2182
+ */
2183
+ setHeight(height: RowHeight | null, opts?: LiveObjectWriteOptions): Promise<ApplyResult>;
2184
+ }
2185
+ /**
2186
+ * Live handle for one table column.
2187
+ */
2188
+ interface TableColumn {
2189
+ /** Parent table id. */
2190
+ readonly tableId: string;
2191
+ /** Zero-based column index. */
2192
+ readonly index: number;
2193
+ /**
2194
+ * Reads the current cell texts for this column.
2195
+ */
2196
+ getCells(opts?: ListTablesOptions): Promise<string[] | null>;
2197
+ /**
2198
+ * Reads the current plain text of this column.
2199
+ *
2200
+ * Cell text is joined using line breaks.
2201
+ */
2202
+ getText(opts?: ListTablesOptions): Promise<string | null>;
2203
+ /**
2204
+ * Sets this column width in twips.
2205
+ */
2206
+ setWidth(width: number, opts?: LiveObjectWriteOptions): Promise<ApplyResult>;
2207
+ }
2208
+ interface SectionsApi {
2209
+ /**
2210
+ * 列出主 body 的所有节(#211)。节按 doc-order 排序。
2211
+ * 无 body 或文档无 sectPr 时返回空数组。
2212
+ */
2213
+ list(): Promise<SectionInfo[]>;
2214
+ }
2215
+ interface TocFieldsApi {
2216
+ /**
2217
+ * 枚举主 body 中的所有 TOC 域(#197)。doc-order 排序。
2218
+ * 无 TOC 域时返回空数组。
2219
+ */
2220
+ list(): Promise<TocFieldRange[]>;
2221
+ }
2222
+ interface DrawingsApi {
2223
+ /**
2224
+ * 枚举文档 drawing 对象(#189)。
2225
+ * - scope: 'body'(默认)只返回主文档 body 内的 drawing
2226
+ * - scope: 'all' 包含 headers / footers / footnotes / endnotes / comments
2227
+ *
2228
+ * 本 API 只暴露形态信号(kind / extent / wrap / position / isInHeaderFooter 等),
2229
+ * 不下 A / B / C 业务分类结论 —— 那是 #191 / #192 的事。
2230
+ */
2231
+ list(opts?: ListDrawingsOptions): Promise<Drawing[]>;
2232
+ /**
2233
+ * Lists picture drawings only.
2234
+ *
2235
+ * Prefer this over filtering `list()` when the task is explicitly about
2236
+ * images.
2237
+ */
2238
+ listPictures(opts?: ListDrawingsOptions): Promise<PictureDrawing[]>;
2239
+ /**
2240
+ * Lists textbox drawings only.
2241
+ *
2242
+ * Prefer this when the task is explicitly about text boxes.
2243
+ */
2244
+ listTextBoxes(opts?: ListDrawingsOptions): Promise<TextBoxDrawing[]>;
2245
+ /**
2246
+ * Lists plain shape drawings only.
2247
+ *
2248
+ * This does not include pictures, text boxes, charts, SmartArt, groups, or
2249
+ * canvases.
2250
+ */
2251
+ listShapes(opts?: ListDrawingsOptions): Promise<ShapeDrawing[]>;
2252
+ /**
2253
+ * 按 drawingId 精确取单个 drawing,O(1)。不存在返回 null。
2254
+ */
2255
+ get(drawingId: string): Promise<Drawing | null>;
2256
+ }
2257
+ interface DrawingImageBytes {
2258
+ bytes: Uint8Array;
2259
+ contentType: string;
2260
+ extentEMU: {
2261
+ cx: number;
2262
+ cy: number;
2263
+ };
2264
+ }
2265
+ /**
2266
+ * Live handle for one drawing object.
2267
+ */
2268
+ interface Drawing extends DrawingInfo {
2269
+ /** Stable alias of `drawingId`, kept for object-style APIs. */
2270
+ readonly id: string;
2271
+ /**
2272
+ * Reads current drawing metadata.
2273
+ */
2274
+ getInfo(): Promise<DrawingInfo | null>;
2275
+ /**
2276
+ * Reads original image bytes when this drawing is a picture.
2277
+ */
2278
+ getImageBytes(): Promise<DrawingImageBytes | null>;
2279
+ /**
2280
+ * Deletes this drawing.
2281
+ */
2282
+ delete(opts?: LiveObjectWriteOptions): Promise<ApplyResult>;
2283
+ /**
2284
+ * Replaces a picture drawing with the shared placeholder image.
2285
+ */
2286
+ replaceWithPlaceholder(opts?: LiveObjectWriteOptions): Promise<ApplyResult>;
2287
+ /**
2288
+ * Replaces text inside a shape/textbox drawing.
2289
+ */
2290
+ replaceShapeInnerText(placeholder: string, opts?: LiveObjectWriteOptions): Promise<ApplyResult>;
2291
+ }
2292
+ /** `WordDocument.assertNotDisposed` 的桥接签名;避免 sub-apis.ts 反向依赖 WordDocument */
2293
+ /**
2294
+ * Live handle for a picture drawing.
2295
+ */
2296
+ interface PictureDrawing extends Drawing {
2297
+ readonly kind: 'picture';
2298
+ /**
2299
+ * Reads original image bytes for this picture drawing.
2300
+ */
2301
+ getImageBytes(): Promise<DrawingImageBytes | null>;
2302
+ /**
2303
+ * Replaces this picture with the shared placeholder image while preserving layout.
2304
+ */
2305
+ replaceWithPlaceholder(opts?: LiveObjectWriteOptions): Promise<ApplyResult>;
2306
+ /**
2307
+ * Deletes this picture drawing.
2308
+ */
2309
+ delete(opts?: LiveObjectWriteOptions): Promise<ApplyResult>;
2310
+ }
2311
+ /**
2312
+ * Live handle for a textbox drawing.
2313
+ */
2314
+ interface TextBoxDrawing extends Drawing {
2315
+ readonly kind: 'textBox';
2316
+ /**
2317
+ * Reads the text currently inside this textbox.
2318
+ *
2319
+ * Returns `null` if the drawing no longer exists or is no longer a textbox.
2320
+ */
2321
+ getText(): Promise<string | null>;
2322
+ /**
2323
+ * Lists live paragraph handles inside this textbox.
2324
+ */
2325
+ getParagraphs(): Promise<Paragraph[]>;
2326
+ /**
2327
+ * Reads direct content blocks inside this textbox, preserving textbox content order.
2328
+ */
2329
+ getBlocks(): Promise<TextBoxBlock[]>;
2330
+ /**
2331
+ * Replaces all textbox content with a single paragraph containing `text`.
2332
+ */
2333
+ replaceText(text: string, opts?: LiveObjectWriteOptions): Promise<ApplyResult>;
2334
+ }
2335
+ type TextBoxBlock = {
2336
+ type: 'paragraph';
2337
+ paragraph: Paragraph;
2338
+ paraId: string;
2339
+ text: string;
2340
+ index: number;
2341
+ } | {
2342
+ type: 'drawing';
2343
+ drawing: Drawing | null;
2344
+ drawingId: string;
2345
+ paraId?: string;
2346
+ index: number;
2347
+ } | {
2348
+ type: 'table';
2349
+ table: Table | null;
2350
+ tableId: string;
2351
+ index: number;
2352
+ };
2353
+ /**
2354
+ * Live handle for a plain shape drawing.
2355
+ */
2356
+ interface ShapeDrawing extends Drawing {
2357
+ readonly kind: 'shape';
2358
+ /**
2359
+ * Reads current plain-shape metadata such as border/fill and line hints.
2360
+ */
2361
+ getInfo(): Promise<(DrawingInfo & {
2362
+ kind: 'shape';
2363
+ }) | null>;
2364
+ /**
2365
+ * Deletes this plain shape drawing.
2366
+ */
2367
+ delete(opts?: LiveObjectWriteOptions): Promise<ApplyResult>;
2368
+ }
2369
+
2370
+ /**
2371
+ * WorkerTransport —— 主线程侧的 RPC 客户端。kernel 跑在 Worker,本类负责:
2372
+ * - 生成 request id
2373
+ * - postMessage 给 Worker
2374
+ * - 监听 Worker 回投的 response/error/progress,关联到对应 pending request
2375
+ * - 返回 Promise,主线程侧消费者像 InlineTransport 一样调用
2376
+ * - **Worker crash → terminate + reload**(#19,docs/03 §4.7)
2377
+ *
2378
+ * **支持的 Worker 运行时**:
2379
+ * - Node `worker_threads`(测试路径,#17 本 PR 主要覆盖)
2380
+ * - 浏览器 `Worker`(代码路径已预留,但本 PR 未在 CI 里验证;#18 / 浏览器示例补齐)
2381
+ *
2382
+ * 错误:Worker 回投的 `SerializableError` 被重建为 `WordError`(如 `code` 存在)或
2383
+ * 原生 `Error`(非 WordError 情况)。
2384
+ *
2385
+ * **Reload 语义(#19)**:
2386
+ * - 未配置 reload:port 崩溃 → 所有 pending 以底层 error reject(旧行为,防御性兜底)
2387
+ * - 配置 reload:port 崩溃 → 旧 pending 全部以 `WordError{WORKER_RELOADED}` reject;
2388
+ * 起新 port,重放 load;期间到达的 `call()` 排队,reload 完成后按序 flush
2389
+ */
2390
+
2391
+ /**
2392
+ * 抽象 WorkerPort —— Node worker_threads 的 `Worker` 与浏览器 `Worker` 接口不完全一致,
2393
+ * 本接口是公约数。
2394
+ */
2395
+ interface WorkerPortLike {
2396
+ postMessage(data: unknown, transferList?: unknown[]): void;
2397
+ /** 注册消息监听 */
2398
+ onMessage(listener: (data: unknown) => void): void;
2399
+ /** 注册错误监听(Worker 内部 crash;Node 侧 exit!=0 也折进这里) */
2400
+ onError(listener: (err: unknown) => void): void;
2401
+ /** terminate —— 返回 Promise 便于 await(某些 API 是 sync void,包成 Promise) */
2402
+ terminate(): Promise<void>;
2403
+ }
2404
+ /** Reload 所需参数(#19);缺省即关闭 reload,onError 退化为 reject all pending */
2405
+ interface WorkerReloadConfig {
2406
+ /** 起一个新 WorkerPortLike(与原 port 同 bundle、同配置) */
2407
+ factory: () => WorkerPortLike | Promise<WorkerPortLike>;
2408
+ /** reload 时重放的 load 参数(保留原始字节 / flat-opc 字符串) */
2409
+ loadParams: KernelLoadParams;
2410
+ /** docId —— WORKER_RELOADED 错误注入用 */
2411
+ docId: string;
2412
+ }
2413
+ interface WorkerTransportOptions {
2414
+ /** 预先创建好的 WorkerPortLike;创建逻辑由调用方负责(环境差异太大,不在本类里) */
2415
+ port: WorkerPortLike;
2416
+ /** 可选 reload 配置(#19);未传则 worker 崩溃后不重启 */
2417
+ reload?: WorkerReloadConfig;
2418
+ }
2419
+ type TransportState = 'idle' | 'reloading' | 'disposed';
2420
+ declare class WorkerTransport implements Transport {
2421
+ private port;
2422
+ private readonly reloadConfig?;
2423
+ private readonly pending;
2424
+ /** reload 期间新到达的 call() 排队于此,reload 完成后按 FIFO 执行 */
2425
+ private readonly queued;
2426
+ private nextId;
2427
+ private state;
2428
+ /** reload 重放 load RPC 的 promise,dispose 时 await 避免竞态 */
2429
+ private reloadingPromise?;
2430
+ /**
2431
+ * 给 port handler 用的代际序号。每次 reload 把 generation++,旧 port 的 onMessage/onError
2432
+ * 回调里捕获了创建时的 gen,gen 与当前不符就静默丢弃 —— 避免旧 port 的延迟 exit 事件
2433
+ * 错误地触发第二次 reload。
2434
+ */
2435
+ private portGeneration;
2436
+ /**
2437
+ * reload 完成后触发的监听器列表(#23)。SnapshotApi 订阅此以在 worker 重建后
2438
+ * 重新初始化内存栈(nextId / changelog)。每次 reload 成功后、flush queued 前
2439
+ * **串行 await** 所有监听器,避免 queued 的 take() 拿到陈旧 nextId 与 adapter
2440
+ * 里已持久化的 id 撞车。
2441
+ */
2442
+ private readonly reloadListeners;
2443
+ /**
2444
+ * change 事件订阅者(WordDocument.on('change', ...) 的底层挂载点)。worker 内
2445
+ * 每次 applyPlan 成功会 post 一条 RpcEvent('word.change'),本类在 handleIncoming
2446
+ * 里 fan-out 给这里的所有 listener。
2447
+ */
2448
+ private readonly changeListeners;
2449
+ constructor(opts: WorkerTransportOptions);
2450
+ call<T>(method: KernelMethod, args: unknown[], onProgress?: KernelProgress): Promise<T>;
2451
+ /**
2452
+ * 04.2 §六:走独立 RPC method `'script.execute'`,**不**进 KernelMethod 联合。
2453
+ * worker-entry 在收到该 method 时分支到 script-execute,绕过 kernelHandlers。
2454
+ *
2455
+ * **超时语义(04.2 §四,#144):**
2456
+ *
2457
+ * - 主线程持有**硬超时**:`timeoutMs > 0` 时 setTimeout;超时未 resolve → 调
2458
+ * `handleWorkerError` 主动触发 reload 路径。所有 pending 以 `WordError(WORKER_RELOADED)`
2459
+ * reject;`worker.terminate()` + 起新 worker + 重放 `load`。
2460
+ * - **不**把 `timeoutMs` 传给 worker —— worker 内 `script-execute.ts` 用 `0` 表示不 race,
2461
+ * 完全交主线程 terminate(避免 worker 内对死循环类同步阻塞无能为力)。
2462
+ * - `timeoutMs === 0` → 主线程不设硬超时(可能 hang,由调用方风险自负)。
2463
+ *
2464
+ * **Abort 语义(#151):**
2465
+ *
2466
+ * - 接 \`AbortSignal\`;abort 触发与 timeout 走**同一条路径**(handleWorkerError →
2467
+ * reload)。pending RPC 以 \`WordError(WORKER_RELOADED)\` reject;\`worker.terminate()\`
2468
+ * 立即终止正在运行的脚本(包括同步死循环类阻塞)。
2469
+ * - 上层(plugin / agent)负责把 abort cause 转为 \`AgentAbortError\`(L2),不影响
2470
+ * transport 层契约:transport 只管 reload,语义解读由 agent。
2471
+ */
2472
+ executeScript(code: string, args: Record<string, unknown> | undefined, timeoutMs: number, signal?: AbortSignal): Promise<unknown>;
2473
+ dispose(): Promise<void>;
2474
+ private attachPortHandlers;
2475
+ private sendCall;
2476
+ private handleIncoming;
2477
+ private handleWorkerError;
2478
+ private reloadAfterCrash;
2479
+ /**
2480
+ * 注册 reload 完成回调(#23)。返回取消订阅函数。listener 可返回 Promise,
2481
+ * reload 流程会串行 await 每个 listener 完成后再 flush queued RPC。
2482
+ *
2483
+ * 触发时机:worker crash → new port + load 重放成功 → state 切回 idle 之后、
2484
+ * flush queued 之前。SnapshotApi 在此重建 nextId(从 adapter.list 读已有快照)。
2485
+ */
2486
+ onReload(listener: () => void | Promise<void>): () => void;
2487
+ onChange(listener: (ev: KernelChangeEvent) => void): () => void;
2488
+ /**
2489
+ * @internal test-only:手动模拟一次 worker 崩溃。
2490
+ * 触发 reload 流程(若 reloadConfig 已配),供 `worker-reload.test.ts` 使用。
2491
+ */
2492
+ _triggerCrashForTest(err?: Error): void;
2493
+ /** @internal test-only:查状态机,用于断言 reload 完成 */
2494
+ _getStateForTest(): TransportState;
2495
+ }
2496
+
2497
+ /**
2498
+ * SnapshotApi —— WordDocument.snapshots 子 API(docs/03.2 §2)。
2499
+ *
2500
+ * 职责:
2501
+ * - `take(reason?, details?)`:通过 transport 让 kernel 序列化 parts,捆装 info + parts 为
2502
+ * SnapshotPayload,交给 adapter.save,返回 id
2503
+ * - `rollback(id, opts?)`:从 adapter.load 取回 payload,通过 transport 让 kernel 用 parts
2504
+ * 重建 pkg;消费语义 —— 成功后 adapter.delete;支持 `opts.onProgress` 分阶段上报
2505
+ * (parse / build-indices / done,docs/03.2 §6)
2506
+ * - `list / delete / clear`:直通 adapter
2507
+ * - `recordChange / changes`:**主线程同步**,不过 transport(零 RPC 开销;docs/03.2 §7)
2508
+ *
2509
+ * 新增 #22:
2510
+ * - FIFO 上限(默认 10,`SnapshotApiInit.maxSnapshots` 可配),take 成功后若超限则按
2511
+ * `adapter.list` 的自增顺序淘汰最早的(`adapter.delete`)
2512
+ * - `rollback` 的 `onProgress` 透传给 transport.call,InlineTransport 直达,
2513
+ * WorkerTransport 通过 RpcProgress 穿过 Worker 边界
2514
+ */
2515
+
2516
+ /** 默认 FIFO 上限(docs/03.2 §3.2) */
2517
+ declare const DEFAULT_MAX_SNAPSHOTS = 10;
2518
+ /** rollback 的进度回调:phase 分 'parse' | 'build-indices' | 'done'(docs/03.2 §6) */
2519
+ type RollbackProgress = (phase: string, pct?: number) => void;
2520
+ interface RollbackOptions {
2521
+ onProgress?: RollbackProgress;
2522
+ }
2523
+ /**
2524
+ * `take` 可选参数(#108,docs/03.2 §3.3)。
2525
+ *
2526
+ * - `pin: true` —— 标记该快照 **不参与 FIFO 淘汰**;即使达到 `maxSnapshots`,
2527
+ * FIFO 也会跳过 pinned 的条目,转而淘汰最老的**非 pinned** 快照。
2528
+ * - `pin: undefined | false` —— 与不传 options 等价,普通快照。
2529
+ *
2530
+ * **使用约束**(agent 层自行约束,core 不强制):pinned 主要给 SDK 内部使用
2531
+ * (例 `WordAgent.create` 的 session-start 快照),plugin 层的 `AgentContext.snapshots`
2532
+ * 应强制 `pin: false`,避免 plugin 把存储塞满 pinned 导致 FIFO 失效。
2533
+ */
2534
+ interface TakeOptions {
2535
+ pin?: boolean;
2536
+ /**
2537
+ * 可选逻辑去重域。提供后,若该域最新快照的 contentHash 与当前文档相同,
2538
+ * `take` 直接返回已有 id,不创建新快照。不同 owner/用途必须使用不同 key。
2539
+ */
2540
+ dedupeKey?: string;
2541
+ }
2542
+ interface SnapshotApi {
2543
+ /**
2544
+ * 保存当前文档状态为一个新快照,返回自增 id(snap-0 / snap-1 / ...)。
2545
+ * 已累加的 changelog 项会一次性吸入新快照的 `changesCaptured`,然后主线程 changelog 清零。
2546
+ *
2547
+ * 超过 `maxSnapshots`(默认 10,docs/03.2 §3.2)时,按 `adapter.list` 返回顺序淘汰
2548
+ * 最早的**非 pinned** 快照;pinned 快照永不淘汰(#108,docs/03.2 §3.3)。
2549
+ *
2550
+ * **能力边界**:若存储里的非 pinned 名额都满而仍要继续 take 普通快照,SDK 会尝试
2551
+ * 按正常 FIFO 淘汰最老非 pinned;若所有快照都是 pinned,则新 take 会直接成功
2552
+ * 保存(超出 maxSnapshots 但无可淘汰目标),SDK 发 `console.warn` 提示;
2553
+ * 上游自行控制 pinned 数量。
2554
+ */
2555
+ take(reason?: string, details?: unknown, options?: TakeOptions): Promise<string>;
2556
+ /**
2557
+ * 用给定 id 的快照覆盖当前文档状态,但**不删除**快照。
2558
+ *
2559
+ * 供需要把恢复结果提交到外部宿主的场景使用:宿主应先 restore,待外部写回成功后
2560
+ * 再显式 delete。这样宿主写回失败时仍可重试同一快照。
2561
+ */
2562
+ restore(id: string, opts?: RollbackOptions): Promise<void>;
2563
+ /**
2564
+ * 用给定 id 的快照覆盖当前文档状态,**消费式**:成功后该快照被 adapter.delete。
2565
+ * 其它快照不受影响。
2566
+ *
2567
+ * `opts.onProgress` 按阶段回调:'parse'(0→100)/ 'build-indices'(0)/ 'done'(100)。
2568
+ */
2569
+ rollback(id: string, opts?: RollbackOptions): Promise<void>;
2570
+ /** 按 id 自增序返回所有快照的 meta(不含 parts 字节) */
2571
+ list(): Promise<SnapshotInfo[]>;
2572
+ /** 按 id 删除某个快照。不存在时静默(幂等) */
2573
+ delete(id: string): Promise<void>;
2574
+ /** 清空该 docId 下的所有快照 */
2575
+ clear(): Promise<void>;
2576
+ /** 主线程同步累加一条 change,下次 take 时会一并吸入 */
2577
+ recordChange(change: {
2578
+ toolName: string;
2579
+ summary?: unknown;
2580
+ }): void;
2581
+ /** 读当前未吸入的 change 数组(主线程同步) */
2582
+ changes(): ChangeLog[];
2583
+ /**
2584
+ * **内部用**:WordDocument 首次装载时从 adapter 恢复 nextId。失败会向上抛,
2585
+ * 防止在无法读取历史时从 snap-0 开始覆盖持久数据。
2586
+ */
2587
+ initializeFromStorage(): Promise<void>;
2588
+ /**
2589
+ * **内部/测试用**:worker reload 完成后由 transport 自动触发,主线程不应直接调。
2590
+ *
2591
+ * 语义(#23,docs/03.2 §9.1):
2592
+ * - 从 adapter.list(docId) 读已持久化快照,把 `nextId` 重设为 `max(snap-<N>) + 1`
2593
+ * - `changelog` 清零(reload 期间主线程的 changelog 视为丢失,无法恢复)
2594
+ * - adapter 里已保存的字节不受影响,rollback 仍可用
2595
+ */
2596
+ reinitializeAfterReload(): Promise<void>;
2597
+ }
2598
+
2599
+ /**
2600
+ * WordDocument —— Word core 的顶层句柄(docs/03.1 §2)。
2601
+ *
2602
+ * 本 PR(#17)把装载 / 输出 / dispose 的真实执行改走 `Transport` 抽象:
2603
+ * - **inline 模式**:`InlineTransport` 直接在主线程创建 Kernel,零 RPC 开销
2604
+ * - **worker 模式**:`WorkerTransport` 把调用序列化成 RPC 消息经 postMessage 发给
2605
+ * Worker 内的 Kernel(Node worker_threads 路径在本 PR 就绪,浏览器 Worker 路径
2606
+ * 留 #18 / 浏览器示例)
2607
+ *
2608
+ * 对消费方完全透明:`WordDocument.fromZip(buf, { mode: 'worker' })` 与 inline 行为一致,
2609
+ * 只是 Kernel 跑在另一线程。`_getPackage` / `_getIndices` 在 worker 模式下会抛错(
2610
+ * Package 在另一线程,无法直接返回引用)。查询类 API(#24 起)将改走 RPC 方法。
2611
+ */
2612
+
2613
+ type RuntimeMode = 'auto' | 'worker' | 'inline';
2614
+ /**
2615
+ * 模式决策的"为什么"。配合 `mode` 让外部平台一眼看清落 inline 还是 worker、以及是哪条规则。
2616
+ *
2617
+ * - `explicit-inline` / `explicit-worker`:消费方在 LoadOptions.mode 显式指定
2618
+ * - `auto/inside-worker-thread`:已在 Node worker_threads 子线程内,拒绝再 spawn
2619
+ * - `auto/node-with-worker-config`:Node 主线程 + 配了 workerFactory / workerBundleUrl
2620
+ * - `auto/node-no-worker-config`:Node 主线程但 worker 基础设施未配,静默 fallback
2621
+ * - `auto/browser-factory`:浏览器侧消费方提供了 workerFactory
2622
+ * - `auto/browser-global`:浏览器侧粗检测到全局 Worker 构造器
2623
+ * - `auto/fallback`:都不命中的兜底
2624
+ */
2625
+ type ModeSource = 'explicit-inline' | 'explicit-worker' | 'auto/inside-worker-thread' | 'auto/node-with-worker-config' | 'auto/node-no-worker-config' | 'auto/browser-factory' | 'auto/browser-global' | 'auto/fallback';
2626
+ interface ModeDecision {
2627
+ mode: 'worker' | 'inline';
2628
+ source: ModeSource;
2629
+ }
2630
+ /** onProgress 回调的 phase 枚举 */
2631
+ type LoadPhase = 'fetch' | 'parse' | 'normalize';
2632
+ interface LoadOptions {
2633
+ /**
2634
+ * 文档身份标识(必填)。宿主提供,典型值 = 文件路径 hash。
2635
+ * - 作为 WordError.docId 自动注入
2636
+ * - 作为快照系统命名空间 key(详见 docs/03.2)
2637
+ */
2638
+ docId: string;
2639
+ /**
2640
+ * 运行时模式(docs/03 §4.2):
2641
+ * - `'inline'`:主线程运行 kernel
2642
+ * - `'worker'`:显式要求 Worker;不可用时抛 WORKER_CREATION_FAILED
2643
+ * - `'auto'`(默认):按 §4.3 顺序检测;不可用时静默 fallback 到 inline
2644
+ */
2645
+ mode?: RuntimeMode;
2646
+ /**
2647
+ * 装载时模式决策回调(#TBD,docs/03 §4.3)。
2648
+ *
2649
+ * - 设了:用 `decision.mode` / `decision.source` 自定义打点,**不再走默认 console.info**
2650
+ * - 未设:走默认 `console.info('[coco-office:word] mode=... source=... docId=...')`
2651
+ *
2652
+ * 平台侧可借此把决策写入自有日志体系,或在 UI 上展示当前 SDK 的执行模式。
2653
+ */
2654
+ onModeResolved?: (decision: ModeDecision, docId: string) => void;
2655
+ onProgress?: (phase: LoadPhase, pct?: number) => void;
2656
+ snapshotStorage?: SnapshotStorageAdapter;
2657
+ /**
2658
+ * 快照 FIFO 上限,未设则用 `DEFAULT_MAX_SNAPSHOTS`(10,docs/03.2 §3.2)。
2659
+ * 必须 >= 1 的整数;测试场景可调低方便验证淘汰行为。
2660
+ */
2661
+ maxSnapshots?: number;
2662
+ }
2663
+ /** 宿主可以自定义 Worker 创建方式(测试 / 非标准环境)*/
2664
+ type WorkerFactory = () => WorkerPortLike | Promise<WorkerPortLike>;
2665
+ declare class WordDocument {
2666
+ readonly docId: string;
2667
+ readonly mode: 'worker' | 'inline';
2668
+ /** 决策来源(配合 `mode` 让外部平台看清是哪条规则把它送到这个模式的) */
2669
+ readonly modeSource: ModeSource;
2670
+ readonly paragraphs: ParagraphApi;
2671
+ readonly bookmarks: BookmarkApi;
2672
+ readonly comments: CommentApi;
2673
+ readonly context: ContextApi;
2674
+ readonly revisions: RevisionApi;
2675
+ readonly styles: StylesApi;
2676
+ /** 表格枚举与结构分析(#185)*/
2677
+ readonly tables: TablesApi;
2678
+ /** Drawing 对象枚举(#189)*/
2679
+ readonly drawings: DrawingsApi;
2680
+ /** 节(section)枚举(#211)*/
2681
+ readonly sections: SectionsApi;
2682
+ /** TOC 域枚举(#197)*/
2683
+ readonly tocFields: TocFieldsApi;
2684
+ /** 快照子 API(docs/03.2);每个 WordDocument 独立实例 */
2685
+ readonly snapshots: SnapshotApi;
2686
+ private readonly transport;
2687
+ private readonly initialBytes?;
2688
+ private readonly initialFlatOpc?;
2689
+ readonly snapshotStorage: SnapshotStorageAdapter;
2690
+ private disposed;
2691
+ /**
2692
+ * change 订阅者表。每个条目记 listener + 它的订阅选项。第一次有人订阅时绑
2693
+ * `transport.onChange`(由 `subscribeTransportLazy()` 控制),最后一个取消订阅时
2694
+ * 不解绑(简化实现;listener 集合空时 dispatch 是 no-op)。
2695
+ *
2696
+ * 派发顺序:每个 listener 各自串行(`tail` 链),不同 listener 并行。这样保证
2697
+ * 同一订阅者按变更发生顺序看到事件,即便其 handler 是 async + 上一次 toFlatOpc
2698
+ * 还没回。跨订阅者不串行,避免一个慢 handler 卡住别人。
2699
+ */
2700
+ private readonly changeSubscribers;
2701
+ private changeTransportUnsubscribe?;
2702
+ private constructor();
2703
+ static createBlank(opts: LoadOptions): Promise<WordDocument>;
2704
+ static fromZip(buf: Uint8Array | ArrayBuffer, opts: LoadOptions): Promise<WordDocument>;
2705
+ static fromFlatOpc(xml: string, opts: LoadOptions): Promise<WordDocument>;
2706
+ toZip(): Promise<Uint8Array>;
2707
+ toFlatOpc(): Promise<string>;
2708
+ dispose(): Promise<void>;
2709
+ /**
2710
+ * 在与本文档同上下文(worker / inline)中执行一段用户脚本。
2711
+ *
2712
+ * 04.2 §六 冻结的运行时环境:
2713
+ * - 脚本以 `new Function('doc', 'args', 'fs', body)(doc, args, fs)` 形式跑
2714
+ * - `doc` = worker 内 Kernel 实例;脚本可同步访问 `doc.listParagraphs()` 等
2715
+ * - `args` = structured-cloneable 入参
2716
+ * - `fs` v1 在 worker 内不传(主线程 plugin 已用过)
2717
+ * - 顶层允许 `await`;`return expression` 即结果
2718
+ *
2719
+ * **agent 层 `execute_code` / `execute_file` tool 通过本方法桥接到执行通道**(04.2 §五)。
2720
+ *
2721
+ * @param code JS 源码;函数体形态
2722
+ * @param args 传给脚本的参数
2723
+ * @param timeoutMs 超时毫秒数,默认 30000;0 = 不超时
2724
+ * @param signal 可选 AbortSignal(#151):abort 触发 → worker 立即 terminate + reload;
2725
+ * inline 模式下 race 拒绝(主线程立即返回,但脚本仍后台跑)
2726
+ * @throws 语法错误 / 脚本运行错 / 超时 / abort
2727
+ *
2728
+ * @see docs/04.2-脚本执行-Tool设计.md §二 §六
2729
+ */
2730
+ executeCode(code: string, args?: Record<string, unknown>, timeoutMs?: number, signal?: AbortSignal): Promise<unknown>;
2731
+ /**
2732
+ * 订阅文档变更事件。在 kernel.applyPlan 成功后触发,涵盖两条入口:
2733
+ *
2734
+ * - `doc.plan().apply()` → ev.source === 'plan'
2735
+ * - `doc.executeCode(script)` → ev.source === 'script'(脚本调 `doc.applyPlan`)
2736
+ *
2737
+ * **不**触发的场景:空 plan;applyPlan 抛错回滚;脚本绕过 kernel.applyPlan 直接
2738
+ * 改 `doc.getPackage()` 的 DOM(v1 不覆盖,见 change-events.ts 注释)。
2739
+ *
2740
+ * **fullDocument 选项**:默认 `'none'`(只发 `{ ops, result, source }`),不付输出
2741
+ * 代价。设为 `'flatOpc'` / `'zip'` 时,WordDocument 在派发前调一次对应方法把全文
2742
+ * 档塞进 payload —— **每次变更一次开销**,worker 模式下还要再 RPC + structured-clone,
2743
+ * 大文档可达几百 ms。多订阅者同次事件共享拉取,因此打开多个 'flatOpc' 订阅不会
2744
+ * 重复跑 toFlatOpc。
2745
+ *
2746
+ * **派发顺序**:同一订阅者按变更发生顺序串行调用 handler(即便 handler 是 async),
2747
+ * 不同订阅者并行 —— 一个慢 handler 不会卡住别人。
2748
+ *
2749
+ * @returns 取消订阅函数。重复调用安全(幂等)。
2750
+ */
2751
+ on(event: 'change', handler: ChangeListener, opts?: ChangeSubscribeOptions): () => void;
2752
+ private subscribeTransportLazy;
2753
+ /**
2754
+ * 把 kernel 推上来的 KernelChangeEvent 转成对外 ChangeEvent,fan-out 给订阅者。
2755
+ * 优化:多订阅者要同一种全文档输出时只拉一次。每个订阅者自己串行(tail chain),
2756
+ * 跨订阅者并行。
2757
+ */
2758
+ private dispatchChange;
2759
+ /**
2760
+ * 创建新 WordPlan(docs/03.1 §2 / §3)。
2761
+ *
2762
+ * - 同步返回,不走 RPC;链式方法只把 op push 进队列,真正 RPC 在 `apply()` 触发
2763
+ * - 多 plan 可并存,各自独立状态(每次调用返回新实例)
2764
+ * - `opts.author` 缺省时走 `WordDocument.setDefaultAuthor` 配置的值;都缺则空串
2765
+ * - `opts.trackChanges` 默认 false
2766
+ * - `opts.date` 默认 `new Date()`(在 addComment 等 op 里实际需要时再取)
2767
+ *
2768
+ * **能力实现进度**(#27 仅提供容器与 apply 状态机;op executor 分批落地):
2769
+ * - 段落修改 → #28
2770
+ * - 段落插入 / 删除 → #29
2771
+ * - 书签 → #34
2772
+ * - 批注 → #35
2773
+ * - 修订 accept/reject → #31 / #32
2774
+ *
2775
+ * 本 PR 期间,任何非空 plan 的 `apply()` 会抛 `UNSUPPORTED_OOXML_FEATURE`。
2776
+ */
2777
+ plan(opts?: PlanOptions): WordPlan;
2778
+ /**
2779
+ * Appends a plain-text paragraph at the end of the main document body.
2780
+ */
2781
+ appendParagraph(text: string, opts?: ParagraphInsertOptions): Promise<ApplyResult>;
2782
+ /** @internal 仅 inline 模式可用(Package 跨 Worker 边界不可直接引用)*/
2783
+ _getPackage(): Package;
2784
+ /** @internal 仅 inline 模式可用 */
2785
+ _getIndices(): PackageIndices;
2786
+ /** @internal inline-only cache diagnostics for core tests. */
2787
+ _debugCacheSnapshot(): WordDomainCacheSnapshot;
2788
+ /** @internal inline-only cache invalidation for consistency tests. */
2789
+ _debugInvalidateCache(domain?: DomainCacheName, reason?: string): void;
2790
+ /** @internal 装载时的初始字节(#19 worker reload 需要)*/
2791
+ _getInitialBytes(): Uint8Array | undefined;
2792
+ /** @internal 装载时的初始 Flat OPC 字符串 */
2793
+ _getInitialFlatOpc(): string | undefined;
2794
+ /** @internal #19 测试用:拿到底层 transport 实例(模拟 worker crash) */
2795
+ _getTransport(): Transport;
2796
+ private assertNotDisposed;
2797
+ static setDefaultMode(mode: RuntimeMode): void;
2798
+ /**
2799
+ * 不创建实例,查当前环境 `'auto'` 模式会选什么。真实反映决策结果
2800
+ * (docs/03 §4.3):
2801
+ *
2802
+ * 1. 已在 Node worker_threads 上下文中 → inline(避免二次 spawn)
2803
+ * 2. Node 环境:
2804
+ * - 配了 workerFactory / workerBundleUrl → worker
2805
+ * - 否则 → inline
2806
+ * 3. 浏览器(或类浏览器)环境:
2807
+ * - 配了 workerFactory → worker
2808
+ * - 全局 `Worker` 存在 → worker(粗检测,真实 ping 见 #52)
2809
+ * - 否则 → inline
2810
+ * 4. 以上都不满足 → inline
2811
+ */
2812
+ static detectMode(): 'worker' | 'inline';
2813
+ /**
2814
+ * 同 `detectMode()`,但返回决策来源,便于平台诊断为什么 auto 落到了某个模式。
2815
+ */
2816
+ static detectModeDecision(): ModeDecision;
2817
+ static setDefaultAuthor(author: string): void;
2818
+ /** 配置自定义 Worker 工厂(测试 / 非 Node-worker_threads 环境)*/
2819
+ static setWorkerFactory(factory: WorkerFactory | undefined): void;
2820
+ /** 配置 Node worker_threads 加载的 bundle URL(通常是 tsup 产物 dist/kernel-worker.mjs)*/
2821
+ static setWorkerBundleUrl(url: string | URL | undefined): void;
2822
+ /** 配置全局默认快照存储。未设 + LoadOptions 也未传 → `InMemorySnapshotStorage`(每次装载独立实例) */
2823
+ static setDefaultSnapshotStorage(adapter: SnapshotStorageAdapter | undefined): void;
2824
+ /** @internal */
2825
+ static _getDefaultAuthor(): string;
2826
+ /** @internal */
2827
+ static _getDefaultMode(): RuntimeMode;
2828
+ /** @internal */
2829
+ static _resetDefaults(): void;
2830
+ }
2831
+
2832
+ /**
2833
+ * 跨 parts 事务 —— docs/03 §13.5 的落地。
2834
+ *
2835
+ * Plan.apply 的底层原语:在一组 part 上执行可能失败的 work,失败时回滚到 work 前状态。
2836
+ *
2837
+ * 设计:
2838
+ * - 进入事务前,对 `affectedPartPaths` 里每个已存在的 part 做深拷贝快照(xmlDom / bytes / _dirty)
2839
+ * - 记录哪些 path 在 work 开始时**不存在**(新建场景)
2840
+ * - work 内可自由变更 part(包括新增 / 删除 / 改 xmlDom)
2841
+ * - 抛错时:
2842
+ * * 原本存在的 part → 从快照恢复 xmlDom / bytes / _dirty
2843
+ * * 原本不存在但 work 新增的 part → 从 pkg 删除
2844
+ * - 成功时:保持 work 结束时的状态(work 自己负责 markDirty)
2845
+ *
2846
+ * 当前实现:deepClone 整个 xmlDom,在 10 万段落档上约 1-2s,优化(反向 op 记录)留后续 issue。
2847
+ */
2848
+
2849
+ /**
2850
+ * 在 `pkg` 上执行可能失败的 `work`。事务作用域仅覆盖 `affectedPartPaths` 列出的 parts:
2851
+ * - work 抛错 → 被列出的 parts 回滚到进入事务前状态(xmlDom / bytes / _dirty),新增的 parts 删除
2852
+ * - work 成功 → 返回 work 的结果
2853
+ *
2854
+ * **调用方职责**:
2855
+ * - `affectedPartPaths` 必须包含 work 里**所有可能触达**的 part 路径(读 + 写 + 新增)
2856
+ * - 未在列表里的 part 即便被 work 改动,回滚时不会被恢复
2857
+ */
2858
+ declare function runTransaction<T>(pkg: Package, affectedPartPaths: readonly string[], work: () => Promise<T> | T): Promise<T>;
2859
+
2860
+ /**
2861
+ * XQuery Update Facility 封装 —— docs/03 §13.2 的 "PUL apply" 行。
2862
+ *
2863
+ * 对 fontoxpath 的 `evaluateUpdatingExpression` + `executePendingUpdateList` 做轻量包装:
2864
+ * - 输入:XQuery Update 表达式 + 上下文节点
2865
+ * - 输出:PUL 条目数量(mutations) + 应用后的 xdmValue
2866
+ *
2867
+ * 用法例:
2868
+ * ```ts
2869
+ * await applyXQueryUpdate(
2870
+ * paraElement,
2871
+ * 'replace value of node ./w:r/w:t with "new text"',
2872
+ * { namespaceResolver: (p) => p === 'w' ? W_NS : null }
2873
+ * );
2874
+ * ```
2875
+ *
2876
+ * 注意:fontoxpath 没有 package.json `exports` 字段,其 main 是 UMD bundle,
2877
+ * Node.js ESM 加载器无法静态解析命名导出,因此改用惰性动态 import()。
2878
+ * Node.js 在 ESM 中 import() 一个 CJS/UMD 模块时,会将其 module.exports 包装
2879
+ * 成 { default: <module.exports> },故下方通过 `.default` 取出完整 API。
2880
+ *
2881
+ * 注意:XQuery 表达式自身性能需要调用方注意 —— 参见 docs/03 §13.2 的 460× 悬崖(
2882
+ * 无谓词 //w:p 在 10 万段落上 36s);本函数不做防御,调用方应只传写针对特定 element
2883
+ * 的精确表达式。
2884
+ */
2885
+ interface XQueryUpdateOptions {
2886
+ /** 命名空间 prefix → URI 的解析器。默认 null(表达式不含 prefix) */
2887
+ namespaceResolver?: (prefix: string) => string | null;
2888
+ /** 外部变量($name → 值) */
2889
+ variables?: Record<string, unknown>;
2890
+ }
2891
+ interface XQueryUpdateResult {
2892
+ /** PUL 条目数量(该次应用的变更数) */
2893
+ mutations: number;
2894
+ /** 表达式返回值(XQuery Update 通常无返回值,此处保持 opaque) */
2895
+ xdmValue: unknown[];
2896
+ }
2897
+ declare function applyXQueryUpdate(contextNode: Node, expression: string, options?: XQueryUpdateOptions): Promise<XQueryUpdateResult>;
2898
+
2899
+ /**
2900
+ * Worker RPC 协议 —— docs/03 §4.1 / §4.7。
2901
+ *
2902
+ * 主线程(WordDocument 代理)与 Worker 内 kernel 之间通过 postMessage 交换五类消息:
2903
+ * - request: { kind: 'request', id, method, args } —— 主 → Worker
2904
+ * - response: { kind: 'response', id, result } —— Worker → 主(成功)
2905
+ * - error: { kind: 'error', id, error } —— Worker → 主(失败)
2906
+ * - progress: { kind: 'progress', id, phase, pct? } —— Worker → 主(onProgress 回调)
2907
+ * - event: { kind: 'event', event, payload } —— Worker → 主(server-push,
2908
+ * 与某个 request 无关;v1 仅用于 'word.change')
2909
+ *
2910
+ * id 是一个 UUID-ish 字符串,主线程用它关联 pending request 与返回的 response/error。
2911
+ *
2912
+ * 错误使用 serializable 形态(code / message / docId / details),跨 Worker 边界后主
2913
+ * 线程用它重建 `WordError` 实例 → 抛给调用方。
2914
+ */
2915
+
2916
+ /** 主线程 → Worker 的方法调用 */
2917
+ interface RpcRequest {
2918
+ kind: 'request';
2919
+ id: string;
2920
+ method: string;
2921
+ args: unknown[];
2922
+ }
2923
+ /** Worker → 主线程:方法成功返回 */
2924
+ interface RpcResponse {
2925
+ kind: 'response';
2926
+ id: string;
2927
+ result: unknown;
2928
+ }
2929
+ /** Worker → 主线程:方法抛错。错误以字段形态序列化,主线程侧重建 WordError */
2930
+ interface RpcError {
2931
+ kind: 'error';
2932
+ id: string;
2933
+ error: SerializableError;
2934
+ }
2935
+ /** 序列化后的错误负载(跨 Worker 边界友好) */
2936
+ interface SerializableError {
2937
+ /** WordError.code;如果抛的是非 WordError,此字段为 undefined,主线程包装成 PACKAGE_CORRUPT */
2938
+ code?: WordErrorCode;
2939
+ message: string;
2940
+ /** WordError.docId;非 WordError 时可能为空串 */
2941
+ docId?: string;
2942
+ details?: Record<string, unknown>;
2943
+ /** 原始错误 name(Error/TypeError/...),调试用 */
2944
+ name?: string;
2945
+ /** 原始 stack(调试用;跨 worker 后行号不可靠,仅参考) */
2946
+ stack?: string;
2947
+ }
2948
+ /** Worker → 主线程:onProgress 回调 */
2949
+ interface RpcProgress {
2950
+ kind: 'progress';
2951
+ /** 关联的 request id */
2952
+ id: string;
2953
+ phase: string;
2954
+ pct?: number;
2955
+ }
2956
+ /**
2957
+ * Worker → 主线程:server-push 事件。与某个 request 无关,因此**没有** id 字段。
2958
+ * v1 仅用于 `'word.change'`(applyPlan 成功后从 worker 推到主线程,主线程 fan-out
2959
+ * 给 `WordDocument.on('change', ...)` 订阅者)。
2960
+ *
2961
+ * payload 必须 structured-cloneable;接收侧按 event 名做类型 narrowing。
2962
+ */
2963
+ interface RpcEvent {
2964
+ kind: 'event';
2965
+ event: string;
2966
+ payload: unknown;
2967
+ }
2968
+ type RpcMessage = RpcRequest | RpcResponse | RpcError | RpcProgress | RpcEvent;
2969
+
2970
+ /**
2971
+ * 浏览器 `Worker` → `WorkerPortLike` 适配器。
2972
+ *
2973
+ * 用于配合 `WordDocument.setWorkerFactory()`:消费方拿到自己 bundler 解析出的 worker
2974
+ * 实例(Vite `?worker`、`new Worker(new URL(...))`、或预构造的 Worker)后,直接传进来:
2975
+ *
2976
+ * ```ts
2977
+ * import KernelWorker from '@coco-vexel/coco-office/kernel-worker-browser?worker';
2978
+ * import { WordDocument, createBrowserWorkerPort } from '@coco-vexel/coco-office/word';
2979
+ *
2980
+ * WordDocument.setWorkerFactory(() => createBrowserWorkerPort(new KernelWorker()));
2981
+ * ```
2982
+ *
2983
+ * 仅在浏览器 / WPS 等具备 `Worker` 全局的环境可用。Node 路径请用 `createNodeWorkerPort`。
2984
+ */
2985
+
2986
+ /**
2987
+ * 把已构造好的浏览器 `Worker`(或 WPS Chromium 内的等价实例)包成 `WorkerPortLike`。
2988
+ *
2989
+ * `terminate()` 同步触发底层 `worker.terminate()`,并 resolve(浏览器 API 是 sync void,
2990
+ * 这里包成 Promise 与 Node 路径对齐)。
2991
+ */
2992
+ declare function createBrowserWorkerPort(worker: Worker): WorkerPortLike;
2993
+
2994
+ type WordCodePlanApiDomain = 'document' | 'paragraph' | 'bookmark' | 'table' | 'drawing' | 'range' | 'comment' | 'revision' | 'style' | 'section' | 'context' | 'toc' | 'snapshot';
2995
+ type WordCodePlanApiKind = 'locator' | 'read' | 'write' | 'format' | 'lifecycle';
2996
+ type WordCodePlanReceiverMap = {
2997
+ doc: WordDocument;
2998
+ 'doc.paragraphs': ParagraphApi;
2999
+ 'doc.bookmarks': BookmarkApi;
3000
+ 'doc.comments': CommentApi;
3001
+ 'doc.context': ContextApi;
3002
+ 'doc.revisions': RevisionApi;
3003
+ 'doc.styles': StylesApi;
3004
+ 'doc.tables': TablesApi;
3005
+ 'doc.drawings': DrawingsApi;
3006
+ 'doc.sections': SectionsApi;
3007
+ 'doc.tocFields': TocFieldsApi;
3008
+ 'doc.snapshots': SnapshotApi;
3009
+ paragraph: Paragraph;
3010
+ range: TextRange;
3011
+ bookmark: Bookmark;
3012
+ comment: Comment;
3013
+ revision: Revision;
3014
+ table: Table;
3015
+ cell: TableCell;
3016
+ row: TableRow;
3017
+ column: TableColumn;
3018
+ drawing: Drawing;
3019
+ picture: PictureDrawing;
3020
+ textBox: TextBoxDrawing;
3021
+ shape: ShapeDrawing;
3022
+ };
3023
+ type ReceiverName = keyof WordCodePlanReceiverMap;
3024
+ type MethodName<T> = {
3025
+ [K in keyof T]-?: T[K] extends (...args: never[]) => unknown ? K : never;
3026
+ }[keyof T] & string;
3027
+ type WordCodePlanSdkApiPath = {
3028
+ [R in ReceiverName]: `${R}.${MethodName<WordCodePlanReceiverMap[R]>}`;
3029
+ }[ReceiverName];
3030
+ interface WordCodePlanApiManifestEntry {
3031
+ path: WordCodePlanSdkApiPath;
3032
+ domain: WordCodePlanApiDomain;
3033
+ kind: WordCodePlanApiKind;
3034
+ codeplan: boolean;
3035
+ requiresAwait: boolean;
3036
+ reason?: string;
3037
+ }
3038
+ declare const WORD_CODEPLAN_API_MANIFEST_VERSION = 1;
3039
+ declare const WORD_CODEPLAN_API_MANIFEST: readonly WordCodePlanApiManifestEntry[];
3040
+ declare const WORD_CODEPLAN_ALLOWED_API_PATHS: WordCodePlanSdkApiPath[];
3041
+
3042
+ export { type ApplyPlanParams, type ApplyResult, type Bookmark, type BookmarkApi, type BookmarkInfo, type BookmarkName$1 as BookmarkName, type CellTextRange, type ChangeEvent, type ChangeListener, type ChangeSubscribeOptions, type Comment, type CommentApi, CommentId$1 as CommentId, CommentInfo, type ContextApi, type ContextBlock, type ContextBookmark, type ContextSearchHighlight, type ContextSearchInclude, type ContextSearchMatch, type ContextSearchOptions, type ContextSearchResult, type ContextSearchTarget, DEFAULT_MAX_SNAPSHOTS, type DateSdtSpec, type Drawing, type DrawingImageBytes, DrawingInfo, type DrawingsApi, EMPTY_APPLY_RESULT, type EnsureParaIdsResult, InlineTransport, type InsertParagraphSpec, Kernel, type KernelChangeEvent, type KernelLoadParams, type KernelLoadSource, type ListBookmarksOptions, ListDrawingsOptions, ListParagraphsOptions, ListResult, ListRevisionsOptions, ListStylesOptions, ListTablesOptions, type LiveObjectWriteOptions, type LoadOptions, type LoadPhase, type ModeDecision, type ModeSource, type Op, PackageIndices, type ParaId, type Paragraph, type ParagraphApi, type ParagraphDeleteOptions, ParagraphInfo, type ParagraphInsertImageSpec, type ParagraphInsertOptions, type ParagraphInsertTableSpec, type ParagraphList, type ParagraphRange, type ParagraphReplaceOptions, type PictureDrawing, type PlainTextSdtSpec, type PlanOptions, type PlanValidationIssue, type PlanValidationItem, type PlanValidationResult, type Range, type RangeClassification, type Revision, type RevisionApi, type RevisionId, RevisionInfo, type RevisionScope, type RichTextSdtSpec, type RollbackOptions, type RollbackProgress, RowHeight, type RpcError, type RpcEvent, type RpcMessage, type RpcProgress, type RpcRequest, type RpcResponse, type RuntimeMode, type SdtSpec, SectionInfo, type SectionsApi, type SerializableError, type ShapeDrawing, type SnapshotApi, type SnapshotPartEntry, StoryId, StyleInfo, type StylesApi, type Table, type TableCell, type TableCellBlock, TableCellInfo, type TableColumn, TableInfo, type TableRow, TableVerbatim, type TablesApi, type TextBoxDrawing, type TextRange, type TextRange$1 as TextRangeDescriptor, type TocFieldRange, type TocFieldsApi, type Transport, WORD_CHANGE_EVENT, WORD_CODEPLAN_ALLOWED_API_PATHS, WORD_CODEPLAN_API_MANIFEST, WORD_CODEPLAN_API_MANIFEST_VERSION, type WordCodePlanApiDomain, type WordCodePlanApiKind, type WordCodePlanApiManifestEntry, type WordCodePlanSdkApiPath, WordDocument, WordError, type WordErrorCode, type WordPlan, WordPlanImpl, type WordPlanImplInit, type WorkerFactory, type WorkerPortLike, WorkerTransport, type XQueryUpdateOptions, type XQueryUpdateResult, applyXQueryUpdate, buildInlineSdt, classifyRange, createBrowserWorkerPort, ensureParaIds, getBookmark, hashSdtId, listBookmarks, listTocFields, runTransaction, searchContext };