@coco-vexel/coco-office 0.0.0-stage → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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 +14111 -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 +14016 -0
  75. package/dist/word.js.map +1 -0
  76. package/package.json +103 -3
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/word/change-events.ts","../src/pack/part.ts","../src/pack/package.ts","../src/pack/zip.ts","../src/pack/content-types.ts","../src/pack/flat-opc.ts","../src/word/kernel.ts","../src/word/namespaces.ts","../src/word/range-kind.ts","../src/word/stories.ts","../src/word/bookmark-queries.ts","../src/word/comment-queries.ts","../src/word/list-tables.ts","../src/word/runs.ts","../src/word/list-paragraphs.ts","../src/word/context-search.ts","../src/word/style-queries.ts","../src/word/list-drawings.ts","../src/word/indices.ts","../src/word/domain-cache.ts","../src/word/para-id.ts","../src/word/word-error.ts","../src/word/plan.ts","../src/word/plan-validation.ts","../src/word/plan-executors/_shared.ts","../src/word/plan-executors/revision-wrappers.ts","../src/word/plan-executors/paragraph-ops.ts","../src/word/plan-executors/bookmark-ops.ts","../src/word/plan-executors/comment-ops.ts","../src/word/plan-executors/paragraph-structure-ops.ts","../src/word/revision-queries.ts","../src/word/plan-executors/revision-ops.ts","../src/word/sdt-builders.ts","../src/word/plan-executors/table-ops.ts","../src/word/plan-executors/placeholder-image.ts","../src/word/plan-executors/placeholder-image-bytes.ts","../src/word/plan-executors/drawing-ops.ts","../src/word/plan-executors/insert-image-ops.ts","../src/word/plan-executors/insert-table-ops.ts","../src/word/plan-executors/settings-ops.ts","../src/word/plan-executors/index.ts","../src/word/transactions.ts","../src/word/section-queries.ts","../src/word/toc-queries.ts","../src/word/kernel-handlers.ts","../src/word/sub-apis.ts","../src/word/sandbox-doc.ts","../src/word/script-execute.ts","../src/word/kernel-worker-shared.ts","../src/word/kernel-worker-browser-entry.ts"],"sourcesContent":["/**\n * change-events —— `WordDocument.on('change', ...)` 的类型定义。\n *\n * 文档变更事件在 `kernel.applyPlan()` 成功后触发,涵盖两条入口:\n * - `doc.plan().apply()` → source = 'plan'\n * - `doc.executeCode(script)` → source = 'script'(脚本内调 `doc.applyPlan`)\n *\n * **不**触发的场景:\n * - 空 plan(`ops.length === 0`)—— kernel 直接返回,不算一次变更\n * - applyPlan 抛错回滚 —— 文档状态未变\n * - 脚本绕过 kernel.applyPlan 直接改 `doc.getPackage()` 的 DOM —— v1 不覆盖,\n * 此类用法被视作\"自负其责\";后续可加 dirty-watcher,但代价大。\n *\n * Payload 默认只带 `ops` + `result` + `source`,**不**带全文档 —— 全文档输出\n * (toFlatOpc / toZip)在 worker 模式下要 RPC + serialize,10 万段落级别可达数百 ms,\n * 不是\"白送\"的开销。订阅时通过 `fullDocument: 'flatOpc' | 'zip'` 显式开启,本模块\n * 在派发前由 WordDocument 一次性拉取(多订阅者共享)。\n */\nimport type { ApplyResult, Op } from './plan.js';\n\n/**\n * Kernel 内部的 change event payload —— 走 worker 边界时被 structured-clone,\n * 因此所有字段必须是 plain JSON。\n */\nexport interface KernelChangeEvent {\n /** 触发本次 apply 的 op 队列(完整传出,便于审计 / 重放) */\n ops: Op[];\n /** kernel.applyPlan 的返回值 */\n result: ApplyResult;\n /**\n * 'plan' = 走 RPC `applyPlan`(`doc.plan().apply()` 路径)\n * 'script' = 走 `doc.applyPlan(...)`(`doc.executeCode(...)` 内部脚本路径)\n *\n * 由触发层(kernel-handlers / script-execute)显式标注;kernel.applyPlan 自己不知道\n * 来源,只接收 `opts.source`。\n */\n source: 'plan' | 'script';\n}\n\n/**\n * `WordDocument.on('change', handler)` 收到的 payload。比 KernelChangeEvent 多了\n * 可选的全文档字段 —— 是否填充由订阅时的 `fullDocument` 决定。\n */\nexport interface ChangeEvent extends KernelChangeEvent {\n /** 仅当 `subscribe.fullDocument === 'flatOpc'` 时存在 */\n flatOpc?: string;\n /** 仅当 `subscribe.fullDocument === 'zip'` 时存在 */\n zip?: Uint8Array;\n}\n\n/** 订阅选项;默认 `fullDocument: 'none'`(只发 metadata,不付全文档输出代价)。 */\nexport interface ChangeSubscribeOptions {\n /**\n * - `'none'`(默认):payload 只含 `{ ops, result, source }`\n * - `'flatOpc'`:派发前调一次 `toFlatOpc()`,payload.flatOpc 填充 XML 字符串\n * - `'zip'`:派发前调一次 `toZip()`,payload.zip 填充 docx 字节\n *\n * **代价警示**:`'flatOpc'` / `'zip'` 在 worker 模式下要 RPC + structured-clone\n * 整篇文档,大文档一次几百 ms;只在确实要\"快照式消费\"时启用。多订阅者共享同一次\n * 拉取,因此打开多个 'flatOpc' 订阅不会重复跑。\n */\n fullDocument?: 'none' | 'flatOpc' | 'zip';\n}\n\n/** 订阅回调;可同步可 async。WordDocument 串行 await 每个订阅者,保证派发顺序与变更顺序一致。 */\nexport type ChangeListener = (ev: ChangeEvent) => void | Promise<void>;\n\n/** RPC event 通道里 word change 事件的 `event` 字符串常量。 */\nexport const WORD_CHANGE_EVENT = 'word.change';\n","/**\n * Part 构造 / 变更 / 查询 的辅助函数。\n *\n * 所有 Part 的\"创建\"都走这里(而非直接字面量),以便:\n * - 守住 path 格式(无前导斜杠)\n * - 守住 XML / 二进制 互斥\n * - 统一 `_dirty` / `_originalBytes` 初始化语义\n */\nimport type { Part } from './types.js';\n\nexport interface CreateXmlPartSpec {\n /** Part 路径,无前导斜杠,如 'word/document.xml' */\n path: string;\n /** MIME content type */\n contentType: string;\n /** 已解析好的 XML DOM(slimdom Document) */\n xmlDom: Document;\n /**\n * 装载时的原始字节。\n * - 传入(来自装载路径):`_dirty` 初始为 `false`,可在 `toZip` 时零 serialize 复用\n * - 省略(新建 part 的场景,后续 #9/#10 的插入新 XML part):`_dirty` 初始为 `true`\n */\n originalBytes?: Uint8Array;\n}\n\nexport interface CreateBinaryPartSpec {\n /** Part 路径,无前导斜杠,如 'word/media/image1.png' */\n path: string;\n /** MIME content type,如 'image/png' */\n contentType: string;\n /** 二进制载荷 */\n bytes: Uint8Array;\n /**\n * 装载时的原始字节;二进制通常装载即最终态,省略时默认 = `bytes`。\n * 二进制 part 初始 `_dirty` 恒为 `false`。\n */\n originalBytes?: Uint8Array;\n}\n\nfunction assertPath(path: string): void {\n if (typeof path !== 'string' || path.length === 0) {\n throw new Error(`invalid part path: must be non-empty string, got: ${JSON.stringify(path)}`);\n }\n if (path.startsWith('/')) {\n throw new Error(`invalid part path: must not start with '/', got: ${path}`);\n }\n}\n\nfunction assertContentType(contentType: string): void {\n if (typeof contentType !== 'string' || contentType.length === 0) {\n throw new Error(`invalid contentType: must be non-empty string`);\n }\n}\n\n/** 从已解析的 XML DOM 创建 XML part。`originalBytes` 传入 → dirty=false;否则 dirty=true(新建场景) */\nexport function createXmlPart(spec: CreateXmlPartSpec): Part {\n assertPath(spec.path);\n assertContentType(spec.contentType);\n if (!spec.xmlDom) {\n throw new Error(`createXmlPart: xmlDom required for ${spec.path}`);\n }\n return {\n path: spec.path,\n contentType: spec.contentType,\n xmlDom: spec.xmlDom,\n _originalBytes: spec.originalBytes,\n _dirty: spec.originalBytes === undefined,\n };\n}\n\n/** 从二进制字节创建 binary part。`originalBytes` 省略时默认 = `bytes`。dirty 恒为 false */\nexport function createBinaryPart(spec: CreateBinaryPartSpec): Part {\n assertPath(spec.path);\n assertContentType(spec.contentType);\n if (!spec.bytes) {\n throw new Error(`createBinaryPart: bytes required for ${spec.path}`);\n }\n return {\n path: spec.path,\n contentType: spec.contentType,\n bytes: spec.bytes,\n _originalBytes: spec.originalBytes ?? spec.bytes,\n _dirty: false,\n };\n}\n\n/** 标记 part 被改动过。toZip / toFlatOpc 会重 serialize 此 part */\nexport function markDirty(part: Part): void {\n part._dirty = true;\n}\n\n/** 查询 part 是否被改动(read-only;读操作不改 part) */\nexport function isDirty(part: Part): boolean {\n return part._dirty;\n}\n\n/** XML part 判定(拥有 xmlDom) */\nexport function isXmlPart(part: Part): boolean {\n return part.xmlDom !== undefined;\n}\n\n/** 二进制 part 判定(拥有 bytes 但无 xmlDom) */\nexport function isBinaryPart(part: Part): boolean {\n return part.bytes !== undefined && part.xmlDom === undefined;\n}\n","/**\n * Package 集合层:create / set / get / has / delete / list\n *\n * Package 只是 path→Part 的 Map 容器;零业务语义,存储格式由 adapter 层(#9 zip / #10 Flat OPC)决定。\n */\nimport type { Package, Part } from './types.js';\n\n/** 空包。后续由 adapter 层填充 parts */\nexport function createPackage(): Package {\n return { parts: new Map() };\n}\n\n/** 以 part.path 为 key 放入 pkg。已存在同 path 时覆盖 */\nexport function setPart(pkg: Package, part: Part): void {\n pkg.parts.set(part.path, part);\n}\n\n/** 按 path 取回 part;不存在返 undefined */\nexport function getPart(pkg: Package, path: string): Part | undefined {\n return pkg.parts.get(path);\n}\n\n/** 按 path 判断存在 */\nexport function hasPart(pkg: Package, path: string): boolean {\n return pkg.parts.has(path);\n}\n\n/** 删除 part,返回是否删除成功(存在即删、不存在返 false) */\nexport function deletePart(pkg: Package, path: string): boolean {\n return pkg.parts.delete(path);\n}\n\n/** 所有 parts 快照数组(稳定遍历顺序 = Map 插入顺序) */\nexport function listParts(pkg: Package): Part[] {\n return Array.from(pkg.parts.values());\n}\n","/**\n * zip ↔ Package 互转(docs/01 §3.2)。\n *\n * - `fromZip(buf)` 解压 .docx,按 `[Content_Types].xml` 恢复每个 part 的 contentType\n * - `toZip(pkg)` 反向:dirty=false 的 part 复用 `_originalBytes`,dirty=true 的按 XML / 二进制重序列化\n *\n * 本实现目标:小文档正确性。极大档性能调优(lazy parse 等)归后续 issue。\n */\nimport JSZip from 'jszip';\nimport { parseXmlDocument, serializeToWellFormedString } from 'slimdom';\nimport type { Package, Part } from './types.js';\nimport { createBinaryPart, createXmlPart, isXmlPart } from './part.js';\nimport { createPackage, setPart } from './package.js';\nimport { ensureContentTypes } from './content-types.js';\n\n/** Content Types 子集 */\nconst CONTENT_TYPES_PATH = '[Content_Types].xml';\nconst CONTENT_TYPES_NS = 'http://schemas.openxmlformats.org/package/2006/content-types';\nconst CONTENT_TYPES_CTYPE = 'application/vnd.openxmlformats-package.content-types+xml';\n\n/**\n * 判断 contentType 是否为 XML 类(决定走 parseXmlDocument 还是保留字节):\n * - 以 `+xml` 结尾(OOXML 所有子 part 的惯例)\n * - 或完全等于 `application/xml` / `text/xml`\n */\nfunction isXmlContentType(ct: string): boolean {\n const normalized = ct.toLowerCase();\n if (\n normalized.startsWith('image/') ||\n normalized.startsWith('audio/') ||\n normalized.startsWith('video/') ||\n normalized === 'application/octet-stream' ||\n normalized === 'application/vnd.openxmlformats-officedocument.oleobject' ||\n normalized.startsWith('application/vnd.ms-office.')\n ) {\n return false;\n }\n return normalized.endsWith('+xml') || normalized === 'application/xml' || normalized === 'text/xml';\n}\n\n/** 解析 [Content_Types].xml 构建 partName → contentType 的查找器 */\ninterface ContentTypeResolver {\n /** partName 无前导 `/`,如 'word/document.xml' */\n resolve(partName: string): string | undefined;\n}\n\nfunction parseContentTypes(xml: string): ContentTypeResolver {\n const doc = parseXmlDocument(xml) as unknown as Document;\n const defaults = new Map<string, string>(); // extension(小写) → contentType\n const overrides = new Map<string, string>(); // partName(无 /)→ contentType\n\n const defaultEls = doc.getElementsByTagNameNS(CONTENT_TYPES_NS, 'Default');\n for (let i = 0; i < defaultEls.length; i++) {\n const el = defaultEls[i];\n if (!el) continue;\n const ext = el.getAttribute('Extension');\n const ct = el.getAttribute('ContentType');\n if (ext && ct) defaults.set(ext.toLowerCase(), ct);\n }\n\n const overrideEls = doc.getElementsByTagNameNS(CONTENT_TYPES_NS, 'Override');\n for (let i = 0; i < overrideEls.length; i++) {\n const el = overrideEls[i];\n if (!el) continue;\n const partName = el.getAttribute('PartName');\n const ct = el.getAttribute('ContentType');\n if (partName && ct) {\n // PartName 以 `/` 开头,剥掉前导斜杠与 Package 内部 path 对齐\n overrides.set(partName.replace(/^\\//, ''), ct);\n }\n }\n\n return {\n resolve(partName: string): string | undefined {\n const override = overrides.get(partName);\n if (override) return override;\n const dot = partName.lastIndexOf('.');\n if (dot === -1) return undefined;\n return defaults.get(partName.slice(dot + 1).toLowerCase());\n },\n };\n}\n\n/**\n * 从 zip 字节重建 Package。\n *\n * 行为:\n * - 先读 `[Content_Types].xml`,构建 contentType 查找器\n * - 遍历 zip entries,跳过目录\n * - 每个 entry 按 contentType 决定 XML / 二进制,创建对应 Part\n * - `[Content_Types].xml` 也作为 XML part 存入 Package\n */\nexport async function fromZip(buf: Uint8Array | ArrayBuffer): Promise<Package> {\n const bytes = buf instanceof Uint8Array ? buf : new Uint8Array(buf);\n const zip = await JSZip.loadAsync(bytes);\n const pkg = createPackage();\n\n const ctFile = zip.file(CONTENT_TYPES_PATH);\n if (!ctFile) {\n throw new Error(`fromZip: missing ${CONTENT_TYPES_PATH}; not a valid OOXML package`);\n }\n const ctXml = await ctFile.async('string');\n const resolver = parseContentTypes(ctXml);\n const ctBytes = await ctFile.async('uint8array');\n setPart(\n pkg,\n createXmlPart({\n path: CONTENT_TYPES_PATH,\n contentType: CONTENT_TYPES_CTYPE,\n xmlDom: parseXmlDocument(ctXml) as unknown as Document,\n originalBytes: ctBytes,\n }),\n );\n\n // 遍历非 [Content_Types].xml 的 entry\n const entryPaths: string[] = [];\n zip.forEach((relativePath, entry) => {\n if (entry.dir) return;\n if (relativePath === CONTENT_TYPES_PATH) return;\n entryPaths.push(relativePath);\n });\n\n for (const path of entryPaths) {\n const entry = zip.file(path);\n if (!entry) continue;\n const contentType = resolver.resolve(path);\n if (!contentType) {\n throw new Error(\n `fromZip: no ContentType for part '${path}' (not in Default by extension, not in Override by partName)`,\n );\n }\n const entryBytes = await entry.async('uint8array');\n\n if (isXmlContentType(contentType)) {\n const xmlText = await entry.async('string');\n const xmlDom = parseXmlDocument(xmlText) as unknown as Document;\n setPart(pkg, createXmlPart({ path, contentType, xmlDom, originalBytes: entryBytes }));\n } else {\n setPart(pkg, createBinaryPart({ path, contentType, bytes: entryBytes }));\n }\n }\n\n return pkg;\n}\n\n/**\n * 将 Package 序列化回 zip 字节。\n *\n * 行为:\n * - `_dirty === false` 且持有 `_originalBytes` → 直接复用字节(零 serialize)\n * - `_dirty === true` 的 XML part → slimdom serialize\n * - `_dirty === true` 的二进制 part → 使用 `bytes`\n */\nexport async function toZip(pkg: Package): Promise<Uint8Array> {\n // Flat OPC → Package 的路径不会产生 [Content_Types].xml;此处补齐以保证产出的 zip 合法。\n // 对 fromZip 出来的 Package 无副作用(CT 已在)。\n ensureContentTypes(pkg);\n\n const zip = new JSZip();\n\n for (const part of pkg.parts.values()) {\n const bytes = partToBytes(part);\n // createFolders=false 显式禁止 JSZip 为含 '/' 的 path 自动创建中间目录 entry——\n // OOXML 规范不允许 zip 包内有空目录 entry,Word 见到会判\"文档已损坏\"拒打开\n // (WPS 宽松能开但产物不合规)。JSZip 3.x 默认 true,必须显式关。\n zip.file(part.path, bytes, { createFolders: false });\n }\n\n // OOXML 主体是高度可压缩的 XML;默认 STORE 会让产物比 Word 原生输出大 10-18×。\n return await zip.generateAsync({\n type: 'uint8array',\n compression: 'DEFLATE',\n compressionOptions: { level: 6 },\n });\n}\n\nfunction partToBytes(part: Part): Uint8Array {\n // dirty=false 且有原始字节:零 serialize\n if (!part._dirty && part._originalBytes) {\n return part._originalBytes;\n }\n\n if (isXmlPart(part)) {\n if (!part.xmlDom) {\n throw new Error(`toZip: XML part '${part.path}' missing xmlDom`);\n }\n // xmlDom 在我们的类型里是 lib.dom 的 Document(消费方友好),slimdom 的 Node 结构兼容但 TS\n // 类型不同;通过 `as never` 绕开 dts 检查,运行时正常。\n const text = serializeToWellFormedString(part.xmlDom as never);\n return new TextEncoder().encode(text);\n }\n\n // 二进制\n if (part.bytes) return part.bytes;\n if (part._originalBytes) return part._originalBytes;\n throw new Error(`toZip: binary part '${part.path}' has no bytes`);\n}\n","/**\n * [Content_Types].xml 的合成与维护。\n *\n * 为什么单列一个模块:\n * - zip 形态要求 [Content_Types].xml 存在(否则 Word/WPS 打不开)\n * - Flat OPC 形态里 contentType 已内联在 <pkg:part> 上,不含 CT 文件\n * - 因此 `fromFlatOpc` 出来的 Package 缺 CT;直接 `toZip` 会产出坏 docx\n *\n * 本模块提供 `ensureContentTypes(pkg)`:若 CT part 缺失,按当前 parts 的\n * (path → contentType)合成一份最小 CT XML 并加入 Package。\n *\n * `toZip` 会在打包前自动调一次,确保产出的 zip 始终可打开。\n */\nimport { parseXmlDocument } from 'slimdom';\nimport { createXmlPart } from './part.js';\nimport { getPart, setPart } from './package.js';\nimport type { Package } from './types.js';\n\nconst CONTENT_TYPES_PATH = '[Content_Types].xml';\nconst CONTENT_TYPES_NS = 'http://schemas.openxmlformats.org/package/2006/content-types';\nconst CONTENT_TYPES_CTYPE = 'application/vnd.openxmlformats-package.content-types+xml';\n\n/** XML 属性值转义(Content Type 里可能含 `+`,但没有 `<` `&` 等需要转义的字符;仍做一遍以防) */\nfunction xmlAttr(v: string): string {\n return v\n .replace(/&/g, '&amp;')\n .replace(/</g, '&lt;')\n .replace(/>/g, '&gt;')\n .replace(/\"/g, '&quot;');\n}\n\n/**\n * 如果 Package 里已有 `[Content_Types].xml` part,返回 false,不做改动。\n * 否则,按当前 parts 的 contentType 合成一份最小 CT XML 并加入 Package,返回 true。\n *\n * 合成策略:每个非 CT part 产生一个 `<Override PartName=\"/path\" ContentType=\"...\"/>`。\n * 不尝试推导 Default 扩展名(正确性优先,简洁性次之)。\n */\nexport function ensureContentTypes(pkg: Package): boolean {\n if (getPart(pkg, CONTENT_TYPES_PATH)) return false;\n\n const overrides: string[] = [];\n for (const part of pkg.parts.values()) {\n if (part.path === CONTENT_TYPES_PATH) continue;\n overrides.push(\n ` <Override PartName=\"/${xmlAttr(part.path)}\" ContentType=\"${xmlAttr(part.contentType)}\"/>`,\n );\n }\n\n const xml =\n `<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\\n` +\n `<Types xmlns=\"${CONTENT_TYPES_NS}\">\\n` +\n overrides.join('\\n') +\n (overrides.length > 0 ? '\\n' : '') +\n `</Types>`;\n\n setPart(\n pkg,\n createXmlPart({\n path: CONTENT_TYPES_PATH,\n contentType: CONTENT_TYPES_CTYPE,\n xmlDom: parseXmlDocument(xml) as unknown as Document,\n originalBytes: new TextEncoder().encode(xml),\n }),\n );\n\n return true;\n}\n","/**\n * Flat OPC ↔ Package 互转(docs/01 §3.3)。\n *\n * Flat OPC 是 WPS `Document.WordOpenXML` 返回的形态,整个包展开成一份大 XML:\n *\n * <?xml version=\"1.0\" standalone=\"yes\"?>\n * <?mso-application progid=\"Word.Document\"?>\n * <pkg:package xmlns:pkg=\"http://schemas.microsoft.com/office/2006/xmlPackage\">\n * <pkg:part pkg:name=\"/word/document.xml\" pkg:contentType=\"...+xml\">\n * <pkg:xmlData>\n * <w:document xmlns:w=\"...\">...</w:document>\n * </pkg:xmlData>\n * </pkg:part>\n * <pkg:part pkg:name=\"/word/media/image1.png\" pkg:contentType=\"image/png\" pkg:compression=\"store\">\n * <pkg:binaryData>iVBORw0KG...=</pkg:binaryData>\n * </pkg:part>\n * ...\n * </pkg:package>\n *\n * **注意**:Flat OPC 里 contentType 直接写在每个 `<pkg:part>` 上,\n * 没有 `[Content_Types].xml` 这个 part 本身。互转时 `[Content_Types].xml` 只在 zip 形态下存在。\n */\nimport { parseXmlDocument, serializeToWellFormedString } from 'slimdom';\nimport type { Package, Part } from './types.js';\nimport { createBinaryPart, createXmlPart, isXmlPart } from './part.js';\nimport { createPackage, setPart } from './package.js';\n\nconst PKG_NS = 'http://schemas.microsoft.com/office/2006/xmlPackage';\nconst CONTENT_TYPES_PATH = '[Content_Types].xml';\n\nfunction isXmlContentType(ct: string): boolean {\n return ct.endsWith('+xml') || ct === 'application/xml' || ct === 'text/xml';\n}\n\n/** Uint8Array → base64(兼容 Node 16+ / 浏览器 / WPS WebView) */\nfunction base64Encode(bytes: Uint8Array): string {\n let binStr = '';\n for (let i = 0; i < bytes.length; i++) {\n binStr += String.fromCharCode(bytes[i]!);\n }\n return btoa(binStr);\n}\n\n/** base64 → Uint8Array */\nfunction base64Decode(b64: string): Uint8Array {\n const cleaned = b64.replace(/\\s+/g, '');\n const binStr = atob(cleaned);\n const bytes = new Uint8Array(binStr.length);\n for (let i = 0; i < binStr.length; i++) {\n bytes[i] = binStr.charCodeAt(i);\n }\n return bytes;\n}\n\n/** 取元素的第一个 Element 类型子节点(跳过文本 / 注释 / 空白) */\nfunction firstElementChild(el: Element): Element | null {\n const kids = el.childNodes;\n for (let i = 0; i < kids.length; i++) {\n const n = kids[i];\n if (n && n.nodeType === 1) return n as Element;\n }\n return null;\n}\n\n/**\n * 从 Flat OPC 字符串重建 Package。\n *\n * - 忽略顶部 `<?mso-application?>` PI(解析器自动处理)\n * - `<pkg:xmlData>` 里的根元素被提取重新序列化为该 part 的独立 XML 文档\n * - `<pkg:binaryData>` 做 base64 解码\n * - **不**产生 `[Content_Types].xml` part(Flat OPC 形态不含它)\n */\nexport function fromFlatOpc(xml: string): Package {\n const flatDoc = parseXmlDocument(xml) as unknown as Document;\n const pkg = createPackage();\n\n const partEls = flatDoc.getElementsByTagNameNS(PKG_NS, 'part');\n for (let i = 0; i < partEls.length; i++) {\n const partEl = partEls[i];\n if (!partEl) continue;\n\n const pkgName = partEl.getAttributeNS(PKG_NS, 'name');\n const ctype = partEl.getAttributeNS(PKG_NS, 'contentType');\n if (!pkgName || !ctype) {\n throw new Error(`fromFlatOpc: <pkg:part> missing name or contentType`);\n }\n const path = pkgName.replace(/^\\//, '');\n if (!path) continue;\n\n // [Content_Types].xml 理论上不会出现在 Flat OPC 里;若遇到,跳过\n if (path === CONTENT_TYPES_PATH) continue;\n\n // 查找 xmlData 或 binaryData(只取第一个,跨命名空间断言)\n let xmlData: Element | null = null;\n let binaryData: Element | null = null;\n const kids = partEl.childNodes;\n for (let j = 0; j < kids.length; j++) {\n const k = kids[j];\n if (!k || k.nodeType !== 1) continue;\n const e = k as Element;\n if (e.namespaceURI !== PKG_NS) continue;\n if (e.localName === 'xmlData' && !xmlData) xmlData = e;\n else if (e.localName === 'binaryData' && !binaryData) binaryData = e;\n }\n\n if (xmlData) {\n const rootChild = firstElementChild(xmlData);\n if (!rootChild) {\n throw new Error(`fromFlatOpc: empty <pkg:xmlData> for part '${path}'`);\n }\n // 将子元素序列化出来,再独立解析为该 part 的 Document\n const xmlText = serializeToWellFormedString(rootChild as never);\n const originalBytes = new TextEncoder().encode(xmlText);\n const dom = parseXmlDocument(xmlText) as unknown as Document;\n setPart(pkg, createXmlPart({ path, contentType: ctype, xmlDom: dom, originalBytes }));\n } else if (binaryData) {\n const b64 = binaryData.textContent ?? '';\n const bytes = base64Decode(b64);\n setPart(pkg, createBinaryPart({ path, contentType: ctype, bytes }));\n } else {\n // 既无 xmlData 也无 binaryData — 按类型决定:XML contentType 用空元素,二进制用空字节\n if (isXmlContentType(ctype)) {\n throw new Error(`fromFlatOpc: XML part '${path}' has no <pkg:xmlData>`);\n }\n setPart(pkg, createBinaryPart({ path, contentType: ctype, bytes: new Uint8Array() }));\n }\n }\n\n return pkg;\n}\n\n/**\n * 将 Package 序列化为 Flat OPC 字符串。\n *\n * - 顶部插入 `<?mso-application progid=\"Word.Document\"?>` PI\n * - 跳过 `[Content_Types].xml` part(Flat OPC 不需要)\n * - XML part:导入 `xmlDom` 的根元素到新 Flat OPC document,包进 `<pkg:xmlData>`\n * - 二进制 part:字节 base64 编码,包进 `<pkg:binaryData>`,加 `pkg:compression=\"store\"`\n */\nexport function toFlatOpc(pkg: Package): string {\n // slimdom 的 DOMImplementation 构造签名与 lib.dom 不同(需要一个虚拟 document 作为 context);\n // 直接用 parseXmlDocument 生成一个带 pkg:package 根的空文档,避免跨类型适配。\n const seed = `<pkg:package xmlns:pkg=\"${PKG_NS}\"/>`;\n const flatDoc = parseXmlDocument(seed) as unknown as Document;\n const root = flatDoc.documentElement;\n if (!root) {\n throw new Error('toFlatOpc: failed to create <pkg:package> root');\n }\n\n for (const part of pkg.parts.values()) {\n if (part.path === CONTENT_TYPES_PATH) continue;\n\n const partEl = flatDoc.createElementNS(PKG_NS, 'pkg:part');\n partEl.setAttributeNS(PKG_NS, 'pkg:name', '/' + part.path);\n partEl.setAttributeNS(PKG_NS, 'pkg:contentType', part.contentType);\n\n if (isXmlPart(part)) {\n appendXmlData(flatDoc, partEl, part);\n } else {\n partEl.setAttributeNS(PKG_NS, 'pkg:compression', 'store');\n appendBinaryData(flatDoc, partEl, part);\n }\n\n root.appendChild(partEl);\n }\n\n // 顶部加 <?mso-application?> PI\n const pi = flatDoc.createProcessingInstruction('mso-application', 'progid=\"Word.Document\"');\n flatDoc.insertBefore(pi as never, flatDoc.documentElement as never);\n\n return serializeToWellFormedString(flatDoc as never);\n}\n\nfunction appendXmlData(flatDoc: Document, partEl: Element, part: Part): void {\n if (!part.xmlDom || !part.xmlDom.documentElement) {\n throw new Error(`toFlatOpc: XML part '${part.path}' missing xmlDom or root`);\n }\n const xmlData = flatDoc.createElementNS(PKG_NS, 'pkg:xmlData');\n // importNode 深拷贝原 part 的根元素到 Flat OPC document,命名空间保留\n const imported = flatDoc.importNode(\n part.xmlDom.documentElement as never,\n true,\n ) as unknown as Node;\n xmlData.appendChild(imported);\n partEl.appendChild(xmlData);\n}\n\nfunction appendBinaryData(flatDoc: Document, partEl: Element, part: Part): void {\n const bytes = part.bytes ?? part._originalBytes;\n if (!bytes) {\n throw new Error(`toFlatOpc: binary part '${part.path}' has no bytes`);\n }\n const binEl = flatDoc.createElementNS(PKG_NS, 'pkg:binaryData');\n binEl.textContent = base64Encode(bytes);\n partEl.appendChild(binEl);\n}\n","interface CollectAffectedPartPathTiming {\n storiesMs: number;\n storyLookups: number;\n storyLookupMs: number;\n byType: Array<{\n type: Op['type'];\n count: number;\n ms: number;\n storyLookups: number;\n storyLookupMs: number;\n }>;\n}\n\ninterface CollectAffectedPartPathsResult {\n paths: string[];\n timing: CollectAffectedPartPathTiming;\n}\n\n/**\n * Kernel —— 持有 Package + 三索引 + 执行装载/输出/变更的\"真实运行体\"。\n *\n * - Worker 模式:kernel 在 Worker 里跑,主线程通过 RPC 协议与之通信\n * - Inline 模式:kernel 直接在主线程跑,`InlineTransport` 调用它的同步 API\n *\n * 本文件不依赖任何 Worker / 主线程特定 API,可被两端复用。\n */\nimport type { Package, Part } from '../pack/index.js';\nimport {\n createBinaryPart,\n createPackage,\n createXmlPart,\n fromFlatOpc as pkgFromFlatOpc,\n fromZip as pkgFromZip,\n isXmlPart,\n listParts,\n setPart,\n toFlatOpc as pkgToFlatOpc,\n toZip as pkgToZip,\n} from '../pack/index.js';\nimport { parseXmlDocument, serializeToWellFormedString } from 'slimdom';\nimport {\n getBookmark as pureGetBookmark,\n listBookmarks as pureListBookmarks,\n type BookmarkInfo,\n type BookmarkName,\n type ListBookmarksOptions,\n} from './bookmark-queries.js';\nimport type { KernelChangeEvent } from './change-events.js';\nimport {\n getComment as pureGetComment,\n listComments as pureListComments,\n type CommentId,\n type CommentInfo,\n} from './comment-queries.js';\nimport {\n searchContext as pureSearchContext,\n type ContextSearchOptions,\n type ContextSearchResult,\n} from './context-search.js';\nimport { BookmarkLoadError, buildIndices, type PackageIndices } from './indices.js';\nimport {\n getParagraphByParaId,\n listParagraphs as pureListParagraphs,\n type ListParagraphsOptions,\n type ListResult,\n type ParagraphInfo,\n} from './list-paragraphs.js';\nimport {\n WordDomainCache,\n type DomainCacheName,\n type WordDomainCacheSnapshot,\n} from './domain-cache.js';\nimport { ensureParaIds } from './para-id.js';\nimport { EMPTY_APPLY_RESULT, type ApplyPlanParams, type ApplyResult, type Op } from './plan.js';\nimport { validatePlanOps } from './plan-validation.js';\nimport { dispatchOp, type ExecutorContext } from './plan-executors/index.js';\nimport { sweepOrphanMediaParts } from './plan-executors/placeholder-image.js';\nimport { runTransaction } from './transactions.js';\nimport { listStories, type Story } from './stories.js';\nimport {\n listRevisions as pureListRevisions,\n type ListRevisionsOptions,\n type RevisionInfo,\n} from './revision-queries.js';\nimport { listSections as pureListSections, type SectionInfo } from './section-queries.js';\nimport { listTocFields as pureListTocFields, type TocFieldRange } from './toc-queries.js';\nimport {\n listStyles as pureListStyles,\n getStyleById as pureGetStyleById,\n type ListStylesOptions,\n type StyleInfo,\n} from './style-queries.js';\nimport {\n listTables as pureListTables,\n getTableById as pureGetTableById,\n getTableVerbatim as pureGetTableVerbatim,\n type ListTablesOptions,\n type TableInfo,\n type TableVerbatim,\n} from './list-tables.js';\nimport {\n listDrawings as pureListDrawings,\n getDrawingById as pureGetDrawingById,\n type DrawingInfo,\n type ListDrawingsOptions,\n} from './list-drawings.js';\nimport { WordError } from './word-error.js';\nimport { getImageBytesSync, type ImageBytesResult } from './plan-executors/insert-image-ops.js';\n\n/** Kernel.load 的输入 */\nexport type KernelLoadSource =\n { type: 'zip'; bytes: Uint8Array } | { type: 'flat-opc'; xml: string };\n\nexport interface KernelLoadParams {\n source: KernelLoadSource;\n docId: string;\n}\n\n/**\n * 装载 / rebuild 进度回调。\n *\n * - load 使用 `'fetch' | 'parse' | 'normalize'`(LoadPhase 对齐)\n * - rebuildFromParts(#22)使用 `'parse' | 'build-indices' | 'done'`\n *\n * 上层 WordDocument.rollback 会把 phase 作为字符串透传,不强制 union 收敛。\n */\nexport type KernelProgress = (phase: string, pct?: number) => void;\n\n/**\n * Kernel —— 持有单一 WordDocument 的内部状态。\n *\n * 一个 WordDocument 代理对应一个 Kernel。生命周期由代理控制:load → 多次操作 → dispose。\n */\nexport class Kernel {\n private pkg?: Package;\n private indices?: PackageIndices;\n private docId?: string;\n private initialBytes?: Uint8Array;\n private initialFlatOpc?: string;\n private disposed = false;\n private readonly domainCache = new WordDomainCache();\n /**\n * change 事件订阅者(applyPlan 成功后 fan-out)。InlineTransport 直接订阅;worker\n * 模式下 worker 内创建 Kernel 时由 worker entry 订阅一个把事件 post 到主线程的\n * 中转 listener(详见 kernel-worker-shared.ts)。\n *\n * 监听器异常被静默吞掉 —— 一个订阅者抛错不该影响其它订阅者,也不该影响 applyPlan\n * 的返回值(applyPlan 已经成功提交,事件只是事后通知)。\n */\n private readonly changeListeners = new Set<(ev: KernelChangeEvent) => void>();\n\n /**\n * applyPlan 互斥链 —— 串行化所有 applyPlan 调用,不论来源(plan / script)。\n *\n * 必要性:applyPlan 内部对 `pkg.parts[*].xmlDom` 做 deepClone(transaction\n * snapshot)+ 同步 mutate + 索引重建。多个 applyPlan 在 microtask 边界穿插\n * 时:\n * - 多份 deepClone 同时占内存(50w 字 doc × 并发数 → WPS WebView OOM)\n * - A 的 dispatch 与 B 的 dispatch 在共享 xmlDom 上交错,paraIdx 错位\n * - A 的回滚 snapshot 包含 B 的 mutation,A 失败回滚会 wipe B 的写\n * - finally 里 buildIndices 互相覆盖\n *\n * 用 promise chain 串行化:每次 applyPlan 等前一个完成才进入 inner。链上\n * resolve 永不 reject —— 把 inner 的成功/失败结果在外层 await 时直接抛给\n * 调用方,链本身只保证\"前一个跑完了\"。\n */\n private _applyPlanChain: Promise<void> = Promise.resolve();\n\n // ─────────── 装载 ───────────\n\n async load(params: KernelLoadParams, onProgress?: KernelProgress): Promise<void> {\n this.assertNotDisposed();\n const { source, docId } = params;\n\n onProgress?.('parse', 0);\n let pkg: Package;\n try {\n if (source.type === 'zip') {\n pkg = await pkgFromZip(source.bytes);\n this.initialBytes = source.bytes;\n } else {\n pkg = pkgFromFlatOpc(source.xml);\n this.initialFlatOpc = source.xml;\n }\n } catch (e) {\n const phase = source.type === 'zip' ? 'fromZip' : 'fromFlatOpc';\n throw wrapPackageError(e, docId, phase);\n }\n\n onProgress?.('normalize', 0);\n ensureParaIds(pkg);\n try {\n this.indices = buildIndices(pkg);\n } catch (e) {\n if (e instanceof BookmarkLoadError) {\n throw new WordError(e.code, e.message, docId, e.details);\n }\n throw wrapPackageError(e, docId, 'normalize');\n }\n onProgress?.('normalize', 100);\n\n this.pkg = pkg;\n this.docId = docId;\n this.domainCache.reset();\n }\n\n // ─────────── 输出 ───────────\n\n async toZip(): Promise<Uint8Array> {\n this.assertLoaded();\n try {\n return await pkgToZip(this.pkg!);\n } catch (e) {\n throw wrapPackageError(e, this.docId!, 'toZip');\n }\n }\n\n async toFlatOpc(): Promise<string> {\n this.assertLoaded();\n try {\n return pkgToFlatOpc(this.pkg!);\n } catch (e) {\n throw wrapPackageError(e, this.docId!, 'toFlatOpc');\n }\n }\n\n // ─────────── 只读查询(#24 起)───────────\n\n /**\n * 段落查询。纯同步,基于当前已装载的 pkg。\n *\n * 所有策略(scope / filter / textFormat / pagination)由入参决定,kernel **不**\n * 做\"智能默认\"——未传 pagination 时按 `DEFAULT_PAGINATION`(byCount(25,0))返回\n * 第一页;要全量请显式 `{ pagination: { mode: 'all' } }`(docs/03 §9.2)。\n *\n * 纯逻辑实现在 `list-paragraphs.ts`,本方法只做:装载态校验 + pkg 传入 + 错误\n * 包装(validation Error → WordError,附 docId)。\n */\n listParagraphs(opts?: ListParagraphsOptions): ListResult {\n this.assertLoaded();\n try {\n const cached = this.domainCache.paragraphs.getCacheableList(opts, () =>\n pureListParagraphs(this.pkg!, opts),\n );\n if (cached) return cached;\n return pureListParagraphs(this.pkg!, opts);\n } catch (e) {\n if (e instanceof WordError) throw e;\n const msg = e instanceof Error ? e.message : String(e);\n // listParagraphs 的抛错主要是 pagination 参数校验失败;归到 UNSUPPORTED_OOXML_FEATURE\n // 语义贴近\"调用方传了不合法的选项\",优于 PACKAGE_CORRUPT / PACKAGE_UNSUPPORTED_FORMAT\n throw new WordError('UNSUPPORTED_OOXML_FEATURE', msg, this.docId!);\n }\n }\n\n /**\n * 按 paraId 精确取段(#25)。走 paraIdx → O(1) 查找;不存在返回 null。\n * paraId 大小写不敏感(索引 key 是大写 8 hex)。\n */\n getParagraph(paraId: string): ParagraphInfo | null {\n this.assertLoaded();\n return this.domainCache.paragraphs.getParagraph(paraId, () =>\n getParagraphByParaId(this.pkg!, this.indices!, paraId),\n );\n }\n\n /**\n * 枚举书签(#25)。默认过滤 `_` 开头的隐藏书签(_Toc... / _GoBack / _Hlk...),\n * `opts.includeHidden=true` 可拿到全部。返回顺序遵循 bookmarkIdx 的迭代序 ——\n * JS Map 按插入序,装载期从上到下、逐 part 逐 `<w:bookmarkStart>` 收集。\n */\n listBookmarks(opts?: ListBookmarksOptions): BookmarkInfo[] {\n this.assertLoaded();\n return pureListBookmarks(this.pkg!, this.indices!, opts);\n }\n\n /**\n * 按 name 精确取书签(#25)。走 bookmarkIdx;不存在返回 null。\n * 不做 hidden 过滤 —— 调用方已知 name,通常就是来找隐藏书签的。\n */\n getBookmark(name: BookmarkName): BookmarkInfo | null {\n this.assertLoaded();\n return pureGetBookmark(this.pkg!, this.indices!, name);\n }\n\n /**\n * 枚举批注(#26)。走 commentIdx,按 Map 插入序(= 装载期 part 顺序 + w:id 升序)\n * 返回。主体缺失或无锚点的 entry 被跳过 —— 调用方看到的都是\"可用\"的批注。\n */\n listComments(): CommentInfo[] {\n this.assertLoaded();\n return pureListComments(this.indices!);\n }\n\n /**\n * 按 id 取批注(#26)。不存在或主体缺失返回 null 。\n */\n getComment(id: CommentId): CommentInfo | null {\n this.assertLoaded();\n return pureGetComment(this.indices!, id);\n }\n\n /**\n * 枚举修订(#26 + #33,Tier 1)。只覆盖 `<w:ins>` / `<w:del>` 标签级修订。\n *\n * **#33 加强**:扫到 `<w:rPrChange>` / `<w:pPrChange>` / `sectPrChange` /\n * `numberingChange` / `moveFrom` / `moveTo` 等 Tier 2 属性级修订 → 抛\n * `UNSUPPORTED_OOXML_FEATURE`(以前是默默忽略)。读写共用守护,与\n * `acceptRevisions` / `rejectRevisions` 行为一致。\n *\n * scope 与 `listParagraphs` 一致:默认 'body',可传 'all' 或 `StoryId[]`。\n */\n listRevisions(opts?: ListRevisionsOptions): RevisionInfo[] {\n this.assertLoaded();\n try {\n return pureListRevisions(this.pkg!, opts);\n } catch (e) {\n // 纯函数 assertNoTier2Revisions 抛错时 docId 占位 '';kernel 层注入真实 docId\n if (e instanceof WordError && e.docId === '') {\n throw new WordError(e.code, e.message, this.docId!, e.details);\n }\n throw e;\n }\n }\n\n getRevision(revId: string, opts?: ListRevisionsOptions): RevisionInfo | null {\n return this.listRevisions(opts).find((revision) => revision.revId === revId) ?? null;\n }\n\n searchContext(opts: ContextSearchOptions): ContextSearchResult {\n this.assertLoaded();\n return pureSearchContext(this.pkg!, this.indices!, opts);\n }\n\n // ─────────── 样式查询(#181)───────────\n\n /** 列出 styles.xml 中的样式,可按 type 过滤。styles.xml 不存在时返回空数组。 */\n listStyles(opts?: ListStylesOptions): StyleInfo[] {\n this.assertLoaded();\n return pureListStyles(this.indices!.stylesIdx, opts);\n }\n\n /** 按 styleId 精确查找,O(1)。不存在返回 null。 */\n getStyle(styleId: string): StyleInfo | null {\n this.assertLoaded();\n return pureGetStyleById(this.indices!.stylesIdx, styleId);\n }\n\n // ─────────── 表格查询(#185)───────────\n\n /** 枚举表格,默认只返回主文档 body 的顶层表格。*/\n listTables(opts?: ListTablesOptions): TableInfo[] {\n this.assertLoaded();\n const cached = this.domainCache.tables.getCacheableList(opts, () =>\n pureListTables(this.pkg!, this.indices!, opts),\n );\n if (cached) return cached;\n return pureListTables(this.pkg!, this.indices!, opts);\n }\n\n /** 按 tableId 精确取单个表格,O(1)。不存在返回 null。 */\n getTable(tableId: string): TableInfo | null {\n this.assertLoaded();\n return this.domainCache.tables.getTable(tableId, () =>\n pureGetTableById(this.pkg!, this.indices!, tableId),\n );\n }\n\n /**\n * 按 tableId verbatim 取一张表的 OOXML 子树 + 格内图字节\n * (task-20260616-table-content-driven,供跨文档搬表 insertTableFrom)。\n * 不存在返回 null。\n */\n getTableVerbatim(tableId: string): TableVerbatim | null {\n this.assertLoaded();\n return pureGetTableVerbatim(this.pkg!, this.indices!, tableId);\n }\n\n // ─────────── Drawing 枚举(#189)───────────\n\n /** 枚举 drawing 对象,默认只返回主文档 body 内的 drawing。*/\n listDrawings(opts?: ListDrawingsOptions): DrawingInfo[] {\n this.assertLoaded();\n return pureListDrawings(this.pkg!, this.indices!, opts);\n }\n\n /** 按 drawingId 精确取单个 drawing,O(1)。不存在返回 null。 */\n getDrawing(drawingId: string): DrawingInfo | null {\n this.assertLoaded();\n return pureGetDrawingById(this.pkg!, this.indices!, drawingId);\n }\n\n /**\n * 读取 drawingId 对应 picture 的原始图片字节(task-insert-image)。\n * drawingId 不存在 / 非 picture / media 找不到 → 返回 null(不抛)。\n */\n getImageBytes(drawingId: string): ImageBytesResult | null {\n this.assertLoaded();\n return getImageBytesSync(this.pkg!, this.indices!, drawingId);\n }\n\n /** 枚举主 body 的所有节(#211)。doc-order 排序。*/\n listSections(): SectionInfo[] {\n this.assertLoaded();\n return pureListSections(this.pkg!);\n }\n\n /** 枚举主 body 的所有 TOC 域(#197)。doc-order 排序。*/\n listTocFields(): TocFieldRange[] {\n this.assertLoaded();\n return pureListTocFields(this.pkg!);\n }\n\n // ─────────── 变更入口:Plan apply(#27)───────────\n\n /**\n * 执行 WordPlan 提交的 op 队列(docs/03.1 §3.2)。\n *\n * **#27 作用域**:本方法只承担 **Plan 容器 + ApplyResult 结构 + 错误状态机**。\n * 真正的 op executor 由后续 PR 分别落地(见 `plan.ts` 顶部注释)。因此本版本:\n * - ops 为空 → 返回 `EMPTY_APPLY_RESULT`(WordPlanImpl 侧通常已拦,这里兜底)\n * - ops 非空 → 抛 `UNSUPPORTED_OOXML_FEATURE`,message 指向待落地的 issue\n *\n * 注意:事务原子性(#16 runTransaction)+ 索引同步 + trackChanges 包装,都在首个\n * executor(#28)落地时接入。本 PR 不引入 executor registry,避免为空抽象付代价;\n * #28 直接在这里改成 switch(op.type) 即可。\n */\n /**\n * 执行 Plan op 队列(docs/03.1 §3.2)。\n *\n * 流程:\n * 1. 预扫 affected parts(每个 op 触达的 part path)\n * 2. `runTransaction` 包裹 dispatch 循环 —— 任一 op throw → 全回滚\n * 3. 成功后重建三索引(paraIdx / bookmarkIdx / commentIdx)—— executor 可能\n * 增删元素,最简单的保真方式是 buildIndices 一次性重跑\n *\n * 返回 Promise 因 runTransaction 是 async;#27 的 sync 签名承诺在 RPC 层\n * (handler `await` + `transport.call` 自带 await)对调用方完全透明。\n */\n async applyPlan(\n params: ApplyPlanParams,\n opts: { source?: 'plan' | 'script' } = {},\n ): Promise<ApplyResult> {\n this.assertLoaded();\n if (params.ops.length === 0) return cloneApplyResult(EMPTY_APPLY_RESULT);\n\n // 进入互斥队列:等前一个 applyPlan 跑完(链上 promise 永不 reject),拿到\n // 自己的 release;真正的 inner 在 await prev 之后才跑。\n const prev = this._applyPlanChain;\n let release!: () => void;\n this._applyPlanChain = new Promise<void>((resolve) => {\n release = resolve;\n });\n await prev;\n try {\n return await this._applyPlanInner(params, opts);\n } finally {\n release();\n }\n }\n\n async validatePlan(params: ApplyPlanParams) {\n this.assertLoaded();\n await this._applyPlanChain;\n return validatePlanOps(params, this.indices!);\n }\n\n private async _applyPlanInner(\n params: ApplyPlanParams,\n opts: { source?: 'plan' | 'script' } = {},\n ): Promise<ApplyResult> {\n const options: ExecutorContext['options'] = {\n trackChanges: params.options.trackChanges ?? false,\n author: params.options.author ?? '',\n date: params.options.date ? new Date(params.options.date) : new Date(),\n };\n const kernelStartedAt = Date.now();\n const collectAffectedPartsStartedAt = Date.now();\n const collectAffected = collectAffectedPartPaths(this, params.ops);\n const affectedPaths = collectAffected.paths;\n const collectAffectedPartsMs = Date.now() - collectAffectedPartsStartedAt;\n const result = cloneApplyResult(EMPTY_APPLY_RESULT);\n const ctx: ExecutorContext = {\n pkg: this.pkg!,\n indices: this.indices!,\n options,\n result,\n opIndex: 0,\n docId: this.docId!,\n orphanMediaCandidates: new Set<string>(),\n };\n const elapsed = (ms: number): string => `${Math.round(ms / 100) / 10}s`;\n const opStats = new Map<string, { count: number; ms: number }>();\n const applyStartedAt = Date.now();\n let txElapsedMs = 0;\n let indicesElapsedMs = 0;\n\n let txCommitted = false;\n try {\n const txStartedAt = Date.now();\n await runTransaction(this.pkg!, affectedPaths, () => {\n for (let i = 0; i < params.ops.length; i++) {\n ctx.opIndex = i;\n const op = params.ops[i]!;\n const opStartedAt = Date.now();\n dispatchOp(op, ctx);\n const stat = opStats.get(op.type) ?? { count: 0, ms: 0 };\n stat.count++;\n stat.ms += Date.now() - opStartedAt;\n opStats.set(op.type, stat);\n }\n });\n txElapsedMs = Date.now() - txStartedAt;\n txCommitted = true;\n } finally {\n // #190 孤儿 media 清理:仅在事务真正 commit 后才删 binary part。\n //\n // 设计动机:\n // - 事务内删 binary part 可借助 transactions.ts 的 createBinaryPart 回滚路径\n // 恢复,但要求 collectAffectedPartPaths 提前 lookup 全部 drawing 的 a:blip\n // reb 解析媒体路径,代价高且与 #190 的\"延迟决策\"语义不符。\n // - 事务外删则简单:rels 已 commit,真正归零(全包 rels 都不再引用 media path)\n // 才删 binary;若事务回滚,rels 同步回到 pre-state,本步骤 short-circuit 不动。\n // - 即便此清理本身抛错,主流程 result 已生效,降级为 warn。\n if (txCommitted && ctx.orphanMediaCandidates && ctx.orphanMediaCandidates.size > 0) {\n try {\n sweepOrphanMediaParts(this.pkg!, ctx.orphanMediaCandidates);\n } catch (e) {\n console.warn(\n `[kernel.applyPlan] orphan media sweep failed: ${e instanceof Error ? e.message : String(e)}`,\n );\n }\n }\n\n // 无论成功还是回滚,都重建三索引:\n // - 成功:executor 可能增删元素,paraIdx / bookmarkIdx / commentIdx 条目\n // 的 Element 引用需同步\n // - 回滚:runTransaction 用 deep-clone 快照恢复 xmlDom,原有索引条目指向\n // **pre-clone 的 Element**(已游离),必须重建\n // 索引重建本身抛错(e.g. 回滚后重名书签 —— 不该发生但保险)时,原外层错误\n // 更重要:重建错误吞掉,走 warn(参照 snapshot-api reinitializeAfterReload)\n const indicesStartedAt = Date.now();\n try {\n this.indices = buildIndices(this.pkg!);\n } catch (e) {\n if (e instanceof BookmarkLoadError) {\n console.warn(\n `[kernel.applyPlan] indices rebuild after apply failed: ${e.code} ${e.message}`,\n );\n } else {\n console.warn(`[kernel.applyPlan] indices rebuild after apply failed: ${String(e)}`);\n }\n }\n indicesElapsedMs = Date.now() - indicesStartedAt;\n const opSummary = Array.from(opStats.entries())\n .map(([type, stat]) => `${type} x${stat.count} ${elapsed(stat.ms)}`)\n .join(', ');\n result.debugTiming = {\n ops: params.ops.length,\n affectedParts: affectedPaths.length,\n collectAffectedPartsMs,\n collectStoriesMs: collectAffected.timing.storiesMs,\n collectStoryLookups: collectAffected.timing.storyLookups,\n collectStoryLookupMs: collectAffected.timing.storyLookupMs,\n collectByType: collectAffected.timing.byType,\n transactionMs: txElapsedMs,\n indicesMs: indicesElapsedMs,\n totalMs: Date.now() - applyStartedAt,\n kernelMs: Date.now() - kernelStartedAt,\n byType: Array.from(opStats.entries()).map(([type, stat]) => ({\n type: type as Op['type'],\n count: stat.count,\n ms: stat.ms,\n })),\n };\n const collectSummary = collectAffected.timing.byType\n .map(\n (entry) =>\n `${entry.type} x${entry.count} ${elapsed(entry.ms)} story=${entry.storyLookups}/${elapsed(entry.storyLookupMs)}`,\n )\n .join(', ');\n console.info(\n `[kernel.applyPlan:timing] ops=${params.ops.length}, affectedParts=${affectedPaths.length}, collectAffectedParts=${elapsed(collectAffectedPartsMs)}, collectStories=${elapsed(collectAffected.timing.storiesMs)}, storyLookups=${collectAffected.timing.storyLookups}/${elapsed(collectAffected.timing.storyLookupMs)}, tx=${elapsed(txElapsedMs)}, indices=${elapsed(indicesElapsedMs)}, total=${elapsed(Date.now() - applyStartedAt)}, kernel=${elapsed(Date.now() - kernelStartedAt)}${opSummary ? `, ${opSummary}` : ''}${collectSummary ? `, collectByType: ${collectSummary}` : ''}`,\n );\n }\n\n // applyPlan 走到这里 = transaction 已 commit;事件在索引重建之后派发,确保\n // 订阅者拿到的 kernel 状态与 result 一致。kernel 自己不知道调用来源,源由\n // opts.source 显式标注:RPC handler 传 'plan',script-execute 经包装后传 'script'。\n this.domainCache.afterSuccessfulApply(params.ops);\n this.emitChange({\n ops: params.ops,\n result,\n source: opts.source ?? 'script',\n });\n\n return result;\n }\n\n // ─────────── change 事件订阅(`WordDocument.on('change', ...)` 走 transport 接此处)───────────\n\n /**\n * 订阅 applyPlan 成功事件。返回取消订阅函数。\n *\n * 监听器同步触发(在 applyPlan 内部 fan-out),抛错被吞掉(不影响其它订阅者\n * 与 applyPlan 返回)。要做 async 工作请在监听器内自行 catch 并 fire-and-forget。\n */\n onChange(listener: (ev: KernelChangeEvent) => void): () => void {\n this.changeListeners.add(listener);\n return () => {\n this.changeListeners.delete(listener);\n };\n }\n\n private emitChange(ev: KernelChangeEvent): void {\n for (const listener of this.changeListeners) {\n try {\n listener(ev);\n } catch {\n // 防御性:监听器异常不影响 applyPlan 的返回路径\n }\n }\n }\n\n // ─────────── 快照原语(供 SnapshotApi 使用,#21)───────────\n\n /**\n * 序列化当前 pkg 为 snapshot 用的 parts 数组。\n * 优化:\n * - dirty=false 且有 _originalBytes → 直接复用原始字节(零 serialize,Uint8Array 引用共享)\n * - dirty=true 的 XML part → slimdom serialize\n * - 二进制 part → 用 bytes / _originalBytes\n */\n serializeParts(): SnapshotPartEntry[] {\n this.assertLoaded();\n const out: SnapshotPartEntry[] = [];\n for (const part of listParts(this.pkg!)) {\n out.push({\n path: part.path,\n contentType: part.contentType,\n bytes: partToBytes(part),\n });\n }\n return out;\n }\n\n /**\n * 从 snapshot 的 parts 数组重建 pkg + 三索引。\n *\n * 覆盖原 pkg:调用方应在 rollback 前确保 dispose/ 清理 transient 状态(如 changelog)。\n * 重建后 ensureParaIds + buildIndices 再跑一次,保证索引准确(docs/03.2 §10)。\n *\n * onProgress 分阶段上报(docs/03.2 §6):\n * - `'parse'` 每个 part 被 parse 完成时,pct 0→100\n * - `'build-indices'` buildIndices 开始前,pct 0\n * - `'done'` 全部完成,pct 100\n */\n rebuildFromParts(parts: readonly SnapshotPartEntry[], onProgress?: KernelProgress): void {\n this.assertNotDisposed();\n const pkg = createPackage();\n const total = parts.length;\n let processed = 0;\n // 即便 parts 为空,也先触发一次 parse 0%,方便调用方感知开始\n onProgress?.('parse', 0);\n for (const entry of parts) {\n if (isXmlContentType(entry.contentType)) {\n const text = new TextDecoder().decode(entry.bytes);\n const dom = parseXmlDocument(text) as unknown as Document;\n setPart(\n pkg,\n createXmlPart({\n path: entry.path,\n contentType: entry.contentType,\n xmlDom: dom,\n originalBytes: entry.bytes,\n }),\n );\n } else {\n setPart(\n pkg,\n createBinaryPart({\n path: entry.path,\n contentType: entry.contentType,\n bytes: entry.bytes,\n }),\n );\n }\n processed++;\n const pct = total > 0 ? Math.round((processed / total) * 100) : 100;\n onProgress?.('parse', pct);\n }\n\n // 与 load 相同的 normalize 流程\n ensureParaIds(pkg);\n onProgress?.('build-indices', 0);\n try {\n this.indices = buildIndices(pkg);\n } catch (e) {\n if (e instanceof BookmarkLoadError) {\n throw new WordError(e.code, e.message, this.docId ?? '', e.details);\n }\n throw e;\n }\n this.pkg = pkg;\n this.domainCache.reset();\n onProgress?.('done', 100);\n }\n\n // ─────────── 释放 ───────────\n\n dispose(): void {\n this.disposed = true;\n // 丢引用,便于 GC(slimdom Document 比较占内存)\n this.pkg = undefined;\n this.indices = undefined;\n this.initialBytes = undefined;\n this.initialFlatOpc = undefined;\n this.domainCache.reset();\n }\n\n // ─────────── 内部访问 ───────────\n\n /** @internal */\n getDocId(): string | undefined {\n return this.docId;\n }\n\n /** @internal */\n getPackage(): Package | undefined {\n return this.pkg;\n }\n\n /** @internal */\n getIndices(): PackageIndices | undefined {\n return this.indices;\n }\n\n /** @internal */\n getInitialBytes(): Uint8Array | undefined {\n return this.initialBytes;\n }\n\n /** @internal */\n getInitialFlatOpc(): string | undefined {\n return this.initialFlatOpc;\n }\n\n /** @internal */\n isDisposed(): boolean {\n return this.disposed;\n }\n\n /** @internal */\n debugCacheSnapshot(): WordDomainCacheSnapshot {\n return this.domainCache.snapshot();\n }\n\n /** @internal */\n debugInvalidateCache(domain: DomainCacheName = 'all', reason = 'debug'): void {\n this.domainCache.invalidate(domain, reason);\n }\n\n private assertLoaded(): void {\n this.assertNotDisposed();\n if (!this.pkg || !this.docId) {\n throw new WordError('PACKAGE_UNSUPPORTED_FORMAT', 'Kernel not loaded', this.docId ?? '');\n }\n }\n\n private assertNotDisposed(): void {\n if (this.disposed) {\n throw new WordError(\n 'PACKAGE_UNSUPPORTED_FORMAT',\n 'Kernel has been disposed',\n this.docId ?? '',\n );\n }\n }\n}\n\n/**\n * 预扫 ops,收集事务要监护的所有 part paths(每个 op 读 + 写可能触达的 part)。\n *\n * #28 executor 只改 paraId 所在 part;future executors(#29 / #34 / #35)会扩展\n * 此函数的分支(e.g. addComment 触达 body part + comments.xml + Content_Types.xml)。\n */\nfunction collectAffectedPartPaths(\n kernel: Kernel,\n ops: readonly Op[],\n): CollectAffectedPartPathsResult {\n const paths = new Set<string>();\n const indices = kernel.getIndices();\n const pkg = kernel.getPackage();\n const emptyTiming: CollectAffectedPartPathTiming = {\n storiesMs: 0,\n storyLookups: 0,\n storyLookupMs: 0,\n byType: [],\n };\n if (!indices || !pkg) return { paths: [], timing: emptyTiming };\n\n const storiesStartedAt = Date.now();\n const stories = listStories(pkg);\n const timing: CollectAffectedPartPathTiming = {\n storiesMs: Date.now() - storiesStartedAt,\n storyLookups: 0,\n storyLookupMs: 0,\n byType: [],\n };\n const byType = new Map<\n Op['type'],\n { type: Op['type']; count: number; ms: number; storyLookups: number; storyLookupMs: number }\n >();\n let currentStat: {\n type: Op['type'];\n count: number;\n ms: number;\n storyLookups: number;\n storyLookupMs: number;\n } | null = null;\n const findStoryPartPathFor = (el: Element): string | null => {\n const startedAt = Date.now();\n let found: Story | null = null;\n for (const story of stories) {\n if (story.root.contains(el as unknown as Node)) {\n found = story;\n break;\n }\n }\n const ms = Date.now() - startedAt;\n timing.storyLookups++;\n timing.storyLookupMs += ms;\n if (currentStat) {\n currentStat.storyLookups++;\n currentStat.storyLookupMs += ms;\n }\n return found?.partPath ?? null;\n };\n // R1 multi-image fix: track maxN across all insertImageAfter ops in this plan\n // so each op's projected media path is distinct (mirrors allocateMediaPath's incremental behavior).\n // Initialized lazily inside the case 'insertImageAfter' branch on first encounter.\n let insertImageMaxN: number | null = null;\n for (const op of ops) {\n const stat = byType.get(op.type) ?? {\n type: op.type,\n count: 0,\n ms: 0,\n storyLookups: 0,\n storyLookupMs: 0,\n };\n stat.count++;\n byType.set(op.type, stat);\n currentStat = stat;\n const opStartedAt = Date.now();\n try {\n switch (op.type) {\n case 'replaceParagraph':\n case 'replaceTextInParagraph':\n case 'formatTextInParagraph':\n case 'formatParagraph':\n case 'insertParagraphBefore':\n case 'insertParagraphAfter': {\n const paraId =\n op.type === 'insertParagraphBefore' || op.type === 'insertParagraphAfter'\n ? op.anchorParaId\n : op.paraId;\n const p = indices.paraIdx.get(paraId.toUpperCase());\n if (p) {\n const partPath = findStoryPartPathFor(p);\n if (partPath) paths.add(partPath);\n }\n break;\n }\n case 'insertParagraphAtBodyStart': {\n // 无锚点 op:直接纳入 body part(<w:document>/<w:body> 所在 part)。\n const [bodyStory] = listStories(pkg, { kinds: ['body'] });\n if (bodyStory) paths.add(bodyStory.partPath);\n break;\n }\n case 'deleteParagraph': {\n const p = indices.paraIdx.get(op.paraId.toUpperCase());\n if (p) {\n const partPath = findStoryPartPathFor(p);\n if (partPath) paths.add(partPath);\n }\n // drop 模式可能删 comments.xml 里的 <w:comment> 主体,并在删光时\n // cleanup CT/rels —— 保守地无条件纳入事务范围,保证原子回滚。\n if (op.onAnchorConflict === 'drop') {\n paths.add('word/comments.xml');\n paths.add('[Content_Types].xml');\n paths.add('word/_rels/document.xml.rels');\n }\n break;\n }\n // #34 书签:createBookmark 在 paraId 所在 part 插元素;\n // deleteBookmark 在 entry.partPath 所在 part 删元素\n case 'createBookmark': {\n const p = indices.paraIdx.get(op.range.paraId.toUpperCase());\n if (p) {\n const partPath = findStoryPartPathFor(p);\n if (partPath) paths.add(partPath);\n }\n break;\n }\n case 'deleteBookmark': {\n const entry = indices.bookmarkIdx.get(op.name);\n if (entry) paths.add(entry.partPath);\n break;\n }\n // #35 addComment:body part + comments.xml + Content_Types + rels(首次时可能改后两者)\n case 'addComment': {\n const p = indices.paraIdx.get(op.range.paraId.toUpperCase());\n if (p) {\n const partPath = findStoryPartPathFor(p);\n if (partPath) paths.add(partPath);\n }\n // comments.xml 无论是否存在,都纳入监护范围(首次创建时需要被回滚)\n paths.add('word/comments.xml');\n paths.add('[Content_Types].xml');\n paths.add('word/_rels/document.xml.rels');\n break;\n }\n // #35 deleteComment:锚点所在 body part + comments.xml + CT + rels\n // cleanup 可能在删光最后一条时修改 CT/rels,必须纳入事务范围保证原子回滚\n case 'deleteComment': {\n const entry = indices.commentIdx.get(op.commentId);\n if (entry) {\n const anchorEl = entry.anchors.start ?? entry.anchors.end ?? entry.anchors.ref;\n if (anchorEl) {\n const partPath = findStoryPartPathFor(anchorEl);\n if (partPath) paths.add(partPath);\n }\n }\n paths.add('word/comments.xml');\n paths.add('[Content_Types].xml');\n paths.add('word/_rels/document.xml.rels');\n break;\n }\n // #186 addTableComment:走 commentsPart + body part(+ 首次创建 comments.xml 时 CT/rels)\n case 'addTableComment': {\n const tbl = indices.tblIdx.get(op.tableId);\n if (tbl) {\n const partPath = findStoryPartPathFor(tbl);\n if (partPath) paths.add(partPath);\n }\n paths.add('word/comments.xml');\n paths.add('[Content_Types].xml');\n paths.add('word/_rels/document.xml.rels');\n break;\n }\n // #186 deleteTable:表格所在 part + drop 模式可能动 comments.xml/CT/rels\n case 'deleteTable': {\n const tbl = indices.tblIdx.get(op.tableId);\n if (tbl) {\n const partPath = findStoryPartPathFor(tbl);\n if (partPath) paths.add(partPath);\n }\n if (op.onAnchorConflict === 'drop') {\n paths.add('word/comments.xml');\n paths.add('[Content_Types].xml');\n paths.add('word/_rels/document.xml.rels');\n }\n break;\n }\n // #188 deleteTableRow:行所在 part + drop 模式可能动 comments.xml/CT/rels\n case 'deleteTableRow': {\n const tbl = indices.tblIdx.get(op.tableId);\n if (tbl) {\n const partPath = findStoryPartPathFor(tbl);\n if (partPath) paths.add(partPath);\n }\n if (op.onAnchorConflict === 'drop') {\n paths.add('word/comments.xml');\n paths.add('[Content_Types].xml');\n paths.add('word/_rels/document.xml.rels');\n }\n break;\n }\n // #190 drawing 替换 / 删除 + #210 shape 内文字替换\n // - drawing 所在 part(从 drawingIdx + findStoryFor 解析)\n // - 该 part 的 .rels 同伴(改 / 删 image relationship / hyperlink relationship)\n // - word/media/placeholder.png(replace 时首次注入)\n // - [Content_Types].xml(首次需要登记 image/png Default 扩展)\n // - 旧 media binary part 的清理在 post-transaction 阶段(transactions.ts 不支持\n // 回滚 pre-existing part 的删除;orphan 清理放在 commit 后)\n case 'formatTableCell': {\n const tbl = indices.tblIdx.get(op.tableId);\n if (tbl) {\n const partPath = findStoryPartPathFor(tbl);\n if (partPath) paths.add(partPath);\n }\n break;\n }\n case 'insertTableCellParagraph': {\n const tbl = indices.tblIdx.get(op.tableId);\n if (tbl) {\n const partPath = findStoryPartPathFor(tbl);\n if (partPath) paths.add(partPath);\n }\n break;\n }\n case 'replaceDrawingWithPlaceholder':\n case 'deleteDrawing':\n case 'replaceShapeInnerText': {\n const dr = indices.drawingIdx.get(op.drawingId);\n if (dr) {\n const partPath = findStoryPartPathFor(dr);\n if (partPath) {\n paths.add(partPath);\n paths.add(relsPathFor(partPath));\n }\n }\n if (op.type === 'replaceDrawingWithPlaceholder') {\n paths.add('word/media/placeholder.png');\n paths.add('[Content_Types].xml');\n }\n break;\n }\n // task-insert-image:insertImageAfter\n // - anchor 所在 part(通常 word/document.xml)\n // - 该 part 的 .rels(新增 image rel)\n // - [Content_Types].xml(登记 ext Default)\n // - 动态新建的 word/media/imageN.ext(R1:必须列出才能回滚删除新 part)\n //\n // 注意:多个 insertImageAfter ops 在 apply 前一次性计算 affected paths;\n // 必须模拟 executor 的逐 op 累加(而非每次都扫初始 pkg),否则多张图同 ext\n // 时会算出相同的 imageN+1,漏列 image2+ 导致回滚不完整。\n // 用 insertImagePlannedPaths(在 collectAffectedPartPaths 调用方维护的闭包变量)\n // 按 ext 分别跟踪\"本 plan 已规划的序号 offset\"。\n case 'insertImageAfter': {\n const anchorEl = indices.paraIdx.get(op.anchorParaId.toUpperCase());\n if (anchorEl) {\n const partPath = findStoryPartPathFor(anchorEl);\n if (partPath) {\n paths.add(partPath);\n paths.add(relsPathFor(partPath));\n }\n }\n paths.add('[Content_Types].xml');\n {\n const ext = contentTypeToExt(op.contentType);\n if (ext) {\n // 初始 pkg 里最大 N(跨所有 ext 共享,与 allocateMediaPath 对齐)\n if (!insertImageMaxN) {\n insertImageMaxN = 0;\n for (const part of listParts(pkg)) {\n const m = /^word\\/media\\/image(\\d+)\\./i.exec(part.path);\n if (m) {\n const n = parseInt(m[1]!, 10);\n if (n > insertImageMaxN) insertImageMaxN = n;\n }\n }\n }\n // 每规划一张图,序号 +1(模拟 executor allocateMediaPath 的 maxN++ 效果)\n insertImageMaxN++;\n // hasPart 防撞:若 image{maxN}.ext 已在初始 pkg 中存在,继续 +1\n while (pkg.parts.has(`word/media/image${insertImageMaxN}.${ext}`)) {\n insertImageMaxN++;\n }\n paths.add(`word/media/image${insertImageMaxN}.${ext}`);\n }\n }\n break;\n }\n // #32 acceptRevisions / rejectRevisions\n case 'acceptRevisions':\n case 'rejectRevisions': {\n if (op.scope.scope === 'paragraph') {\n const p = indices.paraIdx.get(op.scope.paraId.toUpperCase());\n if (p) {\n const partPath = findStoryPartPathFor(p);\n if (partPath) paths.add(partPath);\n }\n } else {\n // all / revision:保守把所有 XML Word 内容 part 都纳入(包括 comments.xml\n // —— 因为批注 part 里可能也有 ins/del)。未用到的 parts 入事务无害。\n for (const part of listParts(pkg)) {\n if (isXmlPart(part) && part.xmlDom) {\n const ct = part.contentType;\n if (\n ct.includes('wordprocessingml') ||\n ct.endsWith('.main+xml') ||\n ct.endsWith('.header+xml') ||\n ct.endsWith('.footer+xml') ||\n ct.endsWith('.footnotes+xml') ||\n ct.endsWith('.endnotes+xml') ||\n ct.endsWith('.comments+xml')\n ) {\n paths.add(part.path);\n }\n }\n }\n }\n break;\n }\n default:\n break;\n }\n } finally {\n stat.ms += Date.now() - opStartedAt;\n currentStat = null;\n }\n }\n timing.byType = Array.from(byType.values());\n return { paths: [...paths], timing };\n}\n\n/**\n * 计算某 part 的 .rels 同伴路径。\n *\n * 规则:`<dir>/<name>.<ext>` → `<dir>/_rels/<name>.<ext>.rels`\n * - 'word/document.xml' → 'word/_rels/document.xml.rels'\n * - 'word/header1.xml' → 'word/_rels/header1.xml.rels'\n * - 'word/footer1.xml' → 'word/_rels/footer1.xml.rels'\n *\n * 顶层 part('xxx.xml' 无目录前缀)走 '_rels/xxx.xml.rels'(与 _rels/.rels 同位)。\n */\nfunction relsPathFor(partPath: string): string {\n const idx = partPath.lastIndexOf('/');\n if (idx < 0) return `_rels/${partPath}.rels`;\n const dir = partPath.slice(0, idx);\n const name = partPath.slice(idx + 1);\n return `${dir}/_rels/${name}.rels`;\n}\n\n/** contentType → ext(与 insert-image-ops.ts 同步;用于 collectAffectedPartPaths R1)*/\nfunction contentTypeToExt(ct: string): string | null {\n const map: Record<string, string> = {\n 'image/png': 'png',\n 'image/jpeg': 'jpeg',\n 'image/gif': 'gif',\n 'image/bmp': 'bmp',\n 'image/tiff': 'tiff',\n };\n return map[ct] ?? null;\n}\n\n/** 浅拷贝 ApplyResult(避免把冻结引用交出去被调用方误写)*/\nfunction cloneApplyResult(r: ApplyResult): ApplyResult {\n return {\n insertedParagraphs: r.insertedParagraphs.slice(),\n insertedBodyStartParaIds: r.insertedBodyStartParaIds.slice(),\n createdComments: r.createdComments.slice(),\n createdBookmarks: r.createdBookmarks.slice(),\n acceptedRevisions: r.acceptedRevisions,\n rejectedRevisions: r.rejectedRevisions,\n replacedTableCells: r.replacedTableCells,\n ...(r.debugTiming !== undefined ? { debugTiming: r.debugTiming } : {}),\n };\n}\n\nfunction wrapPackageError(err: unknown, docId: string, phase: string): WordError {\n if (err instanceof WordError) return err;\n const msg = err instanceof Error ? err.message : String(err);\n return new WordError('PACKAGE_CORRUPT', `${phase} failed: ${msg}`, docId, { phase });\n}\n\n/** Kernel.serializeParts / rebuildFromParts 的 entry 形态(与 SnapshotPayload.parts 一致) */\nexport interface SnapshotPartEntry {\n path: string;\n contentType: string;\n bytes: Uint8Array;\n}\n\nfunction isXmlContentType(ct: string): boolean {\n return ct.endsWith('+xml') || ct === 'application/xml' || ct === 'text/xml';\n}\n\nfunction partToBytes(part: Part): Uint8Array {\n // dirty=false + 原始字节:零 serialize\n if (!part._dirty && part._originalBytes) {\n return part._originalBytes;\n }\n if (isXmlPart(part)) {\n if (!part.xmlDom) {\n throw new Error(`partToBytes: XML part '${part.path}' missing xmlDom`);\n }\n const text = serializeToWellFormedString(part.xmlDom as never);\n return new TextEncoder().encode(text);\n }\n // 二进制\n if (part.bytes) return part.bytes;\n if (part._originalBytes) return part._originalBytes;\n throw new Error(`partToBytes: binary part '${part.path}' has no bytes`);\n}\n","/**\n * OOXML 常用命名空间 URI 常量。\n *\n * 所有 XPath / DOM 查询必须按 URI 比较(不依赖前缀)—— serializer 可能改前缀,URI 不变。\n * 来源:docs/01 附录 A。\n */\n\n/** Word 正文命名空间 */\nexport const W_NS = 'http://schemas.openxmlformats.org/wordprocessingml/2006/main';\n\n/** 关系(.rels 文件 / r:id 引用) */\nexport const R_NS = 'http://schemas.openxmlformats.org/officeDocument/2006/relationships';\n\n/** DrawingML(Word / Excel / PPT 共用) */\nexport const A_NS = 'http://schemas.openxmlformats.org/drawingml/2006/main';\n\n/** DrawingML wordprocessing 容器(wp:inline / wp:anchor / wp:extent / wp:wrap*) */\nexport const WP_NS = 'http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing';\n\n/** DrawingML picture(pic:pic) */\nexport const PIC_NS = 'http://schemas.openxmlformats.org/drawingml/2006/picture';\n\n/** DrawingML chart(c:chart 引用) */\nexport const CHART_NS = 'http://schemas.openxmlformats.org/drawingml/2006/chart';\n\n/** DrawingML diagram(SmartArt;dgm:relIds) */\nexport const DGM_NS = 'http://schemas.openxmlformats.org/drawingml/2006/diagram';\n\n/** Word 2010+ wordprocessing shape(wps:wsp / wps:txbx) */\nexport const WPS_NS = 'http://schemas.microsoft.com/office/word/2010/wordprocessingShape';\n\n/** Word 2010+ wordprocessing group(wpg:wgp) */\nexport const WPG_NS = 'http://schemas.microsoft.com/office/word/2010/wordprocessingGroup';\n\n/** Word 2010+ wordprocessing canvas(wpc:wpc) */\nexport const WPC_NS = 'http://schemas.microsoft.com/office/word/2010/wordprocessingCanvas';\n\n/** Markup Compatibility(Choice / Fallback) */\nexport const MC_NS = 'http://schemas.openxmlformats.org/markup-compatibility/2006';\n\n/** VML(旧版形状降级;v:line / v:rect / v:shape,多见于 mc:Fallback) */\nexport const VML_NS = 'urn:schemas-microsoft-com:vml';\n\n/** Word 2010+ 扩展(w14:paraId / w14:textId) */\nexport const W14_NS = 'http://schemas.microsoft.com/office/word/2010/wordml';\n\n/** Flat OPC 包格式 */\nexport const PKG_NS = 'http://schemas.microsoft.com/office/2006/xmlPackage';\n\n/** xml:space 等 xml 标准命名空间 */\nexport const XML_NS = 'http://www.w3.org/XML/1998/namespace';\n\n/** OMML 数学公式命名空间(Word「插入→公式」生成的 m:oMath / m:oMathPara) */\nexport const MATH_NS = 'http://schemas.openxmlformats.org/officeDocument/2006/math';\n","/**\n * rangeKind 判定共享逻辑(#25 bookmark + #26 comment)。\n *\n * BookmarkInfo / CommentInfo 都有同款 `rangeKind`(paragraph / text / complex)语义,\n * 判定依赖一对 \"start / end\" marker 元素在 DOM 中的相对位置。本模块把这个判定 +\n * 区间文本收集抽出来,两端共享。\n *\n * 判定规则(docs/03.1 §1.5):\n * 1. end 为 null → 'complex'(缺失 end)\n * 2. start.parent ≠ end.parent → 'complex'(跨节点)\n * 3. parent 不是 `<w:p>` → 'complex'(e.g. `<w:tc>` / `<w:body>` 直挂)\n * 4. 同一 `<w:p>` 内:\n * - start 之前 / end 之后**没有**内容节点 → 'paragraph'\n * - 否则 → 'text'(text 字段 = start/end 间所有 `<w:t>` 拼接)\n *\n * \"内容节点\" = W_NS 下非 marker 元素(marker 集:pPr / rPr / bookmarkStart /\n * bookmarkEnd / commentRangeStart / commentRangeEnd / commentReference / proofErr /\n * permStart / permEnd)+ 任意非 W_NS 元素(保守视为内容,避免未知扩展误判成\n * paragraph 覆盖)。\n */\nimport { W14_NS, W_NS } from './namespaces.js';\n\nexport interface RangeClassification {\n kind: 'paragraph' | 'text' | 'complex';\n /** 'paragraph' / 'text' 命中时,containing `<w:p>` 的 paraId(大写 8 hex) */\n paraId?: string;\n /** 'text' 命中时,start/end 之间所有 `<w:t>` 的纯文本拼接 */\n text?: string;\n}\n\nexport function classifyRange(start: Element | null, end: Element | null): RangeClassification {\n if (!start || !end) return { kind: 'complex' };\n\n const sp = start.parentNode;\n const ep = end.parentNode;\n if (!sp || sp !== ep) return { kind: 'complex' };\n\n const parent = sp as Element;\n if (parent.namespaceURI !== W_NS || parent.localName !== 'p') {\n return { kind: 'complex' };\n }\n\n const paraIdRaw = parent.getAttributeNS(W14_NS, 'paraId');\n const paraId = paraIdRaw && paraIdRaw.length > 0 ? paraIdRaw.toUpperCase() : undefined;\n\n const before = hasContentBefore(parent, start);\n const after = hasContentAfter(parent, end);\n\n if (!before && !after) {\n const info: RangeClassification = { kind: 'paragraph' };\n if (paraId !== undefined) info.paraId = paraId;\n return info;\n }\n\n const text = collectTextBetween(start, end);\n const info: RangeClassification = { kind: 'text', text };\n if (paraId !== undefined) info.paraId = paraId;\n return info;\n}\n\n// ─────────── 内部:内容 / 文本 ───────────\n\n/**\n * `<w:p>` 直属 W_NS 子元素中,**不算内容**的 marker/meta 节点集。\n * 未知的 W_NS 元素 **不在此集中** → 被保守视为内容。\n */\nconst W_MARKER_LOCAL_NAMES = new Set<string>([\n 'pPr',\n 'rPr',\n 'bookmarkStart',\n 'bookmarkEnd',\n 'commentRangeStart',\n 'commentRangeEnd',\n 'commentReference',\n 'proofErr',\n 'permStart',\n 'permEnd',\n]);\n\nfunction isContentChild(n: Node | null): boolean {\n if (!n || n.nodeType !== 1) return false; // 文本 / 注释 节点不算内容\n const el = n as Element;\n if (el.namespaceURI === W_NS) {\n if (W_MARKER_LOCAL_NAMES.has(el.localName ?? '')) return false;\n // \"marker run\":一个 `<w:r>` 只包 rPr + marker 元素(典型:`<w:r><w:commentReference/>\n // </w:r>` 放在 commentRangeEnd 之后)—— 不算内容,否则所有含批注引用的段落都会\n // 被判成 'text' rangeKind。\n if (el.localName === 'r' && isMarkerOnlyRun(el)) return false;\n return true;\n }\n // 非 W_NS(mc:AlternateContent / drawing 等):保守当作内容\n return true;\n}\n\n/**\n * `<w:r>` 的子只含 rPr / commentReference / bookmarkStart / bookmarkEnd /\n * commentRangeStart / commentRangeEnd 时视为 marker-only(run 不贡献内容)。\n *\n * 任何其它 W_NS 子(w:t / w:br / w:tab / w:sym / w:drawing / w:pict / w:fldChar /\n * w:delText ...)或非 W_NS 子都视为 run 有内容。\n */\nfunction isMarkerOnlyRun(run: Element): boolean {\n const children = run.childNodes;\n for (let i = 0; i < children.length; i++) {\n const c = children[i];\n if (!c || c.nodeType !== 1) continue; // 文本 / 注释节点忽略(空白不算内容)\n const el = c as Element;\n if (el.namespaceURI !== W_NS) return false;\n const local = el.localName ?? '';\n if (local === 'rPr') continue;\n if (W_MARKER_LOCAL_NAMES.has(local)) continue;\n return false;\n }\n return true;\n}\n\nfunction hasContentBefore(parent: Element, target: Element): boolean {\n const children = parent.childNodes;\n for (let i = 0; i < children.length; i++) {\n const c = children[i]!;\n if (c === target) return false;\n if (isContentChild(c)) return true;\n }\n return false;\n}\n\nfunction hasContentAfter(parent: Element, target: Element): boolean {\n const children = parent.childNodes;\n let seen = false;\n for (let i = 0; i < children.length; i++) {\n const c = children[i]!;\n if (seen && isContentChild(c)) return true;\n if (c === target) seen = true;\n }\n return false;\n}\n\n/**\n * 收集 start..end(都 exclusive)之间所有 `<w:t>` 文本拼接。\n *\n * 区间内兄弟可能是 `<w:r>`(递归含 `<w:t>`)/ `<w:hyperlink>` / `<w:ins>` 等包装\n * 元素 —— 统一调 `getElementsByTagNameNS(W_NS, 't')` 吃全部后代 `<w:t>`。marker\n * 节点本身无 `<w:t>` 子,不会被计入。\n */\nfunction collectTextBetween(start: Element, end: Element): string {\n const parent = start.parentNode;\n if (!parent) return '';\n const children = parent.childNodes;\n let inRange = false;\n let out = '';\n for (let i = 0; i < children.length; i++) {\n const c = children[i]!;\n if (c === start) {\n inRange = true;\n continue;\n }\n if (c === end) break;\n if (inRange && c.nodeType === 1) {\n const el = c as Element;\n const ts = el.getElementsByTagNameNS(W_NS, 't');\n for (let j = 0; j < ts.length; j++) {\n out += ts[j]!.textContent ?? '';\n }\n }\n }\n return out;\n}\n","/**\n * Word 跨 stories 枚举(docs/03 §10)。\n *\n * 一个 Word 文档可能包含 6 类 story:\n * | 类型 | contentType 尾缀 | 根元素 | 数量 |\n * | body | .document.main+xml | <w:document>/<w:body> | 1 |\n * | header | .header+xml | <w:hdr> | 0..N |\n * | footer | .footer+xml | <w:ftr> | 0..N |\n * | footnote | .footnotes+xml 内每个 | 单个 <w:footnote>(该 part 多个) | 0..M |\n * | endnote | .endnotes+xml 内每个 | 单个 <w:endnote> | 0..M |\n * | comment | .comments+xml 内每个 | 单个 <w:comment> | 0..M |\n *\n * **关键约束**:枚举实现**必须**走 `Document#getElementsByTagNameNS`。\n * `fontoxpath` 的 `//w:p` 无谓词 XPath 在 10 万段落上慢 460×(见 bench/xml-stack-worker)。\n * CI 的 `pnpm check:xpath` 会在源码里扫到此类调用即失败(scripts/check-no-unqualified-xpath.mjs)。\n */\nimport type { Package } from '../pack/index.js';\nimport { isXmlPart } from '../pack/index.js';\nimport { W_NS } from './namespaces.js';\n\nexport type StoryKind = 'body' | 'header' | 'footer' | 'footnote' | 'endnote' | 'comment';\n\n/**\n * Story 唯一标识:\n * - 'body' — 唯一主 body\n * - 'header:<part path>' / 'footer:<part path>' — 1 part 1 story\n * - 'footnote:<id>' / 'endnote:<id>' / 'comment:<id>' — 多 sub-story 按 w:id 区分\n */\nexport type StoryId =\n | 'body'\n | `header:${string}`\n | `footer:${string}`\n | `footnote:${number}`\n | `endnote:${number}`\n | `comment:${number}`;\n\nexport interface Story {\n id: StoryId;\n kind: StoryKind;\n /** story 的根 Element(body = <w:body>,footnote = 单个 <w:footnote>,依此类推) */\n root: Element;\n /** 所在 part 的 path */\n partPath: string;\n}\n\nexport interface ListStoriesOptions {\n /** 仅枚举指定 kinds(默认全枚举)*/\n kinds?: StoryKind[];\n}\n\n/** 把 HTMLCollection-ish 枚举结果快照成数组 */\nfunction snapshot<T extends Element>(col: { length: number } & Record<number, T>): T[] {\n const out: T[] = [];\n for (let i = 0; i < col.length; i++) {\n const el = col[i];\n if (el) out.push(el);\n }\n return out;\n}\n\n/**\n * 枚举 Package 内所有 stories。\n *\n * 按 contentType 尾缀识别 part,内部用 `getElementsByTagNameNS` 提取根元素或\n * sub-story 元素。**不做**任何带谓词/路径的 XPath。\n */\nexport function listStories(pkg: Package, opts: ListStoriesOptions = {}): Story[] {\n const wanted = new Set<StoryKind>(\n opts.kinds ?? ['body', 'header', 'footer', 'footnote', 'endnote', 'comment'],\n );\n const out: Story[] = [];\n\n for (const part of pkg.parts.values()) {\n if (!isXmlPart(part) || !part.xmlDom) continue;\n const ct = part.contentType;\n\n if (\n wanted.has('body') &&\n (ct.endsWith('.document.main+xml') ||\n ct.endsWith('.document.macroEnabled.main+xml') ||\n ct.endsWith('.template.main+xml') ||\n ct.endsWith('.template.macroEnabledTemplate.main+xml'))\n ) {\n // body 是 <w:document>/<w:body> 的唯一子元素\n const bodies = snapshot(part.xmlDom.getElementsByTagNameNS(W_NS, 'body'));\n if (bodies.length > 0) {\n out.push({ id: 'body', kind: 'body', root: bodies[0]!, partPath: part.path });\n }\n continue;\n }\n\n if (wanted.has('header') && ct.endsWith('.header+xml')) {\n const hdrs = snapshot(part.xmlDom.getElementsByTagNameNS(W_NS, 'hdr'));\n if (hdrs.length > 0) {\n out.push({\n id: `header:${part.path}`,\n kind: 'header',\n root: hdrs[0]!,\n partPath: part.path,\n });\n }\n continue;\n }\n\n if (wanted.has('footer') && ct.endsWith('.footer+xml')) {\n const ftrs = snapshot(part.xmlDom.getElementsByTagNameNS(W_NS, 'ftr'));\n if (ftrs.length > 0) {\n out.push({\n id: `footer:${part.path}`,\n kind: 'footer',\n root: ftrs[0]!,\n partPath: part.path,\n });\n }\n continue;\n }\n\n if (wanted.has('footnote') && ct.endsWith('.footnotes+xml')) {\n const notes = snapshot(part.xmlDom.getElementsByTagNameNS(W_NS, 'footnote'));\n for (const note of notes) {\n const id = numAttr(note, W_NS, 'id');\n if (id === null) continue;\n out.push({\n id: `footnote:${id}`,\n kind: 'footnote',\n root: note,\n partPath: part.path,\n });\n }\n continue;\n }\n\n if (wanted.has('endnote') && ct.endsWith('.endnotes+xml')) {\n const notes = snapshot(part.xmlDom.getElementsByTagNameNS(W_NS, 'endnote'));\n for (const note of notes) {\n const id = numAttr(note, W_NS, 'id');\n if (id === null) continue;\n out.push({\n id: `endnote:${id}`,\n kind: 'endnote',\n root: note,\n partPath: part.path,\n });\n }\n continue;\n }\n\n if (wanted.has('comment') && ct.endsWith('.comments+xml')) {\n const comments = snapshot(part.xmlDom.getElementsByTagNameNS(W_NS, 'comment'));\n for (const c of comments) {\n const id = numAttr(c, W_NS, 'id');\n if (id === null) continue;\n out.push({\n id: `comment:${id}`,\n kind: 'comment',\n root: c,\n partPath: part.path,\n });\n }\n }\n }\n\n return out;\n}\n\n/**\n * 取 story 根下的所有 <w:p> 元素。\n *\n * - body / header / footer:story root 整个子树的 w:p\n * - footnote / endnote / comment:单个 sub-story root 下的 w:p(不跨 sub-story)\n */\nexport function getStoryParagraphs(story: Story): Element[] {\n // 使用 getElementsByTagNameNS 枚举 —— 根元素调用时只返回该子树下的匹配\n return snapshot(story.root.getElementsByTagNameNS(W_NS, 'p'));\n}\n\n/**\n * 反查元素所属 story(#25)。用 `Node.contains()` 逐个比对,命中首个返回。\n *\n * 一个 pkg 内 stories 数量通常 <20,contains 是 ~O(depth) 的祖先遍历,整体代价\n * 可忽略。找不到(元素不在任何已识别 story 的子树里)返回 null 。\n */\nexport function findStoryFor(pkg: Package, el: Element): Story | null {\n for (const s of listStories(pkg)) {\n if (s.root.contains(el as unknown as Node)) return s;\n }\n return null;\n}\n\n/**\n * scope 枚举解析为 Story 列表(#24 / #26 共用)。\n *\n * - `'body'` —— 只枚举 body\n * - `'all'` —— 全部 6 类 story\n * - `StoryId[]` —— 精确筛选;**未命中的 id 忽略**(调用方自己负责正确性)\n */\nexport function resolveScope(pkg: Package, scope: 'body' | 'all' | StoryId[]): Story[] {\n if (scope === 'body') return listStories(pkg, { kinds: ['body'] });\n if (scope === 'all') return listStories(pkg);\n const wanted = new Set<StoryId>(scope);\n return listStories(pkg).filter((s) => wanted.has(s.id));\n}\n\nfunction numAttr(el: Element, ns: string, local: string): number | null {\n const v = el.getAttributeNS(ns, local);\n if (v === null) return null;\n const n = Number(v);\n return Number.isFinite(n) ? n : null;\n}\n","/**\n * Bookmark 只读查询(docs/03.1 §1.5 / §2,#25)。\n *\n * 基于 `PackageIndices.bookmarkIdx`(#13 建好)做 O(1) 反查,没有任何 fontoxpath\n * 调用。rangeKind 判定走 DOM 遍历(孩子顺序 + 同 `<w:p>` 判断)。\n *\n * 三类 rangeKind(docs/03.1 §1.5):\n * - `'paragraph'` —— start / end 在**同一 `<w:p>`** 中,且 `<w:bookmarkStart>`\n * 之前没有任何内容节点、`<w:bookmarkEnd>` 之后也没有 —— 即书签覆盖整段的\"内容区\"\n * - `'text'` —— 同一 `<w:p>`,但 start / end 不在段首/段尾(书签仅覆盖段内文本片段)\n * - `'complex'` —— 跨段落、缺 end、start / end parent 不同、或 parent 不是 `<w:p>`\n * (表 cell、body 直子等),core 不简单建模,只标 kind\n *\n * `hidden`:name 以 `_` 开头(如 `_Toc123` / `_GoBack` / `_Hlk12345`)。`listBookmarks`\n * 默认过滤;`getBookmark(name)` 不过滤(调用方已知 name)。\n */\nimport type { Package } from '../pack/index.js';\nimport type { BookmarkEntry, PackageIndices } from './indices.js';\nimport { classifyRange } from './range-kind.js';\nimport { findStoryFor, type StoryId } from './stories.js';\n\nexport type BookmarkName = string;\n\nexport interface BookmarkInfo {\n name: BookmarkName;\n story: StoryId;\n rangeKind: 'paragraph' | 'text' | 'complex';\n /** rangeKind = 'paragraph' | 'text' 时给(书签所属的段落 paraId,大写 8 hex) */\n paraId?: string;\n /** rangeKind = 'text' 时给(start / end 之间所有 `<w:t>` 的纯文本拼接) */\n text?: string;\n /** name 以 `_` 开头时 true;否则缺字段 */\n hidden?: boolean;\n}\n\nexport interface ListBookmarksOptions {\n /** 默认 false。true 时返回所有书签,包括 `_` 开头的隐藏书签 */\n includeHidden?: boolean;\n /**\n * 名字前缀过滤(大小写敏感)。提供时只返回 `name.startsWith(prefix)` 的书签。\n *\n * 配合 `InsertParagraphSpec.bookmark.prefix` 的规则化命名(`{prefix}_{anchorParaId}` /\n * 冲突时 `{prefix}_{anchorParaId}_2` 等)使用,可批量回查\"某语义标签下的所有书签\"。\n * `_` 开头的隐藏书签若未设置 `includeHidden=true` 仍被过滤(prefix 与 hidden 是\n * 独立轴)。\n */\n prefix?: string;\n}\n\n// ─────────── 公共入口 ───────────\n\nexport function listBookmarks(\n pkg: Package,\n indices: PackageIndices,\n opts: ListBookmarksOptions = {},\n): BookmarkInfo[] {\n const includeHidden = opts.includeHidden === true;\n const prefix = opts.prefix;\n const out: BookmarkInfo[] = [];\n for (const [name, entry] of indices.bookmarkIdx) {\n if (prefix !== undefined && !name.startsWith(prefix)) continue;\n const hidden = isHiddenName(name);\n if (hidden && !includeHidden) continue;\n const info = buildBookmarkInfo(pkg, name, entry);\n if (info) out.push(info);\n }\n return out;\n}\n\nexport function getBookmark(\n pkg: Package,\n indices: PackageIndices,\n name: BookmarkName,\n): BookmarkInfo | null {\n const entry = indices.bookmarkIdx.get(name);\n if (!entry) return null;\n return buildBookmarkInfo(pkg, name, entry);\n}\n\n// ─────────── 内部 ───────────\n\nfunction isHiddenName(name: string): boolean {\n return name.startsWith('_');\n}\n\nfunction buildBookmarkInfo(pkg: Package, name: string, entry: BookmarkEntry): BookmarkInfo | null {\n // story 由 start 元素反查(bookmark 横跨 part 的情况极少见;若 start 不在任一 story\n // 子树里,入索引时本应不会发生 —— 此处保险返回 null)。\n const story = findStoryFor(pkg, entry.start);\n if (!story) return null;\n\n const { kind, paraId, text } = classifyRange(entry.start, entry.end);\n\n const info: BookmarkInfo = {\n name,\n story: story.id,\n rangeKind: kind,\n };\n if (paraId !== undefined) info.paraId = paraId;\n if (text !== undefined) info.text = text;\n if (isHiddenName(name)) info.hidden = true;\n return info;\n}\n","/**\n * Comment 只读查询(docs/03.1 §1.5 / §2,#26)。\n *\n * 批注由两部分组成:\n * - **主体**(`<w:comment>` in comments.xml):id / author / date / 批注正文\n * - **锚点**(`<w:commentRangeStart>` / `<w:commentRangeEnd>` / `<w:commentReference>`\n * in body / headers / footers 等):标识被批注的范围\n *\n * `PackageIndices.commentIdx` 已在装载期把两边按 `w:id`(数字)串联。这里做:\n * - 读主体拿 author / date / text\n * - 用锚点 start / end 判 rangeKind(复用 [range-kind.ts](./range-kind.ts) 的\n * `classifyRange`)\n * - 由 start 元素反查 story(`findStoryFor`)\n *\n * 跟 bookmark 的字段差异:\n * - BookmarkInfo 的 `text` 字段 → CommentInfo 的 `anchorText` 字段(语义更明确)\n * - 没有 `hidden` 概念\n */\nimport type { CommentEntry, PackageIndices } from './indices.js';\nimport { W_NS } from './namespaces.js';\nimport { classifyRange } from './range-kind.js';\n\nexport type CommentId = number;\n\nexport interface CommentInfo {\n id: CommentId;\n /** w:author,缺则 '' */\n author: string;\n /** w:date(ISO 8601);缺则 '' */\n date: string;\n /** 批注正文:`<w:comment>` 内所有 `<w:t>` 拼接 */\n text: string;\n rangeKind: 'paragraph' | 'text' | 'complex';\n /** rangeKind = 'paragraph' | 'text' 时给(批注锚定的段落 paraId) */\n paraId?: string;\n /** rangeKind = 'text' 时给(start/end 之间的正文片段) */\n anchorText?: string;\n}\n\n// ─────────── 公共入口 ───────────\n\n/**\n * 枚举所有批注。\n *\n * 顺序按 `commentIdx` 的迭代序(Map 插入序;装载期按 part 遍历 + w:id 升序扫到)。\n *\n * 主体缺失(`entry.comment === null`)或锚点无 start/end 的批注 **被跳过** ——\n * 调用方看到的永远是\"主体 + 至少一个锚点\"都有的条目。\n */\nexport function listComments(indices: PackageIndices): CommentInfo[] {\n const out: CommentInfo[] = [];\n for (const [id, entry] of indices.commentIdx) {\n const info = buildCommentInfo(id, entry);\n if (info) out.push(info);\n }\n return out;\n}\n\n/** 按 id 取单条批注。不存在或主体缺失返回 null */\nexport function getComment(indices: PackageIndices, id: CommentId): CommentInfo | null {\n const entry = indices.commentIdx.get(id);\n if (!entry) return null;\n return buildCommentInfo(id, entry);\n}\n\n// ─────────── 内部 ───────────\n\nfunction buildCommentInfo(id: CommentId, entry: CommentEntry): CommentInfo | null {\n const comment = entry.comment;\n // 主体缺失:批注数据异常(只有锚点没有 <w:comment>)—— 此时 author/date/text 都\n // 无法给,返回 null 比\"空壳占位\"更诚实。装载期对此情形不抛错(buildIndices 允许\n // entry.comment 为 null),只有查询时才显式忽略。\n if (!comment) return null;\n\n const author = comment.getAttributeNS(W_NS, 'author') ?? '';\n const date = comment.getAttributeNS(W_NS, 'date') ?? '';\n const text = collectDescendantTText(comment);\n\n // rangeKind:基于锚点 start / end。两边都缺则退化 'complex'。\n // `classifyRange.text` 在 comment 语境下含义 = anchorText。\n const {\n kind,\n paraId,\n text: anchorText,\n } = classifyRange(entry.anchors.start ?? null, entry.anchors.end ?? null);\n\n const info: CommentInfo = {\n id,\n author,\n date,\n text,\n rangeKind: kind,\n };\n if (paraId !== undefined) info.paraId = paraId;\n if (anchorText !== undefined) info.anchorText = anchorText;\n return info;\n}\n\n/**\n * 拉 `<w:comment>` 内全部 `<w:t>` 的纯文本,按文档序拼接。\n *\n * `<w:comment>` 可能包含多个 `<w:p>` → `<w:r>` → `<w:t>` 层级,也可能混有\n * `<w:hyperlink>` 等包装 —— 一次性 `getElementsByTagNameNS(W_NS, 't')` 吃全部后代。\n * 段落分隔不在文本里(不加 `\\n`),与 Bookmark 的 text 字段口径一致。\n */\nfunction collectDescendantTText(el: Element): string {\n const ts = el.getElementsByTagNameNS(W_NS, 't');\n let out = '';\n for (let i = 0; i < ts.length; i++) {\n out += ts[i]!.textContent ?? '';\n }\n return out;\n}\n","/**\n * 表格枚举与结构分析(#185)\n *\n * 为骨架化 M2 阶段(表格分类/取样/域化)提供表格数据。\n *\n * 设计原则:\n * - 只走 getElementsByTagNameNS,禁用 XPath(性能约束,同 list-paragraphs.ts)\n * - tableId 由 buildIndices 在装载期分配(tbl-0001 起),存入 tblIdx\n * - 默认只枚举主文档 body(scope: 'body'),不含嵌套表格(includeNested: false)\n * - 前后邻段落(prevParaId / nextParaId)只取紧邻兄弟 <w:p>,供题注绑定(#193)\n */\n\nimport { serializeToWellFormedString } from 'slimdom';\nimport { getPart, isXmlPart, type Package } from '../pack/index.js';\nimport { A_NS, R_NS, W_NS, W14_NS } from './namespaces.js';\nimport type { PackageIndices } from './indices.js';\nimport { getParagraphText } from './runs.js';\nimport { findStoryFor, resolveScope, type Story } from './stories.js';\n\n// ─────────── 公开类型 ───────────\n\n/**\n * 行高(对照 columnWidths)。w:tr/w:trPr/w:trHeight。\n *\n * 空行塌缩正是 hRule+val 没带过去所致,两者必须一起读/写。\n */\nexport interface RowHeight {\n /** w:trHeight/@w:val,行高 twips(1 twip = 1/20 磅)*/\n val: number;\n /** w:trHeight/@w:hRule:auto(默认,最小高度) / atLeast(至少) / exact(精确)。\n * 缺省(无 hRule 属性)按 OOXML 默认 'auto'。*/\n hRule: 'auto' | 'atLeast' | 'exact';\n}\n\n/**\n * 单个物理 <w:tc> 的 span 信息,携带文本与合并状态。\n * cellGrid[i][j] 对应第 i 行第 j 个物理 <w:tc>。\n */\nexport interface TableCellInfo {\n /** 单元格纯文本(多段以 \\n 连接),与 cells[i][j] 完全一致 */\n text: string;\n /** 水平合并跨列数(<w:gridSpan w:val>,无则默认 1) */\n gridSpan: number;\n /**\n * 垂直合并状态:\n * 'restart' = 纵向合并的起始格(<w:vMerge w:val=\"restart\"/>)\n * 'continue' = 被并入上方格的续行占位格(<w:vMerge/> 无 val 或 val=\"continue\")\n * null = 无纵向合并\n */\n vMerge: 'restart' | 'continue' | null;\n /** Direct cell width from w:tcPr/w:tcW, in twips. */\n width?: number;\n /** Direct cell shading from w:tcPr/w:shd. */\n shading?: {\n fill?: string;\n color?: string;\n val?: string;\n };\n /** Direct vertical alignment from w:tcPr/w:vAlign. */\n verticalAlignment?: 'top' | 'center' | 'bottom' | 'both';\n /**\n * 单元格首段(首个直属 `<w:p>`)的 paraId(w14:paraId)。无首段或首段缺 paraId 时 undefined。\n *\n * 用途(task-bug2-cell-image,决策点 C):merge 重建表后要往**正确 cell** 插单元格图,\n * 而 clone 出来的表 cell 段 paraId 是 cloneTableAfter 重分配的新值——调用方拿不到。\n * 暴露 firstParaId 后,调用方对 clone 表再 `tables.list({includeCellTexts:true})` 即可拿到\n * 每个 cell 首段 paraId,用 `plan.insertImageAfter(firstParaId)` 把图插进该 cell(insertImageAfter\n * 在 anchor 的 parentNode 内插段——anchor 在 `<w:tc>` 里,新图段就落在该 cell 内)。\n *\n * 与 replaceTableCellText 无冲突:后者只动 cell **首段**的 run,插在首段之后的独立图段不受影响。\n */\n firstParaId?: string;\n /**\n * Direct paragraph ids in this cell, in cell content order.\n *\n * Nested table paragraphs are not included.\n */\n paragraphIds: string[];\n /**\n * Direct content blocks in this cell, in OOXML child-node order.\n *\n * Paragraph drawings are emitted as drawing blocks as well, so callers can\n * preserve flows such as text paragraphs, then an image, then more text.\n */\n blocks: TableCellBlockInfo[];\n /**\n * 本单元格内直属 `<w:drawing>`(图片/形状等)的 drawingId 列表(与 drawingIdx 同 ID 空间)。\n *\n * 用途(task-bug2-cell-image,决策点 A1):表格单元格内的图此前在 cellGrid 这层就丢了\n * (cellGrid 只搬 cell 文字),导致单元格图在 structure 抽取阶段成孤儿(图字节在 word/media\n * 但 body 无 blip 引用)。收录 drawingId 后,typeset 抽表时把 cell 图当 content 带出、merge\n * 重建时用 `drawing.getImageBytes()` + `insertImageAfter(firstParaId)` 把图插回对应 cell。\n *\n * 收录范围:只取**本 cell 子树内、且不在嵌套表/嵌套 cell 内**的 drawing(嵌套表 cell 的图归属\n * 嵌套表自己的 cellGrid,不上浮污染外层)。空(无图)时为 `[]`(与 cells 同条件填充,\n * 字段恒在便于下游免判 undefined)。\n */\n imageDrawingIds: string[];\n}\n\nexport type TableCellBlockInfo =\n | { type: 'paragraph'; paraId: string; text: string }\n | { type: 'drawing'; drawingId: string; paraId?: string }\n | { type: 'table'; tableId: string };\n\nexport interface TableInfo {\n /** 分配的表格 ID(装载期顺序,'tbl-0001' 起),供 plan executor 引用 */\n tableId: string;\n /** 所在 part 路径(如 'word/document.xml')*/\n partPath: string;\n /** 在本次枚举结果中的顺序(1-based)*/\n index: number;\n /** 是否嵌套在另一个表格内(祖先链上存在 <w:tbl>)*/\n isNested: boolean;\n /** 行数(w:tr 直接子元素数量)*/\n rowCount: number;\n /** 列数(w:tblGrid/w:gridCol 数量;无 tblGrid 时为 0)*/\n colCount: number;\n /** 是否有合并单元格(gridSpan > 1 或存在 vMerge)*/\n hasMerge: boolean;\n /** 表格样式 ID(w:tblPr/w:tblStyle @w:val),未设时 undefined */\n tableStyleId?: string;\n /** 是否包含图片(w:drawing 元素)*/\n hasImages: boolean;\n /** 是否包含嵌套表格(直接子孙 <w:tbl>)*/\n hasNestedTables: boolean;\n /**\n * 紧邻前一个兄弟 <w:p> 的 paraId,用于题注绑定(#193)。\n * 仅检查紧邻兄弟:若前一个兄弟不是 <w:p>(如另一个 <w:tbl>)则为 undefined。\n */\n prevParaId?: string;\n /**\n * 紧邻后一个兄弟 <w:p> 的 paraId,用于题注绑定(#193)。\n * 仅检查紧邻兄弟。\n */\n nextParaId?: string;\n /**\n * 每列的列宽(twips,来自 `<w:tblGrid>/<w:gridCol w:w=\"...\">`)。\n *\n * - `columnWidths[i]` = 第 i 列的 `w:w` 值(1 twip = 1/20 磅)\n * - 无 `<w:tblGrid>` 时为 `[]`(空数组)\n * - `tblLayout=fixed` 的表格列宽完全由此决定;`auto` 布局表格也记录但仅供参考\n * - 供 merger 套用源表列宽(task-core-table-grid:克隆模板时保真列宽)\n */\n columnWidths: number[];\n /**\n * 每行行高,doc 序,每行一个;该行无 <w:trHeight> 则为 null。\n *\n * - `rowHeights[i]` = 第 i 行的 w:trPr/w:trHeight val+hRule\n * - 恒填(不依赖 includeCellTexts)\n * - 只取直属 <w:tr>,不误抓嵌套表行\n * - 供 merger 套用源表行高(空行塌缩修复)\n */\n rowHeights: (RowHeight | null)[];\n /**\n * 单元格文本网格(#186)。仅当 `includeCellTexts: true` 时填充。\n *\n * - `cells[i][j]` = 第 i 行第 j 列单元格的纯文本\n * - 单元格内含多段时用 `\\n` 连接(保留分段信号,供 has-multi-content 判定)\n * - 嵌套表格内的段落不展开(不污染外层网格)\n */\n cells?: string[][];\n /**\n * 单元格网格(span-aware),仅当 `includeCellTexts: true` 时填充(与 cells 同条件)。\n *\n * - `cellGrid[i][j]` 对应第 i 行第 j 个**物理** `<w:tc>`,携带 gridSpan/vMerge\n * - 与 cells 同源同序:`cells[i][j] === cellGrid[i][j].text`\n * - 嵌套表内段落不展开(与 extractCellTexts 一致)\n */\n cellGrid?: TableCellInfo[][];\n}\n\nexport interface ListTablesOptions {\n /** 枚举范围(默认 'body')*/\n scope?: 'body' | 'all';\n /** 是否包含嵌套在其他表格内的表格(默认 false,只返回顶层表格)*/\n includeNested?: boolean;\n /**\n * 是否抽取单元格文本(#186)。默认 false(保持 #185 默认行为)。\n *\n * 开启后每张 TableInfo 会带 `cells: string[][]`,用于关键词匹配/分类。\n * 性能:每张表会枚举所有 <w:tc> 及其直属 <w:p>,按需开启。\n */\n includeCellTexts?: boolean;\n}\n\n// ─────────── 内部工具 ───────────\n\n/** 把 HTMLCollection-ish 枚举结果快照成数组(避免 live 行为)*/\nfunction snapshot<T extends Element>(col: { length: number } & Record<number, T>): T[] {\n const out: T[] = [];\n for (let i = 0; i < col.length; i++) {\n const el = col[i];\n if (el) out.push(el);\n }\n return out;\n}\n\n/** 判断元素是否嵌套在某个祖先 <w:tbl> 内(止于 story 根元素)*/\nfunction hasTableAncestor(el: Element): boolean {\n let p = el.parentElement;\n while (p) {\n if (p.namespaceURI === W_NS) {\n if (p.localName === 'tbl') return true;\n // story 根元素:停止向上走\n if (\n p.localName === 'body' ||\n p.localName === 'hdr' ||\n p.localName === 'ftr' ||\n p.localName === 'footnote' ||\n p.localName === 'endnote' ||\n p.localName === 'comment'\n ) {\n return false;\n }\n }\n p = p.parentElement;\n }\n return false;\n}\n\n/** 紧邻前一个兄弟 <w:p> 的 paraId(只看直接前兄弟)*/\nfunction prevParaId(tbl: Element): string | undefined {\n const sib = tbl.previousElementSibling;\n if (sib && sib.namespaceURI === W_NS && sib.localName === 'p') {\n return sib.getAttributeNS(W14_NS, 'paraId') ?? undefined;\n }\n return undefined;\n}\n\n/** 紧邻后一个兄弟 <w:p> 的 paraId(只看直接后兄弟)*/\nfunction nextParaId(tbl: Element): string | undefined {\n const sib = tbl.nextElementSibling;\n if (sib && sib.namespaceURI === W_NS && sib.localName === 'p') {\n return sib.getAttributeNS(W14_NS, 'paraId') ?? undefined;\n }\n return undefined;\n}\n\n/**\n * 读取 <w:tc> 的直属 <w:tcPr> 中的 gridSpan(返回整数,无则 1)。\n * 只查 tcPr 直属子元素,不用 getElementsByTagNameNS(避免误抓嵌套表)。\n */\nfunction readGridSpan(tc: Element): number {\n for (let i = 0; i < tc.childNodes.length; i++) {\n const child = tc.childNodes[i] as Element;\n if (child.nodeType !== 1 || child.namespaceURI !== W_NS || child.localName !== 'tcPr') continue;\n // found tcPr — look for direct child gridSpan\n for (let j = 0; j < child.childNodes.length; j++) {\n const sub = child.childNodes[j] as Element;\n if (sub.nodeType !== 1 || sub.namespaceURI !== W_NS || sub.localName !== 'gridSpan') continue;\n const val = sub.getAttributeNS(W_NS, 'val');\n const parsed = val !== null ? parseInt(val, 10) : NaN;\n return !isNaN(parsed) && parsed > 1 ? parsed : 1;\n }\n break; // tcPr found but no gridSpan child\n }\n return 1;\n}\n\n/**\n * 读取 <w:tc> 的直属 <w:tcPr> 中的 vMerge 状态。\n * - 'restart' = <w:vMerge w:val=\"restart\"/>\n * - 'continue' = <w:vMerge/> (无 val 或 val=\"continue\")\n * - null = 无 vMerge 元素\n * 只查 tcPr 直属子元素,不用 getElementsByTagNameNS。\n */\nfunction readVMerge(tc: Element): 'restart' | 'continue' | null {\n for (let i = 0; i < tc.childNodes.length; i++) {\n const child = tc.childNodes[i] as Element;\n if (child.nodeType !== 1 || child.namespaceURI !== W_NS || child.localName !== 'tcPr') continue;\n // found tcPr — look for direct child vMerge\n for (let j = 0; j < child.childNodes.length; j++) {\n const sub = child.childNodes[j] as Element;\n if (sub.nodeType !== 1 || sub.namespaceURI !== W_NS || sub.localName !== 'vMerge') continue;\n const val = sub.getAttributeNS(W_NS, 'val');\n return val === 'restart' ? 'restart' : 'continue';\n }\n break; // tcPr found but no vMerge child\n }\n return null;\n}\n\n/**\n * 读取 <w:tr> 的直属 <w:trPr> 中的 trHeight(val + hRule)。\n * - 无 trPr 或 trPr 内无 trHeight → null\n * - 只查 trPr 直属子元素,不用 getElementsByTagNameNS(避免误抓嵌套表)。\n */\nfunction readCellWidth(tc: Element): number | undefined {\n const tcPr = firstDirectChildW(tc, 'tcPr');\n if (!tcPr) return undefined;\n const tcW = firstDirectChildW(tcPr, 'tcW');\n if (!tcW) return undefined;\n const raw = tcW.getAttributeNS(W_NS, 'w') ?? tcW.getAttribute('w:w');\n if (raw === null) return undefined;\n const parsed = parseInt(raw, 10);\n return Number.isFinite(parsed) ? parsed : undefined;\n}\n\nfunction readCellShading(tc: Element): { fill?: string; color?: string; val?: string } | undefined {\n const tcPr = firstDirectChildW(tc, 'tcPr');\n if (!tcPr) return undefined;\n const shd = firstDirectChildW(tcPr, 'shd');\n if (!shd) return undefined;\n const result: { fill?: string; color?: string; val?: string } = {};\n const fill = shd.getAttributeNS(W_NS, 'fill') ?? shd.getAttribute('w:fill');\n const color = shd.getAttributeNS(W_NS, 'color') ?? shd.getAttribute('w:color');\n const val = shd.getAttributeNS(W_NS, 'val') ?? shd.getAttribute('w:val');\n if (fill !== null) result.fill = fill;\n if (color !== null) result.color = color;\n if (val !== null) result.val = val;\n return Object.keys(result).length > 0 ? result : undefined;\n}\n\nfunction readCellVerticalAlignment(tc: Element): 'top' | 'center' | 'bottom' | 'both' | undefined {\n const tcPr = firstDirectChildW(tc, 'tcPr');\n if (!tcPr) return undefined;\n const vAlign = firstDirectChildW(tcPr, 'vAlign');\n if (!vAlign) return undefined;\n const raw = vAlign.getAttributeNS(W_NS, 'val') ?? vAlign.getAttribute('w:val');\n if (raw === 'top' || raw === 'center' || raw === 'bottom' || raw === 'both') return raw;\n return undefined;\n}\n\nfunction firstDirectChildW(el: Element, localName: string): Element | null {\n for (let i = 0; i < el.childNodes.length; i++) {\n const child = el.childNodes[i];\n if (\n child?.nodeType === 1 &&\n (child as Element).namespaceURI === W_NS &&\n (child as Element).localName === localName\n ) {\n return child as Element;\n }\n }\n return null;\n}\n\nfunction readTrHeight(tr: Element): RowHeight | null {\n for (let i = 0; i < tr.childNodes.length; i++) {\n const child = tr.childNodes[i] as Element;\n if (child.nodeType !== 1 || child.namespaceURI !== W_NS || child.localName !== 'trPr') continue;\n // found trPr — look for direct child trHeight\n for (let j = 0; j < child.childNodes.length; j++) {\n const sub = child.childNodes[j] as Element;\n if (sub.nodeType !== 1 || sub.namespaceURI !== W_NS || sub.localName !== 'trHeight') continue;\n const valAttr = sub.getAttributeNS(W_NS, 'val');\n const val = valAttr !== null ? parseInt(valAttr, 10) : 0;\n const hRuleAttr = sub.getAttributeNS(W_NS, 'hRule');\n let hRule: RowHeight['hRule'] = 'auto';\n if (hRuleAttr === 'atLeast') hRule = 'atLeast';\n else if (hRuleAttr === 'exact') hRule = 'exact';\n return { val: isNaN(val) ? 0 : val, hRule };\n }\n break; // trPr found but no trHeight child\n }\n return null;\n}\n\n/**\n * 取 `<w:tc>` 首个直属 `<w:p>` 的 w14:paraId(task-bug2-cell-image,决策点 C)。\n * 无直属 `<w:p>` 或缺 paraId 时返回 undefined。\n */\nfunction firstCellParaId(tc: Element): string | undefined {\n for (let k = 0; k < tc.childNodes.length; k++) {\n const p = tc.childNodes[k] as Element;\n if (!p || p.nodeType !== 1 || p.namespaceURI !== W_NS || p.localName !== 'p') continue;\n return p.getAttributeNS(W14_NS, 'paraId') ?? undefined;\n }\n return undefined;\n}\n\n/**\n * 收集**本 cell 子树内、不在嵌套表内**的 `<w:drawing>`,反查出 drawingId 列表\n * (task-bug2-cell-image,决策点 A1)。\n *\n * - 用 `getElementsByTagNameNS(W_NS,'drawing')` 取 cell 子树全部 drawing(含嵌套表内的),\n * 再用 `cellOf(drawing) === tc` 过滤掉嵌套表 cell 内的图(它们归属嵌套表自己的 cellGrid)。\n * - 反查 drawingId 走传入的 `drawingToId`(drawingIdx 反转),未命中(不在索引内,\n * 如 mc:Fallback 内被装载期跳过的 drawing)则跳过——与 drawings.list 枚举集保持一致。\n */\nfunction collectCellDrawingIds(tc: Element, drawingToId: Map<Element, string>): string[] {\n const ids: string[] = [];\n const drawings = tc.getElementsByTagNameNS(W_NS, 'drawing');\n for (let i = 0; i < drawings.length; i++) {\n const dr = drawings[i];\n if (!dr) continue;\n // 只收归属本 cell(最近祖先 <w:tc> 即 tc)的 drawing,排除嵌套表 cell 内的图。\n if (nearestCellOf(dr) !== tc) continue;\n const id = drawingToId.get(dr);\n if (id !== undefined) ids.push(id);\n }\n return ids;\n}\n\n/** 向上找元素最近的祖先 `<w:tc>`(止于 story 根);不在任何 cell 内返回 null。 */\nfunction nearestCellOf(el: Element): Element | null {\n let p = el.parentElement;\n while (p) {\n if (p.namespaceURI === W_NS) {\n if (p.localName === 'tc') return p;\n if (\n p.localName === 'body' ||\n p.localName === 'hdr' ||\n p.localName === 'ftr' ||\n p.localName === 'footnote' ||\n p.localName === 'endnote' ||\n p.localName === 'comment'\n ) {\n return null;\n }\n }\n p = p.parentElement;\n }\n return null;\n}\n\nfunction collectCellParagraphIds(tc: Element): string[] {\n const ids: string[] = [];\n for (let k = 0; k < tc.childNodes.length; k++) {\n const p = tc.childNodes[k] as Element;\n if (!p || p.nodeType !== 1 || p.namespaceURI !== W_NS || p.localName !== 'p') continue;\n const paraId = p.getAttributeNS(W14_NS, 'paraId');\n if (paraId) ids.push(paraId);\n }\n return ids;\n}\n\nfunction directDrawingIdsInParagraph(\n p: Element,\n ownerCell: Element,\n drawingToId: Map<Element, string>,\n): string[] {\n const ids: string[] = [];\n const drawings = p.getElementsByTagNameNS(W_NS, 'drawing');\n for (let i = 0; i < drawings.length; i++) {\n const dr = drawings[i];\n if (!dr || nearestCellOf(dr) !== ownerCell) continue;\n const id = drawingToId.get(dr);\n if (id !== undefined) ids.push(id);\n }\n return ids;\n}\n\nfunction collectCellBlocks(\n tc: Element,\n drawingToId: Map<Element, string>,\n tableToId: Map<Element, string>,\n): TableCellBlockInfo[] {\n const blocks: TableCellBlockInfo[] = [];\n for (let k = 0; k < tc.childNodes.length; k++) {\n const child = tc.childNodes[k] as Element;\n if (!child || child.nodeType !== 1 || child.namespaceURI !== W_NS) continue;\n\n if (child.localName === 'p') {\n const paraId = child.getAttributeNS(W14_NS, 'paraId') ?? undefined;\n const text = getParagraphText(child);\n const drawingIds = directDrawingIdsInParagraph(child, tc, drawingToId);\n if (paraId && (text.length > 0 || drawingIds.length === 0)) {\n blocks.push({ type: 'paragraph', paraId, text });\n }\n for (const drawingId of drawingIds) {\n blocks.push(\n paraId ? { type: 'drawing', drawingId, paraId } : { type: 'drawing', drawingId },\n );\n }\n continue;\n }\n\n if (child.localName === 'tbl') {\n const tableId = tableToId.get(child);\n if (tableId) blocks.push({ type: 'table', tableId });\n }\n }\n return blocks;\n}\n\n/**\n * 抽取整张表的单元格网格(span-aware, task-core-table-span)。\n * - 只看 <w:tbl> 直属的 <w:tr>,每行枚举直属 <w:tc>\n * - 每个 <w:tc> 内取直属 <w:p>(不展开嵌套表),多段以 `\\n` 连接\n * - 每格携带 gridSpan / vMerge(只读 tcPr 直属子元素,不误抓嵌套表)\n * - 每格携带 firstParaId(首段 paraId)/ imageDrawingIds(cell 内图 drawingId)\n * (task-bug2-cell-image:决策点 C / A1)\n *\n * @param drawingToId drawingIdx 反转(Element→drawingId),用于把 cell 内 `<w:drawing>` 反查成 ID。\n */\nfunction extractCellGrid(\n tbl: Element,\n drawingToId: Map<Element, string>,\n tableToId: Map<Element, string>,\n): TableCellInfo[][] {\n const rows: TableCellInfo[][] = [];\n for (let i = 0; i < tbl.childNodes.length; i++) {\n const tr = tbl.childNodes[i] as Element;\n if (!tr || tr.nodeType !== 1 || tr.namespaceURI !== W_NS || tr.localName !== 'tr') continue;\n\n const rowCells: TableCellInfo[] = [];\n for (let j = 0; j < tr.childNodes.length; j++) {\n const tc = tr.childNodes[j] as Element;\n if (!tc || tc.nodeType !== 1 || tc.namespaceURI !== W_NS || tc.localName !== 'tc') continue;\n\n const paragraphs: string[] = [];\n for (let k = 0; k < tc.childNodes.length; k++) {\n const p = tc.childNodes[k] as Element;\n if (!p || p.nodeType !== 1 || p.namespaceURI !== W_NS || p.localName !== 'p') continue;\n paragraphs.push(getParagraphText(p));\n }\n const cell: TableCellInfo = {\n text: paragraphs.join('\\n'),\n gridSpan: readGridSpan(tc),\n vMerge: readVMerge(tc),\n paragraphIds: collectCellParagraphIds(tc),\n blocks: collectCellBlocks(tc, drawingToId, tableToId),\n imageDrawingIds: collectCellDrawingIds(tc, drawingToId),\n };\n const fpid = firstCellParaId(tc);\n if (fpid !== undefined) cell.firstParaId = fpid;\n const width = readCellWidth(tc);\n if (width !== undefined) cell.width = width;\n const shading = readCellShading(tc);\n if (shading !== undefined) cell.shading = shading;\n const verticalAlignment = readCellVerticalAlignment(tc);\n if (verticalAlignment !== undefined) cell.verticalAlignment = verticalAlignment;\n rowCells.push(cell);\n }\n rows.push(rowCells);\n }\n return rows;\n}\n\n/** 从 <w:tbl> 元素提取结构信息。\n *\n * @param drawingToId drawingIdx 反转(Element→drawingId),仅在 includeCellTexts 时用于\n * cell 图 drawingId 反查;不开 includeCellTexts 时传空 Map 即可(不进 extractCellGrid)。\n */\nfunction analyzeTable(\n tbl: Element,\n tableId: string,\n partPath: string,\n index: number,\n includeCellTexts: boolean,\n drawingToId: Map<Element, string>,\n tableToId: Map<Element, string>,\n): TableInfo {\n let rowCount = 0;\n let hasMerge = false;\n const rowHeights: (RowHeight | null)[] = [];\n\n // 嵌套表深度检测(#203):嵌套表在 tbl/tr/tc/tbl 路径上,不是 tbl 直接子,\n // 旧逻辑扫直接子永远扫不到。getElementsByTagNameNS 只返回后代(不含自身),\n // 命中即说明存在嵌套表。\n const hasNestedTables = tbl.getElementsByTagNameNS(W_NS, 'tbl').length > 0;\n\n // 一次遍历直接子节点:统计行数、检测合并单元格、读取行高\n for (let i = 0; i < tbl.childNodes.length; i++) {\n const child = tbl.childNodes[i] as Element;\n if (child.nodeType !== 1 /* ELEMENT_NODE */) continue;\n if (child.namespaceURI !== W_NS) continue;\n\n if (child.localName === 'tr') {\n rowCount++;\n // 读取行高(直属 tr,不误抓嵌套表行)\n rowHeights.push(readTrHeight(child));\n // 检测合并单元格(只在未确认时扫)\n if (!hasMerge) {\n const cells = snapshot(child.getElementsByTagNameNS(W_NS, 'tc'));\n for (const tc of cells) {\n // 水平合并:gridSpan > 1\n const gridSpanEls = tc.getElementsByTagNameNS(W_NS, 'gridSpan');\n if (gridSpanEls.length > 0) {\n const val = gridSpanEls[0]!.getAttributeNS(W_NS, 'val');\n if (val && Number(val) > 1) {\n hasMerge = true;\n break;\n }\n }\n // 垂直合并:vMerge 存在即可\n if (tc.getElementsByTagNameNS(W_NS, 'vMerge').length > 0) {\n hasMerge = true;\n break;\n }\n }\n }\n }\n }\n\n // 列数 + 列宽:w:tblGrid/w:gridCol 数量及每列 w:w(task-core-table-grid)\n let colCount = 0;\n const columnWidths: number[] = [];\n const tblGridEls = tbl.getElementsByTagNameNS(W_NS, 'tblGrid');\n if (tblGridEls.length > 0) {\n const gridCols = tblGridEls[0]!.getElementsByTagNameNS(W_NS, 'gridCol');\n colCount = gridCols.length;\n for (let i = 0; i < gridCols.length; i++) {\n const wAttr = gridCols[i]!.getAttributeNS(W_NS, 'w');\n columnWidths.push(wAttr !== null ? Number(wAttr) : 0);\n }\n }\n\n // 表格样式\n let tableStyleId: string | undefined;\n const tblStyleEls = tbl.getElementsByTagNameNS(W_NS, 'tblStyle');\n if (tblStyleEls.length > 0) {\n tableStyleId = tblStyleEls[0]!.getAttributeNS(W_NS, 'val') ?? undefined;\n }\n\n // 图片检测:w:drawing 子孙\n const hasImages = tbl.getElementsByTagNameNS(W_NS, 'drawing').length > 0;\n\n const info: TableInfo = {\n tableId,\n partPath,\n index,\n isNested: hasTableAncestor(tbl),\n rowCount,\n colCount,\n hasMerge,\n hasImages,\n hasNestedTables,\n columnWidths,\n rowHeights,\n };\n if (tableStyleId !== undefined) info.tableStyleId = tableStyleId;\n const prev = prevParaId(tbl);\n if (prev !== undefined) info.prevParaId = prev;\n const next = nextParaId(tbl);\n if (next !== undefined) info.nextParaId = next;\n if (includeCellTexts) {\n const grid = extractCellGrid(tbl, drawingToId, tableToId);\n info.cellGrid = grid;\n info.cells = grid.map((row) => row.map((cell) => cell.text));\n }\n\n return info;\n}\n\n/**\n * 把 drawingIdx(id→Element)反转成 Element→id,供 cell 图 drawingId 反查\n * (task-bug2-cell-image, A1)。仅 includeCellTexts 时构建(避免无谓开销)。\n */\nfunction buildDrawingReverseMap(drawingIdx: Map<string, Element>): Map<Element, string> {\n const rev = new Map<Element, string>();\n for (const [id, el] of drawingIdx) rev.set(el, id);\n return rev;\n}\n\nfunction buildTableReverseMap(tblIdx: Map<string, Element>): Map<Element, string> {\n const rev = new Map<Element, string>();\n for (const [id, el] of tblIdx) rev.set(el, id);\n return rev;\n}\n\n/** 找元素所属的 Story(用 contains 检测,stories 数量通常 < 20)*/\nfunction findStoryForEl(el: Element, stories: Story[]): Story | undefined {\n for (const s of stories) {\n if (s.root.contains(el as unknown as Node)) return s;\n }\n return undefined;\n}\n\n// ─────────── 公开函数 ───────────\n\n/**\n * 枚举文档表格,按文档顺序返回(与 tblIdx 插入顺序一致)。\n *\n * - `scope: 'body'`(默认)—— 仅主文档 <w:body>\n * - `includeNested: false`(默认)—— 跳过嵌套在其他表格内的表格\n */\nexport function listTables(\n pkg: Package,\n indices: PackageIndices,\n opts?: ListTablesOptions,\n): TableInfo[] {\n const scope = opts?.scope ?? 'body';\n const includeNested = opts?.includeNested ?? false;\n const includeCellTexts = opts?.includeCellTexts ?? false;\n\n const stories = resolveScope(pkg, scope);\n const result: TableInfo[] = [];\n let idx = 1;\n\n // cell 图 drawingId 反查表:仅 includeCellTexts 时构建(A1)。\n const drawingToId = includeCellTexts\n ? buildDrawingReverseMap(indices.drawingIdx)\n : EMPTY_DRAWING_REV;\n const tableToId = includeCellTexts ? buildTableReverseMap(indices.tblIdx) : EMPTY_TABLE_REV;\n\n // 直接遍历 tblIdx(插入顺序 = 文档顺序)\n for (const [tableId, tbl] of indices.tblIdx) {\n if (!includeNested && hasTableAncestor(tbl)) continue;\n\n const story = findStoryForEl(tbl, stories);\n if (!story) continue; // 不在请求的 scope 内\n\n result.push(\n analyzeTable(tbl, tableId, story.partPath, idx++, includeCellTexts, drawingToId, tableToId),\n );\n }\n\n return result;\n}\n\n/** includeCellTexts=false 时复用的空反查表(不分配)。 */\nconst EMPTY_DRAWING_REV: Map<Element, string> = new Map();\nconst EMPTY_TABLE_REV: Map<Element, string> = new Map();\n\n/**\n * 按 tableId 精确取单个表格,O(1)。不存在返回 null。\n * 入参 `includeCellTexts` 与 `listTables` 同义(默认 false)。\n */\nexport function getTableById(\n pkg: Package,\n indices: PackageIndices,\n tableId: string,\n opts?: { includeCellTexts?: boolean },\n): TableInfo | null {\n const tbl = indices.tblIdx.get(tableId);\n if (!tbl) return null;\n\n // 找所属 story 以获取 partPath\n const stories = resolveScope(pkg, 'all');\n const story = findStoryForEl(tbl, stories);\n if (!story) return null;\n\n const includeCellTexts = opts?.includeCellTexts ?? false;\n const drawingToId = includeCellTexts\n ? buildDrawingReverseMap(indices.drawingIdx)\n : EMPTY_DRAWING_REV;\n const tableToId = includeCellTexts ? buildTableReverseMap(indices.tblIdx) : EMPTY_TABLE_REV;\n\n return analyzeTable(tbl, tableId, story.partPath, 0, includeCellTexts, drawingToId, tableToId);\n}\n\n// ─────────── getTableVerbatim(task-20260616-table-content-driven)───────────\n\n/** 一张格内图的预解析字节(按源 <a:blip @r:embed> 原始 rId 索引)。 */\nexport interface TableVerbatimImage {\n originalRId: string;\n bytes: Uint8Array;\n contentType: string;\n}\n\n/** verbatim 取一张表的自包含 payload(供跨文档搬表 insertTableFrom)。 */\nexport interface TableVerbatim {\n /** `<w:tbl>` 子树序列化字符串(命名空间随子树带入)。 */\n tableXml: string;\n /** 表内所有格内图的预解析字节(按原 rId)。原 rId 解析不到字节的图不收(搬入时 warn 降级)。 */\n images: TableVerbatimImage[];\n}\n\n/**\n * 按 tableId verbatim 取一张表的 OOXML 子树 + 其格内图字节,打包成自包含 payload。\n *\n * 这是\"数据表 = 内容块\"(§13.9)的**源侧读取**:调用方(typeset)拿到此 payload 后用\n * `plan.insertTableFrom(...)` 把整表 verbatim 搬进输出文档(与图片 getImageBytes→insertImageAfter\n * 同构)。表的行/列/值/合并/嵌套/格内图全保真——这里只做读取 + 序列化 + 解析格内图字节,\n * **不裁剪、不重建**。\n *\n * tableId 不存在 → 返回 null。\n */\nexport function getTableVerbatim(\n pkg: Package,\n indices: PackageIndices,\n tableId: string,\n): TableVerbatim | null {\n const tbl = indices.tblIdx.get(tableId);\n if (!tbl) return null;\n\n // 序列化 <w:tbl> 子树(命名空间随子树带入,已验证 importNode 往返保真)。\n const tableXml = serializeToWellFormedString(tbl as never);\n\n // 收集表内所有 <a:blip @r:embed>,按原 rId 解析出原始字节。\n const story = findStoryFor(pkg, tbl);\n const hostPartPath = story?.partPath;\n const images: TableVerbatimImage[] = [];\n if (hostPartPath) {\n const seen = new Set<string>();\n const blips = tbl.getElementsByTagNameNS(A_NS, 'blip');\n for (let i = 0; i < blips.length; i++) {\n const blip = blips[i];\n if (!blip) continue;\n const rId = blip.getAttributeNS(R_NS, 'embed');\n if (!rId || seen.has(rId)) continue;\n seen.add(rId);\n const resolved = resolveImageBytesByRId(pkg, hostPartPath, rId);\n if (resolved) {\n images.push({ originalRId: rId, bytes: resolved.bytes, contentType: resolved.contentType });\n }\n // 解析不到(如外链图/损坏 rels)→ 不收;搬入时该 blip embed 清掉 + warn(结构/文字保真)。\n }\n }\n\n return { tableXml, images };\n}\n\n/**\n * 按宿主 part + rId 解析图片字节(rels → media part)。\n * 与 insert-image-ops.getImageBytesSync 的 rels/media 解析同源,但入口是 rId(非 drawingId),\n * 供 getTableVerbatim 直接拿格内图的原始字节。\n */\nfunction resolveImageBytesByRId(\n pkg: Package,\n hostPartPath: string,\n rId: string,\n): { bytes: Uint8Array; contentType: string } | null {\n const relsPath = relsPathFor(hostPartPath);\n const relsPart = getPart(pkg, relsPath);\n if (!relsPart || !isXmlPart(relsPart) || !relsPart.xmlDom) return null;\n const RELS_NS = 'http://schemas.openxmlformats.org/package/2006/relationships';\n const rels = relsPart.xmlDom.getElementsByTagNameNS(RELS_NS, 'Relationship');\n let mediaPath: string | null = null;\n for (let i = 0; i < rels.length; i++) {\n const r = rels[i]!;\n if (r.getAttribute('Id') === rId) {\n mediaPath = resolveRelTarget(relsPath, r.getAttribute('Target') ?? '');\n break;\n }\n }\n if (!mediaPath) return null;\n const mediaPart = getPart(pkg, mediaPath);\n if (!mediaPart) return null;\n const bytes = (mediaPart as unknown as { bytes?: Uint8Array }).bytes;\n if (!bytes) return null;\n return { bytes, contentType: mediaPart.contentType };\n}\n\n/** part 路径 → 对应 .rels 路径('word/document.xml' → 'word/_rels/document.xml.rels')。 */\nfunction relsPathFor(partPath: string): string {\n const idx = partPath.lastIndexOf('/');\n if (idx < 0) return `_rels/${partPath}.rels`;\n const dir = partPath.slice(0, idx);\n const name = partPath.slice(idx + 1);\n return `${dir}/_rels/${name}.rels`;\n}\n\n/** rels Target → 绝对 package 路径(处理 '/' 前缀、'./'、'../' 回溯)。 */\nfunction resolveRelTarget(relsPartPath: string, target: string): string {\n let t = target.trim();\n if (t.startsWith('/')) return t.slice(1);\n while (t.startsWith('./')) t = t.slice(2);\n const idx = relsPartPath.lastIndexOf('/_rels/');\n if (idx < 0) return t;\n const hostDir = relsPartPath.slice(0, idx);\n let parts = hostDir.split('/').filter(Boolean);\n while (t.startsWith('../')) {\n parts = parts.slice(0, -1);\n t = t.slice(3);\n }\n return parts.length === 0 ? t : `${parts.join('/')}/${t}`;\n}\n\n/**\n * 装载期构建 tblIdx:枚举 Package 中所有内容 part 的 <w:tbl>,\n * 按文档顺序分配 'tbl-NNNN' ID。由 buildIndices 调用。\n *\n * 内部函数,不对外导出。\n */\nexport function buildTableIndex(\n parts: Iterable<{\n contentType: string;\n xmlDom?: {\n getElementsByTagNameNS(\n ns: string,\n local: string,\n ): { length: number } & Record<number, Element>;\n };\n }>,\n): Map<string, Element> {\n const tblIdx = new Map<string, Element>();\n let n = 1;\n\n for (const part of parts) {\n const ct = part.contentType;\n // 只扫 Word 内容 part(同 buildIndices 的 isWordContentPart 逻辑)\n if (\n !ct.includes('wordprocessingml') &&\n !ct.endsWith('.main+xml') &&\n !ct.endsWith('.header+xml') &&\n !ct.endsWith('.footer+xml') &&\n !ct.endsWith('.footnotes+xml') &&\n !ct.endsWith('.endnotes+xml')\n // 不扫 comments.xml:注释内通常无表格,跳过\n ) {\n continue;\n }\n if (!part.xmlDom) continue;\n\n const tbls = part.xmlDom.getElementsByTagNameNS(W_NS, 'tbl');\n for (let i = 0; i < tbls.length; i++) {\n const tbl = tbls[i];\n if (!tbl) continue;\n const id = `tbl-${String(n).padStart(4, '0')}`;\n tblIdx.set(id, tbl);\n n++;\n }\n }\n\n return tblIdx;\n}\n","/**\n * Run 操作原语 —— 给后续 #28 replaceTextInParagraph 调用。\n *\n * 本模块只提供最小、可组合的基本操作:\n * - getParagraphRuns / getRunText / getParagraphText:只读查询\n * - splitRunAt:在 run 内 text offset 处拆一个 run 为两个(共享 <w:rPr>)\n *\n * **边界**(本期限制,后续按需扩展):\n * - splitRunAt 仅支持 \"run 下恰有一个 <w:t>\" 的简单情况\n * - 复杂结构(多个 <w:t>、含 <w:br> / <w:tab> / <w:sym> / <w:fldChar> 等)明确抛错\n * - <w:t xml:space=\"preserve\"> 的 xml:space 属性在拆分时保留\n *\n * **保真读 opt-in**(task-20260623-core-tab-faithful-read):\n * - `getRunText(run, { structuralWhitespace: true })` 按 appendSegmentsToRun 的精确逆运算还原\n * `<w:tab/>` → `\\t`、`<w:br/>` (无 type 或 textWrapping)→ `\\n`。\n * - 默认(不传 opts 或 structuralWhitespace: false)行为逐字节不变:只拼 `<w:t>`。\n * - **偏移算术调用方**(bookmark-ops / comment-ops / paragraph-ops 共 7 处)\n * **不得**传 `structuralWhitespace: true`——偏移依赖 tab 算 0 长保持稳定。\n */\nimport { W_NS } from './namespaces.js';\n\n/**\n * `getRunText` / `getParagraphText` 可选参数(task-20260623-core-tab-faithful-read)。\n *\n * - `structuralWhitespace: true`:保真读模式——按 appendSegmentsToRun 的精确逆运算,\n * `<w:tab/>` → `\\t`、`<w:br/>` (无 w:type 或 w:type=\"textWrapping\")→ `\\n`。\n * - 缺省 / `false`:现行为(只拼 `<w:t>`),**偏移算术安全**。\n */\nexport interface RunTextOptions {\n /**\n * 启用结构空白保真读:`<w:tab/>` → `\\t`,`<w:br/>` → `\\n`。\n * **仅用于内容读取**,不得用于偏移算术(bookmark/comment/replaceText 等)。\n */\n structuralWhitespace?: boolean;\n}\n\nfunction isWElement(node: Node, localName: string): boolean {\n return (\n node.nodeType === 1 &&\n (node as Element).namespaceURI === W_NS &&\n (node as Element).localName === localName\n );\n}\n\n/** 段落 `<w:p>` 下所有直接 `<w:r>` 子元素(不递归到嵌套段落 / smartTag 等) */\nexport function getParagraphRuns(paragraph: Element): Element[] {\n const runs: Element[] = [];\n const children = paragraph.childNodes;\n for (let i = 0; i < children.length; i++) {\n const child = children[i];\n if (child && isWElement(child, 'r')) {\n runs.push(child as Element);\n }\n }\n return runs;\n}\n\n/**\n * 取 run 的文本。\n *\n * - 默认(opts 缺省 / `structuralWhitespace: false`):只拼 `<w:t>` 文本,忽略 `<w:br>` / `<w:tab>`。\n * **偏移算术安全**:`<w:tab/>` 算 0 长,保持 bookmark/comment/replaceText 偏移稳定。\n * - `structuralWhitespace: true`:保真读——按文档顺序遍历子节点:\n * `<w:t>` → textContent、`<w:tab/>` → `\\t`、`<w:br/>` (无 w:type 或 textWrapping)→ `\\n`。\n * 这是 `appendSegmentsToRun` 的精确逆运算。\n */\nexport function getRunText(run: Element, opts?: RunTextOptions): string {\n const faithful = opts?.structuralWhitespace === true;\n let text = '';\n const children = run.childNodes;\n for (let i = 0; i < children.length; i++) {\n const child = children[i];\n if (!child || child.nodeType !== 1) continue;\n const el = child as Element;\n if (el.namespaceURI !== W_NS) continue;\n const local = el.localName;\n if (local === 't') {\n text += el.textContent ?? '';\n } else if (faithful) {\n if (local === 'tab') {\n text += '\\t';\n } else if (local === 'br') {\n // 只还原无 type 或 type=\"textWrapping\" 的 <w:br/>(写侧产出的两种)\n // page/column break 等不在写侧逆运算内,忽略\n const type = el.getAttributeNS(W_NS, 'type');\n if (type === null || type === '' || type === 'textWrapping') {\n text += '\\n';\n }\n }\n }\n }\n return text;\n}\n\n/**\n * 段落的纯文本(所有直接 run 的文本拼接)。\n *\n * - 默认(opts 缺省):只拼 `<w:t>`,偏移算术安全。\n * - `structuralWhitespace: true`:保真读,透传到 `getRunText`。\n */\nexport function getParagraphText(paragraph: Element, opts?: RunTextOptions): string {\n return getParagraphRuns(paragraph)\n .map((r) => getRunText(r, opts))\n .join('');\n}\n\n/** splitRunAt 返回值 */\nexport interface SplitResult {\n /** 原 run,文本截取到 [0, offset) */\n before: Element;\n /**\n * 分裂出的新 run,文本为 [offset, end)。\n * 与 `before` 共享 `<w:rPr>` 结构(深拷贝,不共享对象引用)。\n * offset=0 或 offset=runLen 时为 null(未发生分裂)\n */\n after: Element | null;\n}\n\n/**\n * 在 run 的文本 offset 处拆分。\n *\n * - `offset === 0` 或 `offset === getRunText(run).length` → 不拆,返回 { before: run, after: null }\n * - 其它情况 → 新 run 插入到原 run 的 nextSibling 位置,返回 { before: run, after: newRun }\n *\n * 本期限制:run 必须恰有 1 个 `<w:t>` 子;否则抛错(多 <w:t>、<w:br>、<w:tab> 等复杂结构交给\n * 后续 #28 的扩展实现)。\n */\nexport function splitRunAt(run: Element, offset: number): SplitResult {\n if (!isWElement(run, 'r')) {\n throw new Error('splitRunAt: argument is not a <w:r> element');\n }\n const tElements: Element[] = [];\n const children = run.childNodes;\n for (let i = 0; i < children.length; i++) {\n const c = children[i];\n if (c && isWElement(c, 't')) tElements.push(c as Element);\n }\n if (tElements.length === 0) {\n throw new Error(\n 'splitRunAt: run has no <w:t> children; this primitive supports single-<w:t> runs only',\n );\n }\n if (tElements.length > 1) {\n throw new Error(\n `splitRunAt: run has ${tElements.length} <w:t> children; this primitive supports single-<w:t> runs only`,\n );\n }\n\n const originalT = tElements[0]!;\n const runText = originalT.textContent ?? '';\n if (offset < 0 || offset > runText.length) {\n throw new Error(`splitRunAt: offset ${offset} out of range [0, ${runText.length}]`);\n }\n if (offset === 0 || offset === runText.length) {\n return { before: run, after: null };\n }\n\n const leftText = runText.slice(0, offset);\n const rightText = runText.slice(offset);\n\n // 截取原 run 的文本到左半\n originalT.textContent = leftText;\n\n // 克隆整个 run 作为 after;克隆深拷贝会把 <w:rPr> 和 <w:t xml:space> 一起复制\n const afterRun = run.cloneNode(true) as Element;\n // 找到 after run 中的那个 <w:t>,写入右半文本\n const afterChildren = afterRun.childNodes;\n for (let i = 0; i < afterChildren.length; i++) {\n const c = afterChildren[i];\n if (c && isWElement(c, 't')) {\n (c as Element).textContent = rightText;\n break;\n }\n }\n\n // 插入 afterRun 到原 run 之后\n const parent = run.parentNode;\n if (!parent) {\n throw new Error('splitRunAt: run has no parent; cannot insert new run');\n }\n parent.insertBefore(afterRun, run.nextSibling);\n\n return { before: run, after: afterRun };\n}\n","/**\n * listParagraphs —— 段落查询纯工具(docs/03 §9 / docs/03.1 §1.6,#24)。\n *\n * 职责:按 scope / filter / textFormat / pagination 返回 ParagraphInfo 列表。\n *\n * 架构:**纯函数**,拿 pkg 给结果,不知道文档尺寸、不做智能默认。\"默认分页\"\n * 是 `{ mode: 'byCount', pageSize: 25, pageIndex: 0 }`,要全量请显式传\n * `{ pagination: { mode: 'all' } }`(2026-04-22 从早期\"≤500 段自动 all\"的智能\n * 默认撤回;见 docs/03 §9.2 的历史说明)。\n *\n * 实现约束:\n * - 段落枚举走 `getStoryParagraphs`(基于 `getElementsByTagNameNS`),**不**用\n * fontoxpath。10 万段落上 `//w:p` 慢 460× —— CI 的 `pnpm check:xpath` 会在\n * 源码里扫到此类无谓词 XPath 即失败。\n * - `filter.contains` 是 O(N) 子串匹配,大档慢(docs 已标注)。\n * - `hasComments` / `hasRevisions` / `hasBookmarks` 用 `el.getElementsByTagNameNS(...).length > 0`\n * 检测段内是否存在对应标记元素,不递归手遍。\n */\nimport type { Package } from '../pack/index.js';\nimport type { PackageIndices } from './indices.js';\nimport { buildTableIndex } from './list-tables.js';\nimport { MATH_NS, W14_NS, W_NS } from './namespaces.js';\nimport { getParagraphText, type RunTextOptions } from './runs.js';\nimport { findStoryFor, getStoryParagraphs, resolveScope, type StoryId } from './stories.js';\n\n/** list scope —— 'body' / 'all' 或显式 StoryId 列表 */\nexport type ListParagraphsScope = 'body' | 'all' | StoryId[];\n\n/** text 返回格式。'preview' = 首 100 字 */\nexport type ListParagraphsTextFormat = 'full' | 'preview';\n\nexport interface ListParagraphsFilter {\n /** 等值匹配 `<w:pPr>/<w:pStyle w:val>` */\n styleId?: string;\n /** **O(N) 子串匹配**,区分大小写。大档谨慎使用。 */\n contains?: string;\n /** 段内是否含 comment 标记(commentRangeStart / commentReference / commentRangeEnd) */\n hasComments?: boolean;\n /** 段内是否含 revision 标记(Tier 1 只看 w:ins / w:del,不含 rPrChange/pPrChange) */\n hasRevisions?: boolean;\n /**\n * 排除位于表格单元格(`<w:tc>`)内的段落。\n *\n * 表格内容由独立的 tables phase 处理,段落 phase 只关心主文本流段落。\n * 开启后会对每个段落向上遍历祖先链(深度通常 ≤5),找到 `<w:tc>` 即排除。\n */\n excludeTableCells?: boolean;\n}\n\nexport type ListParagraphsPagination =\n | { mode: 'all' }\n | { mode: 'byCount'; pageSize: number; pageIndex: number }\n | { mode: 'byChar'; charPerPage: number; pageIndex: number };\n\n/**\n * 段落直接格式属性(#182)。\n *\n * 仅包含在 `<w:pPr>` 上**直接设置**的值,不做样式继承计算。\n * 消费方(如骨架化引擎)可将这些值与 styleId 组合为聚类 key,\n * 区分同一样式但有手工格式覆盖的段落。\n *\n * 所有字段均为可选——未直接设置的属性不出现在结果中(继承自样式或默认值)。\n */\nexport interface ParagraphFormat {\n /**\n * 水平对齐(`w:pPr/w:jc@w:val`)。\n * `'both'` 对应 OOXML 的 \"both\"(两端对齐)。\n */\n alignment?: 'left' | 'center' | 'right' | 'both' | 'distribute';\n /**\n * 缩进(`w:pPr/w:ind`),单位 twips(1/20 磅)。\n * `firstLine` 正值为首行缩进,负值为悬挂缩进(来自 `w:hanging`)。\n */\n indent?: {\n left?: number;\n right?: number;\n /** 首行缩进(正)或悬挂缩进(负,源自 `w:hanging`) */\n firstLine?: number;\n };\n /**\n * 段间距(`w:pPr/w:spacing`),单位 twips(line 例外:受 lineRule 影响)。\n */\n spacing?: {\n before?: number;\n after?: number;\n line?: number;\n lineRule?: 'auto' | 'exact' | 'atLeast';\n };\n /**\n * 段落级默认字体大小(`w:pPr/w:rPr/w:sz@w:val ÷ 2`),单位磅。\n * 仅当段落属性中显式设置了 `w:rPr/w:sz` 时有值;继承自样式的字号不在此字段。\n */\n fontSize?: number;\n /**\n * 段落级默认粗体(`w:pPr/w:rPr/w:b`)。\n * `true` = 显式开启;`false` = 显式关闭(`w:val=\"0\"`);\n * 字段不存在 = 未直接设置(继承自样式)。\n */\n bold?: boolean;\n /**\n * 大纲级别(`w:pPr/w:outlineLvl@w:val`),0–8 对应标题 1–9,9 表示正文。\n * WPS / Word 的自定义标题样式通常在此字段直接编码级别,即使 basedOn 是 Normal。\n * 字段不存在 = 未在段落级直接设置(继承自样式或默认值)。\n */\n outlineLevel?: number;\n /**\n * 段落是否直接挂有编号属性(`w:pPr/w:numPr` 存在且含 `w:numId@w:val != \"0\"`)。\n * 用于列表检测:有编号属性的段落通常是列表项。\n */\n hasNumbering?: boolean;\n /**\n * 段落是否强制从新页起始(`w:pPr/w:pageBreakBefore`,#211)。\n * true = 渲染该段时从新页开始(封面段的强信号之一)。\n * 字段不存在 = 未在段落级直接设置(继承自样式或默认 false)。\n */\n pageBreakBefore?: boolean;\n /**\n * 段落是否承载节属性(`w:pPr/w:sectPr` 存在,#211)。\n * true = 该段是其所属节的最后一段,节边界在此结束。\n * 与 doc.sections.list() 的 lastParaId 字段对应。\n */\n hasSectionBreak?: boolean;\n /**\n * 段落内是否含手工分页符(`w:r/w:br[@w:type=\"page\"]`,#211)。\n * 与 pageBreakBefore 互补 —— 后者作用于段首,前者可出现在段中/段尾。\n * 字段不存在 = 段内无手工分页符。\n */\n hasManualPageBreak?: boolean;\n /**\n * 段落级默认字体颜色(`w:pPr/w:rPr/w:color@w:val`,task-20260615-redhead-fingerprint)。\n * 段标 run 颜色,作用于无独立 rPr 的 run。值为 6 位十六进制 `RRGGBB`(如 `FF0000`)或 `auto`。\n * 仅当段落属性中显式设置了 `w:pPr/w:rPr/w:color` 时有值;继承自样式的颜色不在此字段。\n *\n * 用途(骨架化 / 排版的视觉簇判据):判定\"封面式文头\"等需区分色异段(如红头)。\n * 注意:行内首 run 的颜色单独由 {@link firstRunColor} 提供——很多文档把红色编码在 run 级\n * 而非段标级,两者互补使用。\n */\n color?: string;\n /**\n * 段落**首个**直属 run(`w:r/w:rPr/w:color@w:val`)的字体颜色(task-20260615-redhead-fingerprint)。\n * 值为 6 位十六进制 `RRGGBB` 或 `auto`。仅当首个直属 run 显式设了 `w:color` 时有值。\n *\n * 与 {@link color}(段标级)互补:红头/标题等视觉显著段的颜色常落在 run 级 rPr 而非段标 rPr,\n * 需读首 run 才能拿到。取**首个直属 run**(非表格/文本框下钻),与 getParagraphText 的直属 run\n * 语义对齐;段内多 run 颜色不一致时只反映首 run(满足\"段首视觉身份\"判据,不做整段聚合)。\n */\n firstRunColor?: string;\n}\n\nexport interface ListParagraphsOptions {\n /** 默认 'body' */\n scope?: ListParagraphsScope;\n filter?: ListParagraphsFilter;\n /** 默认 'full' */\n textFormat?: ListParagraphsTextFormat;\n /** 默认 `{ mode: 'byCount', pageSize: 25, pageIndex: 0 }`(不再有\"智能默认\") */\n pagination?: ListParagraphsPagination;\n /**\n * 是否在结果中包含段落直接格式属性(`ParagraphFormat`)。\n * 默认 `false`。开启后每个 `ParagraphInfo.format` 会携带从 `<w:pPr>` 读取的直接设置值。\n * 仅包含直接设置的属性,不做样式继承计算。\n */\n includeFormat?: boolean;\n /**\n * 启用结构空白保真读(task-20260623-core-tab-faithful-read)。\n * `true` 时 `ParagraphInfo.text` 含 `\\t`(制表符)和 `\\n`(软换行),\n * 是 `appendSegmentsToRun` 的精确逆运算。\n * 默认 `false`:只拼 `<w:t>`,偏移算术安全(与历史行为完全一致)。\n */\n structuralWhitespace?: boolean;\n /**\n * 是否在结果中包含段落所在表格的坐标信息(task-20260625-para-table-info)。\n * 默认 `false`。\n *\n * 开启后,位于表格单元格内的段落会携带 `ParagraphInfo.table`(tableId / row / col)。\n * 表格外段落的 `table` 字段不出现。\n *\n * 与 `includeFormat` 是独立开关:表格归属是结构信息,不是格式。\n * 开启时会对每个段落做一次祖先链遍历(深度 ≤ 5),\n * 并在首次调用时构建 `<w:tbl> Element → tableId` 反查映射(O(表格数))。\n */\n includeTableInfo?: boolean;\n}\n\nexport interface ParagraphInfo {\n paraId: string;\n story: StoryId;\n /** textFormat='preview' 时为首 100 字 */\n text: string;\n /** preview 模式被截断时为 true;full 模式/未截断不给 */\n truncated?: boolean;\n /** `<w:pStyle w:val>` 未设则缺 */\n styleId?: string;\n hasRevisions?: boolean;\n hasComments?: boolean;\n hasBookmarks?: boolean;\n /**\n * 段落子树是否含 OMML 公式对象(`<m:oMath>`,math namespace)。\n * Word「插入→公式」生成的公式对象。纯文字写的\"公式\"(如 \"F=ma\")不算。\n * 含则为 true;不含时不给(与 hasComments 等同风格)。\n */\n hasMath?: boolean;\n /**\n * 段落直接格式属性。仅在 `listParagraphs` 传入 `includeFormat: true` 时存在。\n * 不包含从样式继承的属性值。\n */\n format?: ParagraphFormat;\n /**\n * 段落所在表格坐标。仅当 `includeTableInfo=true` 且段落位于表格单元格内时存在。\n *\n * - `tableId`:与 `doc.tables.list()` / `getTable()` 使用的 id 完全一致(装载期\n * `buildIndices` 分配的 `tbl-NNNN`)。\n * - `row`:所在 `<w:tr>` 在该表中的 0 基行号。\n * - `col`:所在 `<w:tc>` 在该行中的 0 基列号(物理序号)。\n *\n * 注:`col` 是物理 `<w:tc>` 序号,**不**做 gridSpan / vMerge 的逻辑列号校正——\n * 含合并单元格的表格中,物理序号与逻辑列号可能不同。v1 取物理序号已能满足\n * \"区分表格内/外编号序列\"的主场景;如需精确逻辑列号,可在 v2 补充。\n *\n * 嵌套表格时报**最内层**的表格。\n */\n table?: { tableId: string; row: number; col: number };\n}\n\nexport interface ListResult {\n paragraphs: ParagraphInfo[];\n pagination: {\n mode: 'all' | 'byCount' | 'byChar';\n pageIndex: number;\n totalPages: number;\n totalParagraphs: number;\n hasNext: boolean;\n /**\n * 保留字段,当前实现恒不填(#24 把\"≤500 段自动 all\"的智能默认撤回,改为恒定\n * byCount(25,0)默认;docs/03 §9.2)。调用方不应依赖。\n */\n autoPaginated?: boolean;\n };\n}\n\n/** 默认分页:首页、25 条 */\nexport const DEFAULT_PAGINATION: ListParagraphsPagination = {\n mode: 'byCount',\n pageSize: 25,\n pageIndex: 0,\n};\n\n/** preview 截断字数 */\nexport const PREVIEW_CHAR_LIMIT = 100;\n\nexport function listParagraphs(pkg: Package, opts: ListParagraphsOptions = {}): ListResult {\n // 1. scope → stories(resolveScope 在 stories.ts,#26 起被 listRevisions 共用)\n const stories = resolveScope(pkg, opts.scope ?? 'body');\n\n // 2. flatten (story, paragraphEl)\n interface Entry {\n story: StoryId;\n el: Element;\n }\n const all: Entry[] = [];\n for (const story of stories) {\n for (const el of getStoryParagraphs(story)) {\n all.push({ story: story.id, el });\n }\n }\n\n // 3. filter(在分页前,totalParagraphs 取过滤后)\n const filtered = opts.filter ? all.filter((e) => matchesFilter(e.el, opts.filter!)) : all;\n\n // 4. 分页\n const pagination = opts.pagination ?? DEFAULT_PAGINATION;\n const { slice, meta } = paginate(filtered, pagination);\n\n // 5. 映射为 ParagraphInfo(textFormat 在此应用 preview 截断)\n const textFormat = opts.textFormat ?? 'full';\n const includeFormat = opts.includeFormat ?? false;\n const runTextOpts: RunTextOptions | undefined = opts.structuralWhitespace\n ? { structuralWhitespace: true }\n : undefined;\n\n // includeTableInfo=true 时构建 tblElement → tableId 反查 Map(O(表格数),只做一次)\n // buildTableIndex 返回 Map<tableId, tblEl>,反转后可从 Element 查 tableId\n let tblReverseIdx: Map<Element, string> | undefined;\n if (opts.includeTableInfo) {\n const tblIdx = buildTableIndex(pkg.parts.values());\n tblReverseIdx = new Map<Element, string>();\n for (const [id, el] of tblIdx) {\n tblReverseIdx.set(el, id);\n }\n }\n\n const paragraphs = slice.map((e) =>\n buildInfo(e.story, e.el, textFormat, includeFormat, runTextOpts, tblReverseIdx),\n );\n\n return { paragraphs, pagination: meta };\n}\n\n// ─────────── filter ───────────\n\nfunction matchesFilter(p: Element, f: ListParagraphsFilter): boolean {\n // excludeTableCells 放最前:祖先遍历 O(depth≤5),比文本扫描快,能快速排除大量表格段落\n if (f.excludeTableCells) {\n if (isInTableCell(p)) return false;\n }\n if (f.styleId !== undefined) {\n if (getStyleId(p) !== f.styleId) return false;\n }\n if (f.hasComments !== undefined) {\n if (detectHasComments(p) !== f.hasComments) return false;\n }\n if (f.hasRevisions !== undefined) {\n if (detectHasRevisions(p) !== f.hasRevisions) return false;\n }\n // contains 放最后:O(N) 全文扫,前面的廉价过滤已能淘汰大部分段落\n if (f.contains !== undefined) {\n if (!getParagraphText(p).includes(f.contains)) return false;\n }\n return true;\n}\n\n// ─────────── 属性检测 ───────────\n\nfunction getStyleId(p: Element): string | undefined {\n // <w:p><w:pPr><w:pStyle w:val=\"xxx\"/></w:pPr>\n const pPr = firstDirectChild(p, W_NS, 'pPr');\n if (!pPr) return undefined;\n const pStyle = firstDirectChild(pPr, W_NS, 'pStyle');\n if (!pStyle) return undefined;\n const val = pStyle.getAttributeNS(W_NS, 'val');\n return val ?? undefined;\n}\n\nfunction firstDirectChild(el: Element, ns: string, local: string): Element | null {\n const children = el.childNodes;\n for (let i = 0; i < children.length; i++) {\n const c = children[i];\n if (\n c &&\n c.nodeType === 1 &&\n (c as Element).namespaceURI === ns &&\n (c as Element).localName === local\n ) {\n return c as Element;\n }\n }\n return null;\n}\n\n/**\n * 判断 `<w:p>` 是否位于表格单元格(`<w:tc>`)内。\n *\n * 向上遍历祖先链:遇到 `<w:tc>` 返回 true,遇到 `<w:body>` 或到达根节点返回 false。\n * 典型深度:body > tbl > tr > tc > p = 4 跳,代价可忽略。\n */\nfunction isInTableCell(p: Element): boolean {\n let el: Element | null = p.parentElement;\n while (el) {\n if (el.namespaceURI === W_NS) {\n if (el.localName === 'tc') return true;\n if (el.localName === 'body') return false; // 到达 body 层,不可能再有 tc\n }\n el = el.parentElement;\n }\n return false;\n}\n\n/**\n * 一次祖先遍历,同时拿到 `<w:tc>`、`<w:tr>`、最内层 `<w:tbl>` 三个祖先元素。\n *\n * 遍历策略:向上走,遇到首个 `<w:tc>` 记录为 tc,继续向上遇到 `<w:tr>` 记录为 tr,\n * 再继续向上遇到首个 `<w:tbl>` 记录为 tbl(即最内层表格),然后停止。\n * 遇到 story 根元素(body / hdr / ftr 等)仍未找到 `<w:tc>` 则返回 null(段落不在表格内)。\n *\n * 嵌套表格时 tbl 是最内层表格(因为自下而上遇到的第一个 tbl 就是最内层的)。\n */\nfunction getTableCellAncestors(p: Element): { tc: Element; tr: Element; tbl: Element } | null {\n let tc: Element | null = null;\n let tr: Element | null = null;\n let el: Element | null = p.parentElement;\n\n while (el) {\n if (el.namespaceURI === W_NS) {\n if (!tc) {\n if (el.localName === 'tc') {\n tc = el;\n } else if (\n el.localName === 'body' ||\n el.localName === 'hdr' ||\n el.localName === 'ftr' ||\n el.localName === 'footnote' ||\n el.localName === 'endnote' ||\n el.localName === 'comment'\n ) {\n // 到达 story 根,段落不在表格内\n return null;\n }\n } else if (!tr) {\n if (el.localName === 'tr') {\n tr = el;\n }\n } else {\n // tc 和 tr 都已找到,找最内层 tbl\n if (el.localName === 'tbl') {\n return { tc, tr, tbl: el };\n }\n }\n }\n el = el.parentElement;\n }\n return null;\n}\n\n/**\n * 计算 `<w:tr>` 在其父 `<w:tbl>` 的直属 `<w:tr>` 子元素序列中的 0 基行号。\n * 只计直属子元素(不误抓嵌套表的 tr)。\n */\nfunction rowIndexOf(tr: Element, tbl: Element): number {\n let idx = 0;\n const children = tbl.childNodes;\n for (let i = 0; i < children.length; i++) {\n const c = children[i] as Element;\n if (c.nodeType !== 1 || c.namespaceURI !== W_NS || c.localName !== 'tr') continue;\n if (c === tr) return idx;\n idx++;\n }\n return -1; // 理论上不可达\n}\n\n/**\n * 计算 `<w:tc>` 在其父 `<w:tr>` 的直属 `<w:tc>` 子元素序列中的 0 基列号(物理序号)。\n *\n * 注:此为物理列号,不做 gridSpan / vMerge 的逻辑列号校正——含合并单元格时物理序号\n * 与逻辑列号可能不同。v1 物理序号已满足\"区分表格内外编号序列\"的主场景。\n */\nfunction colIndexOf(tc: Element, tr: Element): number {\n let idx = 0;\n const children = tr.childNodes;\n for (let i = 0; i < children.length; i++) {\n const c = children[i] as Element;\n if (c.nodeType !== 1 || c.namespaceURI !== W_NS || c.localName !== 'tc') continue;\n if (c === tc) return idx;\n idx++;\n }\n return -1; // 理论上不可达\n}\n\n/** 段内是否含 revision 标记(Tier 1:只看 w:ins / w:del) */\nfunction detectHasRevisions(p: Element): boolean {\n return (\n p.getElementsByTagNameNS(W_NS, 'ins').length > 0 ||\n p.getElementsByTagNameNS(W_NS, 'del').length > 0\n );\n}\n\n/** 段内是否含 comment 标记 */\nfunction detectHasComments(p: Element): boolean {\n return (\n p.getElementsByTagNameNS(W_NS, 'commentRangeStart').length > 0 ||\n p.getElementsByTagNameNS(W_NS, 'commentRangeEnd').length > 0 ||\n p.getElementsByTagNameNS(W_NS, 'commentReference').length > 0\n );\n}\n\n/** 段内是否含 bookmark 标记 */\nfunction detectHasBookmarks(p: Element): boolean {\n return (\n p.getElementsByTagNameNS(W_NS, 'bookmarkStart').length > 0 ||\n p.getElementsByTagNameNS(W_NS, 'bookmarkEnd').length > 0\n );\n}\n\n/**\n * 段落子树是否含 OMML 公式对象(`<m:oMath>`)。\n * 覆盖块级(oMathPara > oMath)和内联(段内裸 oMath、run/hyperlink 内嵌 oMath)两种情形。\n * `getElementsByTagNameNS` 递归子树,天然覆盖所有深度。\n */\nfunction detectHasMath(p: Element): boolean {\n return p.getElementsByTagNameNS(MATH_NS, 'oMath').length > 0;\n}\n\n// ─────────── 分页 ───────────\n\ninterface PaginationOut<T> {\n slice: T[];\n meta: ListResult['pagination'];\n}\n\nfunction paginate<T extends { el: Element }>(\n items: T[],\n pag: ListParagraphsPagination,\n): PaginationOut<T> {\n const total = items.length;\n\n if (pag.mode === 'all') {\n return {\n slice: items,\n meta: {\n mode: 'all',\n pageIndex: 0,\n totalPages: total === 0 ? 0 : 1,\n totalParagraphs: total,\n hasNext: false,\n },\n };\n }\n\n if (pag.mode === 'byCount') {\n validatePositiveInt('pageSize', pag.pageSize);\n validateNonNegativeInt('pageIndex', pag.pageIndex);\n const totalPages = total === 0 ? 0 : Math.ceil(total / pag.pageSize);\n const start = pag.pageSize * pag.pageIndex;\n const slice = items.slice(start, start + pag.pageSize);\n return {\n slice,\n meta: {\n mode: 'byCount',\n pageIndex: pag.pageIndex,\n totalPages,\n totalParagraphs: total,\n hasNext: pag.pageIndex < totalPages - 1,\n },\n };\n }\n\n // byChar(docs/03 §9.3):按段落文本长度打包成页\n // 1. 累加当前段 text.length 到 buffer\n // 2. buf == 0 且 cur.length > charPerPage → 单段成页(保证完整)\n // 3. buf + next.length > charPerPage → 当前页结束,next 进下一页\n // 4. buf + next.length <= charPerPage → next 追加进当前页\n validatePositiveInt('charPerPage', pag.charPerPage);\n validateNonNegativeInt('pageIndex', pag.pageIndex);\n const pages: T[][] = [];\n let cur: T[] = [];\n let buf = 0;\n for (const item of items) {\n const len = getParagraphText(item.el).length;\n if (buf === 0 && len > pag.charPerPage) {\n // 规则 2:单段成页\n pages.push([item]);\n cur = [];\n buf = 0;\n continue;\n }\n if (buf + len > pag.charPerPage) {\n // 规则 3:当前页结束\n if (cur.length > 0) pages.push(cur);\n cur = [item];\n buf = len;\n } else {\n // 规则 4:追加到当前页\n cur.push(item);\n buf += len;\n }\n }\n if (cur.length > 0) pages.push(cur);\n const totalPages = pages.length;\n const slice = pages[pag.pageIndex] ?? [];\n return {\n slice,\n meta: {\n mode: 'byChar',\n pageIndex: pag.pageIndex,\n totalPages,\n totalParagraphs: total,\n hasNext: pag.pageIndex < totalPages - 1,\n },\n };\n}\n\nfunction validatePositiveInt(name: string, v: number): void {\n if (!Number.isInteger(v) || v < 1) {\n throw new Error(`listParagraphs: ${name} must be a positive integer, got: ${v}`);\n }\n}\n\nfunction validateNonNegativeInt(name: string, v: number): void {\n if (!Number.isInteger(v) || v < 0) {\n throw new Error(`listParagraphs: ${name} must be a non-negative integer, got: ${v}`);\n }\n}\n\n// ─────────── 单段查询(#25)───────────\n\n/**\n * 按 paraId 精确取段。走 paraIdx → O(1) 命中后反查 story。不存在或所属 story 识别\n * 不出(理论上只在 pkg 与 indices 脱钩时发生)返回 null。\n *\n * 总是返回 full 文本(无 textFormat/preview 选项,与 docs/03.1 §2 的签名一致)。\n */\nexport function getParagraphByParaId(\n pkg: Package,\n indices: PackageIndices,\n paraId: string,\n): ParagraphInfo | null {\n const el = indices.paraIdx.get(paraId.toUpperCase());\n if (!el) return null;\n const story = findStoryFor(pkg, el);\n if (!story) return null;\n return buildParagraphInfo(story.id, el, 'full');\n}\n\n// ─────────── ParagraphInfo 构建 ───────────\n\n/**\n * 从单个 `<w:p>` Element 构建 ParagraphInfo。\n *\n * 在 listParagraphs 内部给每个命中段落调用;**也供 `getParagraph`(#25)复用** ——\n * 它通过 paraIdx 拿到 Element 后,用 `findStoryFor` 找到 story,再调这里组装。\n */\nexport function buildParagraphInfo(\n story: StoryId,\n p: Element,\n textFormat: ListParagraphsTextFormat = 'full',\n includeFormat = false,\n runTextOpts?: RunTextOptions,\n): ParagraphInfo {\n return buildInfo(story, p, textFormat, includeFormat, runTextOpts);\n}\n\nfunction buildInfo(\n story: StoryId,\n p: Element,\n textFormat: ListParagraphsTextFormat,\n includeFormat: boolean,\n runTextOpts?: RunTextOptions,\n tblReverseIdx?: Map<Element, string>,\n): ParagraphInfo {\n const paraIdRaw = p.getAttributeNS(W14_NS, 'paraId') ?? '';\n // 与 indices.ts 的 paraIdx 一致,对外用大写(indices.ts:116 也做了 toUpperCase)\n const paraId = paraIdRaw.toUpperCase();\n\n const fullText = getParagraphText(p, runTextOpts);\n const truncated = textFormat === 'preview' && fullText.length > PREVIEW_CHAR_LIMIT;\n const text = truncated ? fullText.slice(0, PREVIEW_CHAR_LIMIT) : fullText;\n\n const styleId = getStyleId(p);\n const hasRevisions = detectHasRevisions(p);\n const hasComments = detectHasComments(p);\n const hasBookmarks = detectHasBookmarks(p);\n const hasMath = detectHasMath(p);\n\n const info: ParagraphInfo = { paraId, story, text };\n if (truncated) info.truncated = true;\n if (styleId !== undefined) info.styleId = styleId;\n if (hasRevisions) info.hasRevisions = true;\n if (hasComments) info.hasComments = true;\n if (hasBookmarks) info.hasBookmarks = true;\n if (hasMath) info.hasMath = true;\n\n if (includeFormat) {\n const pPr = firstDirectChild(p, W_NS, 'pPr');\n let fmt = pPr ? parseParagraphFormat(pPr) : undefined;\n // hasManualPageBreak 来源是 run 而非 pPr,单独检测后合并\n if (detectManualPageBreak(p)) {\n fmt = { ...(fmt ?? {}), hasManualPageBreak: true };\n }\n // firstRunColor 来源是首个直属 run 的 rPr(task-20260615-redhead-fingerprint),单独检测后合并\n const runColor = detectFirstRunColor(p);\n if (runColor !== undefined) {\n fmt = { ...(fmt ?? {}), firstRunColor: runColor };\n }\n if (fmt) info.format = fmt;\n }\n\n // includeTableInfo=true 时:一次祖先遍历拿 tc/tr/tbl,反查 tableId,计算 row/col\n if (tblReverseIdx !== undefined) {\n const ancestors = getTableCellAncestors(p);\n if (ancestors !== null) {\n const { tc, tr, tbl } = ancestors;\n const tableId = tblReverseIdx.get(tbl);\n if (tableId !== undefined) {\n const row = rowIndexOf(tr, tbl);\n const col = colIndexOf(tc, tr);\n info.table = { tableId, row, col };\n }\n }\n }\n\n return info;\n}\n\n// ─────────── 段落直接格式解析(#182)───────────\n\n/**\n * 从 `<w:pPr>` Element 解析段落直接格式属性。\n *\n * 只读取 pPr 上**直接写明**的值;继承自样式或文档默认值的属性不在此处理。\n * 若 pPr 中没有任何已知格式元素,返回 undefined(调用方可跳过 format 字段赋值)。\n */\nfunction parseParagraphFormat(pPr: Element): ParagraphFormat | undefined {\n const fmt: ParagraphFormat = {};\n let hasAny = false;\n\n // ── 对齐 w:jc ──\n const jc = firstDirectChild(pPr, W_NS, 'jc');\n if (jc) {\n const val = jc.getAttributeNS(W_NS, 'val');\n if (\n val === 'left' ||\n val === 'center' ||\n val === 'right' ||\n val === 'both' ||\n val === 'distribute'\n ) {\n fmt.alignment = val;\n hasAny = true;\n }\n }\n\n // ── 缩进 w:ind ──\n const ind = firstDirectChild(pPr, W_NS, 'ind');\n if (ind) {\n const left = numAttrTwips(ind, 'left');\n const right = numAttrTwips(ind, 'right');\n const firstLineRaw = numAttrTwips(ind, 'firstLine');\n const hangingRaw = numAttrTwips(ind, 'hanging');\n\n // firstLine 和 hanging 互斥,同时出现时 OOXML 规范以 firstLine 优先\n const firstLine =\n firstLineRaw !== undefined\n ? firstLineRaw\n : hangingRaw !== undefined\n ? -hangingRaw\n : undefined;\n\n if (left !== undefined || right !== undefined || firstLine !== undefined) {\n fmt.indent = {};\n if (left !== undefined) fmt.indent.left = left;\n if (right !== undefined) fmt.indent.right = right;\n if (firstLine !== undefined) fmt.indent.firstLine = firstLine;\n hasAny = true;\n }\n }\n\n // ── 段间距 w:spacing ──\n const spacing = firstDirectChild(pPr, W_NS, 'spacing');\n if (spacing) {\n const before = numAttrTwips(spacing, 'before');\n const after = numAttrTwips(spacing, 'after');\n const line = numAttrTwips(spacing, 'line');\n const lineRuleRaw = spacing.getAttributeNS(W_NS, 'lineRule');\n const lineRule =\n lineRuleRaw === 'auto' || lineRuleRaw === 'exact' || lineRuleRaw === 'atLeast'\n ? lineRuleRaw\n : undefined;\n\n if (\n before !== undefined ||\n after !== undefined ||\n line !== undefined ||\n lineRule !== undefined\n ) {\n fmt.spacing = {};\n if (before !== undefined) fmt.spacing.before = before;\n if (after !== undefined) fmt.spacing.after = after;\n if (line !== undefined) fmt.spacing.line = line;\n if (lineRule !== undefined) fmt.spacing.lineRule = lineRule;\n hasAny = true;\n }\n }\n\n // ── 段落级默认字体大小 w:pPr/w:rPr/w:sz ──\n const pRpr = firstDirectChild(pPr, W_NS, 'rPr');\n if (pRpr) {\n const sz = firstDirectChild(pRpr, W_NS, 'sz');\n if (sz) {\n const szVal = numAttrTwips(sz, 'val'); // w:sz 单位是半磅\n if (szVal !== undefined) {\n fmt.fontSize = szVal / 2; // 转为磅\n hasAny = true;\n }\n }\n\n // ── 段落级默认粗体 w:pPr/w:rPr/w:b ──\n const b = firstDirectChild(pRpr, W_NS, 'b');\n if (b) {\n const bVal = b.getAttributeNS(W_NS, 'val');\n // 无 val 属性或 val=\"1\"/\"true\" → bold; val=\"0\"/\"false\" → 显式关闭\n fmt.bold = bVal !== '0' && bVal !== 'false';\n hasAny = true;\n }\n\n // ── 段落级默认颜色 w:pPr/w:rPr/w:color(task-20260615-redhead-fingerprint)──\n const color = firstDirectChild(pRpr, W_NS, 'color');\n if (color) {\n const cVal = color.getAttributeNS(W_NS, 'val');\n if (cVal) {\n fmt.color = cVal;\n hasAny = true;\n }\n }\n }\n\n // ── 大纲级别 w:outlineLvl ──\n const outlineLvl = firstDirectChild(pPr, W_NS, 'outlineLvl');\n if (outlineLvl) {\n const val = numAttrTwips(outlineLvl, 'val');\n if (val !== undefined && val >= 0 && val <= 9) {\n fmt.outlineLevel = val;\n hasAny = true;\n }\n }\n\n // ── 编号属性 w:numPr ──\n const numPr = firstDirectChild(pPr, W_NS, 'numPr');\n if (numPr) {\n const numId = firstDirectChild(numPr, W_NS, 'numId');\n // numId@w:val=\"0\" 表示移除继承来的编号,不算\"有编号\"\n const numIdVal = numId?.getAttributeNS(W_NS, 'val');\n if (numIdVal !== undefined && numIdVal !== '0') {\n fmt.hasNumbering = true;\n hasAny = true;\n }\n }\n\n // ── 强制分页 w:pageBreakBefore(#211)──\n // 存在 = true;带 val=\"0\"/\"false\" = 显式关闭\n const pbb = firstDirectChild(pPr, W_NS, 'pageBreakBefore');\n if (pbb) {\n const v = pbb.getAttributeNS(W_NS, 'val');\n fmt.pageBreakBefore = v !== '0' && v !== 'false';\n hasAny = true;\n }\n\n // ── 节属性 w:sectPr(#211)──\n // 存在即视为该段承载节边界\n if (firstDirectChild(pPr, W_NS, 'sectPr')) {\n fmt.hasSectionBreak = true;\n hasAny = true;\n }\n\n return hasAny ? fmt : undefined;\n}\n\n/**\n * 检测段落内是否含手工分页符(`<w:r>/<w:br w:type=\"page\"/>`,#211)。\n *\n * 遍历段落直属 `<w:r>` 的 `<w:br>` 子元素,找 type='page' 的即返回 true。\n * 段属性外的 ins/del 包装内 run 暂不深入(保守:v1 只看直属 run,与 getRunText 行为对齐)。\n */\nfunction detectManualPageBreak(p: Element): boolean {\n const runs = p.getElementsByTagNameNS(W_NS, 'r');\n for (let i = 0; i < runs.length; i++) {\n const run = runs[i];\n if (!run || run.parentNode !== p) continue; // 仅直属 run\n const brs = run.getElementsByTagNameNS(W_NS, 'br');\n for (let j = 0; j < brs.length; j++) {\n const br = brs[j];\n if (!br) continue;\n const type = br.getAttributeNS(W_NS, 'type');\n if (type === 'page') return true;\n }\n }\n return false;\n}\n\n/**\n * 读取段落**首个直属 run**(`<w:p>/<w:r>`)的字体颜色(`w:rPr/w:color@w:val`)。\n * task-20260615-redhead-fingerprint:红头/标题等视觉显著段的颜色常在 run 级而非段标级。\n *\n * 只看首个直属 run(`run.parentNode === p`),与 getParagraphText / detectManualPageBreak 的\n * \"仅直属 run\"语义一致——不下钻表格/文本框/超链接内的 run。首 run 无 color 则返回 undefined。\n */\nfunction detectFirstRunColor(p: Element): string | undefined {\n const runs = p.getElementsByTagNameNS(W_NS, 'r');\n for (let i = 0; i < runs.length; i++) {\n const run = runs[i];\n if (!run || run.parentNode !== p) continue; // 仅直属 run\n const rPr = firstDirectChild(run, W_NS, 'rPr');\n if (!rPr) return undefined; // 首个直属 run 无 rPr → 无 run 级颜色\n const color = firstDirectChild(rPr, W_NS, 'color');\n if (!color) return undefined;\n const val = color.getAttributeNS(W_NS, 'val');\n return val ?? undefined;\n }\n return undefined;\n}\n\n/** 读取 Element 上指定 w: 属性并解析为数字,不是有效整数则返回 undefined。 */\nfunction numAttrTwips(el: Element, local: string): number | undefined {\n const raw = el.getAttributeNS(W_NS, local);\n if (raw === null) return undefined;\n const n = parseInt(raw, 10);\n return Number.isFinite(n) ? n : undefined;\n}\n","import type { Package } from '../pack/index.js';\nimport type { BookmarkInfo, ListBookmarksOptions } from './bookmark-queries.js';\nimport { getBookmark, listBookmarks } from './bookmark-queries.js';\nimport type { PackageIndices } from './indices.js';\nimport type { ParagraphInfo } from './list-paragraphs.js';\nimport { listParagraphs } from './list-paragraphs.js';\n\nexport type ContextSearchScope = 'body' | 'all';\n\nexport interface ContextSearchInclude {\n paragraphs?: boolean;\n tables?: boolean;\n headings?: boolean;\n bookmarks?: 'none' | 'metadata' | 'coveredText';\n comments?: 'none' | 'anchors';\n revisions?: 'none' | 'flag' | 'visibleText';\n headersFooters?: boolean;\n footnotesEndnotes?: boolean;\n}\n\nexport interface ContextSearchOptions {\n query: string;\n keywords?: string[];\n scope?: ContextSearchScope;\n include?: ContextSearchInclude;\n context?: {\n before?: number;\n after?: number;\n };\n limit?: number;\n bookmarkFilter?: {\n name?: string;\n prefix?: string;\n includeHidden?: boolean;\n };\n}\n\nexport interface ContextSearchResult {\n matches: ContextSearchMatch[];\n truncated?: boolean;\n}\n\nexport interface ContextSearchMatch {\n matchId: string;\n score: number;\n reason: 'keyword' | 'bookmark' | 'heading' | 'table' | 'metadata';\n target: ContextSearchTarget;\n text: string;\n highlights?: ContextSearchHighlight[];\n before?: ContextBlock[];\n after?: ContextBlock[];\n headingPath?: string[];\n flags?: {\n hasComments?: boolean;\n hasRevisions?: boolean;\n };\n bookmarks?: ContextBookmark[];\n}\n\nexport interface ContextSearchHighlight {\n text: string;\n start: number;\n end: number;\n}\n\nexport type ContextSearchTarget =\n | { kind: 'paragraph'; paraId: string; story: string }\n | { kind: 'tableCell'; tableId: string; row: number; col: number; paraId?: string; story: string }\n | {\n kind: 'bookmark';\n bookmarkName: string;\n rangeKind: 'paragraph' | 'text' | 'complex';\n paraId?: string;\n story: string;\n }\n | { kind: 'heading'; paraId: string; story: string };\n\nexport interface ContextBlock {\n paraId: string;\n story: string;\n text: string;\n table?: { tableId: string; row: number; col: number };\n}\n\nexport interface ContextBookmark {\n name: string;\n rangeKind: 'paragraph' | 'text' | 'complex';\n writable: boolean;\n}\n\ninterface ParagraphEntry {\n paragraph: ParagraphInfo;\n index: number;\n headingPath: string[];\n}\n\nconst DEFAULT_LIMIT = 10;\nconst DEFAULT_CONTEXT_SIZE = 2;\n\nexport function searchContext(\n pkg: Package,\n indices: PackageIndices,\n options: ContextSearchOptions,\n): ContextSearchResult {\n const include = normalizeInclude(options.include);\n const terms = normalizeTerms(options.query, options.keywords);\n const limit = normalizeLimit(options.limit);\n const beforeCount = normalizeContextCount(options.context?.before);\n const afterCount = normalizeContextCount(options.context?.after);\n const scope = options.scope ?? 'body';\n\n const paragraphEntries = buildParagraphEntries(pkg, scope);\n const bookmarkInfos = collectBookmarks(pkg, indices, options.bookmarkFilter, include.bookmarks);\n const bookmarksByParaId = buildBookmarksByParaId(bookmarkInfos);\n\n const matches: ContextSearchMatch[] = [];\n\n if (terms.length > 0) {\n for (const entry of paragraphEntries) {\n const paragraph = entry.paragraph;\n const isTable = paragraph.table !== undefined;\n const isHeadingMatch = isHeading(paragraph);\n\n if (isTable && include.tables !== true) continue;\n if (!isTable && include.paragraphs !== true && !isHeadingMatch) continue;\n if (isHeadingMatch && include.headings !== true && include.paragraphs !== true) continue;\n\n const highlights = findHighlights(paragraph.text, terms);\n if (highlights.length === 0) continue;\n\n const reason = isHeadingMatch ? 'heading' : isTable ? 'table' : 'keyword';\n matches.push(\n buildParagraphMatch(\n matches.length + 1,\n entry,\n paragraphEntries,\n beforeCount,\n afterCount,\n reason,\n highlights,\n bookmarksByParaId.get(paragraph.paraId),\n include,\n ),\n );\n if (matches.length >= limit) return { matches, truncated: true };\n }\n }\n\n if (include.bookmarks === 'coveredText') {\n for (const bookmark of bookmarkInfos) {\n const text = resolveBookmarkText(bookmark, paragraphEntries);\n if (text.length === 0) continue;\n const highlights = terms.length > 0 ? findHighlights(text, terms) : [];\n if (terms.length > 0 && highlights.length === 0) continue;\n const entry = bookmark.paraId\n ? paragraphEntries.find((candidate) => candidate.paragraph.paraId === bookmark.paraId)\n : undefined;\n matches.push(\n buildBookmarkMatch(\n matches.length + 1,\n bookmark,\n text,\n highlights,\n entry,\n paragraphEntries,\n beforeCount,\n afterCount,\n ),\n );\n if (matches.length >= limit) return { matches, truncated: true };\n }\n }\n\n return { matches };\n}\n\nfunction normalizeInclude(\n include: ContextSearchInclude | undefined,\n): Required<ContextSearchInclude> {\n return {\n paragraphs: include?.paragraphs ?? true,\n tables: include?.tables ?? true,\n headings: include?.headings ?? true,\n bookmarks: include?.bookmarks ?? 'metadata',\n comments: include?.comments ?? 'anchors',\n revisions: include?.revisions ?? 'flag',\n headersFooters: include?.headersFooters ?? false,\n footnotesEndnotes: include?.footnotesEndnotes ?? false,\n };\n}\n\nfunction normalizeTerms(query: string, keywords: string[] | undefined): string[] {\n const out: string[] = [];\n for (const raw of [query, ...(keywords ?? [])]) {\n const term = raw.trim();\n if (term.length > 0 && !out.includes(term)) out.push(term);\n }\n return out;\n}\n\nfunction normalizeLimit(limit: number | undefined): number {\n if (limit === undefined) return DEFAULT_LIMIT;\n if (!Number.isFinite(limit) || limit < 1) return DEFAULT_LIMIT;\n return Math.floor(limit);\n}\n\nfunction normalizeContextCount(value: number | undefined): number {\n if (value === undefined) return DEFAULT_CONTEXT_SIZE;\n if (!Number.isFinite(value) || value < 0) return DEFAULT_CONTEXT_SIZE;\n return Math.floor(value);\n}\n\nfunction buildParagraphEntries(pkg: Package, scope: ContextSearchScope): ParagraphEntry[] {\n const result = listParagraphs(pkg, {\n scope,\n pagination: { mode: 'all' },\n includeFormat: true,\n includeTableInfo: true,\n });\n const headingStack: string[] = [];\n return result.paragraphs.map((paragraph, index) => {\n if (paragraph.table === undefined && isHeading(paragraph)) {\n const level = headingLevel(paragraph);\n if (level !== undefined) {\n headingStack.length = level;\n headingStack[level] = paragraph.text;\n } else {\n headingStack.length = 0;\n headingStack.push(paragraph.text);\n }\n }\n return {\n paragraph,\n index,\n headingPath: headingStack.filter((value) => value.length > 0),\n };\n });\n}\n\nfunction collectBookmarks(\n pkg: Package,\n indices: PackageIndices,\n filter: ContextSearchOptions['bookmarkFilter'],\n includeMode: Required<ContextSearchInclude>['bookmarks'],\n): BookmarkInfo[] {\n if (includeMode === 'none') return [];\n if (filter?.name) {\n const bookmark = getBookmark(pkg, indices, filter.name);\n return bookmark ? [bookmark] : [];\n }\n const opts: ListBookmarksOptions = {\n ...(filter?.prefix !== undefined ? { prefix: filter.prefix } : {}),\n includeHidden:\n filter?.includeHidden === true ||\n (filter?.prefix !== undefined && filter.prefix.startsWith('_')),\n };\n return listBookmarks(pkg, indices, opts);\n}\n\nfunction buildBookmarksByParaId(bookmarks: BookmarkInfo[]): Map<string, ContextBookmark[]> {\n const out = new Map<string, ContextBookmark[]>();\n for (const bookmark of bookmarks) {\n if (!bookmark.paraId) continue;\n const existing = out.get(bookmark.paraId) ?? [];\n existing.push({\n name: bookmark.name,\n rangeKind: bookmark.rangeKind,\n writable: bookmark.rangeKind === 'paragraph' || bookmark.rangeKind === 'text',\n });\n out.set(bookmark.paraId, existing);\n }\n return out;\n}\n\nfunction isHeading(paragraph: ParagraphInfo): boolean {\n return headingLevel(paragraph) !== undefined;\n}\n\nfunction headingLevel(paragraph: ParagraphInfo): number | undefined {\n const outline = paragraph.format?.outlineLevel;\n if (outline !== undefined && outline >= 0 && outline <= 8) return outline;\n const style = paragraph.styleId?.toLowerCase();\n if (!style) return undefined;\n const headingMatch = style.match(/^heading([1-9])$/);\n if (headingMatch) return Number(headingMatch[1]) - 1;\n const chineseMatch = style.match(/^标题([1-9])$/);\n if (chineseMatch) return Number(chineseMatch[1]) - 1;\n return undefined;\n}\n\nfunction findHighlights(text: string, terms: string[]): ContextSearchHighlight[] {\n const highlights: ContextSearchHighlight[] = [];\n for (const term of terms) {\n const start = text.indexOf(term);\n if (start >= 0) highlights.push({ text: term, start, end: start + term.length });\n }\n return highlights;\n}\n\nfunction buildParagraphMatch(\n ordinal: number,\n entry: ParagraphEntry,\n entries: ParagraphEntry[],\n beforeCount: number,\n afterCount: number,\n reason: 'keyword' | 'heading' | 'table',\n highlights: ContextSearchHighlight[],\n bookmarks: ContextBookmark[] | undefined,\n include: Required<ContextSearchInclude>,\n): ContextSearchMatch {\n const paragraph = entry.paragraph;\n const target: ContextSearchTarget = paragraph.table\n ? {\n kind: 'tableCell',\n tableId: paragraph.table.tableId,\n row: paragraph.table.row,\n col: paragraph.table.col,\n paraId: paragraph.paraId,\n story: paragraph.story,\n }\n : reason === 'heading'\n ? { kind: 'heading', paraId: paragraph.paraId, story: paragraph.story }\n : { kind: 'paragraph', paraId: paragraph.paraId, story: paragraph.story };\n\n return cleanMatch({\n matchId: `ctx-${ordinal}`,\n score: scoreFor(reason, highlights.length),\n reason,\n target,\n text: paragraph.text,\n highlights,\n before: contextBlocks(entries, entry.index, -beforeCount, -1),\n after: contextBlocks(entries, entry.index, 1, afterCount),\n headingPath: entry.headingPath,\n flags: {\n ...(include.comments !== 'none' && paragraph.hasComments ? { hasComments: true } : {}),\n ...(include.revisions !== 'none' && paragraph.hasRevisions ? { hasRevisions: true } : {}),\n },\n bookmarks,\n });\n}\n\nfunction buildBookmarkMatch(\n ordinal: number,\n bookmark: BookmarkInfo,\n text: string,\n highlights: ContextSearchHighlight[],\n entry: ParagraphEntry | undefined,\n entries: ParagraphEntry[],\n beforeCount: number,\n afterCount: number,\n): ContextSearchMatch {\n return cleanMatch({\n matchId: `ctx-${ordinal}`,\n score: highlights.length > 0 ? 0.9 : 0.72,\n reason: 'bookmark',\n target: {\n kind: 'bookmark',\n bookmarkName: bookmark.name,\n rangeKind: bookmark.rangeKind,\n ...(bookmark.paraId !== undefined ? { paraId: bookmark.paraId } : {}),\n story: bookmark.story,\n },\n text,\n highlights,\n before: entry ? contextBlocks(entries, entry.index, -beforeCount, -1) : undefined,\n after: entry ? contextBlocks(entries, entry.index, 1, afterCount) : undefined,\n headingPath: entry?.headingPath,\n bookmarks: [\n {\n name: bookmark.name,\n rangeKind: bookmark.rangeKind,\n writable: bookmark.rangeKind === 'paragraph' || bookmark.rangeKind === 'text',\n },\n ],\n });\n}\n\nfunction scoreFor(reason: 'keyword' | 'heading' | 'table', hitCount: number): number {\n const base = reason === 'heading' ? 0.86 : reason === 'table' ? 0.84 : 0.82;\n return Math.min(0.99, base + Math.max(0, hitCount - 1) * 0.03);\n}\n\nfunction contextBlocks(\n entries: ParagraphEntry[],\n index: number,\n fromOffset: number,\n toOffset: number,\n): ContextBlock[] | undefined {\n const start = Math.max(0, index + fromOffset);\n const end = Math.min(entries.length - 1, index + toOffset);\n if (start > end) return undefined;\n const blocks: ContextBlock[] = [];\n for (let i = start; i <= end; i++) {\n if (i === index) continue;\n const paragraph = entries[i]!.paragraph;\n if (paragraph.text.length === 0) continue;\n blocks.push({\n paraId: paragraph.paraId,\n story: paragraph.story,\n text: paragraph.text,\n ...(paragraph.table ? { table: paragraph.table } : {}),\n });\n }\n return blocks.length > 0 ? blocks : undefined;\n}\n\nfunction resolveBookmarkText(bookmark: BookmarkInfo, entries: ParagraphEntry[]): string {\n if (bookmark.rangeKind === 'text') return bookmark.text ?? '';\n if (!bookmark.paraId) return '';\n return entries.find((entry) => entry.paragraph.paraId === bookmark.paraId)?.paragraph.text ?? '';\n}\n\nfunction cleanMatch(match: ContextSearchMatch): ContextSearchMatch {\n if (match.highlights?.length === 0) delete match.highlights;\n if (match.before?.length === 0) delete match.before;\n if (match.after?.length === 0) delete match.after;\n if (match.headingPath?.length === 0) delete match.headingPath;\n if (match.bookmarks?.length === 0) delete match.bookmarks;\n if (match.flags && Object.keys(match.flags).length === 0) delete match.flags;\n return match;\n}\n","/**\n * style-queries —— styles.xml 解析与样式索引构建(#181)。\n *\n * 职责:\n * - `buildStylesIndex(pkg)`:扫 Package 找 styles.xml,构建 Map<styleId, StyleInfo>\n * - `listStyles(stylesIdx, opts?)`:按可选 type 过滤后返回数组\n * - `getStyleById(stylesIdx, styleId)`:O(1) 精确查找\n *\n * 健壮性契约:\n * - styles.xml 不存在 → 返回空 Map,不抛错\n * - `w:type` 未知值 → fallback 到 'paragraph'(OOXML 规范默认)\n * - `w:name` 子元素缺失 → name fallback 到 styleId 本身\n * - 同一 styleId 重复定义 → 后者覆盖前者(与 Word 行为一致)\n * - basedOn 环路 → SDK 不检测,消费方遍历时须自行防环\n *\n * 不暴露 `builtIn` 字段:`<w:builtIn/>` 元素在实际文档中不一致(Word 某些版本省略),\n * 单向可信(存在则肯定是内置,不存在不代表是自定义)会误导消费方。\n * 消费方应通过 `name` + basedOn 链判断语义角色。\n */\nimport type { Package } from '../pack/index.js';\nimport { W_NS } from './namespaces.js';\n\n// ─────────── 类型 ───────────\n\n/** OOXML 定义的四种样式类型(`w:style@w:type`)。 */\nexport type StyleType = 'paragraph' | 'character' | 'table' | 'numbering';\n\nexport interface StyleInfo {\n /** `w:style@w:styleId`。段落 `w:pStyle@w:val` 引用的 key,大小写敏感。 */\n styleId: string;\n /**\n * `w:name@w:val`。\n * - OOXML 规范:内置样式(如 Heading 1、Normal)的 name 永远是英文规范名,\n * 不随文档语言变化。消费方可据此判断语义角色。\n * - 自定义样式:name 为用户输入,可能是中文或任意字符串。\n * - 若 `<w:name>` 元素缺失(非规范文档),fallback 到 `styleId`。\n */\n name: string;\n /**\n * `w:style@w:type`。\n * 未知值 fallback 到 `'paragraph'`(OOXML 规范默认类型)。\n */\n type: StyleType;\n /**\n * 父样式的 `styleId`(`w:basedOn@w:val`)。\n * 根样式(如 Normal)无继承关系,此字段不存在。\n *\n * ⚠ 消费方遍历 basedOn 链时须自行防环,SDK 不检测循环继承。\n */\n basedOn?: string;\n /**\n * 样式定义中的大纲级别(`w:style/w:pPr/w:outlineLvl@w:val`),0–8。\n * 0 = 标题 1,1 = 标题 2,…,8 = 标题 9;9 表示正文(不视为标题)。\n *\n * WPS / Word 的自定义标题样式(如\"公文-一级标题\")通常不 basedOn heading 1,\n * 而是在此字段直接编码级别。消费方可将其作为 basedOn 链之外的第二信号。\n *\n * 字段不存在 = 样式未设置大纲级别(继承自父样式或使用默认值)。\n */\n outlineLevel?: number;\n}\n\nexport interface ListStylesOptions {\n /** 按样式类型过滤。不传则返回全部样式(含所有类型)。 */\n type?: StyleType;\n}\n\n// ─────────── styles.xml 的标准 ContentType ───────────\n\nconst STYLES_CONTENT_TYPE =\n 'application/vnd.openxmlformats-officedocument.wordprocessingml.styles+xml';\n\n// ─────────── 内部工具 ───────────\n\n/** 按 contentType 定位 styles.xml Part(不硬编码路径)。 */\nfunction findStylesPart(pkg: Package): { xmlDom: Document } | undefined {\n for (const part of pkg.parts.values()) {\n if (part.contentType === STYLES_CONTENT_TYPE && part.xmlDom) {\n return part as { xmlDom: Document };\n }\n }\n return undefined;\n}\n\n/** 取第一个直接子元素(指定 namespace + localName)的某属性值。 */\nfunction childAttr(\n el: Element,\n ns: string,\n localName: string,\n attrNs: string,\n attrLocal: string,\n): string | null {\n const children = el.childNodes;\n for (let i = 0; i < children.length; i++) {\n const c = children[i];\n if (\n c &&\n c.nodeType === 1 &&\n (c as Element).namespaceURI === ns &&\n (c as Element).localName === localName\n ) {\n return (c as Element).getAttributeNS(attrNs, attrLocal);\n }\n }\n return null;\n}\n\n/**\n * 从 `<w:style>` 元素读取其 pPr 中的 outlineLvl。\n * 返回 0–8 的数字,或 undefined(未设置 / 值为 9 表示正文不视为标题)。\n */\nfunction styleOutlineLevel(styleEl: Element): number | undefined {\n const children = styleEl.childNodes;\n for (let i = 0; i < children.length; i++) {\n const c = children[i];\n if (!c || c.nodeType !== 1) continue;\n const el = c as Element;\n if (el.namespaceURI !== W_NS || el.localName !== 'pPr') continue;\n\n // 找到 pPr,再找 outlineLvl\n const pPrChildren = el.childNodes;\n for (let j = 0; j < pPrChildren.length; j++) {\n const pc = pPrChildren[j];\n if (!pc || pc.nodeType !== 1) continue;\n const pcel = pc as Element;\n if (pcel.namespaceURI !== W_NS || pcel.localName !== 'outlineLvl') continue;\n\n const raw = pcel.getAttributeNS(W_NS, 'val');\n if (raw === null) return undefined;\n const n = parseInt(raw, 10);\n // 0–8 才是标题级别;9 表示正文,不视为标题\n return Number.isFinite(n) && n >= 0 && n <= 8 ? n : undefined;\n }\n }\n return undefined;\n}\n\n/** `w:type` 原始字符串 → StyleType(未知值 fallback 到 'paragraph')。 */\nfunction parseStyleType(raw: string | null): StyleType {\n switch (raw) {\n case 'paragraph':\n return 'paragraph';\n case 'character':\n return 'character';\n case 'table':\n return 'table';\n case 'numbering':\n return 'numbering';\n default:\n return 'paragraph';\n }\n}\n\n// ─────────── 公开 API ───────────\n\n/**\n * 扫 Package 构建样式索引。\n *\n * - styles.xml 不存在 → 返回空 Map,不抛错\n * - 同一 styleId 重复出现 → 后者覆盖(与 Word 行为一致)\n */\nexport function buildStylesIndex(pkg: Package): Map<string, StyleInfo> {\n const idx = new Map<string, StyleInfo>();\n\n const stylesPart = findStylesPart(pkg);\n if (!stylesPart) return idx;\n\n const styleEls = stylesPart.xmlDom.getElementsByTagNameNS(W_NS, 'style');\n for (let i = 0; i < styleEls.length; i++) {\n const el = styleEls[i];\n if (!el) continue;\n\n const styleId = el.getAttributeNS(W_NS, 'styleId');\n if (!styleId) continue; // styleId 缺失则跳过(非规范文档)\n\n const type = parseStyleType(el.getAttributeNS(W_NS, 'type'));\n const name = childAttr(el, W_NS, 'name', W_NS, 'val') ?? styleId;\n const basedOnRaw = childAttr(el, W_NS, 'basedOn', W_NS, 'val');\n\n const info: StyleInfo = { styleId, name, type };\n if (basedOnRaw) info.basedOn = basedOnRaw;\n\n // 大纲级别:从 w:style/w:pPr/w:outlineLvl@w:val 读取\n const outlineLvlVal = styleOutlineLevel(el);\n if (outlineLvlVal !== undefined) info.outlineLevel = outlineLvlVal;\n\n idx.set(styleId, info); // 重复时后者覆盖\n }\n\n return idx;\n}\n\n/**\n * 列出样式索引中的所有样式。\n *\n * @param stylesIdx 由 `buildStylesIndex` 构建的 Map\n * @param opts 可选过滤(目前支持按 type 过滤)\n */\nexport function listStyles(\n stylesIdx: Map<string, StyleInfo>,\n opts?: ListStylesOptions,\n): StyleInfo[] {\n const all = Array.from(stylesIdx.values());\n if (!opts?.type) return all;\n return all.filter((s) => s.type === opts.type);\n}\n\n/**\n * 按 styleId 精确查找,O(1)。\n * styleId 大小写敏感(与 OOXML 规范一致)。\n */\nexport function getStyleById(stylesIdx: Map<string, StyleInfo>, styleId: string): StyleInfo | null {\n return stylesIdx.get(styleId) ?? null;\n}\n","/**\n * Drawing 对象枚举(#189)\n *\n * 为骨架化 M3 阶段(图片分类/Shape 分类/占位图替换)提供 drawing 数据。\n *\n * 边界(实施前澄清,见 #189 评论):\n * - **本模块只做\"枚举 + 形态信号\"**,不下 A / B / C 业务分类结论\n * - C 类细分(水印 / 装饰线 / 背景图)需语义判断,属于 #191\n * - 分组键计算、代表样本选取属于 #191 / #192\n * - 占位图替换属于 #190\n *\n * 设计原则(对齐 #185 list-tables.ts):\n * - 只走 getElementsByTagNameNS / 直接子节点遍历,禁用 XPath(性能约束)\n * - drawingId 由 buildIndices 装载期分配('dr-0001' 起),存入 drawingIdx\n * - 默认枚举主文档 body(scope: 'body')\n * - 提供 isInHeaderFooter 字段,让 #191 直接识别 C 类页眉页脚 logo(无需自己查 part 路径)\n */\n\nimport type { Package } from '../pack/index.js';\nimport {\n W_NS,\n WP_NS,\n A_NS,\n PIC_NS,\n CHART_NS,\n DGM_NS,\n WPS_NS,\n WPG_NS,\n WPC_NS,\n W14_NS,\n MC_NS,\n VML_NS,\n} from './namespaces.js';\nimport type { PackageIndices } from './indices.js';\nimport { getRunText, type RunTextOptions } from './runs.js';\nimport { resolveScope, type Story } from './stories.js';\n\n// ─────────── 公开类型 ───────────\n\n/** 锚定方式:inline(行内嵌入)/ anchor(浮动定位)*/\nexport type DrawingAnchoringMode = 'inline' | 'anchor';\n\n/**\n * Drawing 内容形态(**OOXML 子树类型**,非 A/B/C 业务分类)。\n *\n * 识别优先级:a:graphicData @uri → 命中预设 URI 之一时按表分发;都不命中时落 'other'。\n * 'textBox' 是 'shape' 的特化(wps:wsp 内含 w:txbxContent),单独抽出便于 #192 处理。\n *\n * | kind | URI 或子元素信号 | 典型场景 |\n * |----------|---------------------------------------------------------------------------|----------|\n * | picture | uri = .../picture | 嵌入/浮动图片 |\n * | chart | uri = .../chart | Word 原生图表 |\n * | smartArt | uri = .../diagram | SmartArt(1.0/2010+)|\n * | shape | uri = .../wordprocessingShape,且 **无** w:txbxContent | 形状(无文字) |\n * | textBox | uri = .../wordprocessingShape,且 **有** w:txbxContent | 文本框 / 标注 |\n * | group | uri = .../wordprocessingGroup | 形状组合 |\n * | canvas | uri = .../wordprocessingCanvas | 绘图画布 |\n * | other | 都不命中 | 未来扩展占位 |\n */\nexport type DrawingKind =\n | 'picture'\n | 'chart'\n | 'smartArt'\n | 'shape'\n | 'textBox'\n | 'group'\n | 'canvas'\n | 'other';\n\nexport type TextBoxBlockInfo =\n | { type: 'paragraph'; paraId: string; text: string }\n | { type: 'drawing'; drawingId: string; paraId?: string }\n | { type: 'table'; tableId: string };\n\n/**\n * 文字环绕方式(仅 anchor 有)。\n *\n * - none:wp:wrapNone(不环绕;配合 behindDoc 形成\"衬于文字下方/上方\")\n * - square:wp:wrapSquare(四周型 / 矩形环绕)\n * - tight:wp:wrapTight(紧密型)\n * - through:wp:wrapThrough(穿越型)\n * - topAndBottom:wp:wrapTopAndBottom(上下型)\n * - behind:wp:wrapNone + behindDoc=\"1\"(衬于文字下方)\n * - inFront:wp:wrapNone + behindDoc=\"0\"(浮于文字上方)\n */\nexport type DrawingWrapType =\n | 'none'\n | 'square'\n | 'tight'\n | 'through'\n | 'topAndBottom'\n | 'behind'\n | 'inFront';\n\n/** 浮动定位的单方向描述(原值透传,由 #191 自行二次解释)*/\nexport interface DrawingPositionAxis {\n /** wp:positionH/V @relativeFrom 原值(如 'page' / 'margin' / 'column' / 'character' / 'paragraph' / 'line')*/\n relativeFrom?: string;\n /** wp:posOffset 文本内容(EMU 整数)。和 align 二选一。*/\n posOffset?: number;\n /** wp:align 文本内容('left' / 'center' / 'right' / 'top' / 'bottom' / 'inside' / 'outside')。和 posOffset 二选一。*/\n align?: string;\n}\n\n/** 浮动位置(仅 anchor 有)*/\nexport interface DrawingPosition {\n horizontal?: DrawingPositionAxis;\n vertical?: DrawingPositionAxis;\n}\n\nexport interface DrawingInfo {\n /** 装载期分配的 ID('dr-NNNN',从 0001 起),供 #190 / #191 / #192 引用 */\n drawingId: string;\n /** 所在 part 路径('word/document.xml' / 'word/header1.xml' 等)*/\n partPath: string;\n /** 枚举结果顺序(1-based,与文档顺序一致)*/\n index: number;\n /** 锚定方式:inline 行内嵌入 / anchor 浮动定位 */\n anchoringMode: DrawingAnchoringMode;\n /** 内容形态(OOXML 层级,非业务分类)*/\n kind: DrawingKind;\n /**\n * 显示尺寸(EMU;1 inch = 914400 EMU)。\n * 来源:wp:extent @cx @cy。\n * 未声明或解析失败时为 { cx: 0, cy: 0 }(保持字段必存在,避免下游需要判 undefined)。\n */\n extentEMU: { cx: number; cy: number };\n /** 文字环绕方式(仅 anchor,inline 不含此字段)*/\n wrap?: DrawingWrapType;\n /** 浮动位置(仅 anchor,inline 不含此字段)*/\n position?: DrawingPosition;\n /**\n * 承载此 drawing 的段落 paraId(w:p @w14:paraId)。\n *\n * 多数情况下,drawing 挂在 w:r 下、该 w:r 属于某个 w:p,本字段就是这个 w:p 的 paraId。\n *\n * **关键例外(CR 设计说明)**:嵌套在 **TextBox 内**(即位于 `w:txbxContent` 子树)\n * 的 drawing,本字段为 `undefined`。这是**主动设计**:textBox 内段落与外层段落是两套\n * 独立的段落流,把外层段落 paraId 挂给文本框内 drawing 会让\"删段落 → 顺带删图\"等\n * 操作误伤外层段落。下游需要文本框内图片的段落引用时,应:\n * 1. 用 `runIndex === undefined && anchorParaId === undefined` 识别该情形\n * 2. 自行向上找最近的 `w:txbxContent`,再用其外层 anchor 段落定位\n *\n * 缺 paraId 时也为 undefined(合法但少见;由 ensureParaIds 在装载期补齐,但本字段\n * 不依赖这一保证)。\n */\n anchorParaId?: string;\n /**\n * 在所在段落里的 run 序号(0-based,承载 drawing 的 w:r 在父 w:p 直接子 w:r 中的位置)。\n * 同段多 drawing 时用于区分;用于题注绑定(#193)/ 占位图替换(#190)的精确引用。\n */\n runIndex?: number;\n /**\n * 是否位于页眉页脚 part(contentType 以 .header+xml / .footer+xml 结尾)。\n *\n * 这是**形态信号**,不是 C 类结论。#191 在做 A/B/C 业务分类时:\n * - true + kind = picture → 大概率 C 类页眉页脚 logo,由 .dot 原生保留\n * - 其余情况由 #191 自行判断\n */\n isInHeaderFooter: boolean;\n /**\n * 形态信号:是否含 pic:pic 子树(A 类正向信号)。\n * - kind = 'picture' 时必为 true\n * - 理论上 chart/shape 也可能套 pic:pic,此时 kind 不变但本字段为 true\n */\n hasPicReference: boolean;\n /**\n * Shape 专属:是否为「线条 / 连接线(line / connector)」几何。仅 kind = 'shape' 时可能为 true,\n * 其余 kind(picture/chart/.../textBox/group/canvas/other)一律 undefined。\n *\n * **形态信号,非业务结论**。下游(skeleton #192 shape-role)用它把版记横线一类「纯几何线条」\n * 与矩形/椭圆等装饰噪声区分开:线条原样保留,其余几何仍按现状裁掉。\n *\n * 识别(命中任一即 true,从强到弱):\n * 1. DrawingML 预设几何:`<a:prstGeom prst=\"...\">` 的 prst 命中线条/连接线预设\n * (line / straightConnector1 / bentConnectorN / curvedConnectorN,N=2..5;见 LINE_CONNECTOR_PRESETS)\n * 2. 连接线非可视属性:wps:wsp 内含 `<wps:cNvCnPr>`(connector non-visual props;\n * 普通 shape 用 wps:cNvSpPr,连接线用 wps:cNvCnPr)\n * 3. VML 回退:子树含 `<v:line>`(mc:Fallback 内的旧版降级线条)\n *\n * 母版实测(生成的公文__会议纪要.docx):版记 3 根横线均 prst=\"line\" + wps:cNvCnPr + v:line 三信号齐全;\n * 红头艺术字文本框是 prst=\"rect\" + wps:cNvSpPr,不命中。\n */\n isLineOrConnector?: boolean;\n /**\n * Shape / TextBox 专属:是否有边框(a:spPr/a:ln 存在且未声明 a:noFill)。\n * 非 shape/textBox 一律 undefined。\n */\n hasBorder?: boolean;\n /**\n * Shape / TextBox 专属:是否有填充(a:spPr 下含 a:solidFill / a:gradFill / a:blipFill / a:pattFill)。\n * 显式 a:noFill 视作无填充。非 shape/textBox 一律 undefined。\n */\n hasFill?: boolean;\n /**\n * TextBox 专属:是否含实质内部文字(w:txbxContent 内 w:t 文本拼接后非空)。\n * 非 textBox 一律 undefined。\n */\n hasInnerText?: boolean;\n /**\n * TextBox 专属:内部文字原文(w:txbxContent 内全部 w:t 文本按文档顺序拼接后 trim)。\n *\n * 供下游(skeleton #192 / typeset 投影)读取红头艺术字等内容型文本框的原文做语义命名/字段化\n * (如「江临市滨河区人民政府」「专题会议纪要」)。\n *\n * 语义:\n * - 仅 kind = 'textBox' 时可能有值;非 textBox 一律 undefined。\n * - trim 后为空(无文字 / 仅空白)→ undefined(与 hasInnerText=false 对应)。\n * - 多段 / 多 run 文本框按 w:t 出现顺序直接拼接,**不插入换行/空格**(保持与 hasInnerText\n * 同源的拼接口径);下游需要分段语义时应自行用 paragraphs API 处理,本字段只给原文快照。\n */\n innerText?: string;\n /**\n * TextBox 专属:文本框内容流里的段落 paraId,按文档顺序排列。\n *\n * 这些 paraId 指向 `w:txbxContent` 内部段落。调用方可通过\n * `doc.paragraphs.get(paraId)` 或 `TextBoxDrawing.getParagraphs()` 继续进行段落/文字级操作。\n * 非 textBox 一律 undefined。\n */\n innerParagraphIds?: string[];\n /**\n * TextBox 专属:文本框内容流的直接内容块,按 OOXML child-node 顺序排列。\n *\n * 目前包含 direct paragraph、paragraph 内 direct drawing,以及 direct table。\n * 非 textBox 一律 undefined。\n */\n innerBlocks?: TextBoxBlockInfo[];\n /**\n * TextBox 专属:首个内部段落的对齐(w:txbxContent 第一段 w:pPr/w:jc @val)。\n *\n * 注:文本框内可能多段且对齐不同,#192 需自行决定如何取代表值;本字段只提供首段值便于快速分组。\n * 非 textBox 或无 jc 设置一律 undefined。\n */\n innerTextAlign?: string;\n}\n\nexport interface ListDrawingsOptions {\n /**\n * 枚举范围(默认 'body')。\n * - 'body':仅主文档 body(不含页眉页脚 / 注释 / 脚注尾注)\n * - 'all':所有 stories(body + headers + footers + footnotes + endnotes + comments)\n *\n * 注意:#189 的 isInHeaderFooter 字段只在 'all' 模式下才可能为 true;\n * 'body' 模式下页眉页脚 drawing 不会被枚出。\n */\n scope?: 'body' | 'all';\n /**\n * 启用结构空白保真读(task-20260623-core-tab-faithful-read)。\n * `true` 时 TextBox 的 `innerText` 含 `\\t`(制表符)和 `\\n`(软换行)——\n * 是 `appendSegmentsToRun` 的精确逆运算。\n * 默认 `false`:只拼 `<w:t>`(与历史行为一致)。\n */\n structuralWhitespace?: boolean;\n}\n\n// ─────────── 内部工具 ───────────\n\n/** 把 HTMLCollection-ish 枚举结果快照成数组(避免 live 行为)*/\nfunction snapshot<T extends Element>(col: { length: number } & Record<number, T>): T[] {\n const out: T[] = [];\n for (let i = 0; i < col.length; i++) {\n const el = col[i];\n if (el) out.push(el);\n }\n return out;\n}\n\n/**\n * OOXML on/off 属性解析。\n *\n * 同一布尔语义在 OOXML 文档中可序列化为多种字面形态(ECMA-376 §17.18.93 ST_OnOff):\n * - true: \"1\" / \"true\" / \"on\"\n * - false: \"0\" / \"false\" / \"off\"\n *\n * 缺值(null)/ 未识别字面 → undefined(区分\"未声明\"与\"显式 false\",由调用方决策默认值)。\n *\n * 触发场景:`<wp:anchor behindDoc=\"true\">`(部分模板/第三方工具用 true 而非 1)\n * —— 旧实现只匹配 \"1\" / \"0\",会把 behindDoc=\"true\" 误判为 inFront。\n */\nfunction parseOnOff(value: string | null): boolean | undefined {\n if (value === null) return undefined;\n const v = value.trim().toLowerCase();\n if (v === '1' || v === 'true' || v === 'on') return true;\n if (v === '0' || v === 'false' || v === 'off') return false;\n return undefined;\n}\n\n/**\n * 判断 element 是否嵌套在 mc:AlternateContent / mc:Fallback 之中。\n *\n * 触发场景:第三方工具或某些 Word 旧版会把 SmartArt / Chart 的\"降级 fallback\"\n * 也用 `<w:drawing>` 包装放进 `<mc:Fallback>`,再被 mc:Choice 里的真版本\"覆盖\"。\n * 此时同一对象会被深遍历枚两次(Choice + Fallback),导致 drawingIdx 双计。\n *\n * 防御方式:装载期主动跳过 Fallback 内部的 drawing —— mc:Choice 已经是规范的\n * \"首选呈现\",Fallback 只在 reader 不识别 Choice 时使用,不应进枚举结果。\n *\n * 实测:Word / WPS 生成的真实文档 Fallback 用 VML `<w:pict>`,不命中本守卫;\n * 加上这一层只为防御第三方工具。\n */\nfunction hasFallbackAncestor(el: Element): boolean {\n let p = el.parentElement;\n while (p) {\n if (p.namespaceURI === MC_NS && p.localName === 'Fallback') return true;\n p = p.parentElement;\n }\n return false;\n}\n\n/** 取 element 直接子中首个匹配 (ns, local) 的,未找到返回 null */\nfunction firstDirectChild(parent: Element, ns: string, local: string): Element | null {\n for (let i = 0; i < parent.childNodes.length; i++) {\n const child = parent.childNodes[i] as Element;\n if (\n child &&\n child.nodeType === 1 /* ELEMENT_NODE */ &&\n child.namespaceURI === ns &&\n child.localName === local\n ) {\n return child;\n }\n }\n return null;\n}\n\n/** 取 element 子孙中首个匹配 (ns, local) 的,未找到返回 null */\nfunction firstDescendant(parent: Element, ns: string, local: string): Element | null {\n const col = parent.getElementsByTagNameNS(ns, local);\n return col.length > 0 ? col[0]! : null;\n}\n\n/** 解析 number-like attribute;缺/非数为 undefined */\nfunction readNumAttr(el: Element, ns: string | null, local: string): number | undefined {\n const v = ns === null ? el.getAttribute(local) : el.getAttributeNS(ns, local);\n if (v === null) return undefined;\n const n = Number(v);\n return Number.isFinite(n) ? n : undefined;\n}\n\n/** 取元素直接文本(不递归)*/\nfunction textContentOfDirect(el: Element): string {\n let s = '';\n for (let i = 0; i < el.childNodes.length; i++) {\n const child = el.childNodes[i] as Node & { nodeValue?: string };\n if (child.nodeType === 3 /* TEXT_NODE */) {\n s += child.nodeValue ?? '';\n }\n }\n return s;\n}\n\n/** 取 wp:positionH / wp:positionV 元素的 axis 描述 */\nfunction readPositionAxis(axisEl: Element): DrawingPositionAxis {\n const out: DrawingPositionAxis = {};\n const relativeFrom = axisEl.getAttribute('relativeFrom');\n if (relativeFrom !== null) out.relativeFrom = relativeFrom;\n\n const posOffsetEl = firstDirectChild(axisEl, WP_NS, 'posOffset');\n if (posOffsetEl) {\n const txt = textContentOfDirect(posOffsetEl).trim();\n const n = Number(txt);\n if (Number.isFinite(n)) out.posOffset = n;\n } else {\n const alignEl = firstDirectChild(axisEl, WP_NS, 'align');\n if (alignEl) {\n const txt = textContentOfDirect(alignEl).trim();\n if (txt) out.align = txt;\n }\n }\n return out;\n}\n\n/** 从 wp:anchor 解析 wrap 类型 */\nfunction readWrap(anchor: Element): DrawingWrapType | undefined {\n // 优先 topAndBottom / square / tight / through\n if (firstDirectChild(anchor, WP_NS, 'wrapTopAndBottom')) return 'topAndBottom';\n if (firstDirectChild(anchor, WP_NS, 'wrapSquare')) return 'square';\n if (firstDirectChild(anchor, WP_NS, 'wrapTight')) return 'tight';\n if (firstDirectChild(anchor, WP_NS, 'wrapThrough')) return 'through';\n if (firstDirectChild(anchor, WP_NS, 'wrapNone')) {\n // wp:wrapNone 自身存在;behindDoc 在 anchor 元素属性上\n // ECMA-376 ST_OnOff:支持 \"1\"/\"true\"/\"on\" 与 \"0\"/\"false\"/\"off\" 多种字面(见 parseOnOff)\n const behind = parseOnOff(anchor.getAttribute('behindDoc'));\n if (behind === true) return 'behind';\n if (behind === false) return 'inFront';\n return 'none';\n }\n return undefined;\n}\n\n/** 从 wp:inline / wp:anchor 解析 extent */\nfunction readExtent(container: Element): { cx: number; cy: number } {\n const ext = firstDirectChild(container, WP_NS, 'extent');\n if (!ext) return { cx: 0, cy: 0 };\n const cx = readNumAttr(ext, null, 'cx') ?? 0;\n const cy = readNumAttr(ext, null, 'cy') ?? 0;\n return { cx, cy };\n}\n\n/** 从 wp:anchor 解析 position */\nfunction readPosition(anchor: Element): DrawingPosition {\n const out: DrawingPosition = {};\n const h = firstDirectChild(anchor, WP_NS, 'positionH');\n if (h) out.horizontal = readPositionAxis(h);\n const v = firstDirectChild(anchor, WP_NS, 'positionV');\n if (v) out.vertical = readPositionAxis(v);\n return out;\n}\n\n/**\n * 从 wp:inline / wp:anchor 子树识别 kind。\n *\n * 一级判定:a:graphicData @uri;命中 6 个预设 URI 之一即落对应 kind。\n * 二级判定:shape kind 内若有 w:txbxContent → 重定为 textBox。\n * 都不命中 → 'other'。\n */\nfunction detectKind(container: Element): DrawingKind {\n const graphic = firstDescendant(container, A_NS, 'graphic');\n if (!graphic) return 'other';\n const gd = firstDescendant(graphic, A_NS, 'graphicData');\n if (!gd) return 'other';\n const uri = gd.getAttribute('uri') ?? '';\n\n if (uri === PIC_NS) return 'picture';\n if (uri === CHART_NS) return 'chart';\n if (uri === DGM_NS) return 'smartArt';\n if (uri === WPG_NS) return 'group';\n if (uri === WPC_NS) return 'canvas';\n if (uri === WPS_NS) {\n // 区分 shape vs textBox:wps:wsp 子树里若有 w:txbxContent,认定为 textBox\n if (gd.getElementsByTagNameNS(W_NS, 'txbxContent').length > 0) return 'textBox';\n return 'shape';\n }\n return 'other';\n}\n\n/** 检测整个 drawing 子树是否含 pic:pic(A 类正向信号;包括套在其他对象内的情况)*/\nfunction hasPicReferenceIn(container: Element): boolean {\n return container.getElementsByTagNameNS(PIC_NS, 'pic').length > 0;\n}\n\n/**\n * 线条 / 连接线的 DrawingML 预设几何(a:prstGeom @prst)白名单。\n *\n * - `line`:经典直线(Word「插入→形状→直线」生成,母版版记横线即此)\n * - `straightConnector1`:直线连接符\n * - `bentConnector2..5` / `curvedConnector2..5`:折线 / 曲线连接符(流程图连线)\n *\n * 仅收\"视觉上是一根线/连线\"的预设;矩形 rect / 椭圆 ellipse / 标注 callout 等不在内。\n * 收紧白名单而非黑名单:未知新预设默认按\"非线条\"处理,保守不误保。\n */\nconst LINE_CONNECTOR_PRESETS = new Set<string>([\n 'line',\n 'straightConnector1',\n 'bentConnector2',\n 'bentConnector3',\n 'bentConnector4',\n 'bentConnector5',\n 'curvedConnector2',\n 'curvedConnector3',\n 'curvedConnector4',\n 'curvedConnector5',\n]);\n\n/**\n * 是否为「线条 / 连接线」几何(只对 kind = 'shape' 有意义)。\n *\n * 命中任一即 true(从强到弱):\n * 1. a:prstGeom @prst ∈ LINE_CONNECTOR_PRESETS\n * 2. 含 wps:cNvCnPr(连接线非可视属性;普通 shape 是 wps:cNvSpPr)\n * 3. 含 VML v:line(旧版降级线条;防御性兜底,通常在 mc:Fallback 内,\n * 而本函数收到的 container 是 mc:Choice 内的 wp:inline/anchor,故此项多数情况不命中,\n * 仅覆盖 container 内嵌 VML 的边角情形)\n */\nfunction isLineOrConnectorShape(container: Element): boolean {\n // 信号 1:a:prstGeom @prst 命中线条/连接线预设\n const prstGeoms = container.getElementsByTagNameNS(A_NS, 'prstGeom');\n for (let i = 0; i < prstGeoms.length; i++) {\n const prst = prstGeoms[i]?.getAttribute('prst');\n if (prst && LINE_CONNECTOR_PRESETS.has(prst)) return true;\n }\n // 信号 2:wps:cNvCnPr(connector non-visual props)\n if (container.getElementsByTagNameNS(WPS_NS, 'cNvCnPr').length > 0) return true;\n // 信号 3:VML v:line(防御性兜底)\n if (container.getElementsByTagNameNS(VML_NS, 'line').length > 0) return true;\n return false;\n}\n\n/**\n * Shape / TextBox 形态信号:边框 / 填充 / 内部文字 / 首段对齐。\n *\n * 只在 kind = shape | textBox 时调用。返回顺序与 DrawingInfo 字段一致:\n * { hasBorder, hasFill, hasInnerText?, innerText?, innerParagraphIds?, innerTextAlign? }\n *\n * @param runTextOpts 传 `{ structuralWhitespace: true }` 时 innerText 保真读(含 \\t / \\n)\n */\nfunction readShapeSignals(\n container: Element,\n isTextBox: boolean,\n runTextOpts?: RunTextOptions,\n drawingToId: Map<Element, string> = new Map(),\n tableToId: Map<Element, string> = new Map(),\n): {\n hasBorder: boolean;\n hasFill: boolean;\n hasInnerText?: boolean;\n innerText?: string;\n innerParagraphIds?: string[];\n innerBlocks?: TextBoxBlockInfo[];\n innerTextAlign?: string;\n} {\n // wps:spPr 是 wps namespace 下的 spPr(与 a:spPr 不同的命名空间,但元素结构一致)\n // 也可能在 a:spPr 下 —— 实际生成的 docx 主要走 wps:spPr,我们两个 NS 都查\n const wspSpPr = firstDescendant(container, WPS_NS, 'spPr');\n const aSpPr = firstDescendant(container, A_NS, 'spPr');\n const spPr = wspSpPr ?? aSpPr;\n\n let hasBorder = false;\n let hasFill = false;\n if (spPr) {\n // 边框:a:ln 存在 且 未声明 a:noFill 子元素 且 w 属性 != \"0\"\n //\n // 三个否定条件:\n // 1. a:ln 不存在 → 无线条定义 → hasBorder = false\n // 2. <a:ln><a:noFill/></a:ln> → 显式声明无填充 → hasBorder = false\n // 3. <a:ln w=\"0\"/> → 零 EMU 宽度 → 视觉无边框 → hasBorder = false\n const ln = firstDirectChild(spPr, A_NS, 'ln');\n if (ln) {\n const noLineFill = firstDirectChild(ln, A_NS, 'noFill');\n // w 是 a:ln 的属性(非命名空间属性),可能为 \"0\" 表示零宽线\n const widthAttr = ln.getAttribute('w');\n const isZeroWidth = widthAttr !== null && widthAttr.trim() === '0';\n hasBorder = !noLineFill && !isZeroWidth;\n }\n // 填充:a:solidFill / a:gradFill / a:blipFill / a:pattFill 之一存在,且不是 noFill\n const noFill = firstDirectChild(spPr, A_NS, 'noFill');\n if (!noFill) {\n hasFill =\n !!firstDirectChild(spPr, A_NS, 'solidFill') ||\n !!firstDirectChild(spPr, A_NS, 'gradFill') ||\n !!firstDirectChild(spPr, A_NS, 'blipFill') ||\n !!firstDirectChild(spPr, A_NS, 'pattFill');\n }\n }\n\n const out: {\n hasBorder: boolean;\n hasFill: boolean;\n hasInnerText?: boolean;\n innerText?: string;\n innerParagraphIds?: string[];\n innerBlocks?: TextBoxBlockInfo[];\n innerTextAlign?: string;\n } = { hasBorder, hasFill };\n\n if (isTextBox) {\n const txbx = firstDescendant(container, W_NS, 'txbxContent');\n if (txbx) {\n const paragraphs = snapshot(txbx.getElementsByTagNameNS(W_NS, 'p'));\n const ids: string[] = [];\n for (const p of paragraphs) {\n const id = p.getAttributeNS(W14_NS, 'paraId');\n if (id) ids.push(id.toUpperCase());\n }\n out.innerParagraphIds = ids;\n out.innerBlocks = collectTextBoxBlocks(txbx, drawingToId, tableToId, runTextOpts);\n\n // 内部文字:按 runTextOpts 决定拼接口径:\n // - 默认(无 opts):所有 w:t 节点文本按文档顺序拼接(与历史行为一致,hasInnerText 同源)\n // - structuralWhitespace: true:按 run 子节点顺序走保真读(\\t/\\n 还原)\n let joined = '';\n if (runTextOpts?.structuralWhitespace) {\n // 保真读:枚举 txbxContent 内所有直属段落的直属 run,逐个 getRunText 保真\n const runs = snapshot(txbx.getElementsByTagNameNS(W_NS, 'r'));\n for (const r of runs) {\n joined += getRunText(r, runTextOpts);\n }\n } else {\n // 默认:只拼 w:t(历史行为,hasInnerText 计算依据不变)\n const tEls = snapshot(txbx.getElementsByTagNameNS(W_NS, 't'));\n for (const t of tEls) {\n joined += textContentOfDirect(t);\n }\n }\n out.hasInnerText = joined.length > 0;\n const trimmed = joined.trim();\n if (trimmed.length > 0) out.innerText = trimmed;\n\n // 首段对齐:第一个 w:p 的 w:pPr/w:jc @val\n const firstP = firstDescendant(txbx, W_NS, 'p');\n if (firstP) {\n const pPr = firstDirectChild(firstP, W_NS, 'pPr');\n if (pPr) {\n const jc = firstDirectChild(pPr, W_NS, 'jc');\n if (jc) {\n const val = jc.getAttributeNS(W_NS, 'val');\n if (val) out.innerTextAlign = val;\n }\n }\n }\n } else {\n out.hasInnerText = false;\n }\n }\n\n return out;\n}\n\n/**\n * 取承载 drawing 的 w:p 元素和在父 w:p 下的 run 序号;找不到时返回 nulls。\n *\n * **两段式**(CR 设计澄清):\n *\n * 1. 向上找最近的 `w:r` 和最近的 `w:p`(这一步遇到 `txbxContent` 前会先撞到内层 `w:p`,\n * 旧实现把 txbxContent 守卫放在这一步是死代码 —— 永远触发不到)\n *\n * 2. 找到 `w:p` 后**继续向上**检查它是否落在 `w:txbxContent` 子树里。若是,返回\n * `{ para: null, runIndex: undefined }`,让 `DrawingInfo.anchorParaId` 留空。\n *\n * 为什么这样设计:文本框内的 `w:p` 与外层 `w:p` 是**两套独立段落流**(不在同一\n * paraIdx scope)。如果把\"文本框内段落 paraId\"挂给 drawing:\n * - 下游\"删 paraId\" 命令找不到(文本框内段落不进 paraIdx body 视图)\n * - 误以为\"删这个段落 = 删这张图\",结果删的是文本框内的整段,留下空文本框\n *\n * 文档站根(body / hdr / ftr / footnote / endnote / comment)作为向上扫描的边界,\n * 避免穿过 story 边界。\n */\nfunction findAnchorParagraph(drawing: Element): {\n para: Element | null;\n runIndex: number | undefined;\n} {\n // 第 1 步:向上找最近的 w:r 与最近的 w:p\n let p: Element | null = drawing.parentElement;\n let runEl: Element | null = null;\n let containerP: Element | null = null;\n while (p) {\n if (p.namespaceURI === W_NS) {\n if (p.localName === 'r' && !runEl) runEl = p;\n if (p.localName === 'p') {\n containerP = p;\n break;\n }\n }\n p = p.parentElement;\n }\n if (!containerP) return { para: null, runIndex: undefined };\n\n // 第 2 步:检查 containerP 是否落在 txbxContent 内 —— 若是,主动返回 null\n // 防御 story 根(body / hdr / ftr / footnote / endnote / comment)作为扫描边界\n let q: Element | null = containerP.parentElement;\n while (q) {\n if (q.namespaceURI === W_NS) {\n if (q.localName === 'txbxContent') {\n return { para: null, runIndex: undefined };\n }\n if (\n q.localName === 'body' ||\n q.localName === 'hdr' ||\n q.localName === 'ftr' ||\n q.localName === 'footnote' ||\n q.localName === 'endnote' ||\n q.localName === 'comment'\n ) {\n break;\n }\n }\n q = q.parentElement;\n }\n\n // 第 3 步:在 containerP 直接子中找 runEl 的序号\n let runIndex: number | undefined;\n if (runEl) {\n let n = 0;\n for (let i = 0; i < containerP.childNodes.length; i++) {\n const child = containerP.childNodes[i] as Element;\n if (child && child.nodeType === 1 && child.namespaceURI === W_NS && child.localName === 'r') {\n if (child === runEl) {\n runIndex = n;\n break;\n }\n n++;\n }\n }\n }\n\n return { para: containerP, runIndex };\n}\n\n/** 判断 drawing 是否嵌套在另一个 drawing 内(用于 group / canvas 内子图过滤的预判)*/\nfunction hasDrawingAncestor(drawing: Element): boolean {\n let p = drawing.parentElement;\n while (p) {\n if (p.namespaceURI === W_NS && p.localName === 'drawing' && p !== drawing) return true;\n p = p.parentElement;\n }\n return false;\n}\n\nfunction nearestAncestor(el: Element, ns: string, localName: string): Element | null {\n let p = el.parentElement;\n while (p) {\n if (p.namespaceURI === ns && p.localName === localName) return p;\n p = p.parentElement;\n }\n return null;\n}\n\nfunction paragraphText(p: Element, runTextOpts?: RunTextOptions): string {\n let text = '';\n for (let i = 0; i < p.childNodes.length; i++) {\n const child = p.childNodes[i] as Element;\n if (!child || child.nodeType !== 1 || child.namespaceURI !== W_NS) continue;\n if (child.localName === 'r') text += getRunText(child, runTextOpts);\n }\n return text;\n}\n\nfunction directDrawingIdsInTextBoxParagraph(\n p: Element,\n ownerTxbx: Element,\n drawingToId: Map<Element, string>,\n): string[] {\n const ids: string[] = [];\n const drawings = p.getElementsByTagNameNS(W_NS, 'drawing');\n for (let i = 0; i < drawings.length; i++) {\n const drawing = drawings[i];\n if (!drawing || nearestAncestor(drawing, W_NS, 'txbxContent') !== ownerTxbx) continue;\n const id = drawingToId.get(drawing);\n if (id) ids.push(id);\n }\n return ids;\n}\n\nfunction collectTextBoxBlocks(\n txbx: Element,\n drawingToId: Map<Element, string>,\n tableToId: Map<Element, string>,\n runTextOpts?: RunTextOptions,\n): TextBoxBlockInfo[] {\n const blocks: TextBoxBlockInfo[] = [];\n for (let i = 0; i < txbx.childNodes.length; i++) {\n const child = txbx.childNodes[i] as Element;\n if (!child || child.nodeType !== 1 || child.namespaceURI !== W_NS) continue;\n\n if (child.localName === 'p') {\n const paraId = child.getAttributeNS(W14_NS, 'paraId') ?? undefined;\n const text = paragraphText(child, runTextOpts);\n const drawingIds = directDrawingIdsInTextBoxParagraph(child, txbx, drawingToId);\n if (paraId && (text.length > 0 || drawingIds.length === 0)) {\n blocks.push({ type: 'paragraph', paraId: paraId.toUpperCase(), text });\n }\n for (const drawingId of drawingIds) {\n blocks.push(\n paraId\n ? { type: 'drawing', drawingId, paraId: paraId.toUpperCase() }\n : { type: 'drawing', drawingId },\n );\n }\n continue;\n }\n\n if (child.localName === 'tbl') {\n const tableId = tableToId.get(child);\n if (tableId) blocks.push({ type: 'table', tableId });\n }\n }\n return blocks;\n}\n\nfunction reverseElementIndex(index: Map<string, Element>): Map<Element, string> {\n const reversed = new Map<Element, string>();\n for (const [id, el] of index) reversed.set(el, id);\n return reversed;\n}\n\n/** 取所在 story(用 contains 检测,stories 数量通常 < 20)*/\nfunction findStoryForEl(el: Element, stories: Story[]): Story | undefined {\n for (const s of stories) {\n if (s.root.contains(el as unknown as Node)) return s;\n }\n return undefined;\n}\n\n/** 判 partPath 对应的 contentType 是否是 header / footer */\nfunction isHeaderFooterPart(pkg: Package, partPath: string): boolean {\n const part = pkg.parts.get(partPath);\n if (!part) return false;\n const ct = part.contentType;\n return ct.endsWith('.header+xml') || ct.endsWith('.footer+xml');\n}\n\n/** 分析单个 w:drawing → DrawingInfo(不含 drawingId / partPath / index / isInHeaderFooter)*/\nfunction analyzeDrawing(\n drawing: Element,\n runTextOpts?: RunTextOptions,\n drawingToId?: Map<Element, string>,\n tableToId?: Map<Element, string>,\n): Omit<DrawingInfo, 'drawingId' | 'partPath' | 'index' | 'isInHeaderFooter'> {\n // 容器:drawing 的直接子是 wp:inline 或 wp:anchor\n const inlineEl = firstDirectChild(drawing, WP_NS, 'inline');\n const anchorEl = firstDirectChild(drawing, WP_NS, 'anchor');\n const container = inlineEl ?? anchorEl;\n\n const anchoringMode: DrawingAnchoringMode = anchorEl ? 'anchor' : 'inline';\n\n const kind: DrawingKind = container ? detectKind(container) : 'other';\n const extentEMU = container ? readExtent(container) : { cx: 0, cy: 0 };\n const hasPicReference = container ? hasPicReferenceIn(container) : false;\n\n const { para, runIndex } = findAnchorParagraph(drawing);\n const anchorParaId = para?.getAttributeNS(W14_NS, 'paraId') ?? undefined;\n\n const info: Omit<DrawingInfo, 'drawingId' | 'partPath' | 'index' | 'isInHeaderFooter'> = {\n anchoringMode,\n kind,\n extentEMU,\n hasPicReference,\n };\n\n if (anchorEl) {\n const wrap = readWrap(anchorEl);\n if (wrap !== undefined) info.wrap = wrap;\n const pos = readPosition(anchorEl);\n if (pos.horizontal || pos.vertical) info.position = pos;\n }\n\n if (anchorParaId !== undefined) info.anchorParaId = anchorParaId;\n if (runIndex !== undefined) info.runIndex = runIndex;\n\n if (kind === 'shape' || kind === 'textBox') {\n const sig = container\n ? readShapeSignals(container, kind === 'textBox', runTextOpts, drawingToId, tableToId)\n : { hasBorder: false, hasFill: false };\n info.hasBorder = sig.hasBorder;\n info.hasFill = sig.hasFill;\n if (sig.hasInnerText !== undefined) info.hasInnerText = sig.hasInnerText;\n if (sig.innerText !== undefined) info.innerText = sig.innerText;\n if (sig.innerParagraphIds !== undefined) info.innerParagraphIds = sig.innerParagraphIds;\n if (sig.innerBlocks !== undefined) info.innerBlocks = sig.innerBlocks;\n if (sig.innerTextAlign !== undefined) info.innerTextAlign = sig.innerTextAlign;\n }\n\n // 线条/连接线信号仅对纯几何 shape 有意义(textBox 是内容载体,不参与线条判定)\n if (kind === 'shape' && container) {\n info.isLineOrConnector = isLineOrConnectorShape(container);\n }\n\n return info;\n}\n\n// ─────────── 公开函数 ───────────\n\n/**\n * 枚举文档 drawing 对象,按文档顺序返回(与 drawingIdx 插入顺序一致)。\n *\n * - `scope: 'body'`(默认)—— 仅主文档 body 内的 drawing\n * - `scope: 'all'` —— 包含 headers / footers / footnotes / endnotes / comments\n *\n * **不做**业务分类(A/B/C)/ 分组键计算 / 代表样本选取 —— 这些属于 #191/#192。\n * 嵌套在另一个 drawing 内的子 drawing(如 group 的成员、canvas 的成员)**会被一并枚出**,\n * 由调用方按 hasDrawingAncestor 自行决定是否合并到外层(保持枚举层\"完整暴露\"的原则)。\n */\nexport function listDrawings(\n pkg: Package,\n indices: PackageIndices,\n opts?: ListDrawingsOptions,\n): DrawingInfo[] {\n const scope = opts?.scope ?? 'body';\n const stories = resolveScope(pkg, scope);\n const result: DrawingInfo[] = [];\n let idx = 1;\n const runTextOpts: RunTextOptions | undefined = opts?.structuralWhitespace\n ? { structuralWhitespace: true }\n : undefined;\n const drawingToId = reverseElementIndex(indices.drawingIdx);\n const tableToId = reverseElementIndex(indices.tblIdx);\n\n // 直接遍历 drawingIdx(插入顺序 = 文档顺序)\n for (const [drawingId, drawing] of indices.drawingIdx) {\n const story = findStoryForEl(drawing, stories);\n if (!story) continue; // 不在请求的 scope 内\n\n const info: DrawingInfo = {\n drawingId,\n partPath: story.partPath,\n index: idx++,\n isInHeaderFooter: isHeaderFooterPart(pkg, story.partPath),\n ...analyzeDrawing(drawing, runTextOpts, drawingToId, tableToId),\n };\n result.push(info);\n }\n\n return result;\n}\n\n/**\n * 按 drawingId 精确取单个 drawing。不存在返回 null。\n *\n * **index 字段语义**:返回 drawing 在 **全局 drawingIdx 插入顺序**中的 1-based 位置\n * —— 与 `listDrawings({ scope: 'all' })` 的 index 一致;与 `listDrawings({ scope: 'body' })`\n * 的 1-based 位置**不一定**相等(后者可能过滤掉了页眉页脚 drawing)。\n *\n * 复杂度:drawingIdx 查找 O(1);全局序号扫描 O(N),N = 包内 drawing 总数。\n * 调用方需要严格按 scope 取序号时应直接走 listDrawings。\n *\n * 旧实现复用了 list-tables.ts 的 `index: 0` 哨兵,下游用 `index` 排序/引用会拿到\n * 错误值(CR BUG-1)—— 改为真实序号。\n */\nexport function getDrawingById(\n pkg: Package,\n indices: PackageIndices,\n drawingId: string,\n): DrawingInfo | null {\n const drawing = indices.drawingIdx.get(drawingId);\n if (!drawing) return null;\n\n // 找所属 story 以获取 partPath\n const stories = resolveScope(pkg, 'all');\n const story = findStoryForEl(drawing, stories);\n if (!story) return null;\n const drawingToId = reverseElementIndex(indices.drawingIdx);\n const tableToId = reverseElementIndex(indices.tblIdx);\n\n // 计算全局 1-based 序号(drawingIdx 是 Map,迭代序 = 文档顺序)\n let globalIndex = 0;\n let i = 0;\n for (const id of indices.drawingIdx.keys()) {\n i++;\n if (id === drawingId) {\n globalIndex = i;\n break;\n }\n }\n\n return {\n drawingId,\n partPath: story.partPath,\n index: globalIndex,\n isInHeaderFooter: isHeaderFooterPart(pkg, story.partPath),\n ...analyzeDrawing(drawing, undefined, drawingToId, tableToId),\n };\n}\n\n/**\n * 装载期构建 drawingIdx:枚举 Package 中所有 Word 内容 part 的 <w:drawing>,\n * 按文档顺序分配 'dr-NNNN' ID。由 buildIndices 调用。\n *\n * 内部函数风格对齐 buildTableIndex(list-tables.ts)。\n */\nexport function buildDrawingIndex(\n parts: Iterable<{\n contentType: string;\n xmlDom?: {\n getElementsByTagNameNS(\n ns: string,\n local: string,\n ): { length: number } & Record<number, Element>;\n };\n }>,\n): Map<string, Element> {\n const drawingIdx = new Map<string, Element>();\n let n = 1;\n\n for (const part of parts) {\n const ct = part.contentType;\n // 与 ListDrawingsOptions / DrawingsApi.list 的 scope:'all' 语义对齐:\n // body + headers + footers + footnotes + endnotes + comments\n //\n // CR 修复:旧实现注释「comments.xml 内通常不含 drawing,跳过」是错误假设\n // —— 评论 part 内合法可含 drawing(如批注图示),漏掉会让 scope:'all' 与文档承诺不一致。\n if (\n !ct.includes('wordprocessingml') &&\n !ct.endsWith('.main+xml') &&\n !ct.endsWith('.header+xml') &&\n !ct.endsWith('.footer+xml') &&\n !ct.endsWith('.footnotes+xml') &&\n !ct.endsWith('.endnotes+xml') &&\n !ct.endsWith('.comments+xml')\n ) {\n continue;\n }\n if (!part.xmlDom) continue;\n\n const drawings = part.xmlDom.getElementsByTagNameNS(W_NS, 'drawing');\n for (let i = 0; i < drawings.length; i++) {\n const dr = drawings[i];\n if (!dr) continue;\n // CR BUG-3:跳过 mc:Fallback 内的 drawing —— mc:Choice 已是首选呈现,\n // Fallback 是降级方案,把它也计入会导致同一对象双计。\n if (hasFallbackAncestor(dr as Element)) continue;\n // 嵌套 drawing:group / canvas 的成员 drawing 仍是 w:drawing,但通常 group/canvas\n // 的 child shapes 在 wpg:grpSp / wpc:wpc 下,不会用 w:drawing 包装。不做主动过滤\n // —— 让上层(#191 / #192)按需用 hasDrawingAncestor 自己判。\n const id = `dr-${String(n).padStart(4, '0')}`;\n drawingIdx.set(id, dr);\n n++;\n }\n }\n\n return drawingIdx;\n}\n\n/** 暴露内部工具:判断元素是否嵌套在另一个 drawing 内(#191 合并 group 子图时用)*/\nexport { hasDrawingAncestor };\n","/**\n * Word 装载期三索引(docs/03 §13.1 / §13.6)。\n *\n * - paraIdx:paraId(大写 8 hex)→ <w:p> Element\n * - bookmarkIdx:name → { start: <w:bookmarkStart>; end: <w:bookmarkEnd>; partPath }\n * - commentIdx:id(number)→ { comment?: <w:comment>; anchors: { start?, end?, ref? } }\n *\n * 同时完成装载期书签校验:**空名抛错**;**重名容错**(保留第一个、忽略后续,绝不崩 ——\n * 真实文档常见重复的 `_GoBack` 等编辑痕迹书签)。未来由 #15 WordError 统一,先用 Error + code。\n *\n * 性能目标:10 万段落 < 100ms(Chrome/Node;WPS WebView 宽松到 < 300ms)。由 `ensureParaIds`\n * 同样走 getElementsByTagNameNS 保证,这里复用同一枚举路径。\n */\nimport type { Package, Part } from '../pack/index.js';\nimport { isXmlPart } from '../pack/index.js';\nimport { W_NS, W14_NS } from './namespaces.js';\nimport { buildStylesIndex, type StyleInfo } from './style-queries.js';\nimport { buildTableIndex } from './list-tables.js';\nimport { buildDrawingIndex } from './list-drawings.js';\n\n/** 书签校验错误 code(暂不挂 WordError;#15 会统一到 WordErrorCode) */\nexport type BookmarkLoadErrorCode =\n // 【已弃用 / 不再抛出】重名书签现为容错(保留第一个、忽略后续),buildIndices 不再产生此 code。\n // 保留在 union 中仅作向后兼容,避免破坏可能引用此类型的消费方。\n 'BOOKMARK_NAME_DUPLICATE_ON_LOAD' | 'BOOKMARK_NAME_EMPTY_ON_LOAD';\n\n/** 装载期抛出的书签错误 */\nexport class BookmarkLoadError extends Error {\n readonly code: BookmarkLoadErrorCode;\n readonly details: Record<string, unknown>;\n constructor(code: BookmarkLoadErrorCode, message: string, details: Record<string, unknown> = {}) {\n super(message);\n this.name = 'BookmarkLoadError';\n this.code = code;\n this.details = details;\n }\n}\n\nexport interface BookmarkEntry {\n /** `<w:bookmarkStart>` 元素 */\n start: Element;\n /** `<w:bookmarkEnd>` 元素;若装载数据里缺失可能为 null */\n end: Element | null;\n /** 所在 part 的 path(如 'word/document.xml') */\n partPath: string;\n}\n\nexport interface CommentEntry {\n /** `<w:comment>` 元素(来自 comments.xml);若无 comments.xml 可能为 null */\n comment: Element | null;\n /** 锚点三件套(在 document.xml / headers / footers 等 body-side part 上) */\n anchors: {\n start: Element | null;\n end: Element | null;\n ref: Element | null;\n };\n}\n\nexport interface PackageIndices {\n /** paraId → <w:p> */\n paraIdx: Map<string, Element>;\n /** bookmark name → entry(含 start/end/partPath) */\n bookmarkIdx: Map<string, BookmarkEntry>;\n /** comment id → entry(comment 主体 + 三锚点) */\n commentIdx: Map<number, CommentEntry>;\n /**\n * styleId → StyleInfo(来自 styles.xml)。\n * styles.xml 不存在时为空 Map。\n * 消费方按 styleId 做 O(1) 查找,沿 basedOn 链判断语义角色时须自行防环。\n */\n stylesIdx: Map<string, StyleInfo>;\n /**\n * tableId('tbl-NNNN')→ <w:tbl> Element(#185)。\n * 装载期按文档顺序分配,包含所有 part 的所有表格(含嵌套)。\n * 供 listTables / getTableById / plan executor(deleteTable)使用。\n */\n tblIdx: Map<string, Element>;\n /**\n * drawingId('dr-NNNN')→ <w:drawing> Element(#189)。\n * 装载期按文档顺序分配,包含所有 Word 内容 part 的所有 drawing。\n * 供 listDrawings / getDrawingById / 占位图替换(#190)使用。\n *\n * 注意:嵌套在 group / canvas 内的子 drawing 也会被收入(保持枚举层完整暴露),\n * 上层(#191 / #192)按需用 hasDrawingAncestor 自行决定合并策略。\n */\n drawingIdx: Map<string, Element>;\n}\n\n// re-export StyleInfo 供其他 word 内部模块从 indices 一站式引入\nexport type { StyleInfo };\n\n/** 判断 part 是否 Word 主要内容 part(按常见 contentType 前缀匹配) */\nfunction isWordContentPart(part: Part): boolean {\n const ct = part.contentType;\n return (\n ct.includes('wordprocessingml') ||\n ct.endsWith('.main+xml') ||\n ct.endsWith('.header+xml') ||\n ct.endsWith('.footer+xml') ||\n ct.endsWith('.footnotes+xml') ||\n ct.endsWith('.endnotes+xml') ||\n ct.endsWith('.comments+xml')\n );\n}\n\n/** 判断 part 是否 comments 存储 part(commentIdx 的 comment 主体来自这里) */\nfunction isCommentsPart(part: Part): boolean {\n return part.contentType.endsWith('.comments+xml');\n}\n\n/** 把 HTMLCollection-ish 枚举结果快照成数组(避免 live 行为) */\nfunction snapshot<T extends Element>(col: { length: number } & Record<number, T>): T[] {\n const out: T[] = [];\n for (let i = 0; i < col.length; i++) {\n const el = col[i];\n if (el) out.push(el);\n }\n return out;\n}\n\n/**\n * 扫 Package 构建三索引。\n *\n * - **装载期书签校验**:遇空名抛 `BookmarkLoadError`(code = BOOKMARK_NAME_EMPTY_ON_LOAD);\n * 遇重名**容错**(保留第一个、忽略后续,不抛错 —— `_GoBack` 等编辑痕迹书签可安全忽略)\n * - 孤儿 `bookmarkEnd`(无匹配 start)忽略\n * - 缺 `bookmarkEnd` 的书签仍入索引,`entry.end` 为 null\n * - 不抛错的其它不一致(comment 无 <w:comment> 主体、anchors 不全)进索引,由调用方决定是否告警\n */\nexport function buildIndices(pkg: Package): PackageIndices {\n const paraIdx = new Map<string, Element>();\n const bookmarkIdx = new Map<string, BookmarkEntry>();\n const commentIdx = new Map<number, CommentEntry>();\n\n // bookmarkStart 临时:id -> { start, partPath, name }(用于和后续 bookmarkEnd 配对)\n const pendingStarts = new Map<string, { start: Element; partPath: string; name: string }>();\n\n for (const part of pkg.parts.values()) {\n if (!isXmlPart(part) || !part.xmlDom) continue;\n if (!isWordContentPart(part)) continue;\n\n // paraIdx\n const paragraphs = snapshot(part.xmlDom.getElementsByTagNameNS(W_NS, 'p'));\n for (const p of paragraphs) {\n const id = p.getAttributeNS(W14_NS, 'paraId');\n if (id) paraIdx.set(id.toUpperCase(), p);\n }\n\n // bookmarkIdx — 先收集 start,后续匹配 end\n const starts = snapshot(part.xmlDom.getElementsByTagNameNS(W_NS, 'bookmarkStart'));\n for (const start of starts) {\n const bId = start.getAttributeNS(W_NS, 'id');\n const bName = start.getAttributeNS(W_NS, 'name');\n if (bName === null) {\n // 缺 name 属性 —— 当作空名\n throw new BookmarkLoadError(\n 'BOOKMARK_NAME_EMPTY_ON_LOAD',\n `bookmarkStart with w:id=\"${bId ?? ''}\" has no w:name`,\n { partPath: part.path, bookmarkId: bId ?? null },\n );\n }\n if (bName.length === 0) {\n throw new BookmarkLoadError(\n 'BOOKMARK_NAME_EMPTY_ON_LOAD',\n `bookmarkStart with w:id=\"${bId ?? ''}\" has empty w:name`,\n { partPath: part.path, bookmarkId: bId ?? null },\n );\n }\n if (bookmarkIdx.has(bName)) {\n // 容错:重名书签**保留第一个、忽略后续**,不抛错(绝不因装载期数据瑕疵崩溃)。\n //\n // 真实文档(多次编辑 / 多工具处理过)经常出现重复书签名 —— 最典型的是 Word 自动\n // 插入的 `_GoBack`(标记上次编辑位置),也可能是模板拼接残留的其它重名书签。\n // OOXML 实践中 Word 自己也容忍重复书签名;bookmarkIdx 是 name→entry 的 Map,按 name\n // 唯一本就是其数据结构约束,保留首个即可满足所有下游(反查 / 重名检查 / 删除)。\n //\n // 注意:这里只跳过往 bookmarkIdx 登记,但**不会**把后续重名的 bookmarkStart 当作\n // pendingStart 处理,因此其配套的 bookmarkEnd 不会错配到第一个 entry 上(end 仍只认\n // 第一个 start 的 id 作用域)。元素本身保留在 DOM 里,保存时原样写回,内容不丢失。\n continue;\n }\n // 先登记:end 稍后补\n bookmarkIdx.set(bName, { start, end: null, partPath: part.path });\n if (bId !== null) {\n pendingStarts.set(`${part.path}::${bId}`, { start, partPath: part.path, name: bName });\n }\n }\n\n // 匹配 bookmarkEnd(按 w:id,作用域限定到 part 内)\n const ends = snapshot(part.xmlDom.getElementsByTagNameNS(W_NS, 'bookmarkEnd'));\n for (const end of ends) {\n const eId = end.getAttributeNS(W_NS, 'id');\n if (eId === null) continue;\n const matched = pendingStarts.get(`${part.path}::${eId}`);\n if (matched) {\n const entry = bookmarkIdx.get(matched.name);\n if (entry) entry.end = end;\n }\n }\n\n // commentIdx — 锚点(document.xml / headers / footers 等 body-side part)\n const anchorStarts = snapshot(part.xmlDom.getElementsByTagNameNS(W_NS, 'commentRangeStart'));\n const anchorEnds = snapshot(part.xmlDom.getElementsByTagNameNS(W_NS, 'commentRangeEnd'));\n const anchorRefs = snapshot(part.xmlDom.getElementsByTagNameNS(W_NS, 'commentReference'));\n for (const anchor of anchorStarts) {\n const id = numAttr(anchor, W_NS, 'id');\n if (id === null) continue;\n getOrCreateCommentEntry(commentIdx, id).anchors.start = anchor;\n }\n for (const anchor of anchorEnds) {\n const id = numAttr(anchor, W_NS, 'id');\n if (id === null) continue;\n getOrCreateCommentEntry(commentIdx, id).anchors.end = anchor;\n }\n for (const anchor of anchorRefs) {\n const id = numAttr(anchor, W_NS, 'id');\n if (id === null) continue;\n getOrCreateCommentEntry(commentIdx, id).anchors.ref = anchor;\n }\n\n // commentIdx — 主体(comments.xml)\n if (isCommentsPart(part)) {\n const comments = snapshot(part.xmlDom.getElementsByTagNameNS(W_NS, 'comment'));\n for (const c of comments) {\n const id = numAttr(c, W_NS, 'id');\n if (id === null) continue;\n getOrCreateCommentEntry(commentIdx, id).comment = c;\n }\n }\n }\n\n const stylesIdx = buildStylesIndex(pkg);\n const tblIdx = buildTableIndex(pkg.parts.values());\n const drawingIdx = buildDrawingIndex(pkg.parts.values());\n\n return { paraIdx, bookmarkIdx, commentIdx, stylesIdx, tblIdx, drawingIdx };\n}\n\nfunction numAttr(el: Element, ns: string, local: string): number | null {\n const v = el.getAttributeNS(ns, local);\n if (v === null) return null;\n const n = Number(v);\n return Number.isFinite(n) ? n : null;\n}\n\nfunction getOrCreateCommentEntry(idx: Map<number, CommentEntry>, id: number): CommentEntry {\n let e = idx.get(id);\n if (!e) {\n e = { comment: null, anchors: { start: null, end: null, ref: null } };\n idx.set(id, e);\n }\n return e;\n}\n","import type { Op } from './plan.js';\nimport type { ListParagraphsOptions, ListResult, ParagraphInfo } from './list-paragraphs.js';\nimport type { ListTablesOptions, RowHeight, TableCellInfo, TableInfo } from './list-tables.js';\n\nexport type DomainCacheState = 'empty' | 'ready' | 'dirty';\nexport type DomainCacheName = 'all' | 'paragraphs' | 'tables';\n\nexport interface ParagraphDomainCacheSnapshot {\n state: DomainCacheState;\n listAllBodyReady: boolean;\n cachedParagraphIds: string[];\n dirtyReason?: string;\n buildCount: number;\n}\n\nexport interface WordDomainCacheSnapshot {\n revision: number;\n paragraphs: ParagraphDomainCacheSnapshot;\n tables: TableDomainCacheSnapshot;\n}\n\nexport interface TableDomainCacheSnapshot {\n state: DomainCacheState;\n cachedProfiles: string[];\n cachedTableIds: string[];\n dirtyReason?: string;\n buildCount: number;\n}\n\nexport class WordDomainCache {\n private revision = 0;\n readonly paragraphs = new ParagraphDomainCache();\n readonly tables = new TableDomainCache();\n\n reset(): void {\n this.revision = 0;\n this.paragraphs.clear();\n this.tables.clear();\n }\n\n currentRevision(): number {\n return this.revision;\n }\n\n afterSuccessfulApply(ops: readonly Op[]): void {\n this.revision++;\n if (ops.some(affectsParagraphTextOrStructure)) {\n this.paragraphs.markDirty('content mutation');\n }\n if (ops.some(affectsTableStructureOrContent)) {\n this.tables.markDirty('content mutation');\n }\n }\n\n invalidate(domain: DomainCacheName = 'all', reason = 'manual'): void {\n if (domain === 'all' || domain === 'paragraphs') {\n this.paragraphs.markDirty(reason);\n }\n if (domain === 'all' || domain === 'tables') {\n this.tables.markDirty(reason);\n }\n }\n\n snapshot(): WordDomainCacheSnapshot {\n return {\n revision: this.revision,\n paragraphs: this.paragraphs.snapshot(),\n tables: this.tables.snapshot(),\n };\n }\n}\n\nexport class ParagraphDomainCache {\n private state: DomainCacheState = 'empty';\n private dirtyReason: string | undefined;\n private listAllBody: ListResult | undefined;\n private byId = new Map<string, ParagraphInfo | null>();\n private buildCount = 0;\n\n getCacheableList(\n opts: ListParagraphsOptions | undefined,\n build: () => ListResult,\n ): ListResult | undefined {\n if (!isCacheableParagraphList(opts)) return undefined;\n this.flushIfDirty();\n if (!this.listAllBody) {\n const result = build();\n this.listAllBody = cloneListResult(result);\n this.byId.clear();\n for (const paragraph of this.listAllBody.paragraphs) {\n this.byId.set(paragraph.paraId.toUpperCase(), paragraph);\n }\n this.state = 'ready';\n this.dirtyReason = undefined;\n this.buildCount++;\n }\n return cloneListResult(this.listAllBody);\n }\n\n getParagraph(paraId: string, build: () => ParagraphInfo | null): ParagraphInfo | null {\n this.flushIfDirty();\n const key = paraId.toUpperCase();\n if (!this.byId.has(key)) {\n const value = build();\n this.byId.set(key, value ? cloneParagraphInfo(value) : null);\n this.state = 'ready';\n this.dirtyReason = undefined;\n this.buildCount++;\n }\n const value = this.byId.get(key) ?? null;\n return value ? cloneParagraphInfo(value) : null;\n }\n\n markDirty(reason: string): void {\n if (this.state === 'empty') return;\n this.state = 'dirty';\n this.dirtyReason = reason;\n }\n\n clear(): void {\n this.state = 'empty';\n this.dirtyReason = undefined;\n this.listAllBody = undefined;\n this.byId.clear();\n this.buildCount = 0;\n }\n\n snapshot(): ParagraphDomainCacheSnapshot {\n return {\n state: this.state,\n listAllBodyReady: !!this.listAllBody && this.state !== 'dirty',\n cachedParagraphIds: Array.from(this.byId.keys()),\n dirtyReason: this.dirtyReason,\n buildCount: this.buildCount,\n };\n }\n\n private flushIfDirty(): void {\n if (this.state !== 'dirty') return;\n this.state = 'empty';\n this.dirtyReason = undefined;\n this.listAllBody = undefined;\n this.byId.clear();\n }\n}\n\nexport function isCacheableParagraphList(opts: ListParagraphsOptions | undefined): boolean {\n if (!opts) return false;\n if (opts.scope !== undefined && opts.scope !== 'body') return false;\n if (opts.filter !== undefined) return false;\n if (opts.textFormat !== undefined && opts.textFormat !== 'full') return false;\n if (opts.includeFormat === true) return false;\n if (opts.structuralWhitespace === true) return false;\n if (opts.includeTableInfo === true) return false;\n return opts.pagination?.mode === 'all';\n}\n\ntype TableListProfile = 'basic' | 'withCellTexts';\n\nexport class TableDomainCache {\n private state: DomainCacheState = 'empty';\n private dirtyReason: string | undefined;\n private lists = new Map<TableListProfile, TableInfo[]>();\n private byIdBasic = new Map<string, TableInfo | null>();\n private buildCount = 0;\n\n getCacheableList(\n opts: ListTablesOptions | undefined,\n build: () => TableInfo[],\n ): TableInfo[] | undefined {\n const profile = tableListProfile(opts);\n if (!profile) return undefined;\n this.flushIfDirty();\n if (!this.lists.has(profile)) {\n const tables = build().map(cloneTableInfo);\n this.lists.set(profile, tables);\n if (profile === 'basic') {\n this.byIdBasic.clear();\n for (const table of tables) {\n this.byIdBasic.set(table.tableId, table);\n }\n }\n this.state = 'ready';\n this.dirtyReason = undefined;\n this.buildCount++;\n }\n return this.lists.get(profile)!.map(cloneTableInfo);\n }\n\n getTable(tableId: string, build: () => TableInfo | null): TableInfo | null {\n this.flushIfDirty();\n if (!this.byIdBasic.has(tableId)) {\n const table = build();\n this.byIdBasic.set(tableId, table ? cloneTableInfo(table) : null);\n this.state = 'ready';\n this.dirtyReason = undefined;\n this.buildCount++;\n }\n const table = this.byIdBasic.get(tableId) ?? null;\n return table ? cloneTableInfo(table) : null;\n }\n\n markDirty(reason: string): void {\n if (this.state === 'empty') return;\n this.state = 'dirty';\n this.dirtyReason = reason;\n }\n\n clear(): void {\n this.state = 'empty';\n this.dirtyReason = undefined;\n this.lists.clear();\n this.byIdBasic.clear();\n this.buildCount = 0;\n }\n\n snapshot(): TableDomainCacheSnapshot {\n return {\n state: this.state,\n cachedProfiles: this.state === 'dirty' ? [] : Array.from(this.lists.keys()),\n cachedTableIds: this.state === 'dirty' ? [] : Array.from(this.byIdBasic.keys()),\n dirtyReason: this.dirtyReason,\n buildCount: this.buildCount,\n };\n }\n\n private flushIfDirty(): void {\n if (this.state !== 'dirty') return;\n this.state = 'empty';\n this.dirtyReason = undefined;\n this.lists.clear();\n this.byIdBasic.clear();\n }\n}\n\nexport function isCacheableTableList(opts: ListTablesOptions | undefined): boolean {\n return tableListProfile(opts) !== null;\n}\n\nfunction tableListProfile(opts: ListTablesOptions | undefined): TableListProfile | null {\n if (opts?.scope !== undefined && opts.scope !== 'body') return null;\n if (opts?.includeNested === true) return null;\n return opts?.includeCellTexts === true ? 'withCellTexts' : 'basic';\n}\n\nfunction affectsParagraphTextOrStructure(op: Op): boolean {\n switch (op.type) {\n case 'replaceParagraph':\n case 'replaceTextInParagraph':\n case 'formatParagraph':\n case 'insertParagraphBefore':\n case 'insertParagraphAfter':\n case 'insertParagraphAtBodyStart':\n case 'deleteParagraph':\n case 'deleteTable':\n case 'replaceTableCellWithSdt':\n case 'deleteTableRow':\n case 'replaceTableCellText':\n case 'insertTableCellParagraph':\n case 'replaceShapeInnerText':\n case 'insertTableRow':\n case 'cloneTableAfter':\n case 'insertImageAfter':\n case 'insertTableFrom':\n return true;\n default:\n return false;\n }\n}\n\nfunction affectsTableStructureOrContent(op: Op): boolean {\n switch (op.type) {\n case 'deleteTable':\n case 'replaceTableCellWithSdt':\n case 'deleteTableRow':\n case 'replaceTableCellText':\n case 'formatTableCell':\n case 'insertTableCellParagraph':\n case 'insertTableRow':\n case 'cloneTableAfter':\n case 'insertTableFrom':\n case 'setTableColumnWidths':\n case 'setTableRowHeights':\n return true;\n case 'deleteParagraph':\n case 'insertParagraphBefore':\n case 'insertParagraphAfter':\n case 'insertParagraphAtBodyStart':\n case 'insertImageAfter':\n case 'deleteDrawing':\n case 'replaceDrawingWithPlaceholder':\n return true;\n default:\n return false;\n }\n}\n\nfunction cloneListResult(result: ListResult): ListResult {\n return {\n paragraphs: result.paragraphs.map(cloneParagraphInfo),\n pagination: { ...result.pagination },\n };\n}\n\nfunction cloneParagraphInfo(info: ParagraphInfo): ParagraphInfo {\n return {\n ...info,\n format: info.format\n ? {\n ...info.format,\n indent: info.format.indent ? { ...info.format.indent } : undefined,\n spacing: info.format.spacing ? { ...info.format.spacing } : undefined,\n }\n : undefined,\n table: info.table ? { ...info.table } : undefined,\n };\n}\n\nfunction cloneTableInfo(info: TableInfo): TableInfo {\n return {\n ...info,\n columnWidths: [...info.columnWidths],\n rowHeights: info.rowHeights.map(cloneRowHeightOrNull),\n cells: info.cells ? info.cells.map((row) => [...row]) : undefined,\n cellGrid: info.cellGrid ? info.cellGrid.map((row) => row.map(cloneTableCellInfo)) : undefined,\n };\n}\n\nfunction cloneRowHeightOrNull(rowHeight: RowHeight | null): RowHeight | null {\n return rowHeight ? { ...rowHeight } : null;\n}\n\nfunction cloneTableCellInfo(cell: TableCellInfo): TableCellInfo {\n return {\n ...cell,\n shading: cell.shading ? { ...cell.shading } : undefined,\n paragraphIds: [...cell.paragraphIds],\n blocks: cell.blocks.map((block) => ({ ...block })),\n imageDrawingIds: [...cell.imageDrawingIds],\n };\n}\n","/**\n * w14:paraId 装载时 normalize —— docs/03 §11.2 / §13.6。\n *\n * 语义:\n * - 扫 Package 里所有 XML part,对缺 `w14:paraId` 的 `<w:p>` 分配随机 8 位十六进制 id\n * - **package 全局唯一**(body / headers / footers / footnotes / endnotes / comments 同集合)\n * - 发生分配的 part 被 markDirty,便于后续 toZip / toFlatOpc 重 serialize\n * - 10 万段落 ≈ 40ms(实测基线,见 bench/xml-stack-worker)\n */\nimport type { Package } from '../pack/index.js';\nimport { isXmlPart, markDirty } from '../pack/index.js';\nimport { W_NS, W14_NS } from './namespaces.js';\n\nexport interface EnsureParaIdsResult {\n /** 本次新分配的 paraId 数量 */\n added: number;\n /** 扫描到的 <w:p> 总数(含既有 paraId) */\n total: number;\n /** 发生分配的 part path 列表 */\n touchedParts: string[];\n}\n\n/** 扫全包收集已有的 paraId,保证新分配不冲突 */\nfunction collectExistingParaIds(pkg: Package): Set<string> {\n const set = new Set<string>();\n for (const part of pkg.parts.values()) {\n if (!isXmlPart(part) || !part.xmlDom) continue;\n const paragraphs = part.xmlDom.getElementsByTagNameNS(W_NS, 'p');\n for (let i = 0; i < paragraphs.length; i++) {\n const p = paragraphs[i];\n if (!p) continue;\n const id = p.getAttributeNS(W14_NS, 'paraId');\n if (id) set.add(id.toUpperCase());\n }\n }\n return set;\n}\n\n/**\n * 生成 8 位十六进制 paraId,冲突重试。\n *\n * 使用 crypto.getRandomValues 取 4 字节(32-bit),转十六进制字符串,大写。\n * export 供 executor(#29 等)在 apply 时分配新段落 id 使用。\n */\nexport function generateParaId(seen: Set<string>, maxAttempts = 100): string {\n const bytes = new Uint8Array(4);\n for (let i = 0; i < maxAttempts; i++) {\n globalThis.crypto.getRandomValues(bytes);\n const hex =\n bytes[0]!.toString(16).padStart(2, '0') +\n bytes[1]!.toString(16).padStart(2, '0') +\n bytes[2]!.toString(16).padStart(2, '0') +\n bytes[3]!.toString(16).padStart(2, '0');\n const id = hex.toUpperCase();\n if (!seen.has(id)) {\n seen.add(id);\n return id;\n }\n }\n throw new Error(`ensureParaIds: unable to generate unique paraId after ${maxAttempts} attempts`);\n}\n\n/**\n * 为 Package 内所有缺 w14:paraId 的 <w:p> 分配随机 id(package 全局唯一)。\n *\n * 发生分配的 part 会被 markDirty。\n */\nexport function ensureParaIds(pkg: Package): EnsureParaIdsResult {\n const seen = collectExistingParaIds(pkg);\n let added = 0;\n let total = 0;\n const touched = new Set<string>();\n\n for (const part of pkg.parts.values()) {\n if (!isXmlPart(part) || !part.xmlDom) continue;\n const paragraphs = part.xmlDom.getElementsByTagNameNS(W_NS, 'p');\n let partTouched = false;\n // 快照成数组,避免下面 setAttributeNS 导致 live collection 行为变化\n const snapshot: Element[] = [];\n for (let i = 0; i < paragraphs.length; i++) {\n const el = paragraphs[i];\n if (el) snapshot.push(el);\n }\n total += snapshot.length;\n for (const p of snapshot) {\n const id = p.getAttributeNS(W14_NS, 'paraId');\n if (!id) {\n const newId = generateParaId(seen);\n p.setAttributeNS(W14_NS, 'w14:paraId', newId);\n added++;\n partTouched = true;\n }\n }\n if (partTouched) {\n markDirty(part);\n touched.add(part.path);\n }\n }\n\n return { added, total, touchedParts: Array.from(touched) };\n}\n","/**\n * WordError —— Word core 的统一错误模型(docs/03.1 §4)。\n *\n * 所有面向消费方的错误都用 WordError 抛出。`code` 枚举覆盖装载期 / 查询 / 变更前置 / Plan 状态\n * 四大类。`docId` 由 core 自动填充(WordDocument 内捕获底层错误后重抛时注入),方便日志\n * 与多文档场景定位。\n */\n\nexport type WordErrorCode =\n // ── 装载期 ──\n | 'PACKAGE_CORRUPT' // 字节 / XML 格式错\n | 'PACKAGE_UNSUPPORTED_FORMAT' // 不是 Word docx / Flat OPC\n | 'BOOKMARK_NAME_DUPLICATE_ON_LOAD' // 【已弃用 / 不再装载期抛出】重名书签现为容错(保留第一个),\n // // code 保留仅作向后兼容,buildIndices 不再产生它(见 indices.ts)\n | 'BOOKMARK_NAME_EMPTY_ON_LOAD'\n | 'WORKER_CREATION_FAILED' // mode='worker' 显式但创建失败\n | 'WORKER_RELOADED' // worker 崩溃后 terminate + reload,执行中的 RPC 以此拒收(docs/03 §4.7)\n // ── 查询 ──\n | 'PARA_NOT_FOUND'\n | 'BOOKMARK_NOT_FOUND'\n | 'COMMENT_NOT_FOUND'\n | 'REVISION_NOT_FOUND'\n | 'TABLE_NOT_FOUND' // 表格 / 单元格 / 行按 (tableId, row?, col?) 查不到; details 带 row/col 详情\n | 'DRAWING_NOT_FOUND' // drawing 按 drawingId 查不到\n // ── 变更前置 ──\n | 'TEXT_NOT_FOUND_IN_PARA'\n | 'BOOKMARK_NAME_EXISTS'\n | 'BOOKMARK_NAME_INVALID'\n | 'ANCHOR_CONFLICT' // 变更区间覆盖活锚点\n | 'UNSUPPORTED_OOXML_FEATURE' // 本期不支持的 OOXML 结构(pPrChange/rPrChange 等)\n | 'INVALID_ARGUMENT' // op 参数越界 / 逻辑错误(如 outlineLevel 超出 0-8 范围)\n // ── Plan 状态 ──\n | 'PLAN_ALREADY_APPLIED'\n | 'PLAN_EMPTY' // apply() 空 plan;默认 warn 不抛,严格模式可抛\n // ── 排版(typeset Layer4)内容核对门禁(D5,接缝4「绝不丢内容」)──\n | 'CONTENT_LOST'; // 排版产物核对发现 content 元素丢失;details 带 lost[] 明细 + metrics\n\nexport class WordError extends Error {\n readonly code: WordErrorCode;\n readonly docId: string;\n readonly details: Record<string, unknown>;\n\n constructor(\n code: WordErrorCode,\n message: string,\n docId: string,\n details: Record<string, unknown> = {},\n ) {\n super(message);\n this.name = 'WordError';\n this.code = code;\n this.docId = docId;\n this.details = details;\n }\n}\n","/**\n * WordPlan —— 变更 builder + apply 机制(docs/03.1 §3,#27)。\n *\n * 职责(本 PR):\n * - 11 个链式 builder 方法 `return this`,**不返回 op 句柄**;每个方法只把 op\n * push 进内部队列,错误集中到 `apply()` 抛(契约 §4.2)\n * - `apply()` 状态机:\n * - 二次 apply → `PLAN_ALREADY_APPLIED`\n * - 空 plan → console.warn 不抛(契约默认语义;严格模式留未来)\n * - 非空 plan → transport RPC 到 kernel 的 `applyPlan`\n * - 多 plan 并存独立,不共享状态(每次 `doc.plan()` 新实例)\n *\n * **不含**任何 op 的真正执行 —— executor 一 PR 一张,#28 起陆续落地:\n * - #28: replaceParagraph / replaceTextInParagraph\n * - #29: insertParagraphBefore/After / deleteParagraph\n * - #34: createBookmark / deleteBookmark\n * - #35: addComment / deleteComment\n * - #31/#32: acceptRevisions / rejectRevisions\n *\n * 当前 kernel 侧 `applyPlan` 对任何非空 ops 直接抛 `UNSUPPORTED_OOXML_FEATURE`。\n */\nimport type { StoryId } from './stories.js';\nimport type { Transport } from './transport.js';\nimport type { WordErrorCode } from './word-error.js';\nimport type { SdtSpec } from './sdt-builders.js';\nimport type { RowHeight } from './list-tables.js';\nimport { WordError } from './word-error.js';\n\n// ─────────── 类型别名(docs/03.1 §1.1 / §1.3 / §1.7)───────────\n\nexport type ParaId = string;\nexport type BookmarkName = string;\nexport type CommentId = number;\nexport type RevisionId = string;\n\n// ─────────── Range(docs/03.1 §1.2)───────────\n\n/** 段落级定位 */\nexport interface ParagraphRange {\n paraId: ParaId;\n}\n\n/** 段落内关键词定位 */\nexport interface TextRange {\n paraId: ParaId;\n text: string;\n /** 默认 'first' */\n scope?: 'first' | 'all';\n}\n\nexport type Range = ParagraphRange | TextRange;\n\n// ─────────── RevisionScope(docs/03.1 §1.3)───────────\n\nexport type RevisionScope =\n | { scope: 'all' }\n | { scope: 'paragraph'; paraId: ParaId }\n | { scope: 'revision'; revId: RevisionId };\n\nexport interface ParagraphDirectFormat {\n alignment?: 'left' | 'center' | 'right' | 'both' | 'distribute';\n outlineLevel?: number;\n pageBreakBefore?: boolean;\n indent?: {\n left?: number;\n right?: number;\n /**\n * Positive value writes first-line indent; negative value writes hanging indent.\n */\n firstLine?: number;\n };\n spacing?: {\n before?: number;\n after?: number;\n line?: number;\n lineRule?: 'auto' | 'exact' | 'atLeast';\n };\n}\n\nexport interface TableCellDirectFormat {\n shading?: {\n /** 6-digit hex fill color without '#', or 'auto'. */\n fill?: string;\n /** 6-digit hex foreground color without '#', or 'auto'. */\n color?: string;\n /** OOXML shading pattern. Defaults to 'clear' when only fill is provided. */\n val?: string;\n };\n verticalAlignment?: 'top' | 'center' | 'bottom' | 'both';\n /** Cell width in twips, written as tcW type='dxa'. */\n width?: number;\n}\n\n// ─────────── 插入段落 spec(docs/03.1 §1.7)───────────\n\nexport interface InsertParagraphSpec {\n text: string;\n /** 'inherit'(默认)继承 anchor 的 `<w:pPr>`;字符串为 styleId */\n style?: 'inherit' | string;\n /**\n * 控制新段内容 run 的 `<w:rPr>` 来源。\n *\n * - `'default'`(默认):裸 run,不附加任何 rPr,行为与未传时完全一致。\n * - `'inherit'`:克隆 anchor 段**首个直属 `<w:r>`** 的 `<w:rPr>`(深拷贝 cloneNode(true))\n * 并应用到新段的内容 run。常用于「簇展开」场景:样式写在直接格式(rPr)而非命名样式上。\n * anchor 无直属 run 或首 run 无 rPr 时退化为 `'default'`(不报错)。\n * 与 `color` 共存时:先继承 rPr,再由 color 覆盖/追加 `<w:color>`(color 优先级更高)。\n * 与 `style` 正交:style 管 pPr,runFormat 管 rPr,可独立组合。\n */\n runFormat?: 'inherit' | 'default';\n /**\n * 整段文字的字体颜色,6 位十六进制无 `#`(如 `'0070C0'` 标准蓝)。\n * 留空则继承样式默认色。\n * 颜色作为 run-level `<w:rPr><w:color w:val=\"...\"/></w:rPr>` 写入新段唯一 run。\n */\n color?: string;\n /**\n * 从指定段(任意 `paraId`)克隆 pPr + 首 run rPr 到新段(全文重组场景)。\n *\n * - **优先级最高**:同时传 `style` / `runFormat` 时以 `styleSource` 为准(pPr + rPr 都来自 styleSource)。\n * - pPr:深拷贝 `<w:pPr>`;styleSource 段无 pPr 则新段也不加 pPr(退化,不报错)。\n * - rPr:克隆 styleSource 段**首个直属 `<w:r>`** 的 `<w:rPr>`;无直属 run 或首 run 无 rPr 则退化裸 run(不报错)。\n * - styleSource 段**不存在**时抛 `PARA_NOT_FOUND`。\n * - styleSource 段自身只读,不被修改。\n * - 与 `color` 共存:先克隆 rPr,再 color 覆盖/追加 `<w:color>`(color 优先,同 #12)。\n * - `styleSource === anchor` 时退化为 `style:'inherit' + runFormat:'inherit'` 效果(#12 兼容)。\n */\n styleSource?: ParaId;\n /**\n * 可选:插入段的同时**原子地**建一个跨段书签,range 涵盖 anchor 段 → 新插段。\n *\n * 调用方只声明命名规则(`prefix`),不传具体名 —— 系统按 `{prefix}_{anchorParaId}`\n * 生成,冲突自动追加 `_2`/`_3` 后缀;实际名通过 `ApplyResult.createdBookmarks[i].name`\n * 回传(同一 entry 的 `range` 给 fromParaId / toParaId)。\n *\n * `prefix` 校验:必须匹配 `^[A-Za-z_][A-Za-z0-9_]*$`(允许 `_` 起头作 Word hidden\n * bookmark);最终名长度受 OOXML 40 字符上限约束,过长抛 `BOOKMARK_NAME_INVALID`。\n *\n * trackChanges=true 时本字段触发 `UNSUPPORTED_OOXML_FEATURE`(与 createBookmark\n * 的现状一致,#31 再统一处理)。\n */\n bookmark?: { prefix: string };\n /**\n * 段落大纲级别(Word outline level),写入 `<w:pPr><w:outlineLvl w:val=\"N\"/>`。\n *\n * - 取值 **0–8**(对应 Word「1 级标题…9 级标题」;heading-1→0, heading-2→1, …)。\n * - 省略(`undefined`):不写 outlineLvl,保持 styleSource 克隆来的 pPr 原样。\n * - 0–8:在新段 pPr 写入/覆盖 `<w:outlineLvl>`(显式值优先于 styleSource 克隆来的)。\n * - 越界(< 0 或 > 8):抛 `INVALID_ARGUMENT`。\n */\n outlineLevel?: number;\n /**\n * 段前分页(Word「段前分页」),写入 `<w:pPr><w:pageBreakBefore/>`。\n *\n * - `true`:该段强制从新页起始(比手工 `<w:br type=\"page\"/>` 更鲁棒:绑在段上不随内容漂移)。\n * - 省略(`undefined`)/ `false`:不写该元素(继承样式或默认)。\n */\n pageBreakBefore?: boolean;\n}\n\n// ─────────── Plan 选项(docs/03.1 §2)───────────\n\nexport interface PlanOptions {\n /** 默认 false */\n trackChanges?: boolean;\n /** 默认走 `WordDocument.setDefaultAuthor` 配置的值 */\n author?: string;\n /** 默认 `new Date()` */\n date?: Date;\n}\n\n// ─────────── Op union(docs/03.1 §5)───────────\n\nexport type Op =\n | {\n type: 'replaceParagraph';\n paraId: ParaId;\n text: string;\n onAnchorConflict: 'error' | 'drop';\n /** 保留段内含图形的 run(w:drawing / w:pict / wps:wsp / v:line / w:object)。\n * 默认 false(现有行为:整段所有 run 全删)。\n * true 时:只删纯文字 run,图形 run 原位保留;新文字 run 插在首个被删文字 run 位置。 */\n keepInlineGraphics?: boolean;\n }\n | {\n type: 'replaceTextInParagraph';\n paraId: ParaId;\n search: string;\n replacement: string;\n scope: 'first' | 'all';\n }\n | {\n type: 'formatTextInParagraph';\n paraId: ParaId;\n search: string;\n format: {\n bold?: boolean;\n color?: string;\n italic?: boolean;\n underline?: boolean;\n highlight?: string;\n fontSize?: number;\n fontFamily?: string;\n };\n scope: 'first' | 'all';\n }\n | {\n type: 'formatParagraph';\n paraId: ParaId;\n format: ParagraphDirectFormat;\n }\n | { type: 'insertParagraphBefore'; anchorParaId: ParaId; spec: InsertParagraphSpec }\n | { type: 'insertParagraphAfter'; anchorParaId: ParaId; spec: InsertParagraphSpec }\n // 无锚点在 <w:body> 起始插一个空段,返回新 paraId(ApplyResult.insertedBodyStartParaIds)。\n // 用途:body 完全无段落(极简/特殊文档,所有正文段被骨架删光)时,下游重建需要一个真实\n // 落点锚段。区别于 insertParagraphBefore/After——后者必须有 anchor 段;本 op 不需要。\n | { type: 'insertParagraphAtBodyStart' }\n | { type: 'deleteParagraph'; paraId: ParaId; onAnchorConflict: 'error' | 'drop' }\n | { type: 'createBookmark'; name: BookmarkName; range: Range }\n | { type: 'deleteBookmark'; name: BookmarkName }\n | {\n type: 'addComment';\n range: Range;\n text: string;\n author?: string;\n /** RPC 友好:按 ISO 8601 字符串序列化;builder 端接 Date,push 前 toISOString */\n date?: string;\n }\n | { type: 'deleteComment'; commentId: CommentId }\n | { type: 'acceptRevisions'; scope: RevisionScope }\n | { type: 'rejectRevisions'; scope: RevisionScope }\n // #186 表格批注与删除。批注实质挂在表格首单元格首段上,但语义入口是 tableId,\n // 避免调用方手算 firstCellFirstParaId。\n | {\n type: 'addTableComment';\n tableId: string;\n text: string;\n author?: string;\n /** ISO 8601 字符串 */\n date?: string;\n }\n | { type: 'deleteTable'; tableId: string; onAnchorConflict: 'error' | 'drop' }\n // #188 表格域化:把指定单元格首段的 runs 替换为 inline SDT(Plain Text / Date / Rich Text)\n | {\n type: 'replaceTableCellWithSdt';\n tableId: string;\n /** 0-based 行索引(对应 TableInfo.cells 网格的 i)*/\n row: number;\n /** 0-based 列索引(对应 cells[i] 的 j) */\n col: number;\n sdt: SdtSpec;\n onAnchorConflict: 'error' | 'drop';\n }\n // #188 §7.2 行级裁剪:删除指定行(可变行数表保留 1~N 样例行,其余删除)\n | {\n type: 'deleteTableRow';\n tableId: string;\n /** 0-based 行索引(按删除时刻表格状态计) */\n row: number;\n onAnchorConflict: 'error' | 'drop';\n }\n // 填纯文字版(排版回填):保留 tcPr(底纹 shd / 边框 / 对齐 vAlign / 列宽 tcW)+ 首段 pPr + 首 run rPr\n | {\n type: 'replaceTableCellText';\n tableId: string;\n /** 0-based 行索引(对应 TableInfo.cells 网格的 i)*/\n row: number;\n /** 0-based 列索引(对应 cells[i] 的 j)*/\n col: number;\n text: string;\n onAnchorConflict: 'error' | 'drop';\n }\n | {\n type: 'formatTableCell';\n tableId: string;\n /** 0-based row index, matching TableInfo.cellGrid[row][col]. */\n row: number;\n /** 0-based column index, matching TableInfo.cellGrid[row][col]. */\n col: number;\n format: TableCellDirectFormat;\n }\n | {\n type: 'insertTableCellParagraph';\n tableId: string;\n /** 0-based row index, matching TableInfo.cellGrid[row][col]. */\n row: number;\n /** 0-based column index, matching TableInfo.cellGrid[row][col]. */\n col: number;\n /** Plain text for the new paragraph. */\n text: string;\n /** Insert before the first direct cell content block or after the last one. */\n position: 'start' | 'end';\n }\n // #190 把指定 drawing 的图片内容替换为统一占位图\n // - 仅接受 kind='picture' 的 drawing(chart/smartArt/shape 走 deleteDrawing 或 #192)\n // - 只改 a:blip/@r:embed,wp:inline / wp:anchor / wp:extent / 环绕 / position 一字不动\n // - 同包内多次调用幂等:首次注入共享 word/media/placeholder.png + image rel,后续复用\n // - 替换后若旧 media 在全包无其它引用,清理 rels 条目 + binary part(保证「原图二进制不残留」)\n | {\n type: 'replaceDrawingWithPlaceholder';\n drawingId: string;\n }\n // #190 删除 drawing 节点(B/C 类裁剪用)\n // - 不限制 kind,任何 drawing 都可删\n // - 删 w:drawing 本身;承载 w:r 若仅含此 drawing(无其它有效内容)一并删除\n // - 清理孤儿 media / rels 同 replaceDrawingWithPlaceholder\n | {\n type: 'deleteDrawing';\n drawingId: string;\n }\n // #210 把 Shape / TextBox 内部文字替换为统一占位文字(#192 内容型保留依赖)\n // - 仅接受含 w:txbxContent 的 drawing(textBox / shape-with-text)\n // - 保留 w:drawing 整个外壳(wsp/spPr/extent/anchor/wrap/position)\n // - 重写 w:txbxContent 内部为单段单 run 占位文字,保留首段 w:pPr/w:jc 对齐\n // - 内部 hyperlink / 嵌套 picture 的 rels 引用按 deleteDrawing 同源清理\n | {\n type: 'replaceShapeInnerText';\n drawingId: string;\n placeholder: string;\n }\n // #14 行克隆/插入:克隆模板行插入到指定位置(支撑可变行数表回填)\n // - templateRow: 0-based 克隆源行索引\n // - position: insert-before 语义,传 'end' 追加到末尾\n // - cellTexts: 可选,各列回填文字;语义见 §1.3\n // - 克隆行内锚点一律剥离;每个 <w:p> 重分配 paraId\n | {\n type: 'insertTableRow';\n tableId: string;\n templateRow: number;\n position: number | 'end';\n cellTexts?: string[];\n }\n // #15 表格克隆/插入:把已有表深克隆一份插到指定段落之后(排版重建:模板表克隆到多处)\n // - sourceTableId: 克隆哪张表(源表只读,不改)\n // - anchorParaId: 克隆表插到此段之后(insert-before anchorParaId.nextSibling)\n // - 克隆表内锚点一律剥离;每个 <w:p> 重分配 paraId(含嵌套表段落)\n | { type: 'cloneTableAfter'; anchorParaId: ParaId; sourceTableId: string }\n // task-insert-image 在指定段后插入 inline 图片新段(跨端,不碰 node fs/Buffer)\n // - anchorParaId: 新段插到此段之后\n // - bytes: 图片二进制(Uint8Array)\n // - contentType: 'image/png' | 'image/jpeg' | 'image/gif' | 'image/bmp' | 'image/tiff'\n // - widthEmu / heightEmu: wp:extent@cx/cy\n | {\n type: 'insertImageAfter';\n anchorParaId: ParaId;\n bytes: Uint8Array;\n contentType: string;\n widthEmu: number;\n heightEmu: number;\n }\n // task-20260616-table-content-driven 跨文档 verbatim 搬表(\"数据表=内容块\"底座)\n // - anchorParaId: 搬入的表插到此段之后\n // - tableXml: 源文档 <w:tbl> 子树序列化字符串(调用方在源 doc 侧 serializeToWellFormedString)\n // - images: 格内图的预解析字节(按源 r:embed 原 rId 索引);executor 在 host 新建 media+rel 重映射\n // - styleTblPrXml: 可选,模板数据表 <w:tblPr> 序列化串;提供则整体替换搬入表 tblPr(样式归一)\n // - 表内锚点(书签/批注 5 类)一律剥离;每个 <w:p> 重分配 paraId(全局唯一)\n // - anchor 不存在 → PARA_NOT_FOUND;tableXml 非 <w:tbl> → INVALID_ARGUMENT\n // - trackChanges=true → UNSUPPORTED_OOXML_FEATURE\n | {\n type: 'insertTableFrom';\n anchorParaId: ParaId;\n tableXml: string;\n images?: Array<{ originalRId: string; bytes: Uint8Array; contentType: string }>;\n styleTblPrXml?: string;\n }\n // task-core-table-grid 设表格 tblGrid 列宽(用于 merger 克隆模板后保真源表列宽)\n // - tableId: 目标表格\n // - widths: 新列宽数组(twips),长度必须等于 colCount;只改 gridCol w:w,不动 tcW\n | { type: 'setTableColumnWidths'; tableId: string; widths: number[] }\n // task-core-table-rowheight 设表格行高(用于 merger 克隆模板后保真源表行高)\n // - tableId: 目标表格\n // - heights: 每行行高数组(RowHeight | null),长度必须等于 rowCount\n // RowHeight → 写/替换 trPr/trHeight;null → 删除 trHeight\n | { type: 'setTableRowHeights'; tableId: string; heights: (RowHeight | null)[] }\n // task-core-update-fields 设 settings.xml 的 updateFields(让含 TOC 域的文档打开时自动更新域)\n // - enabled=true → 写/更新 <w:updateFields w:val=\"true\"/>\n // - enabled=false → 写 <w:updateFields w:val=\"false\"/>\n | { type: 'setUpdateFields'; enabled: boolean };\n\n// ─────────── ApplyResult(docs/03.1 §1.8)───────────\n\nexport interface ApplyResult {\n /** 插入段落产生的新 paraId,按 op 顺序 */\n insertedParagraphs: Array<{\n opIndex: number;\n anchorParaId: ParaId;\n position: 'before' | 'after';\n newParaId: ParaId;\n }>;\n /**\n * `insertParagraphAtBodyStart` 在 body 起始合成的空段 paraId,按 op 顺序。\n * 调用方据此拿到锚点 paraId 做后续重建(与 insertedParagraphs 分开,语义清晰)。\n */\n insertedBodyStartParaIds: ParaId[];\n /** 新建批注分配的 commentId,按 op 顺序 */\n createdComments: Array<{\n opIndex: number;\n commentId: CommentId;\n }>;\n /**\n * 新建书签清单。\n *\n * - 显式 `createBookmark` op 产生的:`name` 是调用方传入的;`range` 给段落 ID\n * (ParagraphRange 时 fromParaId === toParaId,TextRange 同段所以也相等)\n * - `insertParagraphAfter` 通过 `spec.bookmark` 触发的:`name` 是按规则解析后的实际名\n * (规则冲突会有 `_2/_3` 后缀);`range.fromParaId` = anchor,`range.toParaId` = newParaId\n */\n createdBookmarks: Array<{\n opIndex: number;\n name: BookmarkName;\n range: { fromParaId: ParaId; toParaId: ParaId };\n }>;\n acceptedRevisions: number;\n rejectedRevisions: number;\n /**\n * 实际替换的表格单元格数 (#188 / #204)。\n *\n * `replaceTableCellWithSdt` op 在 `onAnchorConflict='drop'` 模式下遇锚点会\n * **静默跳过**, 该计数只统计真正完成替换的单元格数, 调用方据此报告准确域化数。\n */\n replacedTableCells: number;\n /** Diagnostic timing, present only when the kernel collects apply timing. */\n debugTiming?: {\n ops: number;\n affectedParts: number;\n collectAffectedPartsMs?: number;\n collectStoriesMs?: number;\n collectStoryLookups?: number;\n collectStoryLookupMs?: number;\n collectByType?: Array<{\n type: Op['type'];\n count: number;\n ms: number;\n storyLookups: number;\n storyLookupMs: number;\n }>;\n transactionMs: number;\n indicesMs: number;\n totalMs: number;\n kernelMs?: number;\n byType: Array<{ type: Op['type']; count: number; ms: number }>;\n };\n}\n\nexport interface PlanValidationIssue {\n code: WordErrorCode;\n message: string;\n details?: Record<string, unknown>;\n}\n\nexport interface PlanValidationItem {\n opIndex: number;\n opType: Op['type'];\n status: 'valid' | 'invalid' | 'unvalidated';\n issue?: PlanValidationIssue;\n}\n\nexport interface PlanValidationResult {\n valid: boolean;\n items: PlanValidationItem[];\n}\n\n/** 空结果常量(空 plan / 内部初始化用)*/\nexport const EMPTY_APPLY_RESULT: ApplyResult = Object.freeze({\n insertedParagraphs: [],\n insertedBodyStartParaIds: [],\n createdComments: [],\n createdBookmarks: [],\n acceptedRevisions: 0,\n rejectedRevisions: 0,\n replacedTableCells: 0,\n}) as ApplyResult;\n\n// ─────────── WordPlan 接口 ───────────\n\nexport interface WordPlan {\n replaceParagraph(\n paraId: ParaId,\n text: string,\n opts?: { onAnchorConflict?: 'error' | 'drop'; keepInlineGraphics?: boolean },\n ): this;\n replaceTextInParagraph(\n paraId: ParaId,\n search: string,\n replacement: string,\n opts?: { scope?: 'first' | 'all' },\n ): this;\n formatTextInParagraph(\n paraId: ParaId,\n search: string,\n format: {\n bold?: boolean;\n color?: string;\n italic?: boolean;\n underline?: boolean;\n highlight?: string;\n fontSize?: number;\n fontFamily?: string;\n },\n opts?: { scope?: 'first' | 'all' },\n ): this;\n formatParagraph(paraId: ParaId, format: ParagraphDirectFormat): this;\n\n insertParagraphBefore(anchorParaId: ParaId, spec: InsertParagraphSpec): this;\n insertParagraphAfter(anchorParaId: ParaId, spec: InsertParagraphSpec): this;\n\n /**\n * 无锚点在 `<w:body>` 起始插一个空段,新 paraId 通过\n * `ApplyResult.insertedBodyStartParaIds` 回传。\n *\n * 用途:body 完全无段落(极简/特殊文档,正文段被骨架删光)时,重建需要一个真实落点锚段。\n * 与 insertParagraphBefore/After 不同——后者必须有 anchor 段;本 op 不依赖任何已有段。\n */\n insertParagraphAtBodyStart(): this;\n\n deleteParagraph(paraId: ParaId, opts?: { onAnchorConflict?: 'error' | 'drop' }): this;\n\n acceptRevisions(scope: RevisionScope): this;\n rejectRevisions(scope: RevisionScope): this;\n\n createBookmark(spec: { name: BookmarkName; range: Range }): this;\n deleteBookmark(name: BookmarkName): this;\n\n addComment(spec: { range: Range; text: string; author?: string; date?: Date }): this;\n deleteComment(commentId: CommentId): this;\n\n /** Resolve and validate supported operation targets without mutating the document. */\n validate(): Promise<PlanValidationResult>;\n\n /**\n * 给表格挂批注(#186 表格分类与保留决策的\"决策理由可追溯\"载体)。\n * 实现上批注挂在表格首单元格的首段落,语义入口走 tableId。\n */\n addTableComment(spec: { tableId: string; text: string; author?: string; date?: Date }): this;\n /**\n * 删除整张表格(#186 不保留表格的裁剪入口)。\n * 表格内段落若含活锚点(书签/批注),按 onAnchorConflict 处理。\n */\n deleteTable(tableId: string, opts?: { onAnchorConflict?: 'error' | 'drop' }): this;\n\n /**\n * 把表格指定单元格首段的 runs 替换为 inline SDT (#188 表格域化)。\n *\n * - (row, col) 对应 `TableInfo.cells[row][col]` 网格坐标(tr 顺序 × tc 顺序)\n * - 段落 pPr / 单元格 tcPr / 边框 / 合并关系全部保留\n * - 原首段 runs 的首 rPr 自动透传到 SDT 内 placeholder run, 字体 / 颜色 / 字号不丢\n * - 单元格首段含锚点 (书签 / 批注) 时按 onAnchorConflict 处理 ('error' 抛 / 'drop' 跳过)\n * - 单元格首段不存在或单元格不存在时抛 PARA_NOT_FOUND\n */\n replaceTableCellWithSdt(spec: {\n tableId: string;\n row: number;\n col: number;\n sdt: SdtSpec;\n onAnchorConflict?: 'error' | 'drop';\n }): this;\n\n /**\n * 替换表格指定单元格首段的内容为单个纯文字 run(排版回填)。\n *\n * - (row, col) 对应 TableInfo.cells[row][col] 网格坐标\n * - **单元格 tcPr(底纹 shd / 边框 / 对齐 vAlign / 列宽 tcW)完全保留**(只动首段内部)\n * - 首段 pPr 保留;原首 run 的 rPr(字体/字号/颜色)透传到新文字 run\n * - 单元格首段含锚点(书签/批注)时按 onAnchorConflict 处理('error' 抛 / 'drop' 跳过不替换)\n * - 单元格不存在 → TABLE_NOT_FOUND;首段不存在 → PACKAGE_CORRUPT\n * - trackChanges=true 暂不支持,抛 UNSUPPORTED_OOXML_FEATURE\n */\n replaceTableCellText(spec: {\n tableId: string;\n row: number;\n col: number;\n text: string;\n onAnchorConflict?: 'error' | 'drop';\n }): this;\n formatTableCell(spec: {\n tableId: string;\n row: number;\n col: number;\n format: TableCellDirectFormat;\n }): this;\n insertTableCellParagraph(spec: {\n tableId: string;\n row: number;\n col: number;\n text: string;\n position: 'start' | 'end';\n }): this;\n\n /**\n * 删除表格指定行 (#188 §7.2 行级裁剪)。\n *\n * - `row` 是 op 执行时的行索引;同一 plan 内连续删多行时调用方按**降序**传入,\n * 避免索引漂移(删 row 3 后原 row 4 变成新的 row 3)\n * - 行内段落含活锚点 (书签 / 批注) 时按 `onAnchorConflict` 处理 ('error' 抛 / 'drop' 跳过)\n * - 删除最后一行会让表格只剩 tblPr / tblGrid —— Word 允许 0 行表格但显示异常,\n * 调用方应在外层保证至少留一行(典型场景:可变行数表保留表头 + 1~N 样例行)\n */\n deleteTableRow(\n tableId: string,\n row: number,\n opts?: { onAnchorConflict?: 'error' | 'drop' },\n ): this;\n\n /**\n * 把 drawing 的图片内容替换为共享占位图 (#190)。\n *\n * - 仅接受 kind = 'picture' 的 drawing;其它 kind(chart / smartArt / shape / textBox /\n * group / canvas / other)抛 UNSUPPORTED_OOXML_FEATURE,需走 deleteDrawing 或 #192\n * - **布局完全保持**:wp:inline / wp:anchor、wp:extent、wrap、position、anchorParaId\n * 都不动,只改 a:blip/@r:embed 指向共享 placeholder\n * - 同一文档内多次调用幂等:共用一份 word/media/placeholder.png + 单条 image rel\n * - 替换后若旧 media 在全包无其它引用,自动清理对应 rels 条目 + binary part\n * (保证「原始图片二进制不出现在输出文档中」的验收条件)\n * - drawingId 不存在抛 DRAWING_NOT_FOUND\n * - trackChanges=true 暂不支持,抛 UNSUPPORTED_OOXML_FEATURE\n */\n replaceDrawingWithPlaceholder(drawingId: string): this;\n\n /**\n * 删除 drawing(B/C 类裁剪入口)。\n *\n * - 不限制 kind,任何 drawing 都可删\n * - 物理删 w:drawing;承载它的 w:r 若仅含该 drawing 一并删除\n * - 同样清理孤儿 media / rels(逻辑与 replaceDrawingWithPlaceholder 共享)\n * - drawingId 不存在抛 DRAWING_NOT_FOUND\n * - trackChanges=true 暂不支持,抛 UNSUPPORTED_OOXML_FEATURE\n */\n deleteDrawing(drawingId: string): this;\n\n /**\n * 把 Shape / TextBox 内部文字替换为统一占位文字 (#210,#192 内容型保留依赖)。\n *\n * - 仅接受含 `w:txbxContent` 的 drawing(textBox / shape-with-text)\n * 其它 kind(picture / chart / smartArt / group / canvas / shape-without-text / other)\n * 抛 UNSUPPORTED_OOXML_FEATURE,需走 replaceDrawingWithPlaceholder 或 deleteDrawing\n * - **外壳完全保留**:w:drawing 整个 wp:inline / wp:anchor / wsp:spPr / wp:extent /\n * wrap / position 一字不动\n * - 内部 `w:txbxContent` 被重写为**单段单 run** placeholder 文本;原首段\n * `w:pPr/w:jc` 对齐保留(沿用 innerTextAlign 维度)\n * - 内部 hyperlink / 嵌套 picture 的 rels 引用按 deleteDrawing 同源清理\n * - 占位文字走默认 run 样式(v1 不保留原首段 run rPr 字体 / 字号 / 颜色)\n * - drawingId 不存在抛 DRAWING_NOT_FOUND\n * - trackChanges=true 暂不支持,抛 UNSUPPORTED_OOXML_FEATURE\n */\n replaceShapeInnerText(drawingId: string, placeholder: string): this;\n\n /**\n * 克隆表格某一行作模板,在指定位置插入新行(可变行数表回填)。(#14)\n *\n * - `templateRow`:0-based,克隆此行的单元格结构(tcPr 含底纹 shd / 边框 /\n * 对齐 vAlign / 列宽 tcW + 首段 pPr + 首 run rPr 全保留)\n * - `position`:插入后新行所在的 0-based 行索引(insert-before 语义);\n * 传 'end' 追加到末尾。范围 [0, rowCount],rowCount 等价 'end'\n * - `cellTexts`:可选,新行各列文字(保留各列 rPr)。\n * - 不传:克隆模板行原样(含模板原文字)\n * - 传 L 个元素:列 i ∈ [0, min(L,C)) 替换为 cellTexts[i];列 i ∈ [L,C) 清空;多余忽略\n * - 克隆行内锚点(书签/批注)一律剥离;行内每个 <w:p> 重新分配 paraId\n * - 表格不存在 / templateRow 越界 / position 越界 → TABLE_NOT_FOUND\n * - trackChanges=true 暂不支持 → UNSUPPORTED_OOXML_FEATURE\n */\n insertTableRow(spec: {\n tableId: string;\n templateRow: number;\n position: number | 'end';\n cellTexts?: string[];\n }): this;\n\n /**\n * 把已有表格深克隆一份,插入到指定段落之后(排版重建:模板表克隆到多处)。(#15)\n *\n * - `sourceTableId`:克隆哪张表。深克隆整个 `<w:tbl>`(tblPr/tblGrid/所有行/\n * 单元格 tcPr/pPr/rPr 全保留)。源表自身**只读,不被修改**。\n * - `anchorParaId`:克隆表插到此段之后(与 insertParagraphAfter 同语义:\n * 插到 anchor 的下一个兄弟之前)。anchor 应为 body story 直属段落。\n * - 克隆表内**锚点(书签/批注 5 类)一律剥离**;克隆表内**每个 `<w:p>`\n * 重新分配 paraId**,保 paraId 全局唯一。\n * - anchorParaId 不存在 → PARA_NOT_FOUND;sourceTableId 不存在 → TABLE_NOT_FOUND。\n * - trackChanges=true 暂不支持 → UNSUPPORTED_OOXML_FEATURE。\n * - v1 不在 ApplyResult 回传新表 tableId;apply 后用 `doc.tables.list()` 按文档顺序定位。\n */\n cloneTableAfter(spec: { anchorParaId: ParaId; sourceTableId: string }): this;\n\n /**\n * 在指定段落之后新插一个段,段内含一个 inline 图片(task-insert-image)。\n *\n * - `anchorParaId`:新段插到此段之后(与 insertParagraphAfter 同语义)\n * - `bytes`:图片二进制(`Uint8Array`,跨端,绝不碰 node fs/Buffer)\n * - `contentType`:'image/png' | 'image/jpeg' | 'image/gif' | 'image/bmp' | 'image/tiff'\n * - `widthEmu` / `heightEmu`:wp:extent@cx/cy(EMU 单位,1 英寸 = 914400 EMU)\n * - anchor 不存在 → `PARA_NOT_FOUND`\n * - 不支持的 contentType → `UNSUPPORTED_OOXML_FEATURE`\n * - trackChanges=true → `UNSUPPORTED_OOXML_FEATURE`\n */\n insertImageAfter(\n anchorParaId: ParaId,\n spec: {\n bytes: Uint8Array;\n contentType: string;\n widthEmu: number;\n heightEmu: number;\n },\n ): this;\n\n /**\n * 跨文档 verbatim 搬一张表进当前文档,插到 anchorParaId 段之后\n * (task-20260616-table-content-driven,\"数据表 = 内容块\" §13.9)。\n *\n * - `anchorParaId`:搬入的表插到此段之后(与 cloneTableAfter 同语义)。\n * - `tableXml`:源文档 `<w:tbl>` 子树序列化字符串。调用方(typeset,持源 doc)用\n * `serializeToWellFormedString(tblElement)` 取得;命名空间随子树带入,无需额外声明。\n * - `images`:格内图预解析字节,按源 `<a:blip @r:embed>` 的**原始 rId** 索引;executor 在\n * host 新建 media part + image rel + content-type,把 embed 改写成新 rId。缺某 rId → 该\n * blip embed 清掉 + warn(结构/文字仍保真,仅该格图降级)。\n * - `styleTblPrXml`:可选,模板数据表 `<w:tblPr>` 序列化串。提供则整体替换搬入表的 tblPr\n * (tblStyle/边框/tblLook/宽度 → 归一到模板样式,覆盖内容表自带样式)。\n * - 表内锚点(书签/批注 5 类)一律剥离;每个 `<w:p>` 重分配 paraId(全局唯一)。\n * - 行/列/值/合并/嵌套表/格内图全部 verbatim 来自 tableXml,executor 不重建/不裁剪/不对位。\n * - anchor 不存在 → `PARA_NOT_FOUND`;tableXml 非 `<w:tbl>` → `INVALID_ARGUMENT`;\n * trackChanges=true → `UNSUPPORTED_OOXML_FEATURE`。\n * - v1 不在 ApplyResult 回传新表 tableId;apply 后用 `doc.tables.list()` 按文档顺序定位。\n */\n insertTableFrom(spec: {\n anchorParaId: ParaId;\n tableXml: string;\n images?: Array<{ originalRId: string; bytes: Uint8Array; contentType: string }>;\n styleTblPrXml?: string;\n }): this;\n\n /**\n * 设表格列宽:同步更新 `<w:tblGrid>` gridCol w:w **和** 每个单元格 `<w:tcW>`\n * (task-core-table-grid:merger 保真源表列宽)。\n *\n * - `tableId`:目标表格(来自 `tables.list()` 的 tableId)。\n * - `widths`:新列宽数组(twips,1 twip = 1/20 磅)。长度必须等于该表格的\n * `colCount`(gridCol 数量)——不等则抛 `INVALID_ARGUMENT`(防止截断/越界)。\n * - 同步设每个单元格 `<w:tcW w:type=\"dxa\">`(Word 渲染优先 tcW over gridCol):\n * 合并单元格(gridSpan > 1)的 tcW = 跨列宽之和;vMerge 续行单元格正常处理。\n * - tableId 不存在 → `TABLE_NOT_FOUND`。\n * - trackChanges=true → `UNSUPPORTED_OOXML_FEATURE`(暂不支持)。\n */\n setTableColumnWidths(spec: { tableId: string; widths: number[] }): this;\n\n /**\n * 设表格行高(task-core-table-rowheight:merger 保真源表行高)。\n *\n * - `tableId`:目标表格(来自 `tables.list()` 的 tableId)。\n * - `heights`:每行行高数组,长度必须等于该表格的 `rowCount`——不等则抛 `INVALID_ARGUMENT`。\n * - `RowHeight`:在该行 `<w:trPr>` 写入/替换 `<w:trHeight w:val=\"N\" w:hRule=\"...\"/>`。\n * - `null`:删除该行的 `<w:trHeight>`(即「不指定行高」)。\n * - `heights[i]` 套到物理第 i 行 `<w:tr>`(与 `TableInfo.rowHeights` 1:1)。\n * - tableId 不存在 → `TABLE_NOT_FOUND`。\n * - trackChanges=true → `UNSUPPORTED_OOXML_FEATURE`(暂不支持)。\n */\n setTableRowHeights(spec: { tableId: string; heights: (RowHeight | null)[] }): this;\n\n /**\n * 在 settings.xml 写入/更新 `<w:updateFields>`,让含 TOC 域的文档打开时自动更新域。\n * (task-core-update-fields)\n *\n * - `enabled=true`:在 settings.xml 根 `<w:settings>` 写入/更新\n * `<w:updateFields w:val=\"true\"/>`——Word/WPS 打开文档时自动重生成所有域(TOC/PAGEREF/SEQ 等)。\n * - `enabled=false`:写 `<w:updateFields w:val=\"false\"/>`(显式禁用,语义更清晰)。\n * - 幂等:settings.xml 已有 `<w:updateFields>` 则改 `w:val`,不重复插入元素。\n * - settings.xml 不存在 → 抛 `UNSUPPORTED_OOXML_FEATURE`(后续跟进新建 settings part)。\n */\n setUpdateFields(enabled: boolean): this;\n\n apply(): Promise<ApplyResult>;\n\n /** 只读 op 队列,用于调试 / 日志 / 测试 */\n readonly ops: ReadonlyArray<Op>;\n /** apply 是否已被调用过(成功与否都置 true,防止二次 apply)*/\n readonly applied: boolean;\n /** Plan 创建时的选项,只读 */\n readonly options: Readonly<\n Required<Pick<PlanOptions, 'trackChanges'>> & Omit<PlanOptions, 'trackChanges'>\n >;\n}\n\n// ─────────── 实现 ───────────\n\nexport interface WordPlanImplInit {\n docId: string;\n transport: Transport;\n options: PlanOptions;\n}\n\nexport class WordPlanImpl implements WordPlan {\n private readonly docId: string;\n private readonly transport: Transport;\n private readonly _options: Readonly<WordPlan['options']>;\n private readonly _ops: Op[] = [];\n private _applied = false;\n\n constructor(init: WordPlanImplInit) {\n this.docId = init.docId;\n this.transport = init.transport;\n // normalize:trackChanges 缺省 false;author / date 保留原值(可能 undefined)\n const normalized: { trackChanges: boolean; author?: string; date?: Date } = {\n trackChanges: init.options.trackChanges ?? false,\n };\n if (init.options.author !== undefined) normalized.author = init.options.author;\n if (init.options.date !== undefined) normalized.date = init.options.date;\n this._options = Object.freeze(normalized);\n }\n\n // ─────────── 状态 accessor ───────────\n\n get ops(): ReadonlyArray<Op> {\n return this._ops;\n }\n\n get applied(): boolean {\n return this._applied;\n }\n\n get options(): Readonly<WordPlan['options']> {\n return this._options;\n }\n\n // ─────────── 段落修改(#28)───────────\n\n replaceParagraph(\n paraId: ParaId,\n text: string,\n opts?: { onAnchorConflict?: 'error' | 'drop'; keepInlineGraphics?: boolean },\n ): this {\n this.ensureOpen('replaceParagraph');\n this._ops.push({\n type: 'replaceParagraph',\n paraId,\n text,\n onAnchorConflict: opts?.onAnchorConflict ?? 'error',\n keepInlineGraphics: opts?.keepInlineGraphics,\n });\n return this;\n }\n\n replaceTextInParagraph(\n paraId: ParaId,\n search: string,\n replacement: string,\n opts?: { scope?: 'first' | 'all' },\n ): this {\n this.ensureOpen('replaceTextInParagraph');\n this._ops.push({\n type: 'replaceTextInParagraph',\n paraId,\n search,\n replacement,\n scope: opts?.scope ?? 'first',\n });\n return this;\n }\n\n formatTextInParagraph(\n paraId: ParaId,\n search: string,\n format: {\n bold?: boolean;\n color?: string;\n italic?: boolean;\n underline?: boolean;\n highlight?: string;\n fontSize?: number;\n fontFamily?: string;\n },\n opts?: { scope?: 'first' | 'all' },\n ): this {\n this.ensureOpen('formatTextInParagraph');\n this._ops.push({\n type: 'formatTextInParagraph',\n paraId,\n search,\n format,\n scope: opts?.scope ?? 'first',\n });\n return this;\n }\n\n formatParagraph(paraId: ParaId, format: ParagraphDirectFormat): this {\n this.ensureOpen('formatParagraph');\n this._ops.push({\n type: 'formatParagraph',\n paraId,\n format: { ...format },\n });\n return this;\n }\n\n // ─────────── 段落插入 / 删除(#29)───────────\n\n insertParagraphBefore(anchorParaId: ParaId, spec: InsertParagraphSpec): this {\n this.ensureOpen('insertParagraphBefore');\n this._ops.push({ type: 'insertParagraphBefore', anchorParaId, spec });\n return this;\n }\n\n insertParagraphAfter(anchorParaId: ParaId, spec: InsertParagraphSpec): this {\n this.ensureOpen('insertParagraphAfter');\n this._ops.push({ type: 'insertParagraphAfter', anchorParaId, spec });\n return this;\n }\n\n insertParagraphAtBodyStart(): this {\n this.ensureOpen('insertParagraphAtBodyStart');\n this._ops.push({ type: 'insertParagraphAtBodyStart' });\n return this;\n }\n\n deleteParagraph(paraId: ParaId, opts?: { onAnchorConflict?: 'error' | 'drop' }): this {\n this.ensureOpen('deleteParagraph');\n this._ops.push({\n type: 'deleteParagraph',\n paraId,\n onAnchorConflict: opts?.onAnchorConflict ?? 'error',\n });\n return this;\n }\n\n // ─────────── 修订(#31 / #32)───────────\n\n acceptRevisions(scope: RevisionScope): this {\n this.ensureOpen('acceptRevisions');\n this._ops.push({ type: 'acceptRevisions', scope });\n return this;\n }\n\n rejectRevisions(scope: RevisionScope): this {\n this.ensureOpen('rejectRevisions');\n this._ops.push({ type: 'rejectRevisions', scope });\n return this;\n }\n\n // ─────────── 书签(#34)───────────\n\n createBookmark(spec: { name: BookmarkName; range: Range }): this {\n this.ensureOpen('createBookmark');\n this._ops.push({ type: 'createBookmark', name: spec.name, range: spec.range });\n return this;\n }\n\n deleteBookmark(name: BookmarkName): this {\n this.ensureOpen('deleteBookmark');\n this._ops.push({ type: 'deleteBookmark', name });\n return this;\n }\n\n // ─────────── 批注(#35)───────────\n\n addComment(spec: { range: Range; text: string; author?: string; date?: Date }): this {\n this.ensureOpen('addComment');\n const op: Extract<Op, { type: 'addComment' }> = {\n type: 'addComment',\n range: spec.range,\n text: spec.text,\n };\n if (spec.author !== undefined) op.author = spec.author;\n if (spec.date !== undefined) op.date = spec.date.toISOString();\n this._ops.push(op);\n return this;\n }\n\n deleteComment(commentId: CommentId): this {\n this.ensureOpen('deleteComment');\n this._ops.push({ type: 'deleteComment', commentId });\n return this;\n }\n\n // ─────────── 表格(#186)───────────\n\n addTableComment(spec: { tableId: string; text: string; author?: string; date?: Date }): this {\n this.ensureOpen('addTableComment');\n const op: Extract<Op, { type: 'addTableComment' }> = {\n type: 'addTableComment',\n tableId: spec.tableId,\n text: spec.text,\n };\n if (spec.author !== undefined) op.author = spec.author;\n if (spec.date !== undefined) op.date = spec.date.toISOString();\n this._ops.push(op);\n return this;\n }\n\n deleteTable(tableId: string, opts?: { onAnchorConflict?: 'error' | 'drop' }): this {\n this.ensureOpen('deleteTable');\n this._ops.push({\n type: 'deleteTable',\n tableId,\n onAnchorConflict: opts?.onAnchorConflict ?? 'error',\n });\n return this;\n }\n\n // ─────────── 表格域化(#188)───────────\n\n replaceTableCellWithSdt(spec: {\n tableId: string;\n row: number;\n col: number;\n sdt: SdtSpec;\n onAnchorConflict?: 'error' | 'drop';\n }): this {\n this.ensureOpen('replaceTableCellWithSdt');\n this._ops.push({\n type: 'replaceTableCellWithSdt',\n tableId: spec.tableId,\n row: spec.row,\n col: spec.col,\n sdt: spec.sdt,\n onAnchorConflict: spec.onAnchorConflict ?? 'error',\n });\n return this;\n }\n\n deleteTableRow(\n tableId: string,\n row: number,\n opts?: { onAnchorConflict?: 'error' | 'drop' },\n ): this {\n this.ensureOpen('deleteTableRow');\n this._ops.push({\n type: 'deleteTableRow',\n tableId,\n row,\n onAnchorConflict: opts?.onAnchorConflict ?? 'error',\n });\n return this;\n }\n\n replaceTableCellText(spec: {\n tableId: string;\n row: number;\n col: number;\n text: string;\n onAnchorConflict?: 'error' | 'drop';\n }): this {\n this.ensureOpen('replaceTableCellText');\n this._ops.push({\n type: 'replaceTableCellText',\n tableId: spec.tableId,\n row: spec.row,\n col: spec.col,\n text: spec.text,\n onAnchorConflict: spec.onAnchorConflict ?? 'error',\n });\n return this;\n }\n\n formatTableCell(spec: {\n tableId: string;\n row: number;\n col: number;\n format: TableCellDirectFormat;\n }): this {\n this.ensureOpen('formatTableCell');\n this._ops.push({\n type: 'formatTableCell',\n tableId: spec.tableId,\n row: spec.row,\n col: spec.col,\n format: spec.format,\n });\n return this;\n }\n\n // ─────────── 图片/Drawing(#190)───────────\n\n insertTableCellParagraph(spec: {\n tableId: string;\n row: number;\n col: number;\n text: string;\n position: 'start' | 'end';\n }): this {\n this.ensureOpen('insertTableCellParagraph');\n this._ops.push({\n type: 'insertTableCellParagraph',\n tableId: spec.tableId,\n row: spec.row,\n col: spec.col,\n text: spec.text,\n position: spec.position,\n });\n return this;\n }\n\n replaceDrawingWithPlaceholder(drawingId: string): this {\n this.ensureOpen('replaceDrawingWithPlaceholder');\n this._ops.push({ type: 'replaceDrawingWithPlaceholder', drawingId });\n return this;\n }\n\n deleteDrawing(drawingId: string): this {\n this.ensureOpen('deleteDrawing');\n this._ops.push({ type: 'deleteDrawing', drawingId });\n return this;\n }\n\n replaceShapeInnerText(drawingId: string, placeholder: string): this {\n this.ensureOpen('replaceShapeInnerText');\n this._ops.push({ type: 'replaceShapeInnerText', drawingId, placeholder });\n return this;\n }\n\n // ─────────── 表格行克隆/插入(#14)───────────\n\n insertTableRow(spec: {\n tableId: string;\n templateRow: number;\n position: number | 'end';\n cellTexts?: string[];\n }): this {\n this.ensureOpen('insertTableRow');\n const op: Extract<Op, { type: 'insertTableRow' }> = {\n type: 'insertTableRow',\n tableId: spec.tableId,\n templateRow: spec.templateRow,\n position: spec.position,\n };\n if (spec.cellTexts !== undefined) op.cellTexts = spec.cellTexts;\n this._ops.push(op);\n return this;\n }\n\n // ─────────── 表格克隆/插入(#15)───────────\n\n cloneTableAfter(spec: { anchorParaId: ParaId; sourceTableId: string }): this {\n this.ensureOpen('cloneTableAfter');\n this._ops.push({\n type: 'cloneTableAfter',\n anchorParaId: spec.anchorParaId,\n sourceTableId: spec.sourceTableId,\n });\n return this;\n }\n\n // ─────────── 图片插入(task-insert-image)───────────\n\n insertImageAfter(\n anchorParaId: ParaId,\n spec: {\n bytes: Uint8Array;\n contentType: string;\n widthEmu: number;\n heightEmu: number;\n },\n ): this {\n this.ensureOpen('insertImageAfter');\n this._ops.push({\n type: 'insertImageAfter',\n anchorParaId,\n bytes: spec.bytes,\n contentType: spec.contentType,\n widthEmu: spec.widthEmu,\n heightEmu: spec.heightEmu,\n });\n return this;\n }\n\n // ─────────── 跨文档搬表(task-20260616-table-content-driven)───────────\n\n insertTableFrom(spec: {\n anchorParaId: ParaId;\n tableXml: string;\n images?: Array<{ originalRId: string; bytes: Uint8Array; contentType: string }>;\n styleTblPrXml?: string;\n }): this {\n this.ensureOpen('insertTableFrom');\n const op: Extract<Op, { type: 'insertTableFrom' }> = {\n type: 'insertTableFrom',\n anchorParaId: spec.anchorParaId,\n tableXml: spec.tableXml,\n };\n if (spec.images !== undefined) op.images = spec.images;\n if (spec.styleTblPrXml !== undefined) op.styleTblPrXml = spec.styleTblPrXml;\n this._ops.push(op);\n return this;\n }\n\n // ─────────── 表格列宽(task-core-table-grid)───────────\n\n setTableColumnWidths(spec: { tableId: string; widths: number[] }): this {\n this.ensureOpen('setTableColumnWidths');\n this._ops.push({\n type: 'setTableColumnWidths',\n tableId: spec.tableId,\n widths: spec.widths,\n });\n return this;\n }\n\n // ─────────── 表格行高(task-core-table-rowheight)───────────\n\n setTableRowHeights(spec: { tableId: string; heights: (RowHeight | null)[] }): this {\n this.ensureOpen('setTableRowHeights');\n this._ops.push({\n type: 'setTableRowHeights',\n tableId: spec.tableId,\n heights: spec.heights,\n });\n return this;\n }\n\n // ─────────── 文档域更新设置(task-core-update-fields)───────────\n\n setUpdateFields(enabled: boolean): this {\n this.ensureOpen('setUpdateFields');\n this._ops.push({ type: 'setUpdateFields', enabled });\n return this;\n }\n\n // ─────────── apply 状态机 ───────────\n\n async apply(): Promise<ApplyResult> {\n if (this._applied) {\n throw new WordError(\n 'PLAN_ALREADY_APPLIED',\n 'WordPlan.apply() called on a plan that was already applied. Create a new plan via doc.plan().',\n this.docId,\n );\n }\n // 进入 apply 立即锁定,无论成败 —— plan 是一次性对象,失败场景由调用方重建\n this._applied = true;\n\n if (this._ops.length === 0) {\n // 契约 §4.1:PLAN_EMPTY 默认 warn 不抛(严格模式留未来引入)\n console.warn(\n `[word-plan] apply() called on empty plan (docId=${this.docId}); returning empty ApplyResult`,\n );\n return cloneEmptyResult();\n }\n\n // 走 RPC 到 kernel.applyPlan;序列化参数为纯 JSON 形态(Date 已在 addComment\n // 里转 ISO 字符串,其它字段均为 primitive / plain object)。\n return this.transport.call<ApplyResult>('applyPlan', [\n {\n ops: this._ops,\n options: {\n trackChanges: this._options.trackChanges ?? false,\n ...(this._options.author !== undefined ? { author: this._options.author } : {}),\n ...(this._options.date !== undefined ? { date: this._options.date.toISOString() } : {}),\n },\n },\n ]);\n }\n\n async validate(): Promise<PlanValidationResult> {\n this.ensureOpen('validate');\n return this.transport.call<PlanValidationResult>('validatePlan', [\n {\n ops: this._ops,\n options: {\n trackChanges: this._options.trackChanges ?? false,\n ...(this._options.author !== undefined ? { author: this._options.author } : {}),\n ...(this._options.date !== undefined ? { date: this._options.date.toISOString() } : {}),\n },\n },\n ]);\n }\n\n // ─────────── 内部 ───────────\n\n private ensureOpen(methodName: string): void {\n if (this._applied) {\n throw new WordError(\n 'PLAN_ALREADY_APPLIED',\n `WordPlan.${methodName}() called after apply(); plans are single-use`,\n this.docId,\n );\n }\n }\n}\n\nfunction cloneEmptyResult(): ApplyResult {\n // 不暴露冻结引用,避免调用方误把 ApplyResult 当只读产物(例如想追加字段调试)\n return {\n insertedParagraphs: [],\n insertedBodyStartParaIds: [],\n createdComments: [],\n createdBookmarks: [],\n acceptedRevisions: 0,\n rejectedRevisions: 0,\n replacedTableCells: 0,\n };\n}\n\n// ─────────── kernel 侧载荷(applyPlan RPC 参数)───────────\n\n/**\n * `kernel.applyPlan` 接收的结构。`date` 是 ISO 8601 字符串(序列化友好),kernel\n * 端需要时用 `new Date(str)` 解回。\n */\nexport interface ApplyPlanParams {\n ops: Op[];\n options: {\n trackChanges: boolean;\n author?: string;\n date?: string;\n };\n}\n\n// story 引用的 placeholder;供 executor PR 未来使用时若要引 StoryId 避免循环\n// import 可直接 import from this module.\nexport type { StoryId };\n","import type { PackageIndices } from './indices.js';\nimport type {\n ApplyPlanParams,\n Op,\n PlanValidationIssue,\n PlanValidationItem,\n PlanValidationResult,\n} from './plan.js';\nimport { getParagraphRuns, getRunText } from './runs.js';\nimport type { WordErrorCode } from './word-error.js';\n\ninterface PlanValidationContext {\n indices: PackageIndices;\n options: ApplyPlanParams['options'];\n}\n\ntype OpValidator = (\n op: Op,\n ctx: PlanValidationContext,\n) => PlanValidationIssue | undefined;\n\nconst validators: Partial<Record<Op['type'], OpValidator>> = {\n addComment: validateAddComment,\n};\n\n/**\n * Validate supported operations against the current immutable document state.\n * Unsupported operation types are reported as `unvalidated`, never assumed valid.\n */\nexport function validatePlanOps(\n params: ApplyPlanParams,\n indices: PackageIndices,\n): PlanValidationResult {\n const ctx: PlanValidationContext = { indices, options: params.options };\n const items: PlanValidationItem[] = params.ops.map((op, opIndex) => {\n const validator = validators[op.type];\n if (!validator) return { opIndex, opType: op.type, status: 'unvalidated' };\n const issue = validator(op, ctx);\n return issue\n ? { opIndex, opType: op.type, status: 'invalid', issue }\n : { opIndex, opType: op.type, status: 'valid' };\n });\n return {\n valid: items.every((item) => item.status === 'valid'),\n items,\n };\n}\n\nfunction validateAddComment(op: Op, ctx: PlanValidationContext): PlanValidationIssue | undefined {\n if (op.type !== 'addComment') return undefined;\n if (ctx.options.trackChanges) {\n return issue(\n 'UNSUPPORTED_OOXML_FEATURE',\n 'addComment with trackChanges=true is not supported',\n { opType: op.type },\n );\n }\n if ('text' in op.range && op.range.scope === 'all') {\n return issue(\n 'UNSUPPORTED_OOXML_FEATURE',\n \"addComment: scope='all' is not supported for a text range\",\n { opType: op.type, scope: 'all' },\n );\n }\n\n const paraId = op.range.paraId;\n const paragraph = ctx.indices.paraIdx.get(paraId.toUpperCase());\n if (!paragraph) {\n return issue('PARA_NOT_FOUND', `addComment: paragraph '${paraId}' not found`, { paraId });\n }\n if ('text' in op.range) {\n const search = op.range.text;\n const paragraphText = getParagraphRuns(paragraph).map((run) => getRunText(run)).join('');\n if (!search || !paragraphText.includes(search)) {\n return issue(\n 'TEXT_NOT_FOUND_IN_PARA',\n `addComment: text '${search}' not found in paragraph ${paraId}`,\n { paraId, search },\n );\n }\n }\n return undefined;\n}\n\nfunction issue(\n code: WordErrorCode,\n message: string,\n details?: Record<string, unknown>,\n): PlanValidationIssue {\n return { code, message, ...(details ? { details } : {}) };\n}\n","/**\n * Executor 共享工具 —— 由 #29 提取,供 #34/#35 等后续 PR 复用。\n *\n * 从 paragraph-ops.ts 提出的三个内部工具:\n * - createW / createT:创建带正确命名空间的 <w:*> / <w:t> 元素\n * - appendTextAsRuns:把 text(含 \\n / \\t)追加为单 <w:r> 到段落,可选传入 rPr\n * - firstDirectChildW:找 element 直属的首个 W_NS 子元素\n *\n * #30 追加:\n * - ParagraphAnchors / collectParagraphAnchors:扫段内活锚点(bookmarks + comments)\n * - collectRangeAnchors:扫一段 sibling 链内的锚点(供 replaceTextInParagraph 使用)\n *\n * task-core-replacepara-rpr 追加(提取自 table-ops.ts,统一事实源):\n * - pickFirstRunRPr:取段落首个 run 后代的 rPr,run 无 rPr 时兜底取 pPr/rPr\n * 供 replaceParagraph(paragraph-ops)和 replaceTableCellText(table-ops)共用\n */\nimport { W_NS, XML_NS } from '../namespaces.js';\n\n// ─────────── #30 锚点检测 ───────────\n\n/** 段落内活锚点汇总 */\nexport interface ParagraphAnchors {\n /** bookmarkStart 的 w:name 数组 */\n bookmarks: string[];\n /** commentRangeStart / commentReference 的 w:id 数组(去重) */\n comments: number[];\n}\n\n/**\n * 扫 `paragraph` 内所有 bookmarkStart(取 w:name)\n * 和 commentRangeStart / commentReference(取 w:id,去重),\n * 返回 `ParagraphAnchors`。\n *\n * 禁无谓词 XPath — 一律 `getElementsByTagNameNS`。\n */\nexport function collectParagraphAnchors(paragraph: Element): ParagraphAnchors {\n const bookmarks: string[] = [];\n const commentIds = new Set<number>();\n\n const bmStarts = paragraph.getElementsByTagNameNS(W_NS, 'bookmarkStart');\n for (let i = 0; i < bmStarts.length; i++) {\n const el = bmStarts[i];\n if (!el) continue;\n const name = el.getAttributeNS(W_NS, 'name') ?? el.getAttribute('w:name') ?? '';\n bookmarks.push(name);\n }\n\n const cStarts = paragraph.getElementsByTagNameNS(W_NS, 'commentRangeStart');\n for (let i = 0; i < cStarts.length; i++) {\n const el = cStarts[i];\n if (!el) continue;\n const raw = el.getAttributeNS(W_NS, 'id') ?? el.getAttribute('w:id') ?? '';\n const id = parseInt(raw, 10);\n if (!isNaN(id)) commentIds.add(id);\n }\n\n const cRefs = paragraph.getElementsByTagNameNS(W_NS, 'commentReference');\n for (let i = 0; i < cRefs.length; i++) {\n const el = cRefs[i];\n if (!el) continue;\n const raw = el.getAttributeNS(W_NS, 'id') ?? el.getAttribute('w:id') ?? '';\n const id = parseInt(raw, 10);\n if (!isNaN(id)) commentIds.add(id);\n }\n\n return { bookmarks, comments: Array.from(commentIds) };\n}\n\n/**\n * 扫 sibling 链 [startNode, endNode] 之间(含两端)的锚点 marker,\n * 用于 replaceTextInParagraph 的区间锚点检测。\n *\n * startNode / endNode 是 paragraph 直属 childNodes 内的节点。\n * 扫描范围:从 startNode 到 endNode(含)的所有 Element 子节点,\n * 以及这些节点自身若是 bookmarkStart / commentRangeStart / commentReference。\n *\n * 注意:锚点 marker 通常是段直属的 Element(非 run 子),\n * 遇到就算在区间内。\n */\nexport function collectRangeAnchors(startNode: Node, endNode: Node): ParagraphAnchors {\n const bookmarks: string[] = [];\n const commentIds = new Set<number>();\n\n let cur: Node | null = startNode;\n while (cur) {\n if (cur.nodeType === 1) {\n const el = cur as Element;\n const localName = el.localName;\n if (el.namespaceURI === W_NS) {\n if (localName === 'bookmarkStart') {\n const name = el.getAttributeNS(W_NS, 'name') ?? el.getAttribute('w:name') ?? '';\n bookmarks.push(name);\n } else if (localName === 'commentRangeStart' || localName === 'commentReference') {\n const raw = el.getAttributeNS(W_NS, 'id') ?? el.getAttribute('w:id') ?? '';\n const id = parseInt(raw, 10);\n if (!isNaN(id)) commentIds.add(id);\n }\n }\n }\n if (cur === endNode) break;\n cur = cur.nextSibling;\n }\n\n return { bookmarks, comments: Array.from(commentIds) };\n}\n\n/** 创建 `<w:localName>` 元素(W_NS)*/\nexport function createW(doc: Document, localName: string): Element {\n return doc.createElementNS(W_NS, `w:${localName}`);\n}\n\n/**\n * 创建 `<w:t xml:space=\"preserve\">` 元素。\n * 所有 `<w:t>` 一律挂 preserve,保留首尾空格。\n */\nexport function createT(doc: Document, text: string): Element {\n const t = createW(doc, 't');\n t.setAttributeNS(XML_NS, 'xml:space', 'preserve');\n t.textContent = text;\n return t;\n}\n\n/**\n * 把 text 里的 `\\n` / `\\t` 映射为 `<w:br/>` / `<w:tab/>`,其它为 `<w:t>`。\n * 追加为单一 `<w:r>` 到 paragraph 末尾。\n * 空 text → 一个空 `<w:t/>` placeholder(段不能完全无 run)。\n *\n * `rPr`(可选):若传入,插到 run 首位作为 `<w:rPr>`,透传字号/字体等格式。\n */\nexport function appendTextAsRuns(paragraph: Element, text: string, rPr?: Element): void {\n const doc = paragraph.ownerDocument;\n if (!doc) throw new Error('paragraph has no ownerDocument');\n\n const run = createW(doc, 'r');\n if (rPr) run.insertBefore(rPr, run.firstChild);\n appendSegmentsToRun(doc, run, text);\n paragraph.appendChild(run);\n}\n\n/**\n * 把 text 里的字符映射为 run 的子元素(`\\n`→`<w:br/>` / `\\t`→`<w:tab/>` / other→`<w:t>`)。\n * export 供 buildReplacementRun 等需要往已存在 run 里填内容的场景使用。\n */\nexport function appendSegmentsToRun(doc: Document, run: Element, text: string): void {\n if (text.length === 0) {\n run.appendChild(createT(doc, ''));\n return;\n }\n let buf = '';\n const flush = (): void => {\n if (buf.length > 0) {\n run.appendChild(createT(doc, buf));\n buf = '';\n }\n };\n for (const ch of text) {\n if (ch === '\\n') {\n flush();\n run.appendChild(createW(doc, 'br'));\n } else if (ch === '\\t') {\n flush();\n run.appendChild(createW(doc, 'tab'));\n } else {\n buf += ch;\n }\n }\n flush();\n}\n\n/** 找 `el` 直属子中首个 localName 匹配的 W_NS 元素(null 表示无)*/\nexport function firstDirectChildW(el: Element, localName: string): Element | null {\n const children = el.childNodes;\n for (let i = 0; i < children.length; i++) {\n const c = children[i];\n if (\n c &&\n c.nodeType === 1 &&\n (c as Element).namespaceURI === W_NS &&\n (c as Element).localName === localName\n ) {\n return c as Element;\n }\n }\n return null;\n}\n\n/**\n * 取段落内**首个 `<w:r>` 后代**的 `<w:rPr>` 克隆;run 无 rPr 时兜底取 `pPr/rPr`。\n *\n * 通用化(task-core-cell-rpr R1):\n * 用 `getElementsByTagNameNS(W_NS,'r')` 取后代 run(DOM document order),\n * 天然覆盖 SDT、hyperlink、smartTag、fldSimple、ins 等任意包裹容器内的 run,\n * 无需逐一判断包裹类型。\n *\n * pPr/rPr 兜底(task-core-cell-rpr R2):\n * 首个 run 无显式 rPr 时,回退到段落 `<w:pPr><w:rPr>`——标准 OOXML\"段落默认\n * run 属性\"来源,通用且符合规范语义。\n *\n * 优先级:\n * 1. 首个后代 run 有 rPr → 返回 run rPr 克隆\n * 2. 首个后代 run 无 rPr,但 pPr/rPr 存在 → 返回 pPr/rPr 克隆\n * 3. 两者都无 → 返回 undefined(裸 run,语义不变)\n *\n * 安全边界:OOXML 规范段落不嵌套表格(嵌套表是 `<w:tc>` 的兄弟,非段落子),\n * 故 `getElementsByTagNameNS` 只覆盖本段显示内容内的 run。\n *\n * 提取自 table-ops.ts(task-core-replacepara-rpr),paragraph-ops 与 table-ops 共用。\n *\n * @returns rPr 克隆,或 undefined(无可用格式来源)。\n */\nexport function pickFirstRunRPr(paragraph: Element): Element | undefined {\n // 1. 首个后代 run 的 rPr(覆盖任意包裹容器)\n const runs = paragraph.getElementsByTagNameNS(W_NS, 'r');\n if (runs.length > 0) {\n const rPr = firstDirectChildW(runs[0]!, 'rPr');\n if (rPr) return rPr.cloneNode(true) as Element;\n }\n // 2. 兜底:pPr/rPr(段落默认 run 属性)\n const pPr = firstDirectChildW(paragraph, 'pPr');\n if (pPr) {\n const pRPr = firstDirectChildW(pPr, 'rPr');\n if (pRPr) return pRPr.cloneNode(true) as Element;\n }\n return undefined;\n}\n","/**\n * revision-wrappers.ts —— #31 trackChanges 包装 helper。\n *\n * 提供把 DOM run 包进 `<w:ins>` / `<w:del>` 的低层工具,以及给段落 mark 加\n * 插入/删除标记的 helper。不依赖 ExecutorContext,只依赖 Package 和选项原始值。\n *\n * **重要 OOXML 约束**:\n * - `<w:ins>` / `<w:del>` 是 run 的包装层,出现在 `<w:p>` 子层(不跨 w:p)\n * - `<w:del>` 内的 run 用 `<w:delText>` 而非 `<w:t>`(显示被删内容)\n * - 段落 mark 的修订标记放在 `<w:pPr><w:rPr><w:ins/>` / `<w:pPr><w:rPr><w:del/>`\n * - `w:id` 必须在 pkg 全局唯一(扫所有 part 的 ins/del,取 max+1)\n */\nimport type { Package } from '../../pack/index.js';\nimport { listParts, isXmlPart } from '../../pack/index.js';\nimport { W_NS } from '../namespaces.js';\nimport { createW } from './_shared.js';\n\n/** 用于构建修订属性的最小选项 */\nexport interface RevisionAttrs {\n author: string;\n date: Date;\n}\n\n// ─────────── allocateRevisionId ───────────\n\n/**\n * 扫 pkg 内所有 XML part 里的 `<w:ins>` / `<w:del>`,读取 `w:id` 属性,\n * 返回 max(存在的数字 id) + 1。\n * 无任何 valid id → 返回 0(首次分配)。\n */\nexport function allocateRevisionId(pkg: Package): number {\n let max = -1;\n const parts = listParts(pkg);\n for (const part of parts) {\n if (!isXmlPart(part) || !part.xmlDom) continue;\n const doc = part.xmlDom as Document;\n const insEls = doc.getElementsByTagNameNS(W_NS, 'ins');\n const delEls = doc.getElementsByTagNameNS(W_NS, 'del');\n max = readMaxId(insEls, max);\n max = readMaxId(delEls, max);\n }\n return max + 1;\n}\n\nfunction readMaxId(col: HTMLCollectionOf<Element>, current: number): number {\n let max = current;\n for (let i = 0; i < col.length; i++) {\n const el = col[i];\n if (!el) continue;\n const raw = el.getAttributeNS(W_NS, 'id') ?? el.getAttribute('w:id');\n if (raw === null) continue;\n const n = parseInt(raw, 10);\n if (!isNaN(n) && n > max) max = n;\n }\n return max;\n}\n\n// ─────────── setRevisionAttrs ───────────\n\n/** 给 `<w:ins>` / `<w:del>` 元素设置 w:id / w:author / w:date 属性 */\nfunction setRevisionAttrs(el: Element, id: number, attrs: RevisionAttrs): void {\n el.setAttributeNS(W_NS, 'w:id', String(id));\n el.setAttributeNS(W_NS, 'w:author', attrs.author);\n el.setAttributeNS(W_NS, 'w:date', attrs.date.toISOString());\n}\n\n// ─────────── wrapRunsAsInsert ───────────\n\n/**\n * 将 runs(深拷贝)包进新建的 `<w:ins w:id=\"N\" w:author=\"...\" w:date=\"...\">`,\n * 并返回该 `<w:ins>` 元素。\n *\n * 调用方负责把返回元素插入 DOM;runs 本身(原始元素)由调用方管理。\n */\nexport function wrapRunsAsInsert(runs: Element[], id: number, attrs: RevisionAttrs): Element {\n if (runs.length === 0) throw new Error('wrapRunsAsInsert: runs must not be empty');\n const doc = runs[0]!.ownerDocument;\n if (!doc) throw new Error('wrapRunsAsInsert: run has no ownerDocument');\n\n const ins = createW(doc, 'ins');\n setRevisionAttrs(ins, id, attrs);\n for (const run of runs) {\n ins.appendChild(run.cloneNode(true));\n }\n return ins;\n}\n\n// ─────────── wrapRunsAsDelete ───────────\n\n/**\n * 将 runs 深拷贝、把拷贝中所有 `<w:t>` 重建为 `<w:delText>` 后,包进新建的\n * `<w:del>`,返回该 `<w:del>` 元素。\n *\n * 约束:不试图 rename 节点(slimdom 不支持 renameNode),用 createElementNS 创建\n * 新 `<w:delText>`,把 textContent + xml:space 属性搬过来。\n */\nexport function wrapRunsAsDelete(runs: Element[], id: number, attrs: RevisionAttrs): Element {\n if (runs.length === 0) throw new Error('wrapRunsAsDelete: runs must not be empty');\n const doc = runs[0]!.ownerDocument;\n if (!doc) throw new Error('wrapRunsAsDelete: run has no ownerDocument');\n\n const del = createW(doc, 'del');\n setRevisionAttrs(del, id, attrs);\n\n for (const run of runs) {\n const cloned = run.cloneNode(true) as Element;\n convertTtoDelText(doc, cloned);\n del.appendChild(cloned);\n }\n return del;\n}\n\n/**\n * 递归遍历 `el` 及其后代,把所有 `<w:t>` 替换为 `<w:delText>`。\n * 属性和 textContent 全搬。\n *\n * 注意:不使用 renameNode(slimdom 不支持)。\n */\nfunction convertTtoDelText(doc: Document, el: Element): void {\n // 先处理子节点(深度优先,避免在枚举时同时修改列表)\n const childrenSnapshot: Node[] = [];\n for (let i = 0; i < el.childNodes.length; i++) {\n const c = el.childNodes[i];\n if (c) childrenSnapshot.push(c);\n }\n\n for (const child of childrenSnapshot) {\n if (\n child.nodeType === 1 &&\n (child as Element).namespaceURI === W_NS &&\n (child as Element).localName === 't'\n ) {\n const t = child as Element;\n const delText = doc.createElementNS(W_NS, 'w:delText');\n // 搬属性(主要是 xml:space=\"preserve\")\n for (let i = 0; i < t.attributes.length; i++) {\n const attr = t.attributes[i];\n if (!attr) continue;\n if (attr.namespaceURI) {\n delText.setAttributeNS(attr.namespaceURI, attr.name, attr.value);\n } else {\n delText.setAttribute(attr.name, attr.value);\n }\n }\n delText.textContent = t.textContent;\n el.replaceChild(delText, t);\n } else if (child.nodeType === 1) {\n // 递归处理子元素\n convertTtoDelText(doc, child as Element);\n }\n }\n}\n\n// ─────────── ensureParaMarkInsert / ensureParaMarkDelete ───────────\n\n/**\n * 在段落的 `<w:pPr><w:rPr>` 里插入 `<w:ins w:id=\"N\" .../>`,\n * 表示该段落 mark 是新插入的(新段的修订标记)。\n *\n * - 如果 pPr 不存在 → 创建 pPr 并插到段落首\n * - 如果 pPr 存在但无 rPr → 创建 rPr 并插到 pPr 首\n * - 如果 rPr 已存在 → 直接 append ins\n */\nexport function ensureParaMarkInsert(paragraph: Element, id: number, attrs: RevisionAttrs): void {\n const doc = paragraph.ownerDocument;\n if (!doc) throw new Error('ensureParaMarkInsert: paragraph has no ownerDocument');\n\n const rPr = ensureRPrInPPr(doc, paragraph);\n const ins = createW(doc, 'ins');\n setRevisionAttrs(ins, id, attrs);\n rPr.appendChild(ins);\n}\n\n/**\n * 在段落的 `<w:pPr><w:rPr>` 里插入 `<w:del w:id=\"N\" .../>`,\n * 表示该段落 mark 是被删除的(deleteParagraph trackChanges 下的段落 mark 标记)。\n */\nexport function ensureParaMarkDelete(paragraph: Element, id: number, attrs: RevisionAttrs): void {\n const doc = paragraph.ownerDocument;\n if (!doc) throw new Error('ensureParaMarkDelete: paragraph has no ownerDocument');\n\n const rPr = ensureRPrInPPr(doc, paragraph);\n const del = createW(doc, 'del');\n setRevisionAttrs(del, id, attrs);\n rPr.appendChild(del);\n}\n\n/** 确保段落有 `<w:pPr>`,并在 pPr 里确保有 `<w:rPr>`,返回 rPr 元素 */\nfunction ensureRPrInPPr(doc: Document, paragraph: Element): Element {\n // 找或建 pPr\n let pPr = firstDirectChildW(paragraph, 'pPr');\n if (!pPr) {\n pPr = createW(doc, 'pPr');\n // pPr 必须是段落第一个子\n paragraph.insertBefore(pPr, paragraph.firstChild);\n }\n\n // 找或建 rPr\n let rPr = firstDirectChildW(pPr, 'rPr');\n if (!rPr) {\n rPr = createW(doc, 'rPr');\n pPr.insertBefore(rPr, pPr.firstChild);\n }\n\n return rPr;\n}\n\n/** 找 `el` 直属子中首个 localName 匹配的 W_NS 元素(null 表示无)*/\nfunction firstDirectChildW(el: Element, localName: string): Element | null {\n const children = el.childNodes;\n for (let i = 0; i < children.length; i++) {\n const c = children[i];\n if (\n c &&\n c.nodeType === 1 &&\n (c as Element).namespaceURI === W_NS &&\n (c as Element).localName === localName\n ) {\n return c as Element;\n }\n }\n return null;\n}\n","/**\n * 段落修改 executor —— #28(replaceParagraph / replaceTextInParagraph)。\n *\n * 设计要点:\n * - 段枚举走 paraIdx,O(1) 定位到 `<w:p>`。\n * - 保留策略:`<w:pPr>`(样式 / 编号 / 段落属性)整体不动;\n * 本 PR **直属 marker**(段内的 bookmarkStart/End / commentRange* 等)在\n * `replaceParagraph` 里一并清掉 —— ANCHOR_CONFLICT 检测留给 #30 补保护层\n * - trackChanges=true(#31):replaceParagraph 把旧 runs 包成 `<w:del>`,\n * 新 runs 包成 `<w:ins>`;replaceTextInParagraph 把匹配区间包成 `<w:del>`,\n * replacement 包成 `<w:ins>`\n * - 新 run 使用既有命名空间前缀(从 ownerDocument 继承),用 `createElementNS`\n * 确保 URI 对齐;`<w:t>` 一律挂 `xml:space=\"preserve\"` 保留首尾空格\n *\n * **复杂 run 限制**(沿用 `splitRunAt`):`replaceTextInParagraph` 跨 run 匹配时,\n * 匹配区间涉及到的 run 必须是\"单 `<w:t>` 简单 run\";遇 `<w:br>` / `<w:tab>` /\n * 多 `<w:t>` 等 → 抛 `UNSUPPORTED_OOXML_FEATURE`。\n */\nimport { getPart, markDirty } from '../../pack/index.js';\nimport { findStoryFor } from '../stories.js';\nimport { W_NS, W14_NS, WPS_NS, VML_NS, XML_NS } from '../namespaces.js';\nimport type { Op } from '../plan.js';\nimport { getParagraphRuns, getRunText, splitRunAt } from '../runs.js';\nimport { WordError } from '../word-error.js';\nimport type { ExecutorContext } from './executor-context.js';\nimport {\n appendSegmentsToRun,\n appendTextAsRuns,\n collectParagraphAnchors,\n collectRangeAnchors,\n createW,\n firstDirectChildW,\n pickFirstRunRPr,\n} from './_shared.js';\nimport {\n allocateRevisionId,\n wrapRunsAsInsert,\n wrapRunsAsDelete,\n type RevisionAttrs,\n} from './revision-wrappers.js';\n\n/** 段落中\"marker\"(非内容)直属子元素,在 replaceParagraph 里**保留**的集合 */\nconst PARAGRAPH_HEADER_MARKERS = new Set<string>(['pPr']);\n\n/** 段落中被 replaceParagraph **移除**的内容元素集合(任何能承载显示字节的 wrapper)*/\nconst PARAGRAPH_CONTENT_ELEMENTS = new Set<string>([\n 'r',\n 'hyperlink',\n 'ins',\n 'del',\n 'moveFrom',\n 'moveTo',\n 'smartTag',\n 'sdt',\n 'fldSimple',\n 'customXml',\n]);\n\n/** 段内 marker 的命名(bookmarkStart / commentRangeStart 等)—— replaceParagraph 当前一并清掉,ANCHOR_CONFLICT 由 #30 保护 */\nconst PARAGRAPH_ANCHOR_MARKERS = new Set<string>([\n 'bookmarkStart',\n 'bookmarkEnd',\n 'commentRangeStart',\n 'commentRangeEnd',\n 'commentReference',\n 'permStart',\n 'permEnd',\n 'proofErr',\n]);\n\n/**\n * 判断 `<w:r>` 是否含图形后代。\n * 检测:`<w:drawing>`、`<w:pict>`、`<wps:wsp>`(Word 2010+ shape)、\n * `<v:line>` / `<v:shape>` / `<v:rect>`(VML)、`<w:object>`(OLE)。\n * 规则:在 `run` 所有后代中查找任意一个满足条件的元素即视为图形 run。\n */\nfunction isGraphicRun(run: Element): boolean {\n // 直接子元素级别的 <w:drawing> / <w:pict> / <w:object>(W_NS)\n for (let i = 0; i < run.childNodes.length; i++) {\n const c = run.childNodes[i];\n if (!c || c.nodeType !== 1) continue;\n const el = c as Element;\n if (el.namespaceURI === W_NS) {\n const ln = el.localName;\n if (ln === 'drawing' || ln === 'pict' || ln === 'object') return true;\n }\n }\n // 深层后代:wps:wsp(在 w:drawing 内部的 mc:AlternateContent 分支中),\n // v:line / v:shape / v:rect(VML,在 w:pict 内或 mc:Fallback 中)\n // 用 getElementsByTagNameNS 比手写递归简洁且在 slimdom 里有效\n if (run.getElementsByTagNameNS(WPS_NS, 'wsp').length > 0) return true;\n if (run.getElementsByTagNameNS(VML_NS, 'line').length > 0) return true;\n if (run.getElementsByTagNameNS(VML_NS, 'shape').length > 0) return true;\n if (run.getElementsByTagNameNS(VML_NS, 'rect').length > 0) return true;\n return false;\n}\n\n// ─────────── replaceParagraph ───────────\n\nexport function executeReplaceParagraph(\n ctx: ExecutorContext,\n op: Extract<Op, { type: 'replaceParagraph' }>,\n): void {\n const paragraph = requireParagraph(ctx, op.paraId, 'replaceParagraph');\n\n if (ctx.options.trackChanges) {\n // trackChanges=true(#31):旧内容(含 bookmark/comment marker)整体包成 <w:del>,\n // 新 runs 包成 <w:ins>;锚点跟随被删内容进入修订包装,语义自洽:\n // 用户接受 → 文本+锚点一起删;拒绝 → 一起恢复(与 Word/WPS 原生 trackChanges 行为对齐)\n executeReplaceParagraphTC(ctx, paragraph, op);\n } else {\n // 非 trackChanges:ANCHOR_CONFLICT 检测(#30)\n // keepInlineGraphics=true 时绕过锚点冲突检测:该模式会就地保留锚点 marker,\n // 不会产生孤儿,不需要拦截。\n // 不带 keepInlineGraphics 时,直接覆盖会让锚点孤立、且无法回滚,拒掉。\n if (!op.keepInlineGraphics) {\n const anchors = collectParagraphAnchors(paragraph);\n if (anchors.bookmarks.length > 0 || anchors.comments.length > 0) {\n if (op.onAnchorConflict === 'drop') {\n // drop:跳过本次替换,保留原段落内容不变\n return;\n }\n throw new WordError(\n 'ANCHOR_CONFLICT',\n `paragraph modification conflicts with active anchors (paraId=${op.paraId}); ` +\n `enable trackChanges to wrap the deletion as a revision`,\n ctx.docId,\n {\n paraId: op.paraId,\n affectedBookmarks: anchors.bookmarks,\n affectedComments: anchors.comments,\n opType: 'replaceParagraph',\n },\n );\n }\n }\n // 删旧内容前先抓首个 run 的 rPr(task-core-replacepara-rpr:透传字号/字体)\n const inheritedRPr = pickFirstRunRPr(paragraph);\n if (op.keepInlineGraphics) {\n // keepInlineGraphics=true:只删纯文字 run,图形 run 与锚点 marker 保留原位。\n // 新文字 run 插在第一个图形 run 之前,保持\"文字在前、线条在后\"原序。\n // 注意:要在 removeContentChildren 之前找到第一个图形 run 的引用,\n // 因为删除后文字 run 引用会脱离 DOM,不能作为 insertBefore 锚点。\n const firstGraphicRunAnchor = findFirstGraphicRunAnchor(paragraph);\n removeContentChildren(paragraph, true);\n const doc = paragraph.ownerDocument;\n if (!doc) throw new WordError('PACKAGE_CORRUPT', 'paragraph has no ownerDocument', ctx.docId);\n appendTextAsRunsAt(paragraph, op.text, inheritedRPr, firstGraphicRunAnchor);\n } else {\n removeContentChildren(paragraph);\n appendTextAsRuns(paragraph, op.text, inheritedRPr);\n }\n }\n\n // markDirty 对应 part\n markStoryPartDirty(ctx, paragraph, 'replaceParagraph');\n}\n\n/**\n * trackChanges=true 模式下的 replaceParagraph:\n * - 旧内容(runs + bookmark/comment marker + 已存在的 ins/del wrapper)整体包成 `<w:del>`\n * (w:t → w:delText;锚点 marker 直接作为 `<w:del>` 子节点保留,与 Word/WPS 行为一致)\n * - 新 runs 整体包成 `<w:ins>`\n * - 顺序:pPr → [图形 run(若 keepInlineGraphics)]… → del → ins → [图形 run(若在文字后)]\n *\n * keepInlineGraphics=true 时:\n * - 图形 run 不进入 `<w:del>`(保留在段落原位,不产生 del 修订)\n * - 只有纯文字的内容子(及非图形 run)被收入旧内容数组,包成 del\n * - `<w:ins>` 插在图形 run 之前(首个图形 run 前),保持\"文字在前、线条在后\"原序\n */\nfunction executeReplaceParagraphTC(\n ctx: ExecutorContext,\n paragraph: Element,\n op: Extract<Op, { type: 'replaceParagraph' }>,\n): void {\n const attrs: RevisionAttrs = { author: ctx.options.author, date: ctx.options.date };\n\n // 0. 删旧内容前先抓首个 run 的 rPr(task-core-replacepara-rpr:透传字号/字体)\n // 必须在 removeContentChildren 之前,否则 run 被清掉后取不到\n const inheritedRPr = pickFirstRunRPr(paragraph);\n\n if (op.keepInlineGraphics) {\n // ── keepInlineGraphics=true 分支 ──\n // 1a. 分离:图形 run 保留原位,纯文字内容子收入待删列表\n const { textChildren, graphicRuns } = separateGraphicAndTextChildren(paragraph);\n\n // 2a. 只删纯文字内容子(图形 run 保留)\n for (const c of textChildren) {\n paragraph.removeChild(c);\n }\n\n // 3a. 若有旧文字内容,包成 <w:del>\n // 插入锚点:首个图形 run 之前(保持文字区在图形区之前)\n const firstGraphicRun = graphicRuns[0] ?? null;\n if (textChildren.length > 0) {\n const delId = allocateRevisionId(ctx.pkg);\n const delEl = wrapRunsAsDelete(textChildren, delId, attrs);\n paragraph.insertBefore(delEl, firstGraphicRun);\n }\n\n // 4a. 构建新 run 并包成 <w:ins>,同样插在首个图形 run 之前\n const doc = paragraph.ownerDocument;\n if (!doc) throw new WordError('PACKAGE_CORRUPT', 'paragraph has no ownerDocument', ctx.docId);\n const newRun = createW(doc, 'r');\n if (inheritedRPr) newRun.insertBefore(inheritedRPr, newRun.firstChild);\n appendSegmentsToRun(doc, newRun, op.text);\n const insId = allocateRevisionId(ctx.pkg);\n const insEl = wrapRunsAsInsert([newRun], insId, attrs);\n paragraph.insertBefore(insEl, firstGraphicRun);\n } else {\n // ── 默认分支(现有行为) ──\n // 1. 收集现有所有内容子(在清之前)—— 不仅是 <w:r>,还包括 bookmarkStart/End、\n // commentRangeStart/End、commentReference、已存在的 <w:ins>/<w:del> wrapper 等。\n // pPr 不包含在内(由 PARAGRAPH_HEADER_MARKERS 排除)。\n const existingChildren = collectContentChildren(paragraph);\n\n // 2. 清掉所有内容子(保留 pPr)\n removeContentChildren(paragraph);\n\n // 3. 若有旧内容,整体包成 <w:del>(wrapRunsAsDelete 会 clone 并把 <w:t> 转 <w:delText>,\n // 锚点 marker 内部没 <w:t>,会被原样保留)\n if (existingChildren.length > 0) {\n const delId = allocateRevisionId(ctx.pkg);\n const delEl = wrapRunsAsDelete(existingChildren, delId, attrs);\n paragraph.appendChild(delEl);\n }\n\n // 4. 构建新 run 并包成 <w:ins>\n const doc = paragraph.ownerDocument;\n if (!doc) throw new WordError('PACKAGE_CORRUPT', 'paragraph has no ownerDocument', ctx.docId);\n const newRun = createW(doc, 'r');\n if (inheritedRPr) newRun.insertBefore(inheritedRPr, newRun.firstChild);\n appendSegmentsToRun(doc, newRun, op.text);\n const insId = allocateRevisionId(ctx.pkg);\n const insEl = wrapRunsAsInsert([newRun], insId, attrs);\n paragraph.appendChild(insEl);\n }\n}\n\n// ─────────── replaceTextInParagraph ───────────\n\nexport function executeReplaceTextInParagraph(\n ctx: ExecutorContext,\n op: Extract<Op, { type: 'replaceTextInParagraph' }>,\n): void {\n if (op.search.length === 0) {\n throw new WordError(\n 'TEXT_NOT_FOUND_IN_PARA',\n `replaceTextInParagraph: 'search' cannot be empty`,\n ctx.docId,\n { paraId: op.paraId, search: op.search },\n );\n }\n\n const paragraph = requireParagraph(ctx, op.paraId, 'replaceTextInParagraph');\n const runs = getParagraphRuns(paragraph);\n\n // 1. 构建段全文 + run 偏移映射(runIndex → [runStartOffset, runEndOffset))\n // 注意:getParagraphRuns 只看直属 <w:r>,跨 hyperlink / ins/del 包装的 run\n // 不被枚举 —— 本 PR 接受(复杂结构抛错)。\n const fullText = runs.map((r) => getRunText(r)).join('');\n\n // 2. 在全文查找所有匹配(first / all 决定取几个),按**倒序**处理 —— 先处理后段\n // 的匹配不影响前段的 run 偏移\n const matches = findMatches(fullText, op.search, op.scope);\n if (matches.length === 0) {\n throw new WordError(\n 'TEXT_NOT_FOUND_IN_PARA',\n `text '${op.search}' not found in paragraph ${op.paraId}`,\n ctx.docId,\n { paraId: op.paraId, search: op.search, scope: op.scope },\n );\n }\n\n // 3. 逐匹配替换(倒序)\n // 每次替换后段内 runs 变化(新增 / 删除),下一个匹配的 run 定位需要基于最新\n // 状态。最稳的做法:**每次替换后重扫 runs / fullText**。倒序处理确保前面\n // 的匹配偏移仍然有效(因为我们先改后面的)。\n const sortedMatches = matches.slice().sort((a, b) => b.start - a.start);\n for (const m of sortedMatches) {\n replaceOneMatch(ctx, paragraph, m, op);\n }\n\n markStoryPartDirty(ctx, paragraph, 'replaceTextInParagraph');\n}\n\nexport function executeFormatTextInParagraph(\n ctx: ExecutorContext,\n op: Extract<Op, { type: 'formatTextInParagraph' }>,\n): void {\n if (op.search.length === 0) {\n throw new WordError(\n 'TEXT_NOT_FOUND_IN_PARA',\n `formatTextInParagraph: 'search' cannot be empty`,\n ctx.docId,\n { paraId: op.paraId, search: op.search },\n );\n }\n validateTextFormat(ctx, op);\n if (ctx.options.trackChanges) {\n throw new WordError(\n 'UNSUPPORTED_OOXML_FEATURE',\n 'formatTextInParagraph does not support trackChanges yet',\n ctx.docId,\n { paraId: op.paraId, opType: 'formatTextInParagraph' },\n );\n }\n\n const paragraph = requireParagraph(ctx, op.paraId, 'formatTextInParagraph');\n const runs = getParagraphRuns(paragraph);\n const fullText = runs.map((r) => getRunText(r)).join('');\n const matches = findMatches(fullText, op.search, op.scope);\n if (matches.length === 0) {\n throw new WordError(\n 'TEXT_NOT_FOUND_IN_PARA',\n `text '${op.search}' not found in paragraph ${op.paraId}`,\n ctx.docId,\n { paraId: op.paraId, search: op.search, scope: op.scope },\n );\n }\n\n const sortedMatches = matches.slice().sort((a, b) => b.start - a.start);\n for (const m of sortedMatches) {\n formatOneMatch(ctx, paragraph, m, op);\n }\n\n markStoryPartDirty(ctx, paragraph, 'formatTextInParagraph');\n}\n\nexport function executeFormatParagraph(\n ctx: ExecutorContext,\n op: Extract<Op, { type: 'formatParagraph' }>,\n): void {\n if (ctx.options.trackChanges) {\n throw new WordError(\n 'UNSUPPORTED_OOXML_FEATURE',\n 'formatParagraph does not support trackChanges yet',\n ctx.docId,\n { paraId: op.paraId, opType: 'formatParagraph' },\n );\n }\n validateParagraphFormat(ctx, op);\n const paragraph = requireParagraph(ctx, op.paraId, 'formatParagraph');\n const pPr = ensureParagraphProperties(paragraph);\n\n if (op.format.alignment !== undefined) {\n removeDirectChildrenW(pPr, 'jc');\n const jc = createW(pPr.ownerDocument!, 'jc');\n jc.setAttributeNS(W_NS, 'w:val', op.format.alignment);\n pPr.insertBefore(jc, findPPrInsertRef(pPr, JC_AFTER_LOCALS));\n }\n\n if (op.format.spacing !== undefined) {\n const spacing = upsertDirectChildW(pPr, 'spacing', SPACING_AFTER_LOCALS);\n if (op.format.spacing.before !== undefined) {\n spacing.setAttributeNS(W_NS, 'w:before', String(op.format.spacing.before));\n }\n if (op.format.spacing.after !== undefined) {\n spacing.setAttributeNS(W_NS, 'w:after', String(op.format.spacing.after));\n }\n if (op.format.spacing.line !== undefined) {\n spacing.setAttributeNS(W_NS, 'w:line', String(op.format.spacing.line));\n }\n if (op.format.spacing.lineRule !== undefined) {\n spacing.setAttributeNS(W_NS, 'w:lineRule', op.format.spacing.lineRule);\n }\n }\n\n if (op.format.indent !== undefined) {\n const ind = upsertDirectChildW(pPr, 'ind', IND_AFTER_LOCALS);\n if (op.format.indent.left !== undefined) {\n ind.setAttributeNS(W_NS, 'w:left', String(op.format.indent.left));\n }\n if (op.format.indent.right !== undefined) {\n ind.setAttributeNS(W_NS, 'w:right', String(op.format.indent.right));\n }\n if (op.format.indent.firstLine !== undefined) {\n if (op.format.indent.firstLine < 0) {\n ind.removeAttributeNS(W_NS, 'firstLine');\n ind.removeAttribute('w:firstLine');\n ind.setAttributeNS(W_NS, 'w:hanging', String(Math.abs(op.format.indent.firstLine)));\n } else {\n ind.removeAttributeNS(W_NS, 'hanging');\n ind.removeAttribute('w:hanging');\n ind.setAttributeNS(W_NS, 'w:firstLine', String(op.format.indent.firstLine));\n }\n }\n }\n\n if (op.format.outlineLevel !== undefined) {\n const existing = firstDirectChildW(pPr, 'outlineLvl');\n if (existing) {\n existing.setAttributeNS(W_NS, 'w:val', String(op.format.outlineLevel));\n } else {\n const outlineLvl = createW(pPr.ownerDocument!, 'outlineLvl');\n outlineLvl.setAttributeNS(W_NS, 'w:val', String(op.format.outlineLevel));\n pPr.insertBefore(outlineLvl, findPPrInsertRef(pPr, OUTLINE_AFTER_LOCALS));\n }\n }\n\n if (op.format.pageBreakBefore !== undefined) {\n removeDirectChildrenW(pPr, 'pageBreakBefore');\n if (op.format.pageBreakBefore) {\n const pageBreakBefore = createW(pPr.ownerDocument!, 'pageBreakBefore');\n pPr.insertBefore(pageBreakBefore, findPPrInsertRef(pPr, PAGE_BREAK_BEFORE_AFTER_LOCALS));\n }\n }\n\n markStoryPartDirty(ctx, paragraph, 'formatParagraph');\n}\n\n// ─────────── 内部:查段 / 去内容 / 生成 run ───────────\n\nfunction requireParagraph(ctx: ExecutorContext, paraId: string, opName: string): Element {\n const el = ctx.indices.paraIdx.get(paraId.toUpperCase());\n if (!el) {\n throw new WordError(\n 'PARA_NOT_FOUND',\n `paragraph with paraId='${paraId}' not found (op: ${opName})`,\n ctx.docId,\n { paraId, opName },\n );\n }\n return el;\n}\n\n/**\n * 从 `<w:p>` 移除所有内容 / marker 子(保留 pPr)。\n * pPr 通常位置在最前,这里**按 localName 判断**,不依赖位置。\n *\n * @param keepInlineGraphics 若为 true,对含图形后代的 `<w:r>` 跳过(保留原位),\n * 同时保留锚点 marker(bookmarkStart/End、commentRangeStart/End、commentReference)。\n * 只删纯文字 run 和非 run 的非锚点内容子。默认 false(现有行为:全删)。\n */\nfunction removeContentChildren(paragraph: Element, keepInlineGraphics = false): void {\n const children = Array.from(paragraph.childNodes);\n for (const child of children) {\n if (child.nodeType !== 1) {\n // 非元素(文本节点等):统一移除\n paragraph.removeChild(child);\n continue;\n }\n const el = child as Element;\n if (el.namespaceURI === W_NS && PARAGRAPH_HEADER_MARKERS.has(el.localName ?? '')) {\n continue; // pPr 保留\n }\n if (keepInlineGraphics) {\n // keepInlineGraphics=true:含图形后代的 <w:r> 跳过不删\n if (el.namespaceURI === W_NS && el.localName === 'r' && isGraphicRun(el)) {\n continue;\n }\n // keepInlineGraphics=true:直属锚点 marker(bookmarkStart/End、commentRangeStart/End)保留\n if (el.namespaceURI === W_NS && PARAGRAPH_ANCHOR_MARKERS.has(el.localName ?? '')) {\n continue;\n }\n // keepInlineGraphics=true:包含 commentReference 的 <w:r>(commentReference 通常在 run 内)保留\n if (\n el.namespaceURI === W_NS &&\n el.localName === 'r' &&\n el.getElementsByTagNameNS(W_NS, 'commentReference').length > 0\n ) {\n continue;\n }\n }\n // 其它都删:内容 wrappers(纯文字 run / hyperlink / ins / del 等)+ 任何非 W_NS 元素\n paragraph.removeChild(child);\n }\n // 断言:keepInlineGraphics=false 时只剩 pPr(或空);keepInlineGraphics=true 时剩 pPr + 图形 run + 锚点 marker。\n // 调用方负责后续追加。\n void PARAGRAPH_CONTENT_ELEMENTS; // 仅用于文档意图,运行时不做 assert\n}\n\n/**\n * 收集段落直属子中所有\"内容子节点\"——除 pPr 之外的所有元素子。\n * 用于 trackChanges 模式下记录旧内容(之后整体包成 `<w:del>`):\n * - `<w:r>` 内容 run\n * - `<w:bookmarkStart>` / `<w:bookmarkEnd>` 等书签 marker\n * - `<w:commentRangeStart>` / `<w:commentRangeEnd>` / `<w:commentReference>` 批注 marker\n * - 已存在的 `<w:ins>` / `<w:del>` wrapper(覆盖性替换时一并裹进新 del)\n * - 任何非 W_NS 元素(SDT 等)\n * 与 `removeContentChildren` 的\"删谁\"集合保持一致(都跳过 pPr)。\n */\nfunction collectContentChildren(paragraph: Element): Element[] {\n const out: Element[] = [];\n const children = paragraph.childNodes;\n for (let i = 0; i < children.length; i++) {\n const c = children[i];\n if (!c || c.nodeType !== 1) continue;\n const el = c as Element;\n if (el.namespaceURI === W_NS && PARAGRAPH_HEADER_MARKERS.has(el.localName ?? '')) {\n continue; // pPr 跳过\n }\n out.push(el);\n }\n return out;\n}\n\n/**\n * keepInlineGraphics=true TC 分支:分离段内图形 run 和纯文字内容子。\n * 返回:\n * - textChildren: 所有非图形的内容子(会被包进 del)\n * - graphicRuns: 所有图形 run(保留原位,不进 del)\n */\nfunction separateGraphicAndTextChildren(paragraph: Element): {\n textChildren: Element[];\n graphicRuns: Element[];\n} {\n const textChildren: Element[] = [];\n const graphicRuns: Element[] = [];\n const children = paragraph.childNodes;\n for (let i = 0; i < children.length; i++) {\n const c = children[i];\n if (!c || c.nodeType !== 1) continue;\n const el = c as Element;\n if (el.namespaceURI === W_NS && PARAGRAPH_HEADER_MARKERS.has(el.localName ?? '')) {\n continue; // pPr 跳过\n }\n if (el.namespaceURI === W_NS && el.localName === 'r' && isGraphicRun(el)) {\n graphicRuns.push(el);\n } else {\n textChildren.push(el);\n }\n }\n return { textChildren, graphicRuns };\n}\n\n/**\n * 找到段内第一个图形 run 的 DOM 引用,作为 insertBefore 的锚点。\n * 用于 keepInlineGraphics=true 非 TC 模式:新文字 run 插在第一个图形 run 之前,\n * 保持\"文字在前、线条在后\"原序。\n *\n * 必须在 removeContentChildren 之前调用,此时图形 run 仍在 DOM 中。\n * 若无图形 run(段内无图形),返回 null(新 run appendchild 到末尾即可)。\n */\nfunction findFirstGraphicRunAnchor(paragraph: Element): Element | null {\n const children = paragraph.childNodes;\n for (let i = 0; i < children.length; i++) {\n const c = children[i];\n if (!c || c.nodeType !== 1) continue;\n const el = c as Element;\n if (el.namespaceURI === W_NS && PARAGRAPH_HEADER_MARKERS.has(el.localName ?? '')) {\n continue; // pPr 跳过\n }\n if (el.namespaceURI === W_NS && el.localName === 'r' && isGraphicRun(el)) {\n return el; // 找到第一个图形 run\n }\n }\n return null; // 无图形 run(纯文字段)\n}\n\n/**\n * 把文本追加为 run(s),插在 `graphicAnchor`(第一个图形 run)之前。\n * `graphicAnchor` 为 null 时退化为 appendChild(无图形 run,纯文字段)。\n * 用于 keepInlineGraphics=true 模式,保持\"新文字 run 在图形 run 之前\"的顺序。\n *\n * 实现:临时把所有图形 run 从段内移走,appendTextAsRuns 追加文字 run 到末尾,\n * 再把图形 run 放回。这样即使 appendTextAsRuns 生成多个 run(\\n → br)也正确。\n */\nfunction appendTextAsRunsAt(\n paragraph: Element,\n text: string,\n inheritedRPr: Element | undefined,\n graphicAnchor: Element | null,\n): void {\n if (graphicAnchor === null) {\n // 无图形 run(纯文字段):直接追加(等同于原有行为)\n appendTextAsRuns(paragraph, text, inheritedRPr);\n return;\n }\n\n // 收集 graphicAnchor 及其后的所有图形 run(已保留在 DOM 中的,需要暂时移走)\n const graphicRuns: Element[] = [];\n let cur: Node | null = graphicAnchor;\n while (cur) {\n if (cur.nodeType === 1) {\n const el = cur as Element;\n if (el.namespaceURI === W_NS && el.localName === 'r' && isGraphicRun(el)) {\n graphicRuns.push(el);\n }\n }\n cur = cur.nextSibling;\n }\n\n // 临时把图形 run 移走(detach),appendTextAsRuns 追加文字,再 re-attach\n for (const gr of graphicRuns) {\n paragraph.removeChild(gr);\n }\n appendTextAsRuns(paragraph, text, inheritedRPr);\n for (const gr of graphicRuns) {\n paragraph.appendChild(gr);\n }\n}\n\n// appendTextAsRuns / createW / firstDirectChildW 已提出到 _shared.ts(#29 重构)\n\nfunction markStoryPartDirty(ctx: ExecutorContext, paragraph: Element, opName: string): void {\n const story = findStoryFor(ctx.pkg, paragraph);\n if (!story) {\n // 理论上不该发生:段在 paraIdx 但不在任何 story —— 说明装载期状态异常\n throw new WordError(\n 'PACKAGE_CORRUPT',\n `paragraph element not found in any story (op: ${opName})`,\n ctx.docId,\n { opName },\n );\n }\n const part = getPart(ctx.pkg, story.partPath);\n if (!part) {\n throw new WordError(\n 'PACKAGE_CORRUPT',\n `story part '${story.partPath}' not found in pkg (op: ${opName})`,\n ctx.docId,\n { opName, partPath: story.partPath },\n );\n }\n markDirty(part);\n}\n\nconst PAGE_BREAK_BEFORE_AFTER_LOCALS = new Set([\n 'framePr',\n 'widowControl',\n 'suppressLineNumbers',\n 'pBdr',\n 'shd',\n 'tabs',\n 'suppressAutoHyphens',\n 'kinsoku',\n 'wordWrap',\n 'overflowPunct',\n 'topLinePunct',\n 'autoSpaceDE',\n 'autoSpaceDN',\n 'bidi',\n 'adjustRightInd',\n 'snapToGrid',\n 'spacing',\n 'ind',\n 'contextualSpacing',\n 'mirrorIndents',\n 'suppressOverlap',\n 'jc',\n 'textDirection',\n 'textAlignment',\n 'textboxTightWrap',\n 'outlineLvl',\n 'divId',\n 'cnfStyle',\n 'rPr',\n 'sectPr',\n 'pPrChange',\n 'numPr',\n]);\n\nconst SPACING_AFTER_LOCALS = new Set([\n 'ind',\n 'contextualSpacing',\n 'mirrorIndents',\n 'suppressOverlap',\n 'jc',\n 'textDirection',\n 'textAlignment',\n 'textboxTightWrap',\n 'outlineLvl',\n 'divId',\n 'cnfStyle',\n 'rPr',\n 'sectPr',\n 'pPrChange',\n]);\n\nconst IND_AFTER_LOCALS = new Set([\n 'contextualSpacing',\n 'mirrorIndents',\n 'suppressOverlap',\n 'jc',\n 'textDirection',\n 'textAlignment',\n 'textboxTightWrap',\n 'outlineLvl',\n 'divId',\n 'cnfStyle',\n 'rPr',\n 'sectPr',\n 'pPrChange',\n]);\n\nconst JC_AFTER_LOCALS = new Set([\n 'textDirection',\n 'textAlignment',\n 'textboxTightWrap',\n 'outlineLvl',\n 'divId',\n 'cnfStyle',\n 'rPr',\n 'sectPr',\n 'pPrChange',\n]);\n\nconst OUTLINE_AFTER_LOCALS = new Set(['rPr', 'sectPr', 'pPrChange', 'divId', 'cnfStyle']);\n\nfunction validateParagraphFormat(\n ctx: ExecutorContext,\n op: Extract<Op, { type: 'formatParagraph' }>,\n): void {\n if (\n op.format.alignment === undefined &&\n op.format.outlineLevel === undefined &&\n op.format.pageBreakBefore === undefined &&\n op.format.indent === undefined &&\n op.format.spacing === undefined\n ) {\n throw new WordError(\n 'INVALID_ARGUMENT',\n 'formatParagraph requires at least one format field',\n ctx.docId,\n { paraId: op.paraId, opType: 'formatParagraph' },\n );\n }\n if (\n op.format.alignment !== undefined &&\n !['left', 'center', 'right', 'both', 'distribute'].includes(op.format.alignment)\n ) {\n throw new WordError(\n 'INVALID_ARGUMENT',\n 'formatParagraph alignment must be left, center, right, both, or distribute',\n ctx.docId,\n { paraId: op.paraId, alignment: op.format.alignment, opType: 'formatParagraph' },\n );\n }\n if (\n op.format.outlineLevel !== undefined &&\n (!Number.isInteger(op.format.outlineLevel) ||\n op.format.outlineLevel < 0 ||\n op.format.outlineLevel > 8)\n ) {\n throw new WordError(\n 'INVALID_ARGUMENT',\n 'formatParagraph outlineLevel must be an integer from 0 to 8',\n ctx.docId,\n { paraId: op.paraId, outlineLevel: op.format.outlineLevel, opType: 'formatParagraph' },\n );\n }\n if (op.format.indent !== undefined) {\n validateOptionalTwips(ctx, op.paraId, 'indent.left', op.format.indent.left);\n validateOptionalTwips(ctx, op.paraId, 'indent.right', op.format.indent.right);\n validateOptionalTwips(ctx, op.paraId, 'indent.firstLine', op.format.indent.firstLine);\n }\n if (op.format.spacing !== undefined) {\n validateOptionalTwips(ctx, op.paraId, 'spacing.before', op.format.spacing.before);\n validateOptionalTwips(ctx, op.paraId, 'spacing.after', op.format.spacing.after);\n validateOptionalTwips(ctx, op.paraId, 'spacing.line', op.format.spacing.line);\n if (\n op.format.spacing.lineRule !== undefined &&\n !['auto', 'exact', 'atLeast'].includes(op.format.spacing.lineRule)\n ) {\n throw new WordError(\n 'INVALID_ARGUMENT',\n 'formatParagraph spacing.lineRule must be auto, exact, or atLeast',\n ctx.docId,\n { paraId: op.paraId, lineRule: op.format.spacing.lineRule, opType: 'formatParagraph' },\n );\n }\n }\n}\n\nfunction validateOptionalTwips(\n ctx: ExecutorContext,\n paraId: string,\n name: string,\n value: number | undefined,\n): void {\n if (value === undefined) return;\n if (!Number.isInteger(value)) {\n throw new WordError(\n 'INVALID_ARGUMENT',\n `formatParagraph ${name} must be an integer twip value`,\n ctx.docId,\n { paraId, value, opType: 'formatParagraph', field: name },\n );\n }\n}\n\nfunction ensureParagraphProperties(paragraph: Element): Element {\n const existing = firstDirectChildW(paragraph, 'pPr');\n if (existing) return existing;\n const pPr = createW(paragraph.ownerDocument!, 'pPr');\n paragraph.insertBefore(pPr, paragraph.firstChild);\n return pPr;\n}\n\nfunction removeDirectChildrenW(parent: Element, localName: string): void {\n const toRemove: Element[] = [];\n for (let i = 0; i < parent.childNodes.length; i++) {\n const child = parent.childNodes[i];\n if (\n child?.nodeType === 1 &&\n (child as Element).namespaceURI === W_NS &&\n (child as Element).localName === localName\n ) {\n toRemove.push(child as Element);\n }\n }\n for (const child of toRemove) {\n parent.removeChild(child);\n }\n}\n\nfunction upsertDirectChildW(parent: Element, localName: string, afterLocals: Set<string>): Element {\n const existing = firstDirectChildW(parent, localName);\n if (existing) return existing;\n const child = createW(parent.ownerDocument!, localName);\n parent.insertBefore(child, findPPrInsertRef(parent, afterLocals));\n return child;\n}\n\nfunction findPPrInsertRef(pPr: Element, afterLocals: Set<string>): Element | null {\n for (let i = 0; i < pPr.childNodes.length; i++) {\n const child = pPr.childNodes[i];\n if (\n child?.nodeType === 1 &&\n (child as Element).namespaceURI === W_NS &&\n afterLocals.has((child as Element).localName)\n ) {\n return child as Element;\n }\n }\n return null;\n}\n\n// ─────────── replaceTextInParagraph:匹配 + 替换 ───────────\n\ninterface Match {\n start: number;\n end: number;\n}\n\nfunction findMatches(text: string, search: string, scope: 'first' | 'all'): Match[] {\n const out: Match[] = [];\n let from = 0;\n while (from <= text.length) {\n const idx = text.indexOf(search, from);\n if (idx < 0) break;\n out.push({ start: idx, end: idx + search.length });\n if (scope === 'first') break;\n from = idx + search.length;\n }\n return out;\n}\n\n/** 替换单个匹配。流程:\n * 1. 重扫当前 runs(因上一次替换可能已变)\n * 2. 找匹配 start 所在 run + run 内偏移 → splitRunAt 切出 startInnerRun\n * 3. 找匹配 end 所在 run + 偏移 → splitRunAt 切出 endInnerRun\n * 4. 收集 [startInnerRun, endInnerRun] 之间所有 run(同级兄弟)\n * 5. 删除这些 run,插入用首 run rPr 深拷贝的新 run(内容来自 replacement)\n */\nfunction replaceOneMatch(\n ctx: ExecutorContext,\n paragraph: Element,\n match: Match,\n op: Extract<Op, { type: 'replaceTextInParagraph' }>,\n): void {\n const runs = getParagraphRuns(paragraph);\n // 构造 (runIndex, runText, cumulativeStart)\n const runSpans: Array<{ run: Element; start: number; end: number }> = [];\n let cursor = 0;\n for (const r of runs) {\n const len = getRunText(r).length;\n runSpans.push({ run: r, start: cursor, end: cursor + len });\n cursor += len;\n }\n\n // 找 match.start 落在的 run:span 的 [start, end)\n const startSpan = runSpans.find((s) => match.start >= s.start && match.start < s.end);\n // match.end 可能恰好等于某个 span 的 end,允许 match.end === s.end\n const endSpan = runSpans.find((s) => match.end > s.start && match.end <= s.end);\n if (!startSpan || !endSpan) {\n throw new WordError(\n 'UNSUPPORTED_OOXML_FEATURE',\n `replaceTextInParagraph: match spans runs not reachable via direct <w:r> enumeration ` +\n `(possibly wrapped in hyperlink/ins/del). paraId=${op.paraId}`,\n ctx.docId,\n { paraId: op.paraId, opType: 'replaceTextInParagraph' },\n );\n }\n\n // 在 startSpan 的 offset = match.start - startSpan.start 切;在 endSpan 的\n // offset = match.end - endSpan.start 切。注意顺序:先切 end 再切 start,避免\n // start 切分改变 endSpan 的 element 引用(若两者同 run,之后需重找)。\n const sameRun = startSpan.run === endSpan.run;\n\n // A host roundtrip may coalesce text separated by `<w:tab/>` into one run with\n // multiple `<w:t>` children. If the match itself stays inside one text child,\n // replace that child in place: this preserves tabs, drawings, and the run format\n // without asking splitRunAt to split the surrounding complex run.\n if (sameRun && !ctx.options.trackChanges && !/[\\r\\n\\t]/.test(op.replacement)) {\n const startOffset = match.start - startSpan.start;\n const endOffset = match.end - startSpan.start;\n let textOffset = 0;\n const children = startSpan.run.childNodes;\n for (let i = 0; i < children.length; i++) {\n const child = children[i];\n if (\n !child ||\n child.nodeType !== 1 ||\n (child as Element).namespaceURI !== W_NS ||\n (child as Element).localName !== 't'\n ) {\n continue;\n }\n const t = child as Element;\n const value = t.textContent ?? '';\n const textEnd = textOffset + value.length;\n if (startOffset >= textOffset && endOffset <= textEnd) {\n const localStart = startOffset - textOffset;\n const localEnd = endOffset - textOffset;\n t.textContent = value.slice(0, localStart) + op.replacement + value.slice(localEnd);\n t.setAttributeNS(XML_NS, 'xml:space', 'preserve');\n return;\n }\n textOffset = textEnd;\n }\n }\n\n // 切 end 点(若同 run,start 的后半经过切后成为\"待删 run\"的 matchRun)\n const endOffset = match.end - endSpan.start;\n let startRunForMatch: Element;\n let endRunForMatch: Element;\n\n try {\n if (sameRun) {\n // 同 run 场景:先在 endOffset 切,得到 [原 run=leftpart+matchpart, 新 run=rightpart]\n // 然后在原 run 内再切 startOffset,得到 [左半, 匹配部分]\n const { after: rightAfterEnd } = splitRunAt(startSpan.run, endOffset);\n // 此时 startSpan.run 的文本为 [span.start, match.end)\n // 再在原 run 的 match.start 偏移处切\n const startOffsetInRun = match.start - startSpan.start;\n const { after: matchRun } = splitRunAt(startSpan.run, startOffsetInRun);\n // matchRun 是仅含 match 的 run;若没切出(startOffset=0),则 startSpan.run 本身就是 matchRun\n startRunForMatch = matchRun ?? startSpan.run;\n endRunForMatch = startRunForMatch;\n // rightAfterEnd 是 end 之后的 run(可能是 null,如果 match.end == span.end)\n void rightAfterEnd;\n } else {\n // 跨 run:分别切 startSpan(在 startOffset 处,保留左半,切出右半=匹配的首 run)\n // 和 endSpan(在 endOffset 处,保留右半,左半=匹配的末 run)\n const startOffsetInRun = match.start - startSpan.start;\n const { after: afterStart } = splitRunAt(startSpan.run, startOffsetInRun);\n startRunForMatch = afterStart ?? startSpan.run;\n\n // endSpan 可能是一个没被上面切过的 run;若是,offset 就是 match.end - endSpan.start\n // 若同一次调用 startSpan === endSpan 已由 sameRun 分支处理\n const { before: leftOfEnd } = splitRunAt(endSpan.run, endOffset);\n endRunForMatch = leftOfEnd;\n }\n } catch (e) {\n // splitRunAt 抛错(如复杂 run:多 <w:t> / <w:br>)→ 规范化为 UNSUPPORTED_OOXML_FEATURE\n const msg = e instanceof Error ? e.message : String(e);\n throw new WordError(\n 'UNSUPPORTED_OOXML_FEATURE',\n `replaceTextInParagraph: run structure too complex to split (${msg}). paraId=${op.paraId}`,\n ctx.docId,\n { paraId: op.paraId, opType: 'replaceTextInParagraph' },\n );\n }\n\n // 5. 收集 [startRunForMatch ... endRunForMatch] 之间所有 sibling run(都在 paragraph 直属层)\n const toRemove: Element[] = [];\n {\n let cur: Node | null = startRunForMatch;\n while (cur) {\n if (cur.nodeType === 1) toRemove.push(cur as Element);\n if (cur === endRunForMatch) break;\n cur = cur.nextSibling;\n }\n if (toRemove.length === 0 || toRemove[toRemove.length - 1] !== endRunForMatch) {\n // 末节点没在兄弟链里遇到 —— 理论不可能,保险抛\n throw new WordError(\n 'UNSUPPORTED_OOXML_FEATURE',\n `replaceTextInParagraph: could not walk from start to end run. paraId=${op.paraId}`,\n ctx.docId,\n { paraId: op.paraId, opType: 'replaceTextInParagraph' },\n );\n }\n }\n\n // 5a. ANCHOR_CONFLICT 检测(#30):仅在非 trackChanges 模式拦截。\n // trackChanges=true 时,锚点 marker 会随 toRemove 一起被包进 <w:del>(wrapRunsAsDelete\n // 不碰非 <w:t> 子,保留原结构),与 Word/WPS 原生 trackChanges 行为一致——\n // 用户接受 → 文本+锚点一起删;拒绝 → 一起恢复。\n if (!ctx.options.trackChanges) {\n const rangeAnchors = collectRangeAnchors(startRunForMatch, endRunForMatch);\n if (rangeAnchors.bookmarks.length > 0 || rangeAnchors.comments.length > 0) {\n throw new WordError(\n 'ANCHOR_CONFLICT',\n `formatTextInParagraph conflicts with active anchors (paraId=${op.paraId})`,\n ctx.docId,\n {\n paraId: op.paraId,\n affectedBookmarks: rangeAnchors.bookmarks,\n affectedComments: rangeAnchors.comments,\n opType: 'replaceTextInParagraph',\n },\n );\n }\n }\n\n // 6. 用首 run 的 rPr 深拷贝 + replacement 组装新 run。\n // replacement 为空表示纯删除,不应额外产生一个空 <w:ins> 修订。\n const hasReplacement = op.replacement.length > 0;\n const newRun = hasReplacement\n ? buildReplacementRun(paragraph, startRunForMatch, op.replacement)\n : null;\n\n const parent = paragraph;\n const insertionPoint = toRemove[0]!;\n\n if (ctx.options.trackChanges) {\n // trackChanges=true:匹配区间包成 <w:del>,新 run 包成 <w:ins>\n const attrs: RevisionAttrs = { author: ctx.options.author, date: ctx.options.date };\n const delId = allocateRevisionId(ctx.pkg);\n const delEl = wrapRunsAsDelete(toRemove, delId, attrs);\n\n // 先在匹配区间位置插入 del;有 replacement 时再插入 ins。\n parent.insertBefore(delEl, insertionPoint);\n if (newRun) {\n const insId = allocateRevisionId(ctx.pkg);\n const insEl = wrapRunsAsInsert([newRun], insId, attrs);\n parent.insertBefore(insEl, insertionPoint);\n }\n // 删掉原始匹配 runs\n for (const r of toRemove) {\n parent.removeChild(r);\n }\n } else {\n // 7. 插入到 toRemove[0] 之前,再把 toRemove 全删\n if (newRun) parent.insertBefore(newRun, insertionPoint);\n for (const r of toRemove) {\n parent.removeChild(r);\n }\n }\n}\n\nfunction formatOneMatch(\n ctx: ExecutorContext,\n paragraph: Element,\n match: Match,\n op: Extract<Op, { type: 'formatTextInParagraph' }>,\n): void {\n const runs = getParagraphRuns(paragraph);\n const runSpans: Array<{ run: Element; start: number; end: number }> = [];\n let cursor = 0;\n for (const r of runs) {\n const len = getRunText(r).length;\n runSpans.push({ run: r, start: cursor, end: cursor + len });\n cursor += len;\n }\n\n const startSpan = runSpans.find((s) => match.start >= s.start && match.start < s.end);\n const endSpan = runSpans.find((s) => match.end > s.start && match.end <= s.end);\n if (!startSpan || !endSpan) {\n throw new WordError(\n 'UNSUPPORTED_OOXML_FEATURE',\n `formatTextInParagraph: match spans runs not reachable via direct <w:r> enumeration ` +\n `(possibly wrapped in hyperlink/ins/del). paraId=${op.paraId}`,\n ctx.docId,\n { paraId: op.paraId, opType: 'formatTextInParagraph' },\n );\n }\n\n const sameRun = startSpan.run === endSpan.run;\n const endOffset = match.end - endSpan.start;\n let startRunForMatch: Element;\n let endRunForMatch: Element;\n\n try {\n if (sameRun) {\n const { after: rightAfterEnd } = splitRunAt(startSpan.run, endOffset);\n const startOffsetInRun = match.start - startSpan.start;\n const { after: matchRun } = splitRunAt(startSpan.run, startOffsetInRun);\n startRunForMatch = matchRun ?? startSpan.run;\n endRunForMatch = startRunForMatch;\n void rightAfterEnd;\n } else {\n const startOffsetInRun = match.start - startSpan.start;\n const { after: afterStart } = splitRunAt(startSpan.run, startOffsetInRun);\n startRunForMatch = afterStart ?? startSpan.run;\n\n const { before: leftOfEnd } = splitRunAt(endSpan.run, endOffset);\n endRunForMatch = leftOfEnd;\n }\n } catch (e) {\n const msg = e instanceof Error ? e.message : String(e);\n throw new WordError(\n 'UNSUPPORTED_OOXML_FEATURE',\n `formatTextInParagraph: run structure too complex to split (${msg}). paraId=${op.paraId}`,\n ctx.docId,\n { paraId: op.paraId, opType: 'formatTextInParagraph' },\n );\n }\n\n const matchedRuns: Element[] = [];\n {\n let cur: Node | null = startRunForMatch;\n while (cur) {\n if (cur.nodeType === 1) matchedRuns.push(cur as Element);\n if (cur === endRunForMatch) break;\n cur = cur.nextSibling;\n }\n if (matchedRuns.length === 0 || matchedRuns[matchedRuns.length - 1] !== endRunForMatch) {\n throw new WordError(\n 'UNSUPPORTED_OOXML_FEATURE',\n `formatTextInParagraph: could not walk from start to end run. paraId=${op.paraId}`,\n ctx.docId,\n { paraId: op.paraId, opType: 'formatTextInParagraph' },\n );\n }\n }\n\n if (!ctx.options.trackChanges) {\n const rangeAnchors = collectRangeAnchors(startRunForMatch, endRunForMatch);\n if (rangeAnchors.bookmarks.length > 0 || rangeAnchors.comments.length > 0) {\n throw new WordError(\n 'ANCHOR_CONFLICT',\n `paragraph modification conflicts with active anchors (paraId=${op.paraId}); ` +\n `enable trackChanges to wrap the deletion as a revision`,\n ctx.docId,\n {\n paraId: op.paraId,\n affectedBookmarks: rangeAnchors.bookmarks,\n affectedComments: rangeAnchors.comments,\n opType: 'formatTextInParagraph',\n },\n );\n }\n }\n\n for (const run of matchedRuns) {\n applyRunFormat(run, op.format);\n }\n}\n\nfunction buildReplacementRun(paragraph: Element, seedRun: Element, replacement: string): Element {\n const doc = paragraph.ownerDocument!;\n const run = createW(doc, 'r');\n\n // 继承 rPr(深拷贝,避免共享引用)\n const seedRPr = firstDirectChildW(seedRun, 'rPr');\n if (seedRPr) {\n run.appendChild(seedRPr.cloneNode(true));\n }\n\n appendSegmentsToRun(doc, run, replacement);\n return run;\n}\n\n// firstDirectChildW / appendTextAsRuns / createW 已提出到 _shared.ts(#29 重构)\nfunction validateTextFormat(\n ctx: ExecutorContext,\n op: Extract<Op, { type: 'formatTextInParagraph' }>,\n): void {\n if (\n op.format.bold === undefined &&\n op.format.color === undefined &&\n op.format.italic === undefined &&\n op.format.underline === undefined &&\n op.format.highlight === undefined &&\n op.format.fontSize === undefined &&\n op.format.fontFamily === undefined\n ) {\n throw new WordError(\n 'INVALID_ARGUMENT',\n 'formatTextInParagraph requires at least one format field',\n ctx.docId,\n { paraId: op.paraId, opType: 'formatTextInParagraph' },\n );\n }\n if (\n op.format.color !== undefined &&\n op.format.color !== 'auto' &&\n !/^[0-9A-Fa-f]{6}$/.test(op.format.color)\n ) {\n throw new WordError(\n 'INVALID_ARGUMENT',\n 'formatTextInParagraph color must be \"auto\" or a 6-digit RRGGBB value',\n ctx.docId,\n { paraId: op.paraId, color: op.format.color, opType: 'formatTextInParagraph' },\n );\n }\n if (op.format.highlight !== undefined && !/^[A-Za-z]+$/.test(op.format.highlight)) {\n throw new WordError(\n 'INVALID_ARGUMENT',\n 'formatTextInParagraph highlight must be a Word highlight color name',\n ctx.docId,\n { paraId: op.paraId, highlight: op.format.highlight, opType: 'formatTextInParagraph' },\n );\n }\n if (\n op.format.fontSize !== undefined &&\n (!Number.isFinite(op.format.fontSize) || op.format.fontSize <= 0)\n ) {\n throw new WordError(\n 'INVALID_ARGUMENT',\n 'formatTextInParagraph fontSize must be a positive point value',\n ctx.docId,\n { paraId: op.paraId, fontSize: op.format.fontSize, opType: 'formatTextInParagraph' },\n );\n }\n if (op.format.fontFamily !== undefined && op.format.fontFamily.trim() === '') {\n throw new WordError(\n 'INVALID_ARGUMENT',\n 'formatTextInParagraph fontFamily cannot be empty',\n ctx.docId,\n { paraId: op.paraId, opType: 'formatTextInParagraph' },\n );\n }\n}\n\nfunction applyRunFormat(\n run: Element,\n format: {\n bold?: boolean;\n color?: string;\n italic?: boolean;\n underline?: boolean;\n highlight?: string;\n fontSize?: number;\n fontFamily?: string;\n },\n): void {\n const rPr = ensureRunProperties(run);\n if (format.bold !== undefined) {\n replaceRunProperty(rPr, 'b', (el) => {\n if (!format.bold) el.setAttributeNS(W_NS, 'w:val', '0');\n });\n }\n if (format.italic !== undefined) {\n replaceRunProperty(rPr, 'i', (el) => {\n if (!format.italic) el.setAttributeNS(W_NS, 'w:val', '0');\n });\n }\n if (format.underline !== undefined) {\n replaceRunProperty(rPr, 'u', (el) => {\n el.setAttributeNS(W_NS, 'w:val', format.underline ? 'single' : 'none');\n });\n }\n if (format.color !== undefined) {\n removeRunProperties(rPr, W14_NS, 'textFill');\n replaceRunProperty(rPr, 'color', (el) => {\n el.setAttributeNS(W_NS, 'w:val', format.color!);\n });\n }\n if (format.highlight !== undefined) {\n replaceRunProperty(rPr, 'highlight', (el) => {\n el.setAttributeNS(W_NS, 'w:val', format.highlight!);\n });\n }\n if (format.fontSize !== undefined) {\n replaceRunProperty(rPr, 'sz', (el) => {\n el.setAttributeNS(W_NS, 'w:val', String(Math.round(format.fontSize! * 2)));\n });\n }\n if (format.fontFamily !== undefined) {\n replaceRunProperty(rPr, 'rFonts', (el) => {\n const family = format.fontFamily!;\n el.setAttributeNS(W_NS, 'w:ascii', family);\n el.setAttributeNS(W_NS, 'w:hAnsi', family);\n el.setAttributeNS(W_NS, 'w:eastAsia', family);\n el.setAttributeNS(W_NS, 'w:cs', family);\n });\n }\n}\n\nfunction ensureRunProperties(run: Element): Element {\n const existing = firstDirectChildW(run, 'rPr');\n if (existing) return existing;\n const rPr = createW(run.ownerDocument!, 'rPr');\n run.insertBefore(rPr, run.firstChild);\n return rPr;\n}\n\nfunction replaceRunProperty(\n rPr: Element,\n localName: 'b' | 'i' | 'u' | 'color' | 'highlight' | 'sz' | 'rFonts',\n configure: (el: Element) => void,\n): void {\n removeRunProperties(rPr, W_NS, localName);\n const el = createW(rPr.ownerDocument!, localName);\n configure(el);\n rPr.appendChild(el);\n}\n\nfunction removeRunProperties(rPr: Element, namespaceURI: string, localName: string): void {\n const existing: Element[] = [];\n for (let i = 0; i < rPr.childNodes.length; i++) {\n const child = rPr.childNodes[i];\n if (\n child?.nodeType === 1 &&\n (child as Element).namespaceURI === namespaceURI &&\n (child as Element).localName === localName\n ) {\n existing.push(child as Element);\n }\n }\n for (const child of existing) {\n rPr.removeChild(child);\n }\n}\n","/**\n * 书签 executor —— #34(createBookmark / deleteBookmark)。\n *\n * 设计要点:\n * - 段枚举走 paraIdx(O(1));bookmarkIdx 做重名检查(O(1))\n * - w:id 分配:扫全包所有 part 的 <w:bookmarkStart> 取 max(w:id)+1,\n * 跨 part 保证 id 唯一(W_NS 枚举,禁用无谓词 XPath)\n * - ParagraphRange:bookmarkStart 置于 pPr 之后、Run 之前;bookmarkEnd 置于段末尾\n * - TextRange:走 splitRunAt 切 run 后插 start/end(复杂 run → UNSUPPORTED_OOXML_FEATURE)\n * - trackChanges=true:本 PR 拒绝(#31 再做)\n * - 校验:name 正则 `^[A-Za-z_][A-Za-z0-9_]{0,39}$`;重名 → BOOKMARK_NAME_EXISTS\n * - deleteBookmark:移除 start + end element,markDirty 对应 part\n * - 索引同步:executor 内同步更新 bookmarkIdx(add/delete)\n */\nimport { getPart, isXmlPart, listParts, markDirty } from '../../pack/index.js';\nimport { W_NS } from '../namespaces.js';\nimport type { Op } from '../plan.js';\nimport { getParagraphRuns, getRunText, splitRunAt } from '../runs.js';\nimport { WordError } from '../word-error.js';\nimport type { ExecutorContext } from './executor-context.js';\n\n// 书签名合法正则:首字符为字母或下划线,后跟最多 39 个字母/数字/下划线 → 总长 1..40\nconst BOOKMARK_NAME_RE = /^[A-Za-z_][A-Za-z0-9_]{0,39}$/;\n\n// ─────────── createBookmark ───────────\n\nexport function executeCreateBookmark(\n ctx: ExecutorContext,\n op: Extract<Op, { type: 'createBookmark' }>,\n): void {\n // 1. trackChanges 拒绝(#31)\n if (ctx.options.trackChanges) {\n throw new WordError(\n 'UNSUPPORTED_OOXML_FEATURE',\n 'createBookmark with trackChanges=true not yet implemented (see #31)',\n ctx.docId,\n { opType: 'createBookmark', name: op.name },\n );\n }\n\n // 2. 校验 name\n validateBookmarkName(ctx, op.name);\n\n // 3. 重名检查\n if (ctx.indices.bookmarkIdx.has(op.name)) {\n throw new WordError(\n 'BOOKMARK_NAME_EXISTS',\n `bookmark name '${op.name}' already exists`,\n ctx.docId,\n { name: op.name },\n );\n }\n\n // 4. 查 paraId 段\n const range = op.range;\n const paraId = range.paraId.toUpperCase();\n const paragraph = ctx.indices.paraIdx.get(paraId);\n if (!paragraph) {\n throw new WordError(\n 'PARA_NOT_FOUND',\n `paragraph with paraId='${op.range.paraId}' not found (op: createBookmark)`,\n ctx.docId,\n { paraId: op.range.paraId, opName: 'createBookmark' },\n );\n }\n\n // 5. 分配 w:id(跨全 pkg 所有 part)\n const newId = allocateBookmarkId(ctx);\n\n // 6. 分 ParagraphRange / TextRange 插入\n const doc = paragraph.ownerDocument;\n if (!doc) {\n throw new WordError('PACKAGE_CORRUPT', 'paragraph element has no ownerDocument', ctx.docId);\n }\n\n let startEl: Element;\n let endEl: Element;\n\n if (isTextRange(range)) {\n // TextRange:splitRunAt 模式\n const result = insertTextRangeBookmark(ctx, doc, paragraph, op.name, newId, range.text);\n startEl = result.start;\n endEl = result.end;\n } else {\n // ParagraphRange:包住整段内容\n startEl = createBookmarkStart(doc, op.name, newId);\n endEl = createBookmarkEnd(doc, newId);\n insertParagraphRangeBookmark(paragraph, startEl, endEl);\n }\n\n // 7. 更新 ApplyResult\n // createBookmark 一定落在单段内(ParagraphRange 包整段、TextRange 走 splitRunAt 也\n // 不跨段,见本文件 §insertTextRangeBookmark),所以 from === to。\n ctx.result.createdBookmarks.push({\n opIndex: ctx.opIndex,\n name: op.name,\n range: { fromParaId: op.range.paraId, toParaId: op.range.paraId },\n });\n\n // 8. 更新索引\n const partPath = findPartPathForElement(ctx, paragraph);\n ctx.indices.bookmarkIdx.set(op.name, { start: startEl, end: endEl, partPath });\n\n // 9. markDirty\n markPartDirtyByPath(ctx, partPath, 'createBookmark');\n}\n\n// ─────────── deleteBookmark ───────────\n\nexport function executeDeleteBookmark(\n ctx: ExecutorContext,\n op: Extract<Op, { type: 'deleteBookmark' }>,\n): void {\n // 1. trackChanges 拒绝(#31)\n if (ctx.options.trackChanges) {\n throw new WordError(\n 'UNSUPPORTED_OOXML_FEATURE',\n 'deleteBookmark with trackChanges=true not yet implemented (see #31)',\n ctx.docId,\n { opType: 'deleteBookmark', name: op.name },\n );\n }\n\n // 2. 查 bookmarkIdx\n const entry = ctx.indices.bookmarkIdx.get(op.name);\n if (!entry) {\n throw new WordError('BOOKMARK_NOT_FOUND', `bookmark '${op.name}' not found`, ctx.docId, {\n name: op.name,\n });\n }\n\n // 3. 移除 bookmarkStart\n const startParent = entry.start.parentNode;\n if (startParent) {\n startParent.removeChild(entry.start);\n }\n\n // 4. 移除 bookmarkEnd(若存在)\n if (entry.end) {\n const endParent = entry.end.parentNode;\n if (endParent) {\n endParent.removeChild(entry.end);\n }\n }\n\n // 5. 更新索引\n ctx.indices.bookmarkIdx.delete(op.name);\n\n // 6. markDirty 对应 part\n markPartDirtyByPath(ctx, entry.partPath, 'deleteBookmark');\n}\n\n// ─────────── 内部:校验 ───────────\n\nfunction validateBookmarkName(ctx: ExecutorContext, name: string): void {\n if (name.length === 0) {\n throw new WordError('BOOKMARK_NAME_INVALID', 'bookmark name cannot be empty', ctx.docId, {\n name,\n });\n }\n if (name.length > 40) {\n throw new WordError(\n 'BOOKMARK_NAME_INVALID',\n `bookmark name is too long (${name.length} chars, max 40)`,\n ctx.docId,\n { name, length: name.length },\n );\n }\n if (!BOOKMARK_NAME_RE.test(name)) {\n throw new WordError(\n 'BOOKMARK_NAME_INVALID',\n `bookmark name '${name}' contains invalid characters or starts with an invalid character (must match /^[A-Za-z_][A-Za-z0-9_]{0,39}$/)`,\n ctx.docId,\n { name },\n );\n }\n}\n\n// ─────────── 内部:id 分配 ───────────\n\n/** 扫全 pkg 所有 part 的 bookmarkStart w:id,返回 max+1(起点 0) */\nfunction allocateBookmarkId(ctx: ExecutorContext): number {\n let maxId = -1;\n for (const part of listParts(ctx.pkg)) {\n if (!isXmlPart(part) || !part.xmlDom) continue;\n const starts = part.xmlDom.getElementsByTagNameNS(W_NS, 'bookmarkStart');\n for (let i = 0; i < starts.length; i++) {\n const el = starts[i]!;\n const idStr = el.getAttributeNS(W_NS, 'id');\n if (idStr === null) continue;\n const n = parseInt(idStr, 10);\n if (!isNaN(n) && n > maxId) maxId = n;\n }\n }\n return maxId + 1;\n}\n\n// ─────────── 内部:元素创建 ───────────\n\nfunction createBookmarkStart(doc: Document, name: string, id: number): Element {\n const el = doc.createElementNS(W_NS, 'w:bookmarkStart');\n el.setAttributeNS(W_NS, 'w:id', String(id));\n el.setAttributeNS(W_NS, 'w:name', name);\n return el;\n}\n\nfunction createBookmarkEnd(doc: Document, id: number): Element {\n const el = doc.createElementNS(W_NS, 'w:bookmarkEnd');\n el.setAttributeNS(W_NS, 'w:id', String(id));\n return el;\n}\n\n// ─────────── 内部:ParagraphRange 插入 ───────────\n\n/**\n * ParagraphRange 插入:\n * - bookmarkStart 放在 pPr 之后,第一个内容节点之前\n * - bookmarkEnd 放在段的最后一个子节点之后\n */\nfunction insertParagraphRangeBookmark(paragraph: Element, startEl: Element, endEl: Element): void {\n // 找到 pPr 之后的第一个内容节点作为插入点\n const insertBefore = findContentInsertPoint(paragraph);\n if (insertBefore) {\n paragraph.insertBefore(startEl, insertBefore);\n } else {\n // 段落完全为空(无 pPr 也无内容):追加到末尾\n paragraph.appendChild(startEl);\n }\n // end 追加到最后\n paragraph.appendChild(endEl);\n}\n\n/**\n * 找到第一个\"内容\"插入点:pPr 之后、第一个非 pPr 元素之前。\n * 返回 null 表示段落除 pPr 外无其他子节点。\n */\nfunction findContentInsertPoint(paragraph: Element): Node | null {\n const children = paragraph.childNodes;\n let pastPPr = false;\n for (let i = 0; i < children.length; i++) {\n const child = children[i]!;\n if (child.nodeType !== 1) continue;\n const el = child as Element;\n if (el.namespaceURI === W_NS && el.localName === 'pPr') {\n pastPPr = true;\n continue;\n }\n // 第一个非 pPr 元素\n if (pastPPr || i === 0) {\n return child;\n }\n }\n return null;\n}\n\n// ─────────── 内部:TextRange 插入 ───────────\n\nfunction isTextRange(range: {\n paraId: string;\n text?: string;\n}): range is { paraId: string; text: string; scope?: string } {\n return typeof (range as { text?: string }).text === 'string';\n}\n\ninterface TextRangeBookmarkResult {\n start: Element;\n end: Element;\n}\n\n/**\n * TextRange 书签插入:\n * 1. 拼段内所有 <w:r> 的 <w:t> 文本\n * 2. indexOf 找第一处 match\n * 3. splitRunAt 切出 matchRun 范围\n * 4. 在 matchRun[0] 之前插 bookmarkStart,在 matchRun[last] 之后插 bookmarkEnd\n */\nfunction insertTextRangeBookmark(\n ctx: ExecutorContext,\n doc: Document,\n paragraph: Element,\n name: string,\n id: number,\n searchText: string,\n): TextRangeBookmarkResult {\n const runs = getParagraphRuns(paragraph);\n\n // 构建全文 + run 偏移映射\n const runSpans: Array<{ run: Element; start: number; end: number }> = [];\n let cursor = 0;\n for (const r of runs) {\n const len = getRunText(r).length;\n runSpans.push({ run: r, start: cursor, end: cursor + len });\n cursor += len;\n }\n const fullText = runSpans.map((s) => getRunText(s.run)).join('');\n\n // indexOf 找第一处\n const matchStart = fullText.indexOf(searchText);\n if (matchStart < 0) {\n throw new WordError(\n 'TEXT_NOT_FOUND_IN_PARA',\n `text '${searchText}' not found in paragraph (op: createBookmark)`,\n ctx.docId,\n { name, text: searchText },\n );\n }\n const matchEnd = matchStart + searchText.length;\n\n // 找 match.start 落在的 run\n const startSpan = runSpans.find((s) => matchStart >= s.start && matchStart < s.end);\n // match.end 可能恰好等于某个 span 的 end\n const endSpan = runSpans.find((s) => matchEnd > s.start && matchEnd <= s.end);\n\n if (!startSpan || !endSpan) {\n throw new WordError(\n 'UNSUPPORTED_OOXML_FEATURE',\n `createBookmark TextRange: match spans runs not reachable via direct <w:r> enumeration`,\n ctx.docId,\n { name, text: searchText, opType: 'createBookmark' },\n );\n }\n\n const sameRun = startSpan.run === endSpan.run;\n\n let startRunForMark: Element;\n let endRunForMark: Element;\n\n try {\n if (sameRun) {\n const endOffset = matchEnd - endSpan.start;\n // 先切 end\n splitRunAt(startSpan.run, endOffset);\n // 再切 start(此时 startSpan.run 文本为 [span.start, matchEnd))\n const startOffsetInRun = matchStart - startSpan.start;\n const { after: matchRun } = splitRunAt(startSpan.run, startOffsetInRun);\n startRunForMark = matchRun ?? startSpan.run;\n endRunForMark = startRunForMark;\n } else {\n // 跨 run:切 startSpan(取右半),切 endSpan(取左半)\n const startOffsetInRun = matchStart - startSpan.start;\n const { after: afterStart } = splitRunAt(startSpan.run, startOffsetInRun);\n startRunForMark = afterStart ?? startSpan.run;\n\n const endOffset = matchEnd - endSpan.start;\n const { before: leftOfEnd } = splitRunAt(endSpan.run, endOffset);\n endRunForMark = leftOfEnd;\n }\n } catch (e) {\n const msg = e instanceof Error ? e.message : String(e);\n throw new WordError(\n 'UNSUPPORTED_OOXML_FEATURE',\n `createBookmark TextRange: run structure too complex to split (${msg})`,\n ctx.docId,\n { name, text: searchText, opType: 'createBookmark' },\n );\n }\n\n // 插入 bookmarkStart 在 startRunForMark 之前\n const startEl = createBookmarkStart(doc, name, id);\n const endEl = createBookmarkEnd(doc, id);\n\n paragraph.insertBefore(startEl, startRunForMark);\n\n // 插入 bookmarkEnd 在 endRunForMark 之后\n const afterEndRun = endRunForMark.nextSibling;\n if (afterEndRun) {\n paragraph.insertBefore(endEl, afterEndRun);\n } else {\n paragraph.appendChild(endEl);\n }\n\n return { start: startEl, end: endEl };\n}\n\n// ─────────── 内部:part 定位 / markDirty ───────────\n\n/** 从 paraIdx 或 Element 的 ownerDocument 反查 partPath */\nfunction findPartPathForElement(ctx: ExecutorContext, el: Element): string {\n // 遍历 pkg.parts,找 xmlDom 包含此 element 的 part\n for (const part of listParts(ctx.pkg)) {\n if (!isXmlPart(part) || !part.xmlDom) continue;\n if (\n part.xmlDom.documentElement &&\n part.xmlDom.documentElement.contains(el as unknown as Node)\n ) {\n return part.path;\n }\n }\n throw new WordError('PACKAGE_CORRUPT', 'element not found in any part', ctx.docId);\n}\n\nfunction markPartDirtyByPath(ctx: ExecutorContext, partPath: string, opName: string): void {\n const part = getPart(ctx.pkg, partPath);\n if (!part) {\n throw new WordError(\n 'PACKAGE_CORRUPT',\n `part '${partPath}' not found in pkg (op: ${opName})`,\n ctx.docId,\n { partPath, opName },\n );\n }\n markDirty(part);\n}\n\n// ─────────── 跨段书签创建(供 paragraph-structure-ops 复用,#176)───────────\n\n/** 命名规则前缀的合法字符:首字符 letter/`_`,后续 letter/digit/`_`(无长度上限) */\nconst BOOKMARK_PREFIX_RE = /^[A-Za-z_][A-Za-z0-9_]*$/;\n\n/** 重名时追加后缀的最大尝试次数(防御性上限,正常场景 1~2 次足够)*/\nconst NAME_COLLISION_MAX_TRIES = 1000;\n\n/**\n * 解析\"插入段同时建跨段书签\"的规则化命名。\n *\n * 公式:`${prefix}_${anchorParaId}`,与已有书签同名时追加 `_2`/`_3`/... 后缀。\n *\n * 校验:\n * - prefix 匹配 `BOOKMARK_PREFIX_RE`,否则 `BOOKMARK_NAME_INVALID`\n * - 最终名长度 ≤ 40,否则 `BOOKMARK_NAME_INVALID`(与 createBookmark 一致)\n * - 1000 次后仍冲突抛 `BOOKMARK_NAME_EXISTS`(实际不可能触发,防止极端场景死循环)\n */\nexport function resolveAppendBookmarkName(\n ctx: ExecutorContext,\n prefix: string,\n anchorParaId: string,\n): string {\n if (!BOOKMARK_PREFIX_RE.test(prefix)) {\n throw new WordError(\n 'BOOKMARK_NAME_INVALID',\n `bookmark prefix '${prefix}' must match /^[A-Za-z_][A-Za-z0-9_]*$/`,\n ctx.docId,\n { prefix },\n );\n }\n\n const base = `${prefix}_${anchorParaId}`;\n\n // 第一次尝试:基底名\n let candidate = base;\n let suffix = 2;\n while (ctx.indices.bookmarkIdx.has(candidate)) {\n if (suffix > NAME_COLLISION_MAX_TRIES) {\n throw new WordError(\n 'BOOKMARK_NAME_EXISTS',\n `bookmark name resolution gave up after ${NAME_COLLISION_MAX_TRIES} attempts (base='${base}')`,\n ctx.docId,\n { prefix, anchorParaId, base },\n );\n }\n candidate = `${base}_${suffix}`;\n suffix += 1;\n }\n\n // 长度校验放在解析之后 —— 含后缀的最终名才是要写进 OOXML 的串\n if (candidate.length > 40) {\n throw new WordError(\n 'BOOKMARK_NAME_INVALID',\n `resolved bookmark name '${candidate}' exceeds 40-char OOXML limit`,\n ctx.docId,\n { prefix, anchorParaId, resolvedName: candidate, length: candidate.length },\n );\n }\n\n return candidate;\n}\n\n/**\n * 在 anchor 段头与 newPara 段尾之间建立跨段书签(#176)。\n *\n * 调用前置条件:\n * - anchor 与 newPara 在同一 part 内(insertParagraphAfter 把 newPara 作为 anchor\n * 下一兄弟插入,因此天然成立)\n * - trackChanges=false(本路径不支持修订包装,与 createBookmark 一致)\n *\n * 副作用:\n * - 在 anchor 段 pPr 之后插 `<w:bookmarkStart>`\n * - 在 newPara 末尾插 `<w:bookmarkEnd>`\n * - 更新 `ctx.indices.bookmarkIdx`\n * - push 一条 `{ opIndex, name, range }` 到 `ctx.result.createdBookmarks`\n * - markDirty 对应 part(若调用方已 markDirty,重复调用是幂等的)\n */\nexport function createCrossParagraphBookmark(\n ctx: ExecutorContext,\n name: string,\n anchor: Element,\n newPara: Element,\n fromParaId: string,\n toParaId: string,\n): void {\n // trackChanges 守卫(insertParagraphAfter 自身在 trackChanges 下也能跑;此处单独\n // 拒绝跨段书签,与 createBookmark 现状一致;LLM/skill 见到 UNSUPPORTED 错误后\n // 自行降级即可)。\n if (ctx.options.trackChanges) {\n throw new WordError(\n 'UNSUPPORTED_OOXML_FEATURE',\n 'insertParagraphAfter with bookmark + trackChanges=true not yet implemented',\n ctx.docId,\n { name, opType: 'insertParagraphAfter' },\n );\n }\n\n validateBookmarkName(ctx, name);\n\n // 重名兜底:resolveAppendBookmarkName 已避免,但若调用路径变了仍报错\n if (ctx.indices.bookmarkIdx.has(name)) {\n throw new WordError(\n 'BOOKMARK_NAME_EXISTS',\n `bookmark name '${name}' already exists`,\n ctx.docId,\n { name },\n );\n }\n\n const doc = anchor.ownerDocument;\n if (!doc) {\n throw new WordError('PACKAGE_CORRUPT', 'anchor paragraph has no ownerDocument', ctx.docId);\n }\n\n const id = allocateBookmarkId(ctx);\n\n // bookmarkStart 放在 anchor 段 pPr 之后、第一个内容节点之前(若全空就 append)\n const startEl = createBookmarkStart(doc, name, id);\n const insertBefore = findContentInsertPoint(anchor);\n if (insertBefore) {\n anchor.insertBefore(startEl, insertBefore);\n } else {\n anchor.appendChild(startEl);\n }\n\n // bookmarkEnd 放在 newPara 末尾\n const endEl = createBookmarkEnd(doc, id);\n newPara.appendChild(endEl);\n\n // 索引同步\n const partPath = findPartPathForElement(ctx, anchor);\n ctx.indices.bookmarkIdx.set(name, { start: startEl, end: endEl, partPath });\n\n // ApplyResult\n ctx.result.createdBookmarks.push({\n opIndex: ctx.opIndex,\n name,\n range: { fromParaId, toParaId },\n });\n\n // anchor 与 newPara 同 part,structure-op 的 markDirty 已经覆盖,这里 markDirty\n // 是幂等的(markDirty 重复调用安全)。显式调用一次,避免依赖调用顺序。\n markPartDirtyByPath(ctx, partPath, 'insertParagraphAfter:bookmark');\n}\n","/**\n * 批注 executor —— #35(addComment / deleteComment)。\n *\n * 设计要点:\n * - 跨 parts 事务:addComment 同时变更 body part + comments.xml +\n * [Content_Types].xml + word/_rels/document.xml.rels(首次加批注时后两者)。\n * 所有 part 变更在同一 runTransaction 范围内,由 kernel.collectAffectedPartPaths\n * 预声明,外层回滚时一同还原。\n * - commentId 分配:扫描 pkg 内所有 <w:comment> 的 w:id + 所有 commentRangeStart\n * 的 w:id,取 max + 1(起点 0)。全 pkg 唯一,不依赖装载期 commentIdx(运行时\n * 追加场景下 commentIdx 未同步)。\n * - scope='all' TextRange:本 PR 抛 UNSUPPORTED_OOXML_FEATURE,留 follow-up。\n * - deleteComment:三锚点按需移除(null 跳过);ref 所在 wrapper <w:r> 若变空则\n * 也整体删除(避免悬空空 run)。\n * - comments.xml 删完最后一条时,移除空 part + 清 CT Override + 清 rels Relationship\n (ensureCommentsPart 的对称反向操作;task-comment-part-cleanup)。\n */\nimport { parseXmlDocument } from 'slimdom';\nimport {\n getPart,\n createXmlPart,\n setPart,\n markDirty,\n isXmlPart,\n deletePart,\n} from '../../pack/index.js';\nimport { findStoryFor } from '../stories.js';\nimport { W_NS, W14_NS, XML_NS } from '../namespaces.js';\nimport type { Op, Range } from '../plan.js';\nimport { getParagraphRuns, getRunText, splitRunAt } from '../runs.js';\nimport { WordError } from '../word-error.js';\nimport type { ExecutorContext } from './executor-context.js';\n\n// ─────────── 常量 ───────────\n\nconst COMMENTS_PART_PATH = 'word/comments.xml';\nconst COMMENTS_CONTENT_TYPE =\n 'application/vnd.openxmlformats-officedocument.wordprocessingml.comments+xml';\nconst COMMENTS_RELATIONSHIP_TYPE =\n 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/comments';\nconst CONTENT_TYPES_PATH = '[Content_Types].xml';\nconst CONTENT_TYPES_NS = 'http://schemas.openxmlformats.org/package/2006/content-types';\nconst RELS_NS = 'http://schemas.openxmlformats.org/package/2006/relationships';\nconst DOC_RELS_PATH = 'word/_rels/document.xml.rels';\n\n// ─────────── addComment ───────────\n\nexport function executeAddComment(\n ctx: ExecutorContext,\n op: Extract<Op, { type: 'addComment' }>,\n): void {\n if (ctx.options.trackChanges) {\n throw new WordError(\n 'UNSUPPORTED_OOXML_FEATURE',\n 'addComment with trackChanges=true not yet implemented (see #31)',\n ctx.docId,\n { opType: 'addComment' },\n );\n }\n\n // TextRange scope='all' 暂不支持(留 follow-up)\n if (isTextRange(op.range) && op.range.scope === 'all') {\n throw new WordError(\n 'UNSUPPORTED_OOXML_FEATURE',\n \"addComment: scope='all' is not yet implemented for TextRange (pending follow-up issue)\",\n ctx.docId,\n { opType: 'addComment', scope: 'all' },\n );\n }\n\n // 1. 查目标段落\n const paragraph = requireParagraph(ctx, op.range.paraId, 'addComment');\n\n // 2-7. 走共享路径(挂段级锚点 + 写主体 + dirty)\n const commentId = attachCommentToParagraph(ctx, paragraph, op.text, {\n range: op.range,\n author: op.author,\n date: op.date,\n });\n\n // 8. 记录 ApplyResult\n ctx.result.createdComments.push({ opIndex: ctx.opIndex, commentId });\n}\n\n/**\n * 给指定段落挂批注 —— addComment / addTableComment 共享核心。\n *\n * 调用方约定:\n * - 已自行校验 paragraph 存在;trackChanges 守护也由调用方负责(addTableComment\n * 语义和 addComment 相同,本函数本身不再二次拦截)\n * - 不写 ApplyResult,由调用方决定要不要往 createdComments 里 push(addTableComment\n * 的 commentId 不返回给调用方,只用于内部锚点串联)\n * - range 缺省时按 ParagraphRange 处理(把整段挂作锚点,符合 addTableComment 的\n * \"挂在表格首段\"语义)\n *\n * 返回新分配的 commentId,供调用方按需上报。\n */\nexport function attachCommentToParagraph(\n ctx: ExecutorContext,\n paragraph: Element,\n text: string,\n opts: {\n range?: Range;\n author?: string;\n /** ISO 8601 字符串 */\n date?: string;\n } = {},\n): number {\n const paraId = paragraph.getAttributeNS(W14_NS, 'paraId') ?? '';\n const range: Range = opts.range ?? { paraId };\n\n const commentId = allocateCommentId(ctx);\n\n const author = opts.author ?? ctx.options.author ?? '';\n const dateStr = opts.date ?? ctx.options.date.toISOString();\n const initials = author.length > 0 ? author[0]! : '';\n\n const wasNew = ensureCommentsPart(ctx);\n\n const commentsPart = getPart(ctx.pkg, COMMENTS_PART_PATH)!;\n if (!isXmlPart(commentsPart) || !commentsPart.xmlDom) {\n throw new WordError('PACKAGE_CORRUPT', 'comments.xml part is not an XML part', ctx.docId);\n }\n const commentsDoc = commentsPart.xmlDom;\n\n // body 侧锚点:复用 addComment 的逻辑入口\n insertBodyAnchors(ctx, paragraph, { type: 'addComment', range, text }, commentId);\n\n insertCommentBody(commentsDoc, commentId, author, dateStr, initials, text);\n\n markBodyPartDirty(ctx, paragraph);\n markDirty(commentsPart);\n void wasNew;\n\n return commentId;\n}\n\n// ─────────── deleteComment ───────────\n\nexport function executeDeleteComment(\n ctx: ExecutorContext,\n op: Extract<Op, { type: 'deleteComment' }>,\n): void {\n if (ctx.options.trackChanges) {\n throw new WordError(\n 'UNSUPPORTED_OOXML_FEATURE',\n 'deleteComment with trackChanges=true not yet implemented (see #31)',\n ctx.docId,\n { opType: 'deleteComment' },\n );\n }\n\n // 1. 查 commentIdx\n const entry = ctx.indices.commentIdx.get(op.commentId);\n if (!entry) {\n throw new WordError(\n 'COMMENT_NOT_FOUND',\n `comment with id=${op.commentId} not found`,\n ctx.docId,\n { commentId: op.commentId },\n );\n }\n\n // 2. 移除三锚点\n const { start, end, ref } = entry.anchors;\n\n // 确定 body part(用于 markDirty);从存在的锚点反查\n const anchorEl = start ?? end ?? ref;\n let bodyPartPath: string | null = null;\n if (anchorEl) {\n const story = findStoryFor(ctx.pkg, anchorEl);\n if (story) bodyPartPath = story.partPath;\n }\n\n if (start) removeFromParent(start);\n if (end) removeFromParent(end);\n if (ref) {\n // ref 可能包在一个 <w:r> 里;若移除 ref 后 run 只剩 rPr(或变空),删掉整个 run\n const parentRun = ref.parentNode;\n removeFromParent(ref);\n if (\n parentRun &&\n parentRun.nodeType === 1 &&\n (parentRun as Element).namespaceURI === W_NS &&\n (parentRun as Element).localName === 'r'\n ) {\n // 检查 run 是否还有非 rPr 的有意义子元素\n if (isRunEffectivelyEmpty(parentRun as Element)) {\n removeFromParent(parentRun as Element);\n }\n }\n }\n\n // 3. 移除 <w:comment> 主体\n if (entry.comment) {\n removeFromParent(entry.comment);\n const commentsPart = getPart(ctx.pkg, COMMENTS_PART_PATH);\n if (commentsPart) markDirty(commentsPart);\n }\n\n // 4. markDirty body part\n if (bodyPartPath) {\n const bodyPart = getPart(ctx.pkg, bodyPartPath);\n if (bodyPart) markDirty(bodyPart);\n }\n\n // 5. 若 comments.xml 已无任何 <w:comment>,移除空 part + 清理 CT/rels 悬空引用\n cleanupEmptyCommentsPart(ctx);\n}\n\n// ─────────── 内部:comments part 清理(ensureCommentsPart 的对称反向)───────────\n\n/**\n * 若 comments.xml 还剩 0 个 `<w:comment>`,执行反向清理:\n * 1. deletePart(comments.xml)\n * 2. 删 [Content_Types].xml 里 PartName=\"/word/comments.xml\" 的 Override\n * 3. 删 word/_rels/document.xml.rels 里 Type=…/comments 的 Relationship\n *\n * 幂等:part 已不存在 / Override 已无 / rel 已无 → 各自跳过,不报错。\n *\n * 导出供 paragraph-structure-ops / table-ops 的 dropCommentById 调用(drop 路径同样\n * 需要在删光最后一条批注后清 part/CT/rels)。\n */\nexport function cleanupEmptyCommentsPart(ctx: ExecutorContext): void {\n const cp = getPart(ctx.pkg, COMMENTS_PART_PATH);\n if (!cp || !isXmlPart(cp) || !cp.xmlDom) return;\n // 还有 <w:comment> 就不清\n const remaining = cp.xmlDom.getElementsByTagNameNS(W_NS, 'comment').length;\n if (remaining > 0) return;\n // 空了:移除 part + 反向清 CT / rels\n deletePart(ctx.pkg, COMMENTS_PART_PATH);\n removeContentTypesOverride(ctx);\n removeDocRel(ctx);\n}\n\nfunction removeContentTypesOverride(ctx: ExecutorContext): void {\n const ctPart = getPart(ctx.pkg, CONTENT_TYPES_PATH);\n if (!ctPart || !isXmlPart(ctPart) || !ctPart.xmlDom) return;\n const overrides = ctPart.xmlDom.getElementsByTagNameNS(CONTENT_TYPES_NS, 'Override');\n // 快照后删(live collection)\n const victims: Element[] = [];\n for (let i = 0; i < overrides.length; i++) {\n const el = overrides[i];\n if (el && el.getAttribute('PartName') === '/word/comments.xml') victims.push(el);\n }\n for (const el of victims) removeFromParent(el);\n if (victims.length > 0) markDirty(ctPart);\n}\n\nfunction removeDocRel(ctx: ExecutorContext): void {\n const relsPart = getPart(ctx.pkg, DOC_RELS_PATH);\n if (!relsPart || !isXmlPart(relsPart) || !relsPart.xmlDom) return;\n const rels = relsPart.xmlDom.getElementsByTagNameNS(RELS_NS, 'Relationship');\n const victims: Element[] = [];\n for (let i = 0; i < rels.length; i++) {\n const el = rels[i];\n if (el && el.getAttribute('Type') === COMMENTS_RELATIONSHIP_TYPE) victims.push(el);\n }\n for (const el of victims) removeFromParent(el);\n if (victims.length > 0) markDirty(relsPart);\n}\n\n// ─────────── 内部:commentId 分配 ───────────\n\n/**\n * 扫整个 pkg 所有 XML part 的 <w:comment> w:id + <w:commentRangeStart> w:id,取 max+1。\n * 基于全 pkg 扫描,而非 commentIdx(运行时追加场景下 commentIdx 仍是装载时快照)。\n */\nfunction allocateCommentId(ctx: ExecutorContext): number {\n let max = -1;\n for (const part of ctx.pkg.parts.values()) {\n if (!isXmlPart(part) || !part.xmlDom) continue;\n const comments = part.xmlDom.getElementsByTagNameNS(W_NS, 'comment');\n for (let i = 0; i < comments.length; i++) {\n const v = numAttr(comments[i]!, W_NS, 'id');\n if (v !== null && v > max) max = v;\n }\n const starts = part.xmlDom.getElementsByTagNameNS(W_NS, 'commentRangeStart');\n for (let i = 0; i < starts.length; i++) {\n const v = numAttr(starts[i]!, W_NS, 'id');\n if (v !== null && v > max) max = v;\n }\n }\n return max + 1;\n}\n\n// ─────────── 内部:确保 comments.xml 存在,首次时更新 CT / rels ───────────\n\n/**\n * 若 comments.xml 不存在,创建最小结构并更新 Content_Types + rels。\n * 返回 true 表示本次首次创建(调用方据此决定是否 markDirty CT/rels)。\n */\nfunction ensureCommentsPart(ctx: ExecutorContext): boolean {\n if (ctx.pkg.parts.has(COMMENTS_PART_PATH)) return false;\n\n // 创建 comments.xml\n const xml =\n `<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\\n` + `<w:comments xmlns:w=\"${W_NS}\"/>`;\n const dom = parseXmlDocument(xml) as unknown as Document;\n const newPart = createXmlPart({\n path: COMMENTS_PART_PATH,\n contentType: COMMENTS_CONTENT_TYPE,\n xmlDom: dom,\n // 不传 originalBytes → dirty=true(新建 part 需要序列化)\n });\n setPart(ctx.pkg, newPart);\n\n // 更新 Content_Types.xml\n updateContentTypes(ctx);\n\n // 更新 word/_rels/document.xml.rels\n updateDocRels(ctx);\n\n return true;\n}\n\nfunction updateContentTypes(ctx: ExecutorContext): void {\n const ctPart = getPart(ctx.pkg, CONTENT_TYPES_PATH);\n if (!ctPart || !isXmlPart(ctPart) || !ctPart.xmlDom) return;\n\n const doc = ctPart.xmlDom;\n // 检查是否已有 Override for comments.xml\n const overrides = doc.getElementsByTagNameNS(CONTENT_TYPES_NS, 'Override');\n for (let i = 0; i < overrides.length; i++) {\n const el = overrides[i]!;\n if (el.getAttribute('PartName') === '/word/comments.xml') return; // 已存在\n }\n\n // 追加 Override\n const root = doc.documentElement;\n const override = doc.createElementNS(CONTENT_TYPES_NS, 'Override');\n override.setAttribute('PartName', '/word/comments.xml');\n override.setAttribute('ContentType', COMMENTS_CONTENT_TYPE);\n root.appendChild(override);\n markDirty(ctPart);\n}\n\nfunction updateDocRels(ctx: ExecutorContext): void {\n const relsPart = getPart(ctx.pkg, DOC_RELS_PATH);\n if (!relsPart || !isXmlPart(relsPart) || !relsPart.xmlDom) return;\n\n const doc = relsPart.xmlDom;\n // 检查是否已有 comments rel\n const rels = doc.getElementsByTagNameNS(RELS_NS, 'Relationship');\n for (let i = 0; i < rels.length; i++) {\n if (rels[i]!.getAttribute('Type') === COMMENTS_RELATIONSHIP_TYPE) return; // 已存在\n }\n\n // 分配新 rId:扫所有 Id=\"rId\\d+\" 取 max+1\n let maxRId = 0;\n for (let i = 0; i < rels.length; i++) {\n const id = rels[i]!.getAttribute('Id') ?? '';\n const m = /^rId(\\d+)$/.exec(id);\n if (m) {\n const n = parseInt(m[1]!, 10);\n if (n > maxRId) maxRId = n;\n }\n }\n const newRId = `rId${maxRId + 1}`;\n\n const root = doc.documentElement;\n const rel = doc.createElementNS(RELS_NS, 'Relationship');\n rel.setAttribute('Id', newRId);\n rel.setAttribute('Type', COMMENTS_RELATIONSHIP_TYPE);\n rel.setAttribute('Target', 'comments.xml');\n root.appendChild(rel);\n markDirty(relsPart);\n}\n\n// ─────────── 内部:body 锚点插入 ───────────\n\nfunction insertBodyAnchors(\n ctx: ExecutorContext,\n paragraph: Element,\n op: Extract<Op, { type: 'addComment' }>,\n commentId: number,\n): void {\n const doc = paragraph.ownerDocument!;\n const range = op.range;\n\n if (isTextRange(range)) {\n insertTextRangeAnchors(ctx, paragraph, doc, range, commentId);\n } else {\n insertParagraphRangeAnchors(paragraph, doc, commentId);\n }\n}\n\n/**\n * ParagraphRange:段起始(紧跟 pPr 之后)插 commentRangeStart,\n * 段末插 commentRangeEnd + <w:r><w:commentReference></w:r>。\n */\nfunction insertParagraphRangeAnchors(paragraph: Element, doc: Document, commentId: number): void {\n const rangeStart = createCommentAnchor(doc, 'commentRangeStart', commentId);\n const rangeEnd = createCommentAnchor(doc, 'commentRangeEnd', commentId);\n const refRun = createCommentRefRun(doc, commentId);\n\n // rangeStart:紧跟 pPr 之后;若无 pPr 则插到 firstChild\n const pPr = firstDirectChildW(paragraph, 'pPr');\n if (pPr && pPr.nextSibling) {\n paragraph.insertBefore(rangeStart, pPr.nextSibling);\n } else if (pPr) {\n paragraph.appendChild(rangeStart);\n } else {\n paragraph.insertBefore(rangeStart, paragraph.firstChild);\n }\n\n // rangeEnd + refRun:追加到段末\n paragraph.appendChild(rangeEnd);\n paragraph.appendChild(refRun);\n}\n\n/**\n * TextRange:找段内第一个命中的文本区间,在 run 边界插入锚点。\n * scope='all' 已在调用方提前拒绝。\n */\nfunction insertTextRangeAnchors(\n ctx: ExecutorContext,\n paragraph: Element,\n doc: Document,\n range: { paraId: string; text: string; scope?: 'first' | 'all' },\n commentId: number,\n): void {\n const runs = getParagraphRuns(paragraph);\n const fullText = runs.map((r) => getRunText(r)).join('');\n const searchText = range.text;\n\n if (searchText.length === 0) {\n throw new WordError(\n 'TEXT_NOT_FOUND_IN_PARA',\n `addComment: 'range.text' cannot be empty`,\n ctx.docId,\n { paraId: range.paraId },\n );\n }\n\n const matchStart = fullText.indexOf(searchText);\n if (matchStart < 0) {\n throw new WordError(\n 'TEXT_NOT_FOUND_IN_PARA',\n `addComment: text '${searchText}' not found in paragraph ${range.paraId}`,\n ctx.docId,\n { paraId: range.paraId, search: searchText },\n );\n }\n const matchEnd = matchStart + searchText.length;\n\n // 构造 (run, runStart, runEnd) 映射\n const runSpans: Array<{ run: Element; start: number; end: number }> = [];\n let cursor = 0;\n for (const r of runs) {\n const len = getRunText(r).length;\n runSpans.push({ run: r, start: cursor, end: cursor + len });\n cursor += len;\n }\n\n const startSpan = runSpans.find((s) => matchStart >= s.start && matchStart < s.end);\n const endSpan = runSpans.find((s) => matchEnd > s.start && matchEnd <= s.end);\n\n if (!startSpan || !endSpan) {\n throw new WordError(\n 'UNSUPPORTED_OOXML_FEATURE',\n `addComment: text match spans runs not reachable via direct <w:r> enumeration. paraId=${range.paraId}`,\n ctx.docId,\n { paraId: range.paraId, opType: 'addComment' },\n );\n }\n\n // 切 start run:在 matchStart - startSpan.start 处切\n const startOffsetInRun = matchStart - startSpan.start;\n let firstMatchRun: Element;\n try {\n if (startOffsetInRun === 0) {\n firstMatchRun = startSpan.run;\n } else {\n const { after } = splitRunAt(startSpan.run, startOffsetInRun);\n firstMatchRun = after ?? startSpan.run;\n }\n } catch (e) {\n const msg = e instanceof Error ? e.message : String(e);\n throw new WordError(\n 'UNSUPPORTED_OOXML_FEATURE',\n `addComment: run too complex to split at start (${msg}). paraId=${range.paraId}`,\n ctx.docId,\n { paraId: range.paraId, opType: 'addComment' },\n );\n }\n\n // 切 end run:在 matchEnd - endSpan.start 处切(需重查,因为 startSpan.run 可能已变)\n // 如果 start 和 end 在同一 run 且 start 切分了,endSpan.run 引用还是旧的 run\n // 需要判断:若 startSpan.run === endSpan.run 且 startOffsetInRun > 0,endSpan 已被切成 firstMatchRun\n let lastMatchRun: Element;\n try {\n const endRunCurrent =\n startSpan.run === endSpan.run && startOffsetInRun > 0 ? firstMatchRun : endSpan.run;\n // matchEnd 在 endRunCurrent 内的偏移:\n // 若同 run 且 start>0 切了:endRunCurrent 从 matchStart 开始,所以 matchEnd 相对其起点\n // = matchEnd - matchStart\n // 否则:matchEnd - endSpan.start\n const endOffsetInRun =\n startSpan.run === endSpan.run && startOffsetInRun > 0\n ? matchEnd - matchStart\n : matchEnd - endSpan.start;\n\n if (endOffsetInRun >= getRunText(endRunCurrent).length) {\n // 恰好到 run 末尾,不需要切\n lastMatchRun = endRunCurrent;\n } else {\n const { before } = splitRunAt(endRunCurrent, endOffsetInRun);\n lastMatchRun = before;\n }\n } catch (e) {\n const msg = e instanceof Error ? e.message : String(e);\n throw new WordError(\n 'UNSUPPORTED_OOXML_FEATURE',\n `addComment: run too complex to split at end (${msg}). paraId=${range.paraId}`,\n ctx.docId,\n { paraId: range.paraId, opType: 'addComment' },\n );\n }\n\n // 插入锚点:rangeStart 在 firstMatchRun 之前,rangeEnd + refRun 在 lastMatchRun 之后\n const rangeStart = createCommentAnchor(doc, 'commentRangeStart', commentId);\n const rangeEnd = createCommentAnchor(doc, 'commentRangeEnd', commentId);\n const refRun = createCommentRefRun(doc, commentId);\n\n paragraph.insertBefore(rangeStart, firstMatchRun);\n\n const afterLastRun = lastMatchRun.nextSibling;\n if (afterLastRun) {\n paragraph.insertBefore(rangeEnd, afterLastRun);\n paragraph.insertBefore(refRun, afterLastRun);\n } else {\n paragraph.appendChild(rangeEnd);\n paragraph.appendChild(refRun);\n }\n}\n\n// ─────────── 内部:comment 主体插入 ───────────\n\nfunction insertCommentBody(\n commentsDoc: Document,\n commentId: number,\n author: string,\n date: string,\n initials: string,\n text: string,\n): void {\n const comment = commentsDoc.createElementNS(W_NS, 'w:comment');\n comment.setAttributeNS(W_NS, 'w:id', String(commentId));\n comment.setAttributeNS(W_NS, 'w:author', author);\n comment.setAttributeNS(W_NS, 'w:date', date);\n if (initials) comment.setAttributeNS(W_NS, 'w:initials', initials);\n\n // 批注正文:按 \\n 拆段,\\t → <w:tab/>,其余 → <w:t>\n // 简洁策略:单段落 + \\n 映射 <w:br>(与 paragraph-ops 一致)\n const p = commentsDoc.createElementNS(W_NS, 'w:p');\n const r = commentsDoc.createElementNS(W_NS, 'w:r');\n appendCommentTextSegments(commentsDoc, r, text);\n p.appendChild(r);\n comment.appendChild(p);\n\n // 追加到 <w:comments> 根\n const root = commentsDoc.documentElement;\n root.appendChild(comment);\n}\n\nfunction appendCommentTextSegments(doc: Document, run: Element, text: string): void {\n if (text.length === 0) {\n run.appendChild(createT(doc, ''));\n return;\n }\n let buf = '';\n const flush = (): void => {\n if (buf.length > 0) {\n run.appendChild(createT(doc, buf));\n buf = '';\n }\n };\n for (const ch of text) {\n if (ch === '\\n') {\n flush();\n run.appendChild(createW(doc, 'br'));\n } else if (ch === '\\t') {\n flush();\n run.appendChild(createW(doc, 'tab'));\n } else {\n buf += ch;\n }\n }\n flush();\n}\n\n// ─────────── 内部:DOM 工具 ───────────\n\nfunction createW(doc: Document, localName: string): Element {\n return doc.createElementNS(W_NS, `w:${localName}`);\n}\n\nfunction createT(doc: Document, text: string): Element {\n const t = createW(doc, 't');\n t.setAttributeNS(XML_NS, 'xml:space', 'preserve');\n t.textContent = text;\n return t;\n}\n\nfunction createCommentAnchor(doc: Document, localName: string, commentId: number): Element {\n const el = createW(doc, localName);\n el.setAttributeNS(W_NS, 'w:id', String(commentId));\n return el;\n}\n\nfunction createCommentRefRun(doc: Document, commentId: number): Element {\n const run = createW(doc, 'r');\n const ref = createW(doc, 'commentReference');\n ref.setAttributeNS(W_NS, 'w:id', String(commentId));\n run.appendChild(ref);\n return run;\n}\n\nfunction firstDirectChildW(el: Element, localName: string): Element | null {\n const children = el.childNodes;\n for (let i = 0; i < children.length; i++) {\n const c = children[i];\n if (\n c &&\n c.nodeType === 1 &&\n (c as Element).namespaceURI === W_NS &&\n (c as Element).localName === localName\n ) {\n return c as Element;\n }\n }\n return null;\n}\n\nfunction removeFromParent(el: Element | Node): void {\n if (el.parentNode) el.parentNode.removeChild(el);\n}\n\n/**\n * 判断 <w:r> 元素是否已无实质性内容(只剩 rPr 或彻底为空)。\n * 用于 deleteComment 后清理空 wrapper run。\n */\nfunction isRunEffectivelyEmpty(run: Element): boolean {\n const children = run.childNodes;\n for (let i = 0; i < children.length; i++) {\n const c = children[i];\n if (!c || c.nodeType !== 1) continue;\n const localName = (c as Element).localName;\n // rPr 是运行属性,不算\"内容\"\n if (localName === 'rPr') continue;\n return false;\n }\n return true;\n}\n\nfunction requireParagraph(ctx: ExecutorContext, paraId: string, opName: string): Element {\n const el = ctx.indices.paraIdx.get(paraId.toUpperCase());\n if (!el) {\n throw new WordError(\n 'PARA_NOT_FOUND',\n `paragraph with paraId='${paraId}' not found (op: ${opName})`,\n ctx.docId,\n { paraId, opName },\n );\n }\n return el;\n}\n\nfunction markBodyPartDirty(ctx: ExecutorContext, paragraph: Element): void {\n const story = findStoryFor(ctx.pkg, paragraph);\n if (!story) return;\n const part = getPart(ctx.pkg, story.partPath);\n if (part) markDirty(part);\n}\n\nfunction numAttr(el: Element, ns: string, local: string): number | null {\n const v = el.getAttributeNS(ns, local);\n if (v === null) return null;\n const n = Number(v);\n return Number.isFinite(n) ? n : null;\n}\n\n/** Range 类型判断:有 text 字段 → TextRange */\nfunction isTextRange(\n range: Range,\n): range is { paraId: string; text: string; scope?: 'first' | 'all' } {\n return 'text' in range;\n}\n","/**\n * 段落结构 executor —— #29(insertParagraphBefore/After / deleteParagraph)。\n *\n * 设计要点:\n * - insertParagraph:先查 anchor,再分配新 paraId(generateParaId),克隆或新建 pPr,\n * 追加 runs,DOM insertBefore / appendChild;最后更新 result.insertedParagraphs\n * - deleteParagraph:先查段,检测 bookmarkStart / commentRangeStart 等活锚点;\n * 无锚点直接 removeChild;有锚点按 onAnchorConflict 抛错\n * - trackChanges=true:两者都抛 UNSUPPORTED_OOXML_FEATURE(#31 负责包装)\n * - 新 paraId 用 generateParaId(seen) —— seen 集合由当前 paraIdx.keys() 构建,\n * 保证 package 全局唯一;apply 后 kernel.applyPlan 的 finally 块重建索引\n */\nimport { getPart, isXmlPart, listParts, markDirty } from '../../pack/index.js';\nimport { generateParaId } from '../para-id.js';\nimport { W_NS, W14_NS } from '../namespaces.js';\nimport type { Op } from '../plan.js';\nimport { findStoryFor, listStories } from '../stories.js';\nimport { WordError } from '../word-error.js';\nimport { createCrossParagraphBookmark, resolveAppendBookmarkName } from './bookmark-ops.js';\nimport { cleanupEmptyCommentsPart } from './comment-ops.js';\nimport type { ExecutorContext } from './executor-context.js';\nimport { appendTextAsRuns, createW, firstDirectChildW } from './_shared.js';\nimport {\n allocateRevisionId,\n ensureParaMarkDelete,\n ensureParaMarkInsert,\n wrapRunsAsDelete,\n wrapRunsAsInsert,\n type RevisionAttrs,\n} from './revision-wrappers.js';\n\nconst COMMENTS_PART_PATH = 'word/comments.xml';\n\n// ─────────── insertParagraphBefore / insertParagraphAfter ───────────\n\nexport function executeInsertParagraph(\n ctx: ExecutorContext,\n op: Extract<Op, { type: 'insertParagraphBefore' | 'insertParagraphAfter' }>,\n position: 'before' | 'after',\n): void {\n // 1. 查 anchor\n const anchor = ctx.indices.paraIdx.get(op.anchorParaId.toUpperCase());\n if (!anchor) {\n throw new WordError(\n 'PARA_NOT_FOUND',\n `paragraph with paraId='${op.anchorParaId}' not found (op: ${op.type})`,\n ctx.docId,\n { paraId: op.anchorParaId, opName: op.type },\n );\n }\n\n const doc = anchor.ownerDocument;\n if (!doc)\n throw new WordError('PACKAGE_CORRUPT', 'anchor paragraph has no ownerDocument', ctx.docId);\n\n // 2. 分配新 paraId(从当前 paraIdx key 集合作为 seen)\n const seen = new Set(ctx.indices.paraIdx.keys());\n const newId = generateParaId(seen);\n\n // 3. 创建 <w:p> 并设 w14:paraId\n const newPara = doc.createElementNS(W_NS, 'w:p');\n newPara.setAttributeNS(W14_NS, 'w14:paraId', newId);\n\n // 4. 生成 pPr\n // styleSource 优先级最高:存在时克隆 styleSource 段的 pPr(覆盖 style 语义)\n const styleSource = op.spec.styleSource;\n if (styleSource !== undefined) {\n // 查 styleSource 段\n const sourcePara = ctx.indices.paraIdx.get(styleSource.toUpperCase());\n if (!sourcePara) {\n // 健壮性降级(绝不崩):styleSource 段在产物里不存在(典型成因:跨文档 / 重建后\n // 该样式源段已被删 / 文本框内段被当 styleSource 但不在 body 重建落点)。此前直接\n // 抛 PARA_NOT_FOUND 会回滚整个 plan,连累整篇 merge 崩(mam-text-box 文本框文档\n // 实测:styleSource paraId 每次不同、merge 按 paraId 找代表段 miss → CRASH)。\n // 降级:回退到 anchor 段的 pPr(anchor 是真实存在的相邻段,是最自然的样式源兜底),\n // 等价于 styleSource===undefined 的「继承 anchor」分支;anchor 无 pPr 则不加(用文档默认)。\n // 绝不崩、不丢段(新段照常插入,只是样式从精确 styleSource 退化为相邻段样式)。\n console.warn(\n `[word] insertParagraph: styleSource paragraph paraId='${styleSource}' not found; ` +\n `degrade to inherit anchor pPr (op: ${op.type}, docId: ${ctx.docId})`,\n );\n const anchorPPr = firstDirectChildW(anchor, 'pPr');\n if (anchorPPr) {\n newPara.appendChild(anchorPPr.cloneNode(true));\n }\n } else {\n // 克隆 styleSource 段的 pPr;源段无 pPr 则退化不加(不报错)\n const sourcePPr = firstDirectChildW(sourcePara, 'pPr');\n if (sourcePPr) {\n newPara.appendChild(sourcePPr.cloneNode(true));\n }\n }\n } else {\n const style = op.spec.style;\n if (style === undefined || style === 'inherit') {\n // 继承 anchor 的 pPr(深拷贝),anchor 无 pPr 时不加\n const anchorPPr = firstDirectChildW(anchor, 'pPr');\n if (anchorPPr) {\n newPara.appendChild(anchorPPr.cloneNode(true));\n }\n } else {\n // 指定 styleId:新建 pPr + pStyle\n const pPr = createW(doc, 'pPr');\n const pStyle = createW(doc, 'pStyle');\n // w:val 属性在 W_NS 下(和 <w:pStyle> 同命名空间)\n pStyle.setAttributeNS(W_NS, 'w:val', style);\n pPr.appendChild(pStyle);\n newPara.appendChild(pPr);\n }\n }\n\n // 4b. outlineLevel:写入/覆盖 <w:outlineLvl w:val=\"N\"/> 到 pPr\n if (op.spec.outlineLevel !== undefined) {\n const lvl = op.spec.outlineLevel;\n if (lvl < 0 || lvl > 8 || !Number.isInteger(lvl)) {\n throw new WordError(\n 'INVALID_ARGUMENT',\n `insertParagraph: outlineLevel must be an integer 0–8, got ${lvl}`,\n ctx.docId,\n { outlineLevel: lvl, opName: op.type },\n );\n }\n // 确保 pPr 存在(styleSource 无 pPr 时需新建)\n let pPr = firstDirectChildW(newPara, 'pPr');\n if (!pPr) {\n pPr = createW(doc, 'pPr');\n newPara.insertBefore(pPr, newPara.firstChild);\n }\n // 写入或替换 <w:outlineLvl>\n const existing = firstDirectChildW(pPr, 'outlineLvl');\n if (existing) {\n existing.setAttributeNS(W_NS, 'w:val', String(lvl));\n } else {\n const outlineLvlEl = createW(doc, 'outlineLvl');\n outlineLvlEl.setAttributeNS(W_NS, 'w:val', String(lvl));\n // CT_PPr schema 顺序:outlineLvl 必须在 rPr/sectPr/pPrChange 之前。\n // 策略:在 pPr 子元素中找第一个「尾部元素」(rPr/sectPr/pPrChange/divId/cnfStyle),\n // 插在其之前;这些都不存在时才 appendChild。\n // 这样 outlineLvl 一定在 rPr 等之前,符合 schema,Word 能识别大纲级别。\n const TAIL_LOCALS = new Set(['rPr', 'sectPr', 'pPrChange', 'divId', 'cnfStyle']);\n let refNode: Element | null = null;\n for (let i = 0; i < pPr.childNodes.length; i++) {\n const c = pPr.childNodes[i];\n if (\n c &&\n c.nodeType === 1 &&\n (c as Element).namespaceURI === W_NS &&\n TAIL_LOCALS.has((c as Element).localName)\n ) {\n refNode = c as Element;\n break;\n }\n }\n pPr.insertBefore(outlineLvlEl, refNode); // refNode=null → insertBefore(el, null) = appendChild\n }\n }\n\n // 4c. pageBreakBefore:写入 <w:pageBreakBefore/>(CT_OnOff,存在即 true)到 pPr\n // CT_PPr schema 顺序:pStyle → keepNext → keepLines → pageBreakBefore → framePr →\n // widowControl → numPr → … → outlineLvl → rPr → sectPr → pPrChange\n // 即 pageBreakBefore 在 pStyle/keepNext/keepLines 之后、framePr/widowControl/numPr 之前。\n // 策略:找 pPr 中第一个「后置于 pageBreakBefore 的元素」,插在其之前;否则 appendChild。\n if (op.spec.pageBreakBefore === true) {\n // 确保 pPr 存在\n let pPr = firstDirectChildW(newPara, 'pPr');\n if (!pPr) {\n pPr = createW(doc, 'pPr');\n newPara.insertBefore(pPr, newPara.firstChild);\n }\n // 不重复写入(styleSource 克隆过来的 pPr 可能已含 pageBreakBefore)\n if (!firstDirectChildW(pPr, 'pageBreakBefore')) {\n const pbbEl = createW(doc, 'pageBreakBefore');\n // CT_PPr 中 pageBreakBefore 之后的元素(作为插入参考点)\n const AFTER_LOCALS = new Set([\n 'framePr',\n 'widowControl',\n 'suppressLineNumbers',\n 'pBdr',\n 'shd',\n 'tabs',\n 'suppressAutoHyphens',\n 'kinsoku',\n 'wordWrap',\n 'overflowPunct',\n 'topLinePunct',\n 'autoSpaceDE',\n 'autoSpaceDN',\n 'bidi',\n 'adjustRightInd',\n 'snapToGrid',\n 'spacing',\n 'ind',\n 'contextualSpacing',\n 'mirrorIndents',\n 'suppressOverlap',\n 'jc',\n 'textDirection',\n 'textAlignment',\n 'textboxTightWrap',\n 'outlineLvl',\n 'divId',\n 'cnfStyle',\n 'rPr',\n 'sectPr',\n 'pPrChange',\n 'numPr',\n ]);\n let refNode: Element | null = null;\n for (let i = 0; i < pPr.childNodes.length; i++) {\n const c = pPr.childNodes[i];\n if (\n c &&\n c.nodeType === 1 &&\n (c as Element).namespaceURI === W_NS &&\n AFTER_LOCALS.has((c as Element).localName)\n ) {\n refNode = c as Element;\n break;\n }\n }\n pPr.insertBefore(pbbEl, refNode); // refNode=null → appendChild\n }\n }\n\n // 5. 生成内容 runs\n appendTextAsRuns(newPara, op.spec.text);\n\n // 5.1 可选 run-level rPr 继承:克隆源段首个直属 <w:r> 的 <w:rPr>,应用到新段所有内容 run。\n // styleSource 存在时以 styleSource 段为源(优先级高于 runFormat);\n // 否则若 runFormat='inherit' 以 anchor 为源(#12 兼容)。\n // 用于「簇展开」/全文重组场景——样式写在直接格式(rPr)而非命名样式上。\n // 源段无直属 run / 首 run 无 rPr → 退化为裸 run 不报错。\n // 注意顺序:在 color 之前(color 覆盖 rPr 里已存在的 color)。\n if (styleSource !== undefined) {\n // styleSource 路径:step 4 查 sourcePara。存在则以它为 rPr 源;\n // 不存在(step 4 已降级回退到 anchor pPr)时以 anchor 为 rPr 源,保持与\n // pPr 降级一致——绝不对 undefined 调 applyInheritedRPrToDirectRuns(会崩)。\n const sourcePara = ctx.indices.paraIdx.get(styleSource.toUpperCase());\n applyInheritedRPrToDirectRuns(newPara, sourcePara ?? anchor);\n } else if (op.spec.runFormat === 'inherit') {\n applyInheritedRPrToDirectRuns(newPara, anchor);\n }\n\n // 5.2 可选 run-level 颜色:为新段所有直属 <w:r> 加 <w:rPr><w:color w:val=\"...\"/></w:rPr>。\n // 双语对照译文场景(word-translate skill)用此区分原段和译文段。\n if (op.spec.color) {\n applyColorToDirectRuns(newPara, op.spec.color);\n }\n\n // 5a. trackChanges=true(#31):把新段的**内容 runs**包成 <w:ins>,且段 pPr\n // 下加段落 mark 插入标记(w:pPr/w:rPr/w:ins)\n if (ctx.options.trackChanges) {\n const attrs: RevisionAttrs = { author: ctx.options.author, date: ctx.options.date };\n // 取出所有直属 <w:r>(appendTextAsRuns 生成的就是一个 <w:r>),包成 ins\n const newRuns: Element[] = [];\n for (let i = 0; i < newPara.childNodes.length; i++) {\n const c = newPara.childNodes[i];\n if (\n c &&\n c.nodeType === 1 &&\n (c as Element).namespaceURI === W_NS &&\n (c as Element).localName === 'r'\n ) {\n newRuns.push(c as Element);\n }\n }\n if (newRuns.length > 0) {\n const insId = allocateRevisionId(ctx.pkg);\n const insEl = wrapRunsAsInsert(newRuns, insId, attrs);\n // 删原 runs,替换为 ins\n for (const r of newRuns) newPara.removeChild(r);\n newPara.appendChild(insEl);\n }\n // 段落 mark 插入标记\n const markId = allocateRevisionId(ctx.pkg);\n ensureParaMarkInsert(newPara, markId, attrs);\n }\n\n // 6. 插入到 DOM\n const parent = anchor.parentNode;\n if (!parent) {\n throw new WordError('PACKAGE_CORRUPT', 'anchor paragraph has no parentNode', ctx.docId);\n }\n if (position === 'before') {\n parent.insertBefore(newPara, anchor);\n } else {\n // after:插到 anchor 的下一个兄弟之前(即 anchor 之后)\n parent.insertBefore(newPara, anchor.nextSibling);\n }\n\n // 7. 更新 ApplyResult\n ctx.result.insertedParagraphs.push({\n opIndex: ctx.opIndex,\n anchorParaId: op.anchorParaId,\n position,\n newParaId: newId,\n });\n\n // 8. markDirty(必须先于 bookmark 创建,createCrossParagraphBookmark 内部也会再\n // markDirty 一次,markDirty 幂等)\n markStoryPartDirty(ctx, anchor, op.type);\n\n // 9. 可选:同事务建跨段书签(#176)\n // 仅 insertParagraphAfter 提供;insertParagraphBefore 显式拒绝 —— 静默忽略会\n // 让调用方误以为书签建好了,后续查询 null 难定位。\n if (op.spec.bookmark) {\n if (position !== 'after') {\n throw new WordError(\n 'UNSUPPORTED_OOXML_FEATURE',\n 'spec.bookmark is only supported on insertParagraphAfter (#176)',\n ctx.docId,\n { opType: op.type, anchorParaId: op.anchorParaId },\n );\n }\n const resolvedName = resolveAppendBookmarkName(ctx, op.spec.bookmark.prefix, op.anchorParaId);\n createCrossParagraphBookmark(ctx, resolvedName, anchor, newPara, op.anchorParaId, newId);\n }\n}\n\n/**\n * 克隆 `sourcePara` 段首个直属 `<w:r>` 的 `<w:rPr>`,深拷贝后插到 `paragraph` 内\n * 所有直属 `<w:r>` 的首位。\n *\n * 调用方传 anchor 段(runFormat:'inherit' 的 #12 场景)或 styleSource 段(全文重组场景)。\n * sourcePara 无直属 run 或首 run 无 rPr → 静默退化,不修改新段 run(裸 run 行为)。\n * 调用时机:在 appendTextAsRuns 之后、applyColorToDirectRuns 之前,让 color 能覆盖继承值。\n */\nfunction applyInheritedRPrToDirectRuns(paragraph: Element, sourcePara: Element): void {\n // 找 sourcePara 首个直属 <w:r>\n const anchorRun = firstDirectChildW(sourcePara, 'r');\n if (!anchorRun) return;\n\n // 取首 run 的 <w:rPr>\n const srcRPr = firstDirectChildW(anchorRun, 'rPr');\n if (!srcRPr) return;\n\n // 应用深拷贝到新段所有直属 <w:r>\n for (let i = 0; i < paragraph.childNodes.length; i++) {\n const c = paragraph.childNodes[i];\n if (\n !c ||\n c.nodeType !== 1 ||\n (c as Element).namespaceURI !== W_NS ||\n (c as Element).localName !== 'r'\n )\n continue;\n const run = c as Element;\n // 插到 run 首位(rPr 必须是 <w:r> 的第一个子元素)\n run.insertBefore(srcRPr.cloneNode(true), run.firstChild);\n }\n}\n\n/**\n * 把 6 位十六进制颜色(无 `#`)写到段内所有直属 `<w:r>` 的 `<w:rPr><w:color w:val=\"...\"/></w:rPr>`。\n * 已存在 rPr 时只补/替 color;rPr 不存在则新建并放在 run 首位。\n */\nfunction applyColorToDirectRuns(paragraph: Element, color: string): void {\n const doc = paragraph.ownerDocument;\n if (!doc) return;\n for (let i = 0; i < paragraph.childNodes.length; i++) {\n const c = paragraph.childNodes[i];\n if (\n !c ||\n c.nodeType !== 1 ||\n (c as Element).namespaceURI !== W_NS ||\n (c as Element).localName !== 'r'\n )\n continue;\n const run = c as Element;\n let rPr = firstDirectChildW(run, 'rPr');\n if (!rPr) {\n rPr = createW(doc, 'rPr');\n run.insertBefore(rPr, run.firstChild);\n }\n let colorEl = firstDirectChildW(rPr, 'color');\n if (!colorEl) {\n colorEl = createW(doc, 'color');\n rPr.appendChild(colorEl);\n }\n colorEl.setAttributeNS(W_NS, 'w:val', color);\n }\n}\n\n// ─────────── insertParagraphAtBodyStart ───────────\n\n/**\n * 无锚点在 `<w:body>` 起始插一个空段(带 w14:paraId),新 paraId 写入\n * `ctx.result.insertedBodyStartParaIds`。\n *\n * 用途(健壮性):body 完全无段落(极简/特殊文档:正文段被骨架删光、或源 body 仅\n * header/footer/文本框内容)时,下游重建需要一个真实落点锚段。此前 typeset 在该情形\n * 直接 throw(\"skeleton body 无任何段落,无法定位 body 重建锚点\")→ 整篇崩。本 op 提供\n * 合成锚点能力,让重建走既有 insertParagraphAfter(anchor) 路径,绝不崩、不丢内容。\n *\n * 插入位置:body 的第一个子元素之前(body 的 <w:sectPr> 恒为最后一个子元素,prepend 不会\n * 破坏 sectPr 在尾部的 schema 约束;body 为空时直接成为唯一子元素)。\n */\nexport function executeInsertParagraphAtBodyStart(\n ctx: ExecutorContext,\n _op: Extract<Op, { type: 'insertParagraphAtBodyStart' }>,\n): void {\n const [bodyStory] = listStories(ctx.pkg, { kinds: ['body'] });\n if (!bodyStory) {\n throw new WordError(\n 'PACKAGE_CORRUPT',\n 'document has no <w:body> story (op: insertParagraphAtBodyStart)',\n ctx.docId,\n );\n }\n const body = bodyStory.root;\n const doc = body.ownerDocument;\n if (!doc) {\n throw new WordError(\n 'PACKAGE_CORRUPT',\n 'body element has no ownerDocument (op: insertParagraphAtBodyStart)',\n ctx.docId,\n );\n }\n\n const seen = new Set(ctx.indices.paraIdx.keys());\n const newId = generateParaId(seen);\n const newPara = doc.createElementNS(W_NS, 'w:p');\n newPara.setAttributeNS(W14_NS, 'w14:paraId', newId);\n\n // 插到 body 第一个子元素之前(body 为空时 firstChild=null → appendChild 语义)。\n body.insertBefore(newPara, body.firstChild);\n\n ctx.result.insertedBodyStartParaIds.push(newId);\n\n const part = getPart(ctx.pkg, bodyStory.partPath);\n if (part) markDirty(part);\n}\n\n// ─────────── deleteParagraph ───────────\n\nexport function executeDeleteParagraph(\n ctx: ExecutorContext,\n op: Extract<Op, { type: 'deleteParagraph' }>,\n): void {\n // 1. 查段\n const paragraph = ctx.indices.paraIdx.get(op.paraId.toUpperCase());\n if (!paragraph) {\n throw new WordError(\n 'PARA_NOT_FOUND',\n `paragraph with paraId='${op.paraId}' not found (op: deleteParagraph)`,\n ctx.docId,\n { paraId: op.paraId, opName: 'deleteParagraph' },\n );\n }\n\n // 2. 检测段内活锚点\n const affectedBookmarks = collectBookmarkNames(paragraph);\n const affectedComments = collectCommentIds(paragraph);\n const hasAnchors = affectedBookmarks.length > 0 || affectedComments.length > 0;\n\n if (hasAnchors) {\n if (op.onAnchorConflict === 'drop') {\n if (ctx.options.trackChanges) {\n // drop + trackChanges(#31):修订包装 + 连带删外部锚点主体的组合语义复杂,留后续\n throw new WordError(\n 'UNSUPPORTED_OOXML_FEATURE',\n \"deleteParagraph with onAnchorConflict='drop' + trackChanges=true not yet implemented\",\n ctx.docId,\n { opType: 'deleteParagraph', paraId: op.paraId },\n );\n }\n // drop 模式(#30):删除段内所有活锚点,然后删段\n // - 书签:移除 bookmarkStart + bookmarkEnd,更新 bookmarkIdx\n // - 批注:移除三锚点(commentRangeStart / commentRangeEnd / commentReference)\n // + comments.xml 里的 <w:comment> 主体\n for (const name of affectedBookmarks) {\n dropBookmarkByName(ctx, name, paragraph);\n }\n for (const id of affectedComments) {\n dropCommentById(ctx, id, paragraph);\n }\n } else {\n // 默认 'error'\n throw new WordError(\n 'ANCHOR_CONFLICT',\n `paragraph '${op.paraId}' contains active anchors (bookmarks: ${affectedBookmarks.join(', ') || 'none'}, comments: ${affectedComments.join(', ') || 'none'})`,\n ctx.docId,\n { paraId: op.paraId, affectedBookmarks, affectedComments, opType: 'deleteParagraph' },\n );\n }\n }\n\n // 3. 无活锚点\n if (ctx.options.trackChanges) {\n // trackChanges=true(#31):不 removeChild;内容 runs 包 <w:del>(w:t→w:delText),\n // 段 pPr 加段落 mark 删除标记\n executeDeleteParagraphTC(ctx, paragraph);\n return;\n }\n\n // 非 trackChanges:直接删除\n const parent = paragraph.parentNode;\n if (!parent) {\n throw new WordError('PACKAGE_CORRUPT', 'paragraph has no parentNode', ctx.docId);\n }\n markStoryPartDirty(ctx, paragraph, 'deleteParagraph');\n parent.removeChild(paragraph);\n}\n\n/**\n * trackChanges=true 下的段落删除:\n * - 不从 DOM 移除段\n * - 收集直属 `<w:r>` 内容 runs,整组包成 `<w:del>`(内部 `<w:t>` 转 `<w:delText>`)\n * - 替换原 runs 为 del\n * - 段 pPr 下加段落 mark 删除标记(`<w:rPr><w:del/>`)\n */\nfunction executeDeleteParagraphTC(ctx: ExecutorContext, paragraph: Element): void {\n const attrs: RevisionAttrs = { author: ctx.options.author, date: ctx.options.date };\n\n // 收集直属 <w:r>\n const runs: Element[] = [];\n for (let i = 0; i < paragraph.childNodes.length; i++) {\n const c = paragraph.childNodes[i];\n if (\n c &&\n c.nodeType === 1 &&\n (c as Element).namespaceURI === W_NS &&\n (c as Element).localName === 'r'\n ) {\n runs.push(c as Element);\n }\n }\n\n if (runs.length > 0) {\n const delId = allocateRevisionId(ctx.pkg);\n const delEl = wrapRunsAsDelete(runs, delId, attrs);\n // 在第一个 run 前插 del,再删掉原 runs\n paragraph.insertBefore(delEl, runs[0]!);\n for (const r of runs) paragraph.removeChild(r);\n }\n\n // 段落 mark 删除标记\n const markId = allocateRevisionId(ctx.pkg);\n ensureParaMarkDelete(paragraph, markId, attrs);\n\n markStoryPartDirty(ctx, paragraph, 'deleteParagraph');\n}\n\n// ─────────── 内部:锚点检测 ───────────\n\n/** 收集段内所有 bookmarkStart 的 w:name(字符串数组)*/\nfunction collectBookmarkNames(paragraph: Element): string[] {\n const names: string[] = [];\n const starts = paragraph.getElementsByTagNameNS(W_NS, 'bookmarkStart');\n for (let i = 0; i < starts.length; i++) {\n const el = starts[i];\n if (!el) continue;\n const name = el.getAttributeNS(W_NS, 'name') ?? el.getAttribute('w:name') ?? '';\n names.push(name);\n }\n return names;\n}\n\n/** 收集段内所有 commentRangeStart / commentReference 的 w:id(数字数组,去重)*/\nfunction collectCommentIds(paragraph: Element): number[] {\n const ids = new Set<number>();\n const rangeStarts = paragraph.getElementsByTagNameNS(W_NS, 'commentRangeStart');\n for (let i = 0; i < rangeStarts.length; i++) {\n const el = rangeStarts[i];\n if (!el) continue;\n const id = parseInt(el.getAttributeNS(W_NS, 'id') ?? el.getAttribute('w:id') ?? '', 10);\n if (!isNaN(id)) ids.add(id);\n }\n const refs = paragraph.getElementsByTagNameNS(W_NS, 'commentReference');\n for (let i = 0; i < refs.length; i++) {\n const el = refs[i];\n if (!el) continue;\n const id = parseInt(el.getAttributeNS(W_NS, 'id') ?? el.getAttribute('w:id') ?? '', 10);\n if (!isNaN(id)) ids.add(id);\n }\n return Array.from(ids);\n}\n\n// ─────────── 内部:drop 模式 —— 书签/批注清理 (#30) ───────────\n\n/**\n * drop 模式下删除书签:移除 bookmarkStart + bookmarkEnd,从 bookmarkIdx 删条目。\n * 简化路径:直接操作 bookmarkIdx 查到的 entry(index 在 applyPlan finally 会重建)。\n */\nfunction dropBookmarkByName(ctx: ExecutorContext, name: string, _paragraph: Element): void {\n const entry = ctx.indices.bookmarkIdx.get(name);\n if (!entry) return; // 已不在索引里(可能索引时重名被去重),直接跳过\n\n const { start, end, partPath } = entry;\n\n // 移除 bookmarkStart\n if (start.parentNode) start.parentNode.removeChild(start);\n\n // 移除 bookmarkEnd(可能为 null 或不在同一段)\n if (end && end.parentNode) end.parentNode.removeChild(end);\n\n // 更新索引(finally 会重建,此处先同步删掉防止 drop 多书签时二次访问)\n ctx.indices.bookmarkIdx.delete(name);\n\n // markDirty\n const part = getPart(ctx.pkg, partPath);\n if (part) markDirty(part);\n}\n\n/**\n * drop 模式下删除批注:移除三锚点(commentRangeStart / commentRangeEnd / commentReference)\n * + comments.xml 里的 <w:comment> 主体。\n * 从 commentIdx 删条目;markDirty body part + comments.xml。\n */\nfunction dropCommentById(ctx: ExecutorContext, id: number, paragraph: Element): void {\n const entry = ctx.indices.commentIdx.get(id);\n\n // 若 commentIdx 里没有(可能首次创建还未重建索引),\n // 则手动从段内找并删除锚点元素\n if (!entry) {\n // 直接扫段删锚点 DOM 节点\n removeCommentAnchorsFromParagraph(ctx, paragraph, id);\n return;\n }\n\n const { start, end, ref } = entry.anchors;\n\n // body part 路径:从存在的锚点反查\n const anchorEl = start ?? end ?? ref;\n let bodyPartPath: string | null = null;\n if (anchorEl) {\n const story = findStoryFor(ctx.pkg, anchorEl);\n if (story) bodyPartPath = story.partPath;\n }\n\n if (start && start.parentNode) start.parentNode.removeChild(start);\n if (end && end.parentNode) end.parentNode.removeChild(end);\n if (ref) {\n // ref 可能包在一个 <w:r> 里;若移除 ref 后 run 变空,整体删 run\n const parentRun = ref.parentNode;\n if (ref.parentNode) ref.parentNode.removeChild(ref);\n if (\n parentRun &&\n parentRun.nodeType === 1 &&\n (parentRun as Element).namespaceURI === W_NS &&\n (parentRun as Element).localName === 'r'\n ) {\n if (isRunEffectivelyEmpty(parentRun as Element)) {\n if (parentRun.parentNode) parentRun.parentNode.removeChild(parentRun);\n }\n }\n }\n\n // 删 <w:comment> 主体\n if (entry.comment && entry.comment.parentNode) {\n entry.comment.parentNode.removeChild(entry.comment);\n const commentsPart = getPart(ctx.pkg, COMMENTS_PART_PATH);\n if (commentsPart) markDirty(commentsPart);\n }\n\n // markDirty body part\n if (bodyPartPath) {\n const bodyPart = getPart(ctx.pkg, bodyPartPath);\n if (bodyPart) markDirty(bodyPart);\n }\n\n // 更新索引\n ctx.indices.commentIdx.delete(id);\n\n // 若 comments.xml 已空,移除 part + 清 CT/rels(与 executeDeleteComment 对称)\n cleanupEmptyCommentsPart(ctx);\n}\n\n/**\n * 当 commentIdx 里没有目标批注时,直接从 paragraph DOM 内扫描并删除所有\n * 属于该 commentId 的锚点元素。\n */\nfunction removeCommentAnchorsFromParagraph(\n ctx: ExecutorContext,\n paragraph: Element,\n commentId: number,\n): void {\n const idStr = String(commentId);\n // 扫段内全部 commentRangeStart / commentRangeEnd / commentReference\n const localNames = ['commentRangeStart', 'commentRangeEnd', 'commentReference'];\n const toRemove: Element[] = [];\n for (const local of localNames) {\n const list = paragraph.getElementsByTagNameNS(W_NS, local);\n for (let i = 0; i < list.length; i++) {\n const el = list[i];\n if (!el) continue;\n const rawId = el.getAttributeNS(W_NS, 'id') ?? el.getAttribute('w:id') ?? '';\n if (rawId === idStr) toRemove.push(el);\n }\n }\n for (const el of toRemove) {\n const parentRun = el.localName === 'commentReference' ? el.parentNode : null;\n if (el.parentNode) el.parentNode.removeChild(el);\n if (\n parentRun &&\n parentRun.nodeType === 1 &&\n (parentRun as Element).namespaceURI === W_NS &&\n (parentRun as Element).localName === 'r' &&\n isRunEffectivelyEmpty(parentRun as Element)\n ) {\n if (parentRun.parentNode) parentRun.parentNode.removeChild(parentRun);\n }\n }\n\n // 同时删 comments.xml 里的主体\n for (const part of listParts(ctx.pkg)) {\n if (!isXmlPart(part) || !part.xmlDom) continue;\n if (!part.contentType.endsWith('.comments+xml')) continue;\n const comments = part.xmlDom.getElementsByTagNameNS(W_NS, 'comment');\n const victims: Element[] = [];\n for (let i = 0; i < comments.length; i++) {\n const c = comments[i];\n if (!c) continue;\n const rawId = c.getAttributeNS(W_NS, 'id') ?? c.getAttribute('w:id') ?? '';\n if (rawId === idStr) victims.push(c);\n }\n for (const v of victims) {\n if (v.parentNode) v.parentNode.removeChild(v);\n }\n if (victims.length > 0) markDirty(part);\n }\n}\n\n/** 判断 <w:r> 是否已无实质性内容(只剩 rPr 或彻底为空) */\nfunction isRunEffectivelyEmpty(run: Element): boolean {\n const children = run.childNodes;\n for (let i = 0; i < children.length; i++) {\n const c = children[i];\n if (!c || c.nodeType !== 1) continue;\n if ((c as Element).localName === 'rPr') continue;\n return false;\n }\n return true;\n}\n\n// ─────────── 内部:markDirty ───────────\n\nfunction markStoryPartDirty(ctx: ExecutorContext, paragraph: Element, opName: string): void {\n const story = findStoryFor(ctx.pkg, paragraph);\n if (!story) {\n throw new WordError(\n 'PACKAGE_CORRUPT',\n `paragraph element not found in any story (op: ${opName})`,\n ctx.docId,\n { opName },\n );\n }\n const part = getPart(ctx.pkg, story.partPath);\n if (!part) {\n throw new WordError(\n 'PACKAGE_CORRUPT',\n `story part '${story.partPath}' not found in pkg (op: ${opName})`,\n ctx.docId,\n { opName, partPath: story.partPath },\n );\n }\n markDirty(part);\n}\n","/**\n * Revision(修订)只读查询(docs/03.1 §1.5 / §2,#26 + #33)。\n *\n * **Tier 1 覆盖面**:只看 `<w:ins>` / `<w:del>` —— 这是 run 级的插入/删除修订,\n * 承载 w:id / w:author / w:date 属性,以及子树内的 `<w:t>`(ins)/ `<w:delText>`(del)\n * 作为涉及文本。\n *\n * **Tier 2 属性级修订**(#33 起显式拒绝):\n * - `<w:rPrChange>`(run 属性变更,在 `<w:rPr>` 里)\n * - `<w:pPrChange>`(段落属性变更,在 `<w:pPr>` 里)\n * - `<w:sectPrChange>` / `<w:tblPrChange>` / `<w:trPrChange>` / `<w:tcPrChange>` 等\n * - `<w:numberingChange>` / `<w:moveFrom>` / `<w:moveTo>` 等\n *\n * 扫到任一 Tier 2 元素即抛 `UNSUPPORTED_OOXML_FEATURE`(`listRevisions` 与\n * `acceptRevisions` / `rejectRevisions` 共用此守护,保证读写一致)。\n *\n * scope 控制枚举的 story 集合(与 `listParagraphs` 共用 `resolveScope`)。\n */\nimport type { Package } from '../pack/index.js';\nimport { W14_NS, W_NS } from './namespaces.js';\nimport { resolveScope, type StoryId } from './stories.js';\nimport { WordError } from './word-error.js';\n\nexport type RevisionId = string;\n\nexport interface RevisionInfo {\n revId: RevisionId;\n kind: 'insert' | 'delete';\n author: string;\n date: string;\n story: StoryId;\n /** 修订归属的段落(若 ins/del 嵌在 `<w:p>` 里才有;极少数嵌在 `<w:body>` 直子层位的则缺) */\n paraId?: string;\n /** 涉及的文本(ins:全部 `<w:t>` 拼接;del:全部 `<w:delText>` 拼接)。为空串时省略 */\n text?: string;\n}\n\nexport interface ListRevisionsOptions {\n /** 默认 'body' */\n scope?: 'body' | 'all' | StoryId[];\n}\n\n// ─────────── Tier 2 属性修订守护(#33,读/写共用)─────────────\n\n/**\n * Tier 2 属性级修订 local name 集合。\n * 扫到任一即抛 `UNSUPPORTED_OOXML_FEATURE`(`listRevisions` 与 `accept/rejectRevisions`\n * 共用此守护,保证只读/只写对 Tier 2 的态度一致)。\n */\nexport const TIER2_REVISION_LOCAL_NAMES: readonly string[] = [\n 'rPrChange',\n 'pPrChange',\n 'sectPrChange',\n 'tblPrChange',\n 'tcPrChange',\n 'trPrChange',\n 'tblPrExChange',\n 'tblGridChange',\n 'numberingChange',\n 'moveFrom',\n 'moveTo',\n];\n\n/**\n * 扫 `root`(Document 或 Element 子树)里是否存在 Tier 2 属性修订元素;\n * 发现一个立即抛 `WordError('UNSUPPORTED_OOXML_FEATURE')`。\n *\n * `docIdForError` 用于错误注入。调用方在读(listRevisions)/ 写(accept/reject)\n * 路径上各自提供自己的 docId。\n */\nexport function assertNoTier2Revisions(\n root: Document | Element,\n docIdForError: string,\n opContext: 'listRevisions' | 'acceptRevisions' | 'rejectRevisions',\n): void {\n for (const local of TIER2_REVISION_LOCAL_NAMES) {\n const els = root.getElementsByTagNameNS(W_NS, local);\n if (els.length > 0) {\n throw new WordError(\n 'UNSUPPORTED_OOXML_FEATURE',\n `Tier 2 revision '<w:${local}>' is not supported (op: ${opContext}); ` +\n `only <w:ins> / <w:del> are covered in Tier 1`,\n docIdForError,\n { revisionKind: local, opName: opContext },\n );\n }\n }\n}\n\n// ─────────── 公共入口 ───────────\n\nexport function listRevisions(pkg: Package, opts: ListRevisionsOptions = {}): RevisionInfo[] {\n const stories = resolveScope(pkg, opts.scope ?? 'body');\n const out: RevisionInfo[] = [];\n\n for (const story of stories) {\n // Tier 2 守护(#33):扫到 rPrChange / pPrChange / 等 → 抛\n // docId 本处没有(`listRevisions` 是 Package 级 helper,不知道 WordDocument.docId);\n // 用占位 '' 让 kernel 层的 toWordError 做二次注入。\n assertNoTier2Revisions(story.root, '', 'listRevisions');\n\n // 直接在 story root 上 getElementsByTagNameNS —— 只取该 story 子树内的 ins/del,\n // 不跨 sub-story(footnote 根单独一个 story,这里会在 footnote root 上再扫一轮)\n for (const { el, kind } of collectRevisionElementsInDocumentOrder(story.root)) {\n const info = buildRevisionInfo(el, kind, story.id);\n if (info) out.push(info);\n }\n }\n\n return out;\n}\n\n// ─────────── 内部 ───────────\n\nfunction buildRevisionInfo(\n el: Element,\n kind: 'insert' | 'delete',\n story: StoryId,\n): RevisionInfo | null {\n const revId = el.getAttributeNS(W_NS, 'id');\n if (revId === null) return null; // 缺 id 的 ins/del 跳过 —— 无法稳定引用\n\n const author = el.getAttributeNS(W_NS, 'author') ?? '';\n const date = el.getAttributeNS(W_NS, 'date') ?? '';\n const paraId = findContainingParaId(el);\n const text = extractRevisionText(el, kind);\n\n const info: RevisionInfo = { revId, kind, author, date, story };\n if (paraId !== undefined) info.paraId = paraId;\n if (text.length > 0) info.text = text;\n return info;\n}\n\n/** 从 ins/del 元素向上走到最近的 `<w:p>`,返回其 `w14:paraId`(大写);没有则返回 undefined */\nfunction findContainingParaId(el: Element): string | undefined {\n let cur: Node | null = el.parentNode;\n while (cur && cur.nodeType === 1) {\n const e = cur as Element;\n if (e.namespaceURI === W_NS && e.localName === 'p') {\n const raw = e.getAttributeNS(W14_NS, 'paraId');\n return raw && raw.length > 0 ? raw.toUpperCase() : undefined;\n }\n cur = cur.parentNode;\n }\n return undefined;\n}\n\n/**\n * 涉及文本:\n * - insert: 后代 `<w:t>`\n * - delete: 后代 `<w:delText>`\n *\n * 说明:`<w:ins>` 可能嵌套内容 wrapper(如 `<w:ins><w:r><w:t>` 或\n * `<w:ins><w:hyperlink><w:r><w:t>`)—— 统一用 getElementsByTagNameNS 吃全部后代。\n */\nfunction extractRevisionText(el: Element, kind: 'insert' | 'delete'): string {\n const tag = kind === 'insert' ? 't' : 'delText';\n const nodes = el.getElementsByTagNameNS(W_NS, tag);\n let out = '';\n for (let i = 0; i < nodes.length; i++) {\n out += nodes[i]!.textContent ?? '';\n }\n return out;\n}\n\nfunction collectRevisionElementsInDocumentOrder(\n root: Document | Element,\n): Array<{ el: Element; kind: 'insert' | 'delete' }> {\n const out: Array<{ el: Element; kind: 'insert' | 'delete' }> = [];\n\n function visit(node: Node): void {\n if (node.nodeType === 1) {\n const el = node as Element;\n if (el.namespaceURI === W_NS) {\n if (el.localName === 'ins') {\n out.push({ el, kind: 'insert' });\n return;\n }\n if (el.localName === 'del') {\n out.push({ el, kind: 'delete' });\n return;\n }\n }\n }\n\n for (let i = 0; i < node.childNodes.length; i++) {\n const child = node.childNodes[i];\n if (child) visit(child);\n }\n }\n\n visit(root);\n return out;\n}\n","/**\n * acceptRevisions / rejectRevisions executor —— #32(Phase D 收尾)。\n *\n * 契约(docs/03.1 §3.1):\n * - 三档 scope:all / paragraph(paraId) / revision(revId)\n * - Accept `<w:ins>` wrapper:剥 wrapper,保留内容\n * - Accept `<w:del>` wrapper:剥 wrapper + 删被删内容\n * - Reject 语义相反\n * - 段落 mark(`<w:pPr><w:rPr><w:ins/>` / `<w:del/>`)一并处理:\n * * Accept `ins` mark:删 mark,段保留\n * * Accept `del` mark:**删整段**(段 mark 的 del 简化为\"段要被删\")\n * * Reject `ins` mark:**删整段**\n * * Reject `del` mark:删 mark,段保留\n * - `<w:rPrChange>` / `<w:pPrChange>` / `<w:sectPrChange>` 等 Tier 2 属性级修订 →\n * 抛 `UNSUPPORTED_OOXML_FEATURE`\n *\n * **段落 mark 简化说明**:OOXML 规范里段落 mark 的修订对应段落**合并 / 分裂**语义\n * (段 mark ins = 分裂点新增;段 mark del = 与下段合并)。本 PR 的 Tier 1 实现\n * 把\"段 mark del accept / 段 mark ins reject\"简化为\"删整段\",不做文本层面的\n * 段落合并。Tier 2 再精细化。\n *\n * 每处理一个 wrapper 或段落 mark 计入 ApplyResult.acceptedRevisions /\n * rejectedRevisions 一次。\n */\nimport { getPart, isXmlPart, listParts, markDirty } from '../../pack/index.js';\nimport { W_NS } from '../namespaces.js';\nimport type { Op } from '../plan.js';\nimport { assertNoTier2Revisions } from '../revision-queries.js';\nimport { findStoryFor } from '../stories.js';\nimport { WordError } from '../word-error.js';\nimport type { ExecutorContext } from './executor-context.js';\n\ntype Action = 'accept' | 'reject';\ntype RevisionKind = 'ins' | 'del';\n\ninterface RevisionTarget {\n el: Element;\n kind: RevisionKind;\n /** true 表示此 ins/del 是段落 mark(位于 pPr/rPr 下) */\n isParaMark: boolean;\n /** 段落 mark 对应的 `<w:p>` 元素(isParaMark=false 时也可能用到,作为 containing paragraph) */\n paragraph: Element | null;\n}\n\n// Tier 2 属性级修订拒绝:用共享的 `assertNoTier2Revisions`(revision-queries.ts),\n// 读 listRevisions + 写 accept/reject 共用同一名单(#33)。\n\n// ─────────── entry ───────────\n\nexport function executeAcceptRevisions(\n ctx: ExecutorContext,\n op: Extract<Op, { type: 'acceptRevisions' }>,\n): void {\n processRevisions(ctx, op.scope, 'accept');\n}\n\nexport function executeRejectRevisions(\n ctx: ExecutorContext,\n op: Extract<Op, { type: 'rejectRevisions' }>,\n): void {\n processRevisions(ctx, op.scope, 'reject');\n}\n\nfunction processRevisions(\n ctx: ExecutorContext,\n scope: Extract<Op, { type: 'acceptRevisions' }>['scope'],\n action: Action,\n): void {\n // 1. 收集 targets(根据 scope);同时扫 Tier 2 属性修订抛 UNSUPPORTED\n const targets = collectTargets(ctx, scope);\n\n // 2. 逐个处理;paragraph mark 要删整段的分支,**把对应 <w:p> 收集到批量删除队列**,\n // 避免同一段上多个 ins/del 导致多次尝试 removeChild\n const paragraphsToDelete = new Set<Element>();\n const markedParts = new Set<string>();\n const addDirty = (el: Element): void => {\n const story = findStoryFor(ctx.pkg, el);\n if (story) markedParts.add(story.partPath);\n };\n\n for (const t of targets) {\n // 先 markDirty(基于处理前 t.el 仍挂在 DOM 上的 parent chain),再应用变更 ——\n // applyWrapper 会 removeChild 导致 t.el.parentNode 变 null,太晚查不到 story\n if (t.paragraph) addDirty(t.paragraph);\n applyToTarget(t, action, paragraphsToDelete, addDirty);\n if (action === 'accept') ctx.result.acceptedRevisions++;\n else ctx.result.rejectedRevisions++;\n }\n\n // 3. 统一删除段落(去重后)\n for (const p of paragraphsToDelete) {\n addDirty(p);\n p.parentNode?.removeChild(p);\n }\n\n // 4. markDirty 所有触达的 parts\n for (const partPath of markedParts) {\n const part = getPart(ctx.pkg, partPath);\n if (part) markDirty(part);\n }\n}\n\n// ─────────── target 收集 ───────────\n\nfunction collectTargets(\n ctx: ExecutorContext,\n scope: Extract<Op, { type: 'acceptRevisions' }>['scope'],\n): RevisionTarget[] {\n if (scope.scope === 'all') {\n return collectFromPkg(ctx);\n }\n if (scope.scope === 'paragraph') {\n const p = ctx.indices.paraIdx.get(scope.paraId.toUpperCase());\n if (!p) {\n throw new WordError(\n 'PARA_NOT_FOUND',\n `paragraph with paraId='${scope.paraId}' not found`,\n ctx.docId,\n { paraId: scope.paraId, opName: 'accept/rejectRevisions' },\n );\n }\n return collectFromSubtree(ctx, p);\n }\n // scope === 'revision'\n const all = collectFromPkg(ctx);\n const matched = all.filter((t) => {\n const id = t.el.getAttributeNS(W_NS, 'id') ?? t.el.getAttribute('w:id');\n return id === scope.revId;\n });\n if (matched.length === 0) {\n throw new WordError(\n 'REVISION_NOT_FOUND',\n `revision with revId='${scope.revId}' not found`,\n ctx.docId,\n { revId: scope.revId, opName: 'accept/rejectRevisions' },\n );\n }\n return matched;\n}\n\nfunction collectFromPkg(ctx: ExecutorContext): RevisionTarget[] {\n const out: RevisionTarget[] = [];\n for (const part of listParts(ctx.pkg)) {\n if (!isXmlPart(part) || !part.xmlDom) continue;\n const doc = part.xmlDom as Document;\n assertNoTier2Revisions(doc, ctx.docId, 'acceptRevisions');\n collectInsDelFromRoot(doc, out);\n }\n return out;\n}\n\nfunction collectFromSubtree(ctx: ExecutorContext, root: Element): RevisionTarget[] {\n assertNoTier2Revisions(root, ctx.docId, 'acceptRevisions');\n const out: RevisionTarget[] = [];\n collectInsDelFromRoot(root, out);\n return out;\n}\n\nfunction collectInsDelFromRoot(root: Document | Element, out: RevisionTarget[]): void {\n const insEls = root.getElementsByTagNameNS(W_NS, 'ins');\n const delEls = root.getElementsByTagNameNS(W_NS, 'del');\n for (let i = 0; i < insEls.length; i++) {\n const el = insEls[i];\n if (!el) continue;\n out.push(buildTarget(el, 'ins'));\n }\n for (let i = 0; i < delEls.length; i++) {\n const el = delEls[i];\n if (!el) continue;\n out.push(buildTarget(el, 'del'));\n }\n}\n\nfunction buildTarget(el: Element, kind: RevisionKind): RevisionTarget {\n const parent = el.parentNode;\n // 段落 mark 检测:parent 是 rPr,rPr 的 parent 是 pPr,pPr 的 parent 是 w:p\n let isParaMark = false;\n let paragraph: Element | null = null;\n if (\n parent &&\n parent.nodeType === 1 &&\n (parent as Element).namespaceURI === W_NS &&\n (parent as Element).localName === 'rPr'\n ) {\n const pPr = parent.parentNode;\n if (\n pPr &&\n pPr.nodeType === 1 &&\n (pPr as Element).namespaceURI === W_NS &&\n (pPr as Element).localName === 'pPr'\n ) {\n const p = pPr.parentNode;\n if (\n p &&\n p.nodeType === 1 &&\n (p as Element).namespaceURI === W_NS &&\n (p as Element).localName === 'p'\n ) {\n isParaMark = true;\n paragraph = p as Element;\n }\n }\n }\n if (!isParaMark) {\n paragraph = findContainingParagraph(el);\n }\n return { el, kind, isParaMark, paragraph };\n}\n\nfunction findContainingParagraph(el: Element): Element | null {\n let cur: Node | null = el.parentNode;\n while (cur && cur.nodeType === 1) {\n const e = cur as Element;\n if (e.namespaceURI === W_NS && e.localName === 'p') return e;\n cur = cur.parentNode;\n }\n return null;\n}\n\n// assertNoPropertyRevisions 已在 #33 提到 revision-queries.ts,更名为 assertNoTier2Revisions\n// 以读 / 写路径共用\n\n// ─────────── 单 target 应用 ───────────\n\nfunction applyToTarget(\n t: RevisionTarget,\n action: Action,\n paragraphsToDelete: Set<Element>,\n _addDirty: (el: Element) => void,\n): void {\n if (t.isParaMark) {\n applyParaMark(t, action, paragraphsToDelete);\n return;\n }\n // 正文 wrapper(markDirty 已在上层循环基于 t.paragraph 做完)\n applyWrapper(t, action);\n}\n\n/** 段落 mark 处理 */\nfunction applyParaMark(t: RevisionTarget, action: Action, paragraphsToDelete: Set<Element>): void {\n const p = t.paragraph!;\n const shouldDeleteParagraph =\n (t.kind === 'ins' && action === 'reject') || (t.kind === 'del' && action === 'accept');\n if (shouldDeleteParagraph) {\n paragraphsToDelete.add(p);\n } else {\n // 仅删 ins/del mark 标记,段保留\n t.el.parentNode?.removeChild(t.el);\n }\n}\n\n/** 正文 wrapper(`<w:ins>` / `<w:del>` 直接包裹 runs)处理 */\nfunction applyWrapper(t: RevisionTarget, action: Action): void {\n const el = t.el;\n const parent = el.parentNode;\n if (!parent) return;\n\n const keepContent =\n (t.kind === 'ins' && action === 'accept') || (t.kind === 'del' && action === 'reject');\n\n if (keepContent) {\n // 剥 wrapper,把内部 children 移到 wrapper 原位\n // del wrapper 的 reject:内部 <w:delText> 要转回 <w:t>\n const children = Array.from(el.childNodes);\n if (t.kind === 'del' && action === 'reject') {\n for (const c of children) {\n if (c.nodeType === 1) convertDelTextToT(c as Element);\n }\n }\n for (const c of children) {\n parent.insertBefore(c, el);\n }\n parent.removeChild(el);\n } else {\n // 整个 wrapper 连带内容一起删\n parent.removeChild(el);\n }\n}\n\n/** 递归把 `<w:delText>` 转回 `<w:t>`(reject del 用);属性搬 xml:space */\nfunction convertDelTextToT(el: Element): void {\n // 先递归处理子孙(深度优先,避免枚举中修改)\n const snapshot: Node[] = [];\n for (let i = 0; i < el.childNodes.length; i++) {\n const c = el.childNodes[i];\n if (c) snapshot.push(c);\n }\n for (const child of snapshot) {\n if (\n child.nodeType === 1 &&\n (child as Element).namespaceURI === W_NS &&\n (child as Element).localName === 'delText'\n ) {\n const delText = child as Element;\n const doc = delText.ownerDocument!;\n const t = doc.createElementNS(W_NS, 'w:t');\n // 搬属性(主要是 xml:space=\"preserve\")\n for (let i = 0; i < delText.attributes.length; i++) {\n const attr = delText.attributes[i];\n if (!attr) continue;\n if (attr.namespaceURI) {\n t.setAttributeNS(attr.namespaceURI, attr.name, attr.value);\n } else {\n t.setAttribute(attr.name, attr.value);\n }\n }\n t.textContent = delText.textContent;\n el.replaceChild(t, delText);\n } else if (child.nodeType === 1) {\n convertDelTextToT(child as Element);\n }\n }\n}\n","/**\n * SDT (Structured Document Tag, Content Control) XML 构建器 —— #188 表格域化。\n *\n * 设计:\n * - 三种子类型: Plain Text / Date Picker / Rich Text\n * - 输出 inline SDT (作 <w:r> 兄弟出现在 <w:p> 内), 段落 pPr 由调用方保留\n * - SDT id 由调用方传入 (典型: hash 输入对象保证幂等), 避免 builder 维护全局状态\n * - rPr 可由调用方拷贝原 run 的 rPr 传入, 保留字体 / 颜色 / 字号等字符属性\n *\n * SDT id 取值: OOXML 规定 32-bit signed integer; Word 加载时容错并按需重分配,\n * 调用方不必严格保证全局唯一, hash 取值即可。\n *\n * 参考: ECMA-376 §17.5 Structured Document Tags。\n */\n\nimport { W_NS, XML_NS } from './namespaces.js';\n\n// ─────────── 公开类型 ───────────\n\n/**\n * SDT 配置 (JSON-serializable, 可走 plan op RPC)。\n *\n * `rPr` 字符属性透传不在 spec 内 —— DOM Element 不能 JSON 序列化, 由 executor 在\n * 替换时从原 run 直接克隆并传给 `buildInlineSdt` 的 `rPr` 参数。\n */\ninterface SdtSpecBase {\n /** UI 显示名 (Word \"Click here...\" 上方的提示标签) */\n alias: string;\n /**\n * 程序匹配 tag (后续模板填充阶段按 tag 定位 SDT)。\n * 缺省时按 `alias` trim + 空白转 `_`。\n */\n tag?: string;\n /** 占位提示文本; 缺省 `\"请输入\" + alias` */\n placeholderText?: string;\n}\n\nexport interface PlainTextSdtSpec extends SdtSpecBase {\n kind: 'text';\n}\n\nexport interface DateSdtSpec extends SdtSpecBase {\n kind: 'date';\n /** 日期格式 (e.g. \"yyyy-M-d\"), 缺省 \"yyyy-M-d\" */\n dateFormat?: string;\n /** Locale, 缺省 \"zh-CN\" */\n locale?: string;\n}\n\nexport interface RichTextSdtSpec extends SdtSpecBase {\n kind: 'richText';\n}\n\nexport type SdtSpec = PlainTextSdtSpec | DateSdtSpec | RichTextSdtSpec;\n\n// ─────────── 主入口 ───────────\n\n/**\n * 构建一个 inline SDT 元素 (`<w:sdt>`), 用于段落内 run 替换场景。\n *\n * 结构:\n * <w:sdt>\n * <w:sdtPr>\n * (rPr?)\n * <w:alias w:val=\"...\"/>\n * <w:tag w:val=\"...\"/>\n * <w:id w:val=\"...\"/>\n * <w:placeholder><w:docPart w:val=\"DefaultPlaceholder_-1854013440\"/></w:placeholder>\n * <w:showingPlcHdr/>\n * (类型标记: <w:text/> | <w:date.../> | <w:richText/>)\n * </w:sdtPr>\n * <w:sdtContent>\n * <w:r>(rPr?)<w:t xml:space=\"preserve\">placeholderText</w:t></w:r>\n * </w:sdtContent>\n * </w:sdt>\n *\n * @param doc owner Document (来自 paragraph.ownerDocument)\n * @param spec SDT 配置 (JSON-serializable)\n * @param id 32-bit 整数 ID; 推荐用 hashSdtId(tableId, row, col, alias) 算\n * @param rPr 可选, 从原 run 克隆的 `<w:rPr>` —— 字符属性透传, 同时挂到\n * sdtPr 与 sdtContent 内 placeholder run 上\n */\nexport function buildInlineSdt(doc: Document, spec: SdtSpec, id: number, rPr?: Element): Element {\n const sdt = createW(doc, 'sdt');\n\n // ─── sdtPr ───\n const sdtPr = createW(doc, 'sdtPr');\n sdt.appendChild(sdtPr);\n\n // rPr (字符属性透传, 影响 sdt 内 placeholder run 的默认字符样式)\n if (rPr) {\n sdtPr.appendChild(rPr.cloneNode(true));\n }\n\n // alias\n const alias = createW(doc, 'alias');\n alias.setAttributeNS(W_NS, 'w:val', spec.alias);\n sdtPr.appendChild(alias);\n\n // tag\n const tag = createW(doc, 'tag');\n tag.setAttributeNS(W_NS, 'w:val', spec.tag ?? deriveTag(spec.alias));\n sdtPr.appendChild(tag);\n\n // id\n const idEl = createW(doc, 'id');\n idEl.setAttributeNS(W_NS, 'w:val', String(normalizeSdtId(id)));\n sdtPr.appendChild(idEl);\n\n // placeholder → docPart 引用 (Word 默认占位)\n const placeholder = createW(doc, 'placeholder');\n const docPart = createW(doc, 'docPart');\n docPart.setAttributeNS(W_NS, 'w:val', 'DefaultPlaceholder_-1854013440');\n placeholder.appendChild(docPart);\n sdtPr.appendChild(placeholder);\n\n // showingPlcHdr (当前显示占位符状态)\n sdtPr.appendChild(createW(doc, 'showingPlcHdr'));\n\n // 类型标记\n switch (spec.kind) {\n case 'text':\n sdtPr.appendChild(createW(doc, 'text'));\n break;\n case 'richText':\n sdtPr.appendChild(createW(doc, 'richText'));\n break;\n case 'date':\n sdtPr.appendChild(buildDateChild(doc, spec));\n break;\n }\n\n // ─── sdtContent ───\n const sdtContent = createW(doc, 'sdtContent');\n sdt.appendChild(sdtContent);\n\n const placeholderText = spec.placeholderText ?? `请输入${spec.alias}`;\n const run = createW(doc, 'r');\n if (rPr) {\n run.appendChild(rPr.cloneNode(true));\n }\n const t = createW(doc, 't');\n t.setAttributeNS(XML_NS, 'xml:space', 'preserve');\n t.textContent = placeholderText;\n run.appendChild(t);\n sdtContent.appendChild(run);\n\n return sdt;\n}\n\n// ─────────── ID hash ───────────\n\n/**\n * 由 (tableId, row, col, alias) 算 SDT id (djb2 hash → 32-bit signed)。\n *\n * 幂等性保证: 同一组输入永远产出同一 id, 重跑骨架化不会因 id 变化制造无意义 diff。\n */\nexport function hashSdtId(tableId: string, row: number, col: number, alias: string): number {\n const input = `${tableId}|${row}|${col}|${alias}`;\n let h = 5381;\n for (let i = 0; i < input.length; i++) {\n h = ((h << 5) + h + input.charCodeAt(i)) | 0;\n }\n return normalizeSdtId(h);\n}\n\n/** SDT id 取 32-bit signed 范围内的正数, 避免负号引起 XML 兼容性问题。 */\nfunction normalizeSdtId(id: number): number {\n const n = id | 0;\n return n < 0 ? -n : n;\n}\n\n// ─────────── 内部工具 ───────────\n\nfunction createW(doc: Document, localName: string): Element {\n return doc.createElementNS(W_NS, `w:${localName}`);\n}\n\nfunction buildDateChild(doc: Document, spec: DateSdtSpec): Element {\n const date = createW(doc, 'date');\n\n const dateFormat = createW(doc, 'dateFormat');\n dateFormat.setAttributeNS(W_NS, 'w:val', spec.dateFormat ?? 'yyyy-M-d');\n date.appendChild(dateFormat);\n\n const lid = createW(doc, 'lid');\n lid.setAttributeNS(W_NS, 'w:val', spec.locale ?? 'zh-CN');\n date.appendChild(lid);\n\n const storeAs = createW(doc, 'storeMappedDataAs');\n storeAs.setAttributeNS(W_NS, 'w:val', 'dateTime');\n date.appendChild(storeAs);\n\n const calendar = createW(doc, 'calendar');\n calendar.setAttributeNS(W_NS, 'w:val', 'gregorian');\n date.appendChild(calendar);\n\n return date;\n}\n\n/**\n * 从 alias 派生 tag: 中文 alias 第一版直接返回原值 (OOXML 允许 tag 含 Unicode);\n * 仅做 trim + 去内部空白。后续可加 pinyin 转换或 hash 标识。\n */\nfunction deriveTag(alias: string): string {\n return alias.trim().replace(/\\s+/g, '_');\n}\n","/**\n * 表格 executor —— #186(addTableComment / deleteTable)。\n *\n * 设计要点:\n * - 入口都是 `tableId`(装载期分配的 'tbl-NNNN',来源:`indices.tblIdx`),不接\n * Element / paraId,避免调用方自己绕 DOM 反查。\n * - addTableComment:语义\"给表格挂批注\",实现\"挂在表格首单元格首段\",复用\n * `attachCommentToParagraph`。这条决定由 docs/07 §06 推论:批注是 #186 决策\n * 理由的可追溯载体,挂表格内段落不会污染表外正文,删表时 drop 模式还能连带\n * 清理(锚点都在表内段落上)。\n * - deleteTable:扫表内所有段落收锚点(书签 + 批注 ID),无锚点直接 removeChild;\n * 有锚点按 onAnchorConflict='error'(默认)抛 ANCHOR_CONFLICT,'drop' 则连带\n * 清理后删表。drop 实现复用段落 deleteParagraph 的清理路径(逐段调,带 drop)。\n * - trackChanges=true 暂不支持(同 deleteParagraph 行为,留 follow-up)。\n * - setTableColumnWidths(task-core-table-grid):只设 tblGrid gridCol w:w,\n * 不动单元格 tcW(本 case 表格 tblLayout=fixed 且无 tcW;若将来 auto-layout\n * 带 tcW 需同步,记 follow-up,不在本 task 范围)。\n */\nimport { getPart, isXmlPart, listParts, markDirty } from '../../pack/index.js';\nimport { findStoryFor } from '../stories.js';\nimport { W_NS, W14_NS, XML_NS } from '../namespaces.js';\nimport type { Op } from '../plan.js';\nimport { WordError } from '../word-error.js';\nimport { attachCommentToParagraph, cleanupEmptyCommentsPart } from './comment-ops.js';\nimport { buildInlineSdt, hashSdtId } from '../sdt-builders.js';\nimport { appendTextAsRuns, collectParagraphAnchors, pickFirstRunRPr } from './_shared.js';\nimport type { ExecutorContext } from './executor-context.js';\nimport { generateParaId } from '../para-id.js';\n\nconst COMMENTS_PART_PATH = 'word/comments.xml';\n\n// ─────────── addTableComment ───────────\n\nexport function executeAddTableComment(\n ctx: ExecutorContext,\n op: Extract<Op, { type: 'addTableComment' }>,\n): void {\n if (ctx.options.trackChanges) {\n throw new WordError(\n 'UNSUPPORTED_OOXML_FEATURE',\n 'addTableComment with trackChanges=true not yet implemented',\n ctx.docId,\n { opType: 'addTableComment', tableId: op.tableId },\n );\n }\n\n const tbl = requireTable(ctx, op.tableId, 'addTableComment');\n const firstPara = findFirstParagraphInTable(tbl);\n if (!firstPara) {\n // 健壮性降级(绝不崩):OOXML 名义上要求每个 <w:tc> 至少一个 <w:p>,但真实文档\n // (poi2-Bug54771a:单元格无 <w:p>)会违反。批注是诊断辅助(题注/角色标注),\n // 无可挂载段时跳过该条批注即可——不影响文档主体内容,绝不为此回滚整个 plan 而崩。\n // 用 warn 显式记录降级(不静默吞),保持可观测。\n console.warn(\n `[word] addTableComment: table '${op.tableId}' contains no <w:p>; ` +\n `skip this comment (degrade, docId: ${ctx.docId})`,\n );\n return;\n }\n\n attachCommentToParagraph(ctx, firstPara, op.text, {\n author: op.author,\n date: op.date,\n });\n // 不写 ApplyResult.createdComments —— addTableComment 不像 addComment 那样\n // 要把 id 回传给调用方(调用方握的是 tableId,不需要 commentId)。\n}\n\n// ─────────── deleteTable ───────────\n\nexport function executeDeleteTable(\n ctx: ExecutorContext,\n op: Extract<Op, { type: 'deleteTable' }>,\n): void {\n if (ctx.options.trackChanges) {\n throw new WordError(\n 'UNSUPPORTED_OOXML_FEATURE',\n 'deleteTable with trackChanges=true not yet implemented',\n ctx.docId,\n { opType: 'deleteTable', tableId: op.tableId },\n );\n }\n\n const tbl = requireTable(ctx, op.tableId, 'deleteTable');\n\n // 收集表内所有活锚点(书签 / 批注)\n const affectedBookmarks = collectBookmarkNamesInTable(tbl);\n const affectedComments = collectCommentIdsInTable(tbl);\n const hasAnchors = affectedBookmarks.length > 0 || affectedComments.length > 0;\n\n if (hasAnchors) {\n if (op.onAnchorConflict === 'error') {\n throw new WordError(\n 'ANCHOR_CONFLICT',\n `table '${op.tableId}' contains active anchors (bookmarks: ${affectedBookmarks.join(', ') || 'none'}, comments: ${affectedComments.join(', ') || 'none'})`,\n ctx.docId,\n {\n tableId: op.tableId,\n affectedBookmarks,\n affectedComments,\n opType: 'deleteTable',\n },\n );\n }\n // drop:连带清理\n for (const name of affectedBookmarks) {\n dropBookmarkByName(ctx, name);\n }\n for (const id of affectedComments) {\n dropCommentById(ctx, id, tbl);\n }\n }\n\n // markDirty 必须在 removeChild 之前(removeChild 后 findStoryFor 找不到 tbl)\n markStoryPartDirty(ctx, tbl, 'deleteTable');\n\n const parent = tbl.parentNode;\n if (!parent) {\n throw new WordError('PACKAGE_CORRUPT', `table '${op.tableId}' has no parentNode`, ctx.docId, {\n tableId: op.tableId,\n });\n }\n parent.removeChild(tbl);\n\n // 索引同步:applyPlan finally 块会 buildIndices 全量重建,这里先从 tblIdx 删,\n // 避免后续 op 在同一 plan 内复用已游离的 tblIdx 条目。\n ctx.indices.tblIdx.delete(op.tableId);\n}\n\n// ─────────── replaceTableCellWithSdt(#188)───────────\n\nexport function executeReplaceTableCellWithSdt(\n ctx: ExecutorContext,\n op: Extract<Op, { type: 'replaceTableCellWithSdt' }>,\n): void {\n if (ctx.options.trackChanges) {\n throw new WordError(\n 'UNSUPPORTED_OOXML_FEATURE',\n 'replaceTableCellWithSdt with trackChanges=true not yet implemented',\n ctx.docId,\n { opType: 'replaceTableCellWithSdt', tableId: op.tableId },\n );\n }\n\n const tbl = requireTable(ctx, op.tableId, 'replaceTableCellWithSdt');\n const tc = findCell(tbl, op.row, op.col);\n if (!tc) {\n throw new WordError(\n 'TABLE_NOT_FOUND',\n `cell at (${op.row}, ${op.col}) not found in table '${op.tableId}'`,\n ctx.docId,\n { tableId: op.tableId, row: op.row, col: op.col, opType: 'replaceTableCellWithSdt' },\n );\n }\n\n const firstPara = firstChildW(tc, 'p');\n if (!firstPara) {\n throw new WordError(\n 'PACKAGE_CORRUPT',\n `cell at (${op.row}, ${op.col}) in table '${op.tableId}' has no <w:p>`,\n ctx.docId,\n { tableId: op.tableId, row: op.row, col: op.col },\n );\n }\n\n // 锚点冲突检测 (与 replaceParagraph 行为对齐)\n const anchors = collectParagraphAnchors(firstPara);\n if (anchors.bookmarks.length > 0 || anchors.comments.length > 0) {\n if (op.onAnchorConflict === 'drop') {\n // drop: 跳过本次替换, 保留单元格内容不变。\n // 不计入 result.replacedTableCells (#204), phase 据此报告准确域化数。\n return;\n }\n throw new WordError(\n 'ANCHOR_CONFLICT',\n `table cell (${op.row}, ${op.col}) modification conflicts with active anchors ` +\n `in table '${op.tableId}'; enable trackChanges or use onAnchorConflict='drop'`,\n ctx.docId,\n {\n tableId: op.tableId,\n row: op.row,\n col: op.col,\n affectedBookmarks: anchors.bookmarks,\n affectedComments: anchors.comments,\n opType: 'replaceTableCellWithSdt',\n },\n );\n }\n\n // 从原首段首 run 取 rPr 透传 (字体 / 颜色 / 字号不丢)\n const inheritedRPr = pickFirstRunRPr(firstPara);\n\n // 替换段落内容: 保留 pPr, 移除其余子节点, 追加 SDT\n const doc = firstPara.ownerDocument;\n if (!doc) {\n throw new WordError('PACKAGE_CORRUPT', 'paragraph has no ownerDocument', ctx.docId, {\n tableId: op.tableId,\n opType: 'replaceTableCellWithSdt',\n });\n }\n\n const id = hashSdtId(op.tableId, op.row, op.col, op.sdt.alias);\n const sdt = buildInlineSdt(doc, op.sdt, id, inheritedRPr);\n\n removeNonPPrChildren(firstPara);\n firstPara.appendChild(sdt);\n\n markStoryPartDirty(ctx, firstPara, 'replaceTableCellWithSdt');\n\n // #204: 真正替换完成才计数 (drop 模式下 anchor 冲突已 return, 不会到这)\n ctx.result.replacedTableCells++;\n}\n\n// ─────────── replaceTableCellText(填纯文字,保留 tcPr/rPr)───────────\n\nexport function executeReplaceTableCellText(\n ctx: ExecutorContext,\n op: Extract<Op, { type: 'replaceTableCellText' }>,\n): void {\n if (ctx.options.trackChanges) {\n throw new WordError(\n 'UNSUPPORTED_OOXML_FEATURE',\n 'replaceTableCellText with trackChanges=true not yet implemented',\n ctx.docId,\n { opType: 'replaceTableCellText', tableId: op.tableId },\n );\n }\n\n const tbl = requireTable(ctx, op.tableId, 'replaceTableCellText');\n const tc = findCell(tbl, op.row, op.col);\n if (!tc) {\n throw new WordError(\n 'TABLE_NOT_FOUND',\n `cell at (${op.row}, ${op.col}) not found in table '${op.tableId}'`,\n ctx.docId,\n { tableId: op.tableId, row: op.row, col: op.col, opType: 'replaceTableCellText' },\n );\n }\n\n const firstPara = firstChildW(tc, 'p');\n if (!firstPara) {\n throw new WordError(\n 'PACKAGE_CORRUPT',\n `cell at (${op.row}, ${op.col}) in table '${op.tableId}' has no <w:p>`,\n ctx.docId,\n { tableId: op.tableId, row: op.row, col: op.col },\n );\n }\n\n // 锚点冲突检测(与 replaceTableCellWithSdt 语义对齐)\n const anchors = collectParagraphAnchors(firstPara);\n if (anchors.bookmarks.length > 0 || anchors.comments.length > 0) {\n if (op.onAnchorConflict === 'drop') {\n // drop:跳过本次替换,保留单元格内容不变。不计入 result.replacedTableCells。\n return;\n }\n throw new WordError(\n 'ANCHOR_CONFLICT',\n `table cell (${op.row}, ${op.col}) modification conflicts with active anchors ` +\n `in table '${op.tableId}'; enable trackChanges or use onAnchorConflict='drop'`,\n ctx.docId,\n {\n tableId: op.tableId,\n row: op.row,\n col: op.col,\n affectedBookmarks: anchors.bookmarks,\n affectedComments: anchors.comments,\n opType: 'replaceTableCellText',\n },\n );\n }\n\n // 从原首段首 run 取 rPr 透传(字体 / 颜色 / 字号不丢)\n const inheritedRPr = pickFirstRunRPr(firstPara);\n\n // 替换段落内容:保留 pPr,移除其余子节点,追加纯文字 run\n const doc = firstPara.ownerDocument;\n if (!doc) {\n throw new WordError('PACKAGE_CORRUPT', 'paragraph has no ownerDocument', ctx.docId, {\n tableId: op.tableId,\n opType: 'replaceTableCellText',\n });\n }\n\n // 构造 <w:r>{rPr?}<w:t xml:space=\"preserve\">{text}</w:t></w:r>\n const run = doc.createElementNS(W_NS, 'w:r');\n if (inheritedRPr) {\n run.appendChild(inheritedRPr); // 已是 cloneNode(true),直接追加\n }\n const t = doc.createElementNS(W_NS, 'w:t');\n t.setAttributeNS(XML_NS, 'xml:space', 'preserve');\n t.textContent = op.text;\n run.appendChild(t);\n\n removeNonPPrChildren(firstPara);\n firstPara.appendChild(run);\n\n markStoryPartDirty(ctx, firstPara, 'replaceTableCellText');\n\n // 真正替换完成才计数(drop 模式下 anchor 冲突已 return,不会到这)\n ctx.result.replacedTableCells++;\n}\n\n// ─────────── deleteTableRow(#188 §7.2)───────────\n\nexport function executeFormatTableCell(\n ctx: ExecutorContext,\n op: Extract<Op, { type: 'formatTableCell' }>,\n): void {\n if (ctx.options.trackChanges) {\n throw new WordError(\n 'UNSUPPORTED_OOXML_FEATURE',\n 'formatTableCell does not support trackChanges yet',\n ctx.docId,\n { tableId: op.tableId, row: op.row, col: op.col, opType: 'formatTableCell' },\n );\n }\n\n validateTableCellFormat(ctx, op);\n\n const tbl = requireTable(ctx, op.tableId, 'formatTableCell');\n const tc = findCell(tbl, op.row, op.col);\n if (!tc) {\n throw new WordError(\n 'TABLE_NOT_FOUND',\n `cell at (${op.row}, ${op.col}) not found in table '${op.tableId}'`,\n ctx.docId,\n { tableId: op.tableId, row: op.row, col: op.col, opType: 'formatTableCell' },\n );\n }\n\n const tcPr = ensureTableCellProperties(tc);\n\n if (op.format.width !== undefined) {\n const tcW = upsertTcPrChild(tcPr, 'tcW', TCW_AFTER_LOCALS);\n tcW.setAttributeNS(W_NS, 'w:w', String(op.format.width));\n tcW.setAttributeNS(W_NS, 'w:type', 'dxa');\n }\n\n if (op.format.shading !== undefined) {\n const shd = upsertTcPrChild(tcPr, 'shd', SHD_AFTER_LOCALS);\n if (op.format.shading.val !== undefined) {\n shd.setAttributeNS(W_NS, 'w:val', op.format.shading.val);\n } else if (op.format.shading.fill !== undefined && !shd.hasAttributeNS(W_NS, 'val')) {\n shd.setAttributeNS(W_NS, 'w:val', 'clear');\n }\n if (op.format.shading.color !== undefined) {\n shd.setAttributeNS(W_NS, 'w:color', op.format.shading.color);\n }\n if (op.format.shading.fill !== undefined) {\n shd.setAttributeNS(W_NS, 'w:fill', op.format.shading.fill);\n }\n }\n\n if (op.format.verticalAlignment !== undefined) {\n const vAlign = upsertTcPrChild(tcPr, 'vAlign', VALIGN_AFTER_LOCALS);\n vAlign.setAttributeNS(W_NS, 'w:val', op.format.verticalAlignment);\n }\n\n markStoryPartDirty(ctx, tc, 'formatTableCell');\n}\n\nexport function executeInsertTableCellParagraph(\n ctx: ExecutorContext,\n op: Extract<Op, { type: 'insertTableCellParagraph' }>,\n): void {\n if (ctx.options.trackChanges) {\n throw new WordError(\n 'UNSUPPORTED_OOXML_FEATURE',\n 'insertTableCellParagraph does not support trackChanges yet',\n ctx.docId,\n { tableId: op.tableId, row: op.row, col: op.col, opType: 'insertTableCellParagraph' },\n );\n }\n\n if (typeof op.text !== 'string') {\n throw new WordError(\n 'INVALID_ARGUMENT',\n 'insertTableCellParagraph text must be a string',\n ctx.docId,\n { tableId: op.tableId, row: op.row, col: op.col, opType: 'insertTableCellParagraph' },\n );\n }\n if (op.position !== 'start' && op.position !== 'end') {\n throw new WordError(\n 'INVALID_ARGUMENT',\n 'insertTableCellParagraph position must be start or end',\n ctx.docId,\n { tableId: op.tableId, row: op.row, col: op.col, position: op.position },\n );\n }\n\n const tbl = requireTable(ctx, op.tableId, 'insertTableCellParagraph');\n const tc = findCell(tbl, op.row, op.col);\n if (!tc) {\n throw new WordError(\n 'TABLE_NOT_FOUND',\n `cell at (${op.row}, ${op.col}) not found in table '${op.tableId}'`,\n ctx.docId,\n { tableId: op.tableId, row: op.row, col: op.col, opType: 'insertTableCellParagraph' },\n );\n }\n\n const doc = tc.ownerDocument;\n if (!doc) {\n throw new WordError('PACKAGE_CORRUPT', 'table cell has no ownerDocument', ctx.docId, {\n tableId: op.tableId,\n row: op.row,\n col: op.col,\n opType: 'insertTableCellParagraph',\n });\n }\n\n const seen = new Set(ctx.indices.paraIdx.keys());\n const newId = generateParaId(seen);\n const newPara = doc.createElementNS(W_NS, 'w:p');\n newPara.setAttributeNS(W14_NS, 'w14:paraId', newId);\n appendTextAsRuns(newPara, op.text);\n\n if (op.position === 'start') {\n tc.insertBefore(newPara, firstCellContentChild(tc));\n } else {\n tc.appendChild(newPara);\n }\n\n ctx.indices.paraIdx.set(newId.toUpperCase(), newPara);\n ctx.result.insertedParagraphs.push({\n opIndex: ctx.opIndex,\n anchorParaId: newId,\n position: op.position === 'start' ? 'before' : 'after',\n newParaId: newId,\n });\n markStoryPartDirty(ctx, tc, 'insertTableCellParagraph');\n}\n\nexport function executeDeleteTableRow(\n ctx: ExecutorContext,\n op: Extract<Op, { type: 'deleteTableRow' }>,\n): void {\n if (ctx.options.trackChanges) {\n throw new WordError(\n 'UNSUPPORTED_OOXML_FEATURE',\n 'deleteTableRow with trackChanges=true not yet implemented',\n ctx.docId,\n { opType: 'deleteTableRow', tableId: op.tableId, row: op.row },\n );\n }\n\n const tbl = requireTable(ctx, op.tableId, 'deleteTableRow');\n const tr = findTableRow(tbl, op.row);\n if (!tr) {\n throw new WordError(\n 'TABLE_NOT_FOUND',\n `row ${op.row} not found in table '${op.tableId}'`,\n ctx.docId,\n { tableId: op.tableId, row: op.row, opType: 'deleteTableRow' },\n );\n }\n\n // 锚点冲突: 行内段落含书签 / 批注时按 onAnchorConflict 处理\n const affectedBookmarks: string[] = [];\n {\n const list = tr.getElementsByTagNameNS(W_NS, 'bookmarkStart');\n for (let i = 0; i < list.length; i++) {\n const el = list[i];\n if (!el) continue;\n const name = el.getAttributeNS(W_NS, 'name') ?? el.getAttribute('w:name') ?? '';\n affectedBookmarks.push(name);\n }\n }\n const affectedComments: number[] = [];\n {\n const idSet = new Set<number>();\n for (const local of ['commentRangeStart', 'commentReference']) {\n const list = tr.getElementsByTagNameNS(W_NS, local);\n for (let i = 0; i < list.length; i++) {\n const el = list[i];\n if (!el) continue;\n const raw = el.getAttributeNS(W_NS, 'id') ?? el.getAttribute('w:id') ?? '';\n const id = parseInt(raw, 10);\n if (!isNaN(id)) idSet.add(id);\n }\n }\n for (const id of idSet) affectedComments.push(id);\n }\n\n if (affectedBookmarks.length > 0 || affectedComments.length > 0) {\n if (op.onAnchorConflict === 'error') {\n throw new WordError(\n 'ANCHOR_CONFLICT',\n `table row (${op.tableId} row ${op.row}) contains active anchors ` +\n `(bookmarks: ${affectedBookmarks.join(', ') || 'none'}, ` +\n `comments: ${affectedComments.join(', ') || 'none'})`,\n ctx.docId,\n {\n tableId: op.tableId,\n row: op.row,\n affectedBookmarks,\n affectedComments,\n opType: 'deleteTableRow',\n },\n );\n }\n // drop: 连带清理\n for (const name of affectedBookmarks) {\n dropBookmarkByName(ctx, name);\n }\n for (const id of affectedComments) {\n dropCommentById(ctx, id, tr);\n }\n }\n\n // markDirty 必须在 removeChild 之前\n markStoryPartDirty(ctx, tr, 'deleteTableRow');\n\n const parent = tr.parentNode;\n if (!parent) {\n throw new WordError(\n 'PACKAGE_CORRUPT',\n `row of table '${op.tableId}' has no parentNode`,\n ctx.docId,\n {\n tableId: op.tableId,\n row: op.row,\n },\n );\n }\n parent.removeChild(tr);\n}\n\n// ─────────── insertTableRow(#14)───────────\n\nexport function executeInsertTableRow(\n ctx: ExecutorContext,\n op: Extract<Op, { type: 'insertTableRow' }>,\n): void {\n if (ctx.options.trackChanges) {\n throw new WordError(\n 'UNSUPPORTED_OOXML_FEATURE',\n 'insertTableRow with trackChanges=true not yet implemented',\n ctx.docId,\n { opType: 'insertTableRow', tableId: op.tableId },\n );\n }\n\n // 1. 拿表格\n const tbl = requireTable(ctx, op.tableId, 'insertTableRow');\n\n // 2. 找模板行\n const templateTr = findTableRow(tbl, op.templateRow);\n if (!templateTr) {\n throw new WordError(\n 'TABLE_NOT_FOUND',\n `template row ${op.templateRow} not found in table '${op.tableId}'`,\n ctx.docId,\n { tableId: op.tableId, templateRow: op.templateRow, opType: 'insertTableRow' },\n );\n }\n\n // 3. 统计当前行数 + 校验 position\n let rowCount = 0;\n for (let i = 0; i < tbl.childNodes.length; i++) {\n const c = tbl.childNodes[i];\n if (\n c &&\n c.nodeType === 1 &&\n (c as Element).namespaceURI === W_NS &&\n (c as Element).localName === 'tr'\n ) {\n rowCount++;\n }\n }\n\n let insertPos: number;\n if (op.position === 'end') {\n insertPos = rowCount;\n } else {\n if (op.position < 0 || op.position > rowCount) {\n throw new WordError(\n 'TABLE_NOT_FOUND',\n `position ${op.position} out of range [0, ${rowCount}] in table '${op.tableId}'`,\n ctx.docId,\n { tableId: op.tableId, position: op.position, rowCount, opType: 'insertTableRow' },\n );\n }\n insertPos = op.position;\n }\n\n // 4. 克隆模板行\n const newTr = templateTr.cloneNode(true) as Element;\n\n // 5. 剥离克隆行内锚点\n stripAnchorsFromClone(newTr);\n\n // 6. 重分配克隆行内每个 <w:p> 的 paraId\n reassignClonedParaIds(ctx, newTr);\n\n // 7. 填 cellTexts(若传)\n if (op.cellTexts !== undefined) {\n fillCellTexts(newTr, op.cellTexts);\n }\n\n // 8. 插入 DOM(markDirty 必须在 newTr 进树之后)\n if (insertPos === rowCount) {\n tbl.appendChild(newTr);\n } else {\n // 找第 insertPos 个 <w:tr>\n let trIdx = 0;\n let refNode: Element | null = null;\n for (let i = 0; i < tbl.childNodes.length; i++) {\n const c = tbl.childNodes[i];\n if (\n c &&\n c.nodeType === 1 &&\n (c as Element).namespaceURI === W_NS &&\n (c as Element).localName === 'tr'\n ) {\n if (trIdx === insertPos) {\n refNode = c as Element;\n break;\n }\n trIdx++;\n }\n }\n tbl.insertBefore(newTr, refNode);\n }\n\n // 9. markDirty(节点已在树内)\n markStoryPartDirty(ctx, newTr, 'insertTableRow');\n}\n\n// ─────────── cloneTableAfter(#15)───────────\n\nexport function executeCloneTableAfter(\n ctx: ExecutorContext,\n op: Extract<Op, { type: 'cloneTableAfter' }>,\n): void {\n if (ctx.options.trackChanges) {\n throw new WordError(\n 'UNSUPPORTED_OOXML_FEATURE',\n 'cloneTableAfter with trackChanges=true not yet implemented',\n ctx.docId,\n { opType: 'cloneTableAfter', sourceTableId: op.sourceTableId },\n );\n }\n\n // 2. 查 anchor 段\n const anchor = ctx.indices.paraIdx.get(op.anchorParaId.toUpperCase());\n if (!anchor) {\n throw new WordError(\n 'PARA_NOT_FOUND',\n `paragraph with paraId='${op.anchorParaId}' not found (op: cloneTableAfter)`,\n ctx.docId,\n { paraId: op.anchorParaId, opName: 'cloneTableAfter' },\n );\n }\n\n // 3. 查源表\n const sourceTbl = requireTable(ctx, op.sourceTableId, 'cloneTableAfter');\n\n // 4. 深克隆\n const cloned = sourceTbl.cloneNode(true) as Element;\n\n // 5. 剥离克隆表内锚点\n stripAnchorsFromClone(cloned);\n\n // 6. 重分配克隆表内所有 <w:p> 的 paraId\n reassignClonedParaIds(ctx, cloned);\n\n // 7. 插入 DOM:紧贴 anchor 之后(insertBefore(cloned, anchor.nextSibling))\n const parent = anchor.parentNode;\n if (!parent) {\n throw new WordError(\n 'PACKAGE_CORRUPT',\n `anchor paragraph '${op.anchorParaId}' has no parentNode`,\n ctx.docId,\n { paraId: op.anchorParaId, opName: 'cloneTableAfter' },\n );\n }\n parent.insertBefore(cloned, anchor.nextSibling);\n\n // 8. markDirty(节点已在树内)\n markStoryPartDirty(ctx, cloned, 'cloneTableAfter');\n}\n\n/**\n * 重分配克隆子树内所有 `<w:p>` 的 paraId(全局唯一)。\n *\n * 从当前 `paraIdx.keys()` 构建 seen 集合,遍历节点内所有 `<w:p>`,\n * 用 `generateParaId(seen)` 分配新 id(generateParaId 内部自动 add,防同棵树多段冲突)。\n * 仅限 table-ops.ts 内部使用,供 insertTableRow 和 cloneTableAfter 共享。\n */\nfunction reassignClonedParaIds(ctx: ExecutorContext, node: Element): void {\n const seen = new Set(ctx.indices.paraIdx.keys());\n const paragraphs = node.getElementsByTagNameNS(W_NS, 'p');\n // 快照成数组避免 live collection 问题\n const paraSnapshot: Element[] = [];\n for (let i = 0; i < paragraphs.length; i++) {\n const p = paragraphs[i];\n if (p) paraSnapshot.push(p);\n }\n for (const p of paraSnapshot) {\n const newId = generateParaId(seen);\n p.setAttributeNS(W14_NS, 'w14:paraId', newId);\n }\n}\n\n/**\n * 剥离克隆行内所有锚点元素:\n * - bookmarkStart / bookmarkEnd\n * - commentRangeStart / commentRangeEnd\n * - commentReference(连同空 run 一并清)\n */\nfunction stripAnchorsFromClone(tr: Element): void {\n const anchorLocals = ['bookmarkStart', 'bookmarkEnd', 'commentRangeStart', 'commentRangeEnd'];\n for (const local of anchorLocals) {\n const list = tr.getElementsByTagNameNS(W_NS, local);\n // 快照避免 live collection 修改问题\n const toRemove: Element[] = [];\n for (let i = 0; i < list.length; i++) {\n const el = list[i];\n if (el) toRemove.push(el);\n }\n for (const el of toRemove) {\n if (el.parentNode) el.parentNode.removeChild(el);\n }\n }\n\n // commentReference:连同空 run 一并清\n const refs = tr.getElementsByTagNameNS(W_NS, 'commentReference');\n const refSnapshot: Element[] = [];\n for (let i = 0; i < refs.length; i++) {\n const el = refs[i];\n if (el) refSnapshot.push(el);\n }\n for (const ref of refSnapshot) {\n const parentRun = ref.parentNode;\n if (ref.parentNode) ref.parentNode.removeChild(ref);\n // 若 run 仅剩 rPr(或完全空),一并删除\n if (\n parentRun &&\n parentRun.nodeType === 1 &&\n (parentRun as Element).namespaceURI === W_NS &&\n (parentRun as Element).localName === 'r' &&\n isRunEffectivelyEmpty(parentRun as Element)\n ) {\n if (parentRun.parentNode) parentRun.parentNode.removeChild(parentRun);\n }\n }\n}\n\n/**\n * 按 §1.3 语义填充克隆行各列文字。\n * 设列数 C,cellTexts 长度 L:\n * - i ∈ [0, min(L,C)):替换该列单元格首段为 cellTexts[i](保留 tcPr/pPr/首 run rPr)\n * - i ∈ [L, C):清空该列(removeNonPPrChildren,不添加文字 run)\n * - i ≥ C:忽略(cellTexts 超出列数的元素)\n */\nfunction fillCellTexts(tr: Element, cellTexts: string[]): void {\n // 收集直属 <w:tc>\n const tcs: Element[] = [];\n for (let i = 0; i < tr.childNodes.length; i++) {\n const c = tr.childNodes[i];\n if (\n c &&\n c.nodeType === 1 &&\n (c as Element).namespaceURI === W_NS &&\n (c as Element).localName === 'tc'\n ) {\n tcs.push(c as Element);\n }\n }\n\n const C = tcs.length;\n const L = cellTexts.length;\n const fillCount = Math.min(L, C);\n\n for (let i = 0; i < C; i++) {\n const tc = tcs[i]!;\n const firstPara = firstChildW(tc, 'p');\n if (!firstPara) continue;\n\n if (i < fillCount) {\n // 替换首段:保留 pPr + 首 run rPr,写入文字\n const inheritedRPr = pickFirstRunRPr(firstPara);\n const doc = firstPara.ownerDocument;\n if (!doc) continue;\n\n const text = cellTexts[i]!;\n const run = doc.createElementNS(W_NS, 'w:r');\n if (inheritedRPr) {\n run.appendChild(inheritedRPr);\n }\n const t = doc.createElementNS(W_NS, 'w:t');\n t.setAttributeNS(XML_NS, 'xml:space', 'preserve');\n t.textContent = text;\n run.appendChild(t);\n\n removeNonPPrChildren(firstPara);\n firstPara.appendChild(run);\n } else {\n // 清空(i ∈ [L, C)):仅保留 pPr,不加文字\n removeNonPPrChildren(firstPara);\n }\n }\n}\n\n// ─────────── setTableColumnWidths(task-core-table-grid)───────────\n\n/**\n * 设表格列宽:同步更新 `<w:tblGrid>` gridCol w:w **和** 每个单元格 `<w:tcW>`。\n *\n * Round 2 修正(lead 实测):真实文档单元格带 `<w:tcW w:type=\"dxa\">`,Word 渲染\n * 优先走 tcW 而非 gridCol,因此只设 gridCol 不够——必须同步 tcW,列宽才生效。\n *\n * 定位逻辑:\n * 1. 按 tableId 找 `<w:tbl>`(tblIdx)。\n * 2. 找 `<w:tblGrid>`(tbl 直属子);若不存在则在 tblPr 之后(或 tbl 首位)创建。\n * 3. 枚举 `<w:gridCol>` 子元素,数量必须与 widths.length 一致(INVALID_ARGUMENT)。\n * 4. 依次把每个 gridCol 的 `w:w` 设为对应 widths 值。\n * 5. 遍历每行(`<w:tr>`)→ 每格(`<w:tc>`),跟踪**网格列索引** col:\n * - 读该 cell 的 `<w:gridSpan w:val>`(默认 1),span 跨几列。\n * - 该 cell 的 tcW = widths[col] + widths[col+1] + … + widths[col+span-1](跨列宽之和)。\n * - 若已有 `<w:tcW>` → 更新 w:w(type 改 dxa);若无 tcW → 补建(更稳,避免\n * 某些渲染器只读 tcW 不读 gridCol 的场景)。\n * - col 前进 span;`<w:vMerge>` 续行单元格照常计入列索引。\n *\n * 边界说明:\n * - 同步 tcW(含 gridSpan 跨列求和),与 gridCol 保持一致;tcW type 统一设 dxa。\n * - trackChanges=true 暂不支持(同其他 table ops 行为)。\n */\nexport function executeSetTableColumnWidths(\n ctx: ExecutorContext,\n op: Extract<Op, { type: 'setTableColumnWidths' }>,\n): void {\n if (ctx.options.trackChanges) {\n throw new WordError(\n 'UNSUPPORTED_OOXML_FEATURE',\n 'setTableColumnWidths with trackChanges=true not yet implemented',\n ctx.docId,\n { opType: 'setTableColumnWidths', tableId: op.tableId },\n );\n }\n\n const tbl = requireTable(ctx, op.tableId, 'setTableColumnWidths');\n\n // ── Step 1: 定位或创建 tblGrid ────────────────────────────────────────────\n let tblGrid = firstChildW(tbl, 'tblGrid');\n if (!tblGrid) {\n const doc = tbl.ownerDocument;\n if (!doc) {\n throw new WordError(\n 'PACKAGE_CORRUPT',\n `table '${op.tableId}' has no ownerDocument`,\n ctx.docId,\n { tableId: op.tableId, opType: 'setTableColumnWidths' },\n );\n }\n tblGrid = doc.createElementNS(W_NS, 'w:tblGrid');\n // 插入到 tblPr 之后(或 tbl 首子节点之前)\n const tblPr = firstChildW(tbl, 'tblPr');\n if (tblPr && tblPr.nextSibling) {\n tbl.insertBefore(tblGrid, tblPr.nextSibling);\n } else if (tblPr) {\n tbl.appendChild(tblGrid);\n } else {\n tbl.insertBefore(tblGrid, tbl.firstChild);\n }\n }\n\n // ── Step 2: 收集 gridCol 元素 ────────────────────────────────────────────\n const gridCols: Element[] = [];\n for (let i = 0; i < tblGrid.childNodes.length; i++) {\n const c = tblGrid.childNodes[i];\n if (\n c &&\n c.nodeType === 1 &&\n (c as Element).namespaceURI === W_NS &&\n (c as Element).localName === 'gridCol'\n ) {\n gridCols.push(c as Element);\n }\n }\n\n // ── Step 3: 校验长度 ─────────────────────────────────────────────────────\n if (gridCols.length !== op.widths.length) {\n throw new WordError(\n 'INVALID_ARGUMENT',\n `setTableColumnWidths: widths.length (${op.widths.length}) must equal colCount (${gridCols.length}) for table '${op.tableId}'`,\n ctx.docId,\n {\n tableId: op.tableId,\n opType: 'setTableColumnWidths',\n widthsLength: op.widths.length,\n colCount: gridCols.length,\n },\n );\n }\n\n // ── Step 4: 设置 gridCol w:w ─────────────────────────────────────────────\n for (let i = 0; i < gridCols.length; i++) {\n gridCols[i]!.setAttributeNS(W_NS, 'w:w', String(op.widths[i]));\n }\n\n // ── Step 5: 同步每个单元格 tcW(Round 2:Word 渲染优先 tcW over gridCol)─\n // 遍历所有 <w:tr>,在每行内按网格列索引逐 <w:tc> 处理。\n // gridSpan > 1 的合并单元格 tcW = 跨列宽之和;vMerge 续行单元格照常计入列位置。\n const doc = tbl.ownerDocument;\n for (let i = 0; i < tbl.childNodes.length; i++) {\n const trNode = tbl.childNodes[i];\n if (\n !trNode ||\n trNode.nodeType !== 1 ||\n (trNode as Element).namespaceURI !== W_NS ||\n (trNode as Element).localName !== 'tr'\n )\n continue;\n const tr = trNode as Element;\n\n let col = 0; // 当前网格列索引\n\n for (let j = 0; j < tr.childNodes.length; j++) {\n const tcNode = tr.childNodes[j];\n if (\n !tcNode ||\n tcNode.nodeType !== 1 ||\n (tcNode as Element).namespaceURI !== W_NS ||\n (tcNode as Element).localName !== 'tc'\n )\n continue;\n const tc = tcNode as Element;\n\n // 读取 gridSpan(默认 1)\n const tcPr = firstChildW(tc, 'tcPr');\n let span = 1;\n if (tcPr) {\n const gridSpanEl = firstChildW(tcPr, 'gridSpan');\n if (gridSpanEl) {\n const val = gridSpanEl.getAttributeNS(W_NS, 'val');\n const parsed = val !== null ? parseInt(val, 10) : NaN;\n if (!isNaN(parsed) && parsed > 1) span = parsed;\n }\n }\n\n // tcW = 跨列宽之和(span=1 退化为 widths[col])\n let tcWidth = 0;\n for (let s = 0; s < span && col + s < op.widths.length; s++) {\n tcWidth += op.widths[col + s]!;\n }\n\n // 更新或补建 <w:tcW>\n if (tcPr) {\n const tcWEl = firstChildW(tcPr, 'tcW');\n if (tcWEl) {\n // 已存在:直接更新 w:w 和 w:type\n tcWEl.setAttributeNS(W_NS, 'w:w', String(tcWidth));\n tcWEl.setAttributeNS(W_NS, 'w:type', 'dxa');\n } else if (doc) {\n // 无 tcW:补建,插入到 tcPr 内适当位置(gridSpan 之后或 tcPr 末尾)\n const newTcW = doc.createElementNS(W_NS, 'w:tcW');\n newTcW.setAttributeNS(W_NS, 'w:w', String(tcWidth));\n newTcW.setAttributeNS(W_NS, 'w:type', 'dxa');\n // 插到 tcPr 首位(tcW 一般是 tcPr 第一个子元素)\n tcPr.insertBefore(newTcW, tcPr.firstChild);\n }\n }\n // 若无 tcPr:不补建(表示该单元格完全继承默认属性,gridCol 已足够)\n\n col += span;\n }\n }\n\n markStoryPartDirty(ctx, tbl, 'setTableColumnWidths');\n}\n\n// ─────────── setTableRowHeights(task-core-table-rowheight)───────────\n\n/**\n * 设表格行高:逐行写/替换/删 `<w:trHeight>`。\n *\n * 实现镜像 executeSetTableColumnWidths:\n * 1. requireTable 拿表。\n * 2. 取表直属 <w:tr> 列表。\n * 3. 长度校验:heights.length 必须 == rowCount,否则 INVALID_ARGUMENT。\n * 4. 逐行:\n * - 确保 <w:trPr> 存在(无则在 <w:tr> 内首位新建)。\n * - RowHeight:找 trPr 内 <w:trHeight>,有则改 w:val/w:hRule,无则新建插入。\n * - null:删除 trPr 内 <w:trHeight>(若存在)。\n * 5. trackChanges=true → not yet implemented。\n *\n * CT_TrPr 顺序:trHeight 在\n * cnfStyle/divId/gridBefore/gridAfter/wBefore/wAfter/cantSplit/[trHeight]/\n * tblHeader/tblCellSpacing/jc/hidden 位置。\n * 实现上:若 trPr 内有 cantSplit,把 trHeight 插到 cantSplit 之后;否则追加到末尾。\n * Word 对 trPr 子元素顺序较宽容,此策略安全。\n */\nexport function executeSetTableRowHeights(\n ctx: ExecutorContext,\n op: Extract<Op, { type: 'setTableRowHeights' }>,\n): void {\n if (ctx.options.trackChanges) {\n throw new WordError(\n 'UNSUPPORTED_OOXML_FEATURE',\n 'setTableRowHeights with trackChanges=true not yet implemented',\n ctx.docId,\n { opType: 'setTableRowHeights', tableId: op.tableId },\n );\n }\n\n const tbl = requireTable(ctx, op.tableId, 'setTableRowHeights');\n\n // ── 收集直属 <w:tr> ──────────────────────────────────────────────────────\n const rows: Element[] = [];\n for (let i = 0; i < tbl.childNodes.length; i++) {\n const c = tbl.childNodes[i];\n if (\n c &&\n c.nodeType === 1 &&\n (c as Element).namespaceURI === W_NS &&\n (c as Element).localName === 'tr'\n ) {\n rows.push(c as Element);\n }\n }\n\n // ── 长度校验 ─────────────────────────────────────────────────────────────\n if (op.heights.length !== rows.length) {\n throw new WordError(\n 'INVALID_ARGUMENT',\n `setTableRowHeights: heights.length (${op.heights.length}) must equal rowCount (${rows.length}) for table '${op.tableId}'`,\n ctx.docId,\n {\n tableId: op.tableId,\n opType: 'setTableRowHeights',\n heightsLength: op.heights.length,\n rowCount: rows.length,\n },\n );\n }\n\n const doc = tbl.ownerDocument;\n\n for (let i = 0; i < rows.length; i++) {\n const tr = rows[i]!;\n const height = op.heights[i]!;\n\n // ── 确保 <w:trPr> 存在 ───────────────────────────────────────────────\n let trPr = firstChildW(tr, 'trPr');\n if (!trPr) {\n if (!doc) {\n throw new WordError(\n 'PACKAGE_CORRUPT',\n `table '${op.tableId}' row ${i} has no ownerDocument`,\n ctx.docId,\n { tableId: op.tableId, opType: 'setTableRowHeights' },\n );\n }\n trPr = doc.createElementNS(W_NS, 'w:trPr');\n // trPr 是 tr 的首个子元素\n tr.insertBefore(trPr, tr.firstChild);\n }\n\n if (height === null) {\n // ── null:删除 trPr 内 <w:trHeight>(若存在)──────────────────────\n const existingTrHeight = firstChildW(trPr, 'trHeight');\n if (existingTrHeight && existingTrHeight.parentNode) {\n existingTrHeight.parentNode.removeChild(existingTrHeight);\n }\n } else {\n // ── RowHeight:写/替换 <w:trHeight> ──────────────────────────────\n const existingTrHeight = firstChildW(trPr, 'trHeight');\n if (existingTrHeight) {\n // 已有 trHeight:更新属性\n existingTrHeight.setAttributeNS(W_NS, 'w:val', String(height.val));\n existingTrHeight.setAttributeNS(W_NS, 'w:hRule', height.hRule);\n } else {\n // 无 trHeight:新建并插入\n if (!doc) {\n throw new WordError(\n 'PACKAGE_CORRUPT',\n `table '${op.tableId}' row ${i} has no ownerDocument`,\n ctx.docId,\n { tableId: op.tableId, opType: 'setTableRowHeights' },\n );\n }\n const newTrHeight = doc.createElementNS(W_NS, 'w:trHeight');\n newTrHeight.setAttributeNS(W_NS, 'w:val', String(height.val));\n newTrHeight.setAttributeNS(W_NS, 'w:hRule', height.hRule);\n // 按 CT_TrPr 顺序:trHeight 在 cantSplit 之后;若无 cantSplit 则追加到末尾。\n const cantSplit = firstChildW(trPr, 'cantSplit');\n if (cantSplit && cantSplit.nextSibling) {\n trPr.insertBefore(newTrHeight, cantSplit.nextSibling);\n } else if (cantSplit) {\n trPr.appendChild(newTrHeight);\n } else {\n trPr.appendChild(newTrHeight);\n }\n }\n }\n }\n\n markStoryPartDirty(ctx, tbl, 'setTableRowHeights');\n}\n\n// ─────────── 内部 ───────────\n\nconst TCW_AFTER_LOCALS = new Set([\n 'gridSpan',\n 'hMerge',\n 'vMerge',\n 'tcBorders',\n 'shd',\n 'noWrap',\n 'tcMar',\n 'textDirection',\n 'tcFitText',\n 'vAlign',\n 'hideMark',\n 'headers',\n 'cellIns',\n 'cellDel',\n 'cellMerge',\n 'tcPrChange',\n]);\n\nconst SHD_AFTER_LOCALS = new Set([\n 'noWrap',\n 'tcMar',\n 'textDirection',\n 'tcFitText',\n 'vAlign',\n 'hideMark',\n 'headers',\n 'cellIns',\n 'cellDel',\n 'cellMerge',\n 'tcPrChange',\n]);\n\nconst VALIGN_AFTER_LOCALS = new Set([\n 'hideMark',\n 'headers',\n 'cellIns',\n 'cellDel',\n 'cellMerge',\n 'tcPrChange',\n]);\n\nfunction requireTable(ctx: ExecutorContext, tableId: string, opName: string): Element {\n const tbl = ctx.indices.tblIdx.get(tableId);\n if (!tbl) {\n throw new WordError(\n 'TABLE_NOT_FOUND',\n `table with tableId='${tableId}' not found (op: ${opName})`,\n ctx.docId,\n { tableId, opName },\n );\n }\n return tbl;\n}\n\n/**\n * 找表格的首段落:第一行 → 第一格 → 第一段。\n * OOXML 保证每个 <w:tc> 至少含一个 <w:p>。\n */\nfunction findFirstParagraphInTable(tbl: Element): Element | null {\n const firstTr = firstChildW(tbl, 'tr');\n if (!firstTr) return null;\n const firstTc = firstChildW(firstTr, 'tc');\n if (!firstTc) return null;\n return firstChildW(firstTc, 'p');\n}\n\nfunction firstChildW(el: Element, localName: string): Element | null {\n for (let i = 0; i < el.childNodes.length; i++) {\n const c = el.childNodes[i];\n if (\n c &&\n c.nodeType === 1 &&\n (c as Element).namespaceURI === W_NS &&\n (c as Element).localName === localName\n ) {\n return c as Element;\n }\n }\n return null;\n}\n\nfunction firstCellContentChild(tc: Element): Element | null {\n for (let i = 0; i < tc.childNodes.length; i++) {\n const child = tc.childNodes[i];\n if (\n child &&\n child.nodeType === 1 &&\n (child as Element).namespaceURI === W_NS &&\n (child as Element).localName !== 'tcPr'\n ) {\n return child as Element;\n }\n }\n return null;\n}\n\n/**\n * 按 row 索引定位 `<w:tr>`。row 是 tbl 下第 i 个 `<w:tr>` 直属子 (按文档顺序)。\n */\nfunction findTableRow(tbl: Element, row: number): Element | null {\n if (row < 0) return null;\n let trIdx = 0;\n for (let i = 0; i < tbl.childNodes.length; i++) {\n const c = tbl.childNodes[i];\n if (\n !c ||\n c.nodeType !== 1 ||\n (c as Element).namespaceURI !== W_NS ||\n (c as Element).localName !== 'tr'\n )\n continue;\n if (trIdx === row) return c as Element;\n trIdx++;\n }\n return null;\n}\n\n/**\n * 按 (row, col) 网格坐标定位 `<w:tc>`。坐标语义与 TableInfo.cells 一致:\n * - row = tbl 下第 i 个 `<w:tr>` 直属子 (按文档顺序)\n * - col = 该 tr 下第 j 个 `<w:tc>` 直属子\n *\n * 合并单元格 (gridSpan / vMerge='continue') 不在坐标系内做展开 —— TableInfo.cells\n * 也是按 tc 顺序填的, 调用方拿到的网格与 executor 解析的网格 1:1 对应。\n */\nfunction findCell(tbl: Element, row: number, col: number): Element | null {\n if (row < 0 || col < 0) return null;\n let trIdx = 0;\n for (let i = 0; i < tbl.childNodes.length; i++) {\n const c = tbl.childNodes[i];\n if (\n !c ||\n c.nodeType !== 1 ||\n (c as Element).namespaceURI !== W_NS ||\n (c as Element).localName !== 'tr'\n )\n continue;\n if (trIdx === row) {\n let tcIdx = 0;\n const tr = c as Element;\n for (let j = 0; j < tr.childNodes.length; j++) {\n const cc = tr.childNodes[j];\n if (\n !cc ||\n cc.nodeType !== 1 ||\n (cc as Element).namespaceURI !== W_NS ||\n (cc as Element).localName !== 'tc'\n )\n continue;\n if (tcIdx === col) return cc as Element;\n tcIdx++;\n }\n return null;\n }\n trIdx++;\n }\n return null;\n}\n\n/** 段落内除 `<w:pPr>` 外所有直属子节点移除 (保留段落属性, 清空内容)。 */\nfunction ensureTableCellProperties(tc: Element): Element {\n const existing = firstChildW(tc, 'tcPr');\n if (existing) return existing;\n const doc = tc.ownerDocument!;\n const tcPr = doc.createElementNS(W_NS, 'w:tcPr');\n tc.insertBefore(tcPr, tc.firstChild);\n return tcPr;\n}\n\nfunction upsertTcPrChild(tcPr: Element, localName: string, afterLocals: Set<string>): Element {\n const existing = firstChildW(tcPr, localName);\n if (existing) return existing;\n const doc = tcPr.ownerDocument!;\n const child = doc.createElementNS(W_NS, `w:${localName}`);\n tcPr.insertBefore(child, findTcPrInsertRef(tcPr, afterLocals));\n return child;\n}\n\nfunction findTcPrInsertRef(tcPr: Element, afterLocals: Set<string>): Element | null {\n for (let i = 0; i < tcPr.childNodes.length; i++) {\n const child = tcPr.childNodes[i];\n if (\n child?.nodeType === 1 &&\n (child as Element).namespaceURI === W_NS &&\n afterLocals.has((child as Element).localName)\n ) {\n return child as Element;\n }\n }\n return null;\n}\n\nfunction validateTableCellFormat(\n ctx: ExecutorContext,\n op: Extract<Op, { type: 'formatTableCell' }>,\n): void {\n if (\n op.format.width === undefined &&\n op.format.shading === undefined &&\n op.format.verticalAlignment === undefined\n ) {\n throw new WordError(\n 'INVALID_ARGUMENT',\n 'formatTableCell requires at least one format field',\n ctx.docId,\n { tableId: op.tableId, row: op.row, col: op.col, opType: 'formatTableCell' },\n );\n }\n if (\n op.format.width !== undefined &&\n (!Number.isInteger(op.format.width) || op.format.width <= 0)\n ) {\n throw new WordError(\n 'INVALID_ARGUMENT',\n 'formatTableCell width must be a positive integer twip value',\n ctx.docId,\n { tableId: op.tableId, row: op.row, col: op.col, width: op.format.width },\n );\n }\n if (\n op.format.verticalAlignment !== undefined &&\n !['top', 'center', 'bottom', 'both'].includes(op.format.verticalAlignment)\n ) {\n throw new WordError(\n 'INVALID_ARGUMENT',\n 'formatTableCell verticalAlignment must be top, center, bottom, or both',\n ctx.docId,\n {\n tableId: op.tableId,\n row: op.row,\n col: op.col,\n verticalAlignment: op.format.verticalAlignment,\n },\n );\n }\n if (op.format.shading !== undefined) {\n validateColorLike(ctx, op, 'shading.fill', op.format.shading.fill);\n validateColorLike(ctx, op, 'shading.color', op.format.shading.color);\n if (\n op.format.shading.fill === undefined &&\n op.format.shading.color === undefined &&\n op.format.shading.val === undefined\n ) {\n throw new WordError(\n 'INVALID_ARGUMENT',\n 'formatTableCell shading requires fill, color, or val',\n ctx.docId,\n { tableId: op.tableId, row: op.row, col: op.col, opType: 'formatTableCell' },\n );\n }\n }\n}\n\nfunction validateColorLike(\n ctx: ExecutorContext,\n op: Extract<Op, { type: 'formatTableCell' }>,\n field: string,\n value: string | undefined,\n): void {\n if (value === undefined) return;\n if (value !== 'auto' && !/^[0-9A-Fa-f]{6}$/.test(value)) {\n throw new WordError(\n 'INVALID_ARGUMENT',\n `formatTableCell ${field} must be a 6-digit hex color or auto`,\n ctx.docId,\n { tableId: op.tableId, row: op.row, col: op.col, field, value },\n );\n }\n}\n\nfunction removeNonPPrChildren(paragraph: Element): void {\n const children = Array.from(paragraph.childNodes);\n for (const c of children) {\n if (c.nodeType !== 1) {\n paragraph.removeChild(c);\n continue;\n }\n const el = c as Element;\n if (el.namespaceURI === W_NS && el.localName === 'pPr') continue;\n paragraph.removeChild(c);\n }\n}\n\nfunction collectBookmarkNamesInTable(tbl: Element): string[] {\n const names: string[] = [];\n const starts = tbl.getElementsByTagNameNS(W_NS, 'bookmarkStart');\n for (let i = 0; i < starts.length; i++) {\n const el = starts[i];\n if (!el) continue;\n const name = el.getAttributeNS(W_NS, 'name') ?? el.getAttribute('w:name') ?? '';\n names.push(name);\n }\n return names;\n}\n\nfunction collectCommentIdsInTable(tbl: Element): number[] {\n const ids = new Set<number>();\n for (const local of ['commentRangeStart', 'commentReference']) {\n const list = tbl.getElementsByTagNameNS(W_NS, local);\n for (let i = 0; i < list.length; i++) {\n const el = list[i];\n if (!el) continue;\n const raw = el.getAttributeNS(W_NS, 'id') ?? el.getAttribute('w:id') ?? '';\n const id = parseInt(raw, 10);\n if (!isNaN(id)) ids.add(id);\n }\n }\n return Array.from(ids);\n}\n\n/**\n * drop 书签:移除 bookmarkStart / bookmarkEnd,删 bookmarkIdx 条目。\n * 与 paragraph-structure-ops.ts dropBookmarkByName 同构,但 #186 表内书签是要\n * 整张表删的,所以单独走一份避免跨文件 export。\n */\nfunction dropBookmarkByName(ctx: ExecutorContext, name: string): void {\n const entry = ctx.indices.bookmarkIdx.get(name);\n if (!entry) return;\n const { start, end, partPath } = entry;\n if (start.parentNode) start.parentNode.removeChild(start);\n if (end && end.parentNode) end.parentNode.removeChild(end);\n ctx.indices.bookmarkIdx.delete(name);\n const part = getPart(ctx.pkg, partPath);\n if (part) markDirty(part);\n}\n\n/**\n * drop 批注:删 commentRangeStart/End + commentReference 三锚点 + comments.xml\n * 里的 <w:comment> 主体。\n *\n * 注:整张表都将被 removeChild,严格说只需要删 comments.xml 里的主体即可;但保留\n * 锚点清理逻辑作为兜底(若某 op 在 deleteTable 之前 / 之后访问 commentIdx 可保\n * 一致)。\n */\nfunction dropCommentById(ctx: ExecutorContext, id: number, tbl: Element): void {\n const entry = ctx.indices.commentIdx.get(id);\n\n if (!entry) {\n // 索引未命中:直接扫表删锚点\n removeCommentAnchorsInTable(ctx, tbl, id);\n return;\n }\n\n const { start, end, ref } = entry.anchors;\n const anchorEl = start ?? end ?? ref;\n let bodyPartPath: string | null = null;\n if (anchorEl) {\n const story = findStoryFor(ctx.pkg, anchorEl);\n if (story) bodyPartPath = story.partPath;\n }\n\n if (start && start.parentNode) start.parentNode.removeChild(start);\n if (end && end.parentNode) end.parentNode.removeChild(end);\n if (ref) {\n const parentRun = ref.parentNode;\n if (ref.parentNode) ref.parentNode.removeChild(ref);\n if (\n parentRun &&\n parentRun.nodeType === 1 &&\n (parentRun as Element).namespaceURI === W_NS &&\n (parentRun as Element).localName === 'r' &&\n isRunEffectivelyEmpty(parentRun as Element)\n ) {\n if (parentRun.parentNode) parentRun.parentNode.removeChild(parentRun);\n }\n }\n\n if (entry.comment && entry.comment.parentNode) {\n entry.comment.parentNode.removeChild(entry.comment);\n const commentsPart = getPart(ctx.pkg, COMMENTS_PART_PATH);\n if (commentsPart) markDirty(commentsPart);\n }\n\n if (bodyPartPath) {\n const bodyPart = getPart(ctx.pkg, bodyPartPath);\n if (bodyPart) markDirty(bodyPart);\n }\n\n ctx.indices.commentIdx.delete(id);\n\n // 若 comments.xml 已空,移除 part + 清 CT/rels(与 executeDeleteComment 对称)\n cleanupEmptyCommentsPart(ctx);\n}\n\nfunction removeCommentAnchorsInTable(ctx: ExecutorContext, tbl: Element, id: number): void {\n const idStr = String(id);\n const toRemove: Element[] = [];\n for (const local of ['commentRangeStart', 'commentRangeEnd', 'commentReference']) {\n const list = tbl.getElementsByTagNameNS(W_NS, local);\n for (let i = 0; i < list.length; i++) {\n const el = list[i];\n if (!el) continue;\n const raw = el.getAttributeNS(W_NS, 'id') ?? el.getAttribute('w:id') ?? '';\n if (raw === idStr) toRemove.push(el);\n }\n }\n for (const el of toRemove) {\n const parentRun = el.localName === 'commentReference' ? el.parentNode : null;\n if (el.parentNode) el.parentNode.removeChild(el);\n if (\n parentRun &&\n parentRun.nodeType === 1 &&\n (parentRun as Element).namespaceURI === W_NS &&\n (parentRun as Element).localName === 'r' &&\n isRunEffectivelyEmpty(parentRun as Element)\n ) {\n if (parentRun.parentNode) parentRun.parentNode.removeChild(parentRun);\n }\n }\n\n for (const part of listParts(ctx.pkg)) {\n if (!isXmlPart(part) || !part.xmlDom) continue;\n if (!part.contentType.endsWith('.comments+xml')) continue;\n const comments = part.xmlDom.getElementsByTagNameNS(W_NS, 'comment');\n const victims: Element[] = [];\n for (let i = 0; i < comments.length; i++) {\n const c = comments[i];\n if (!c) continue;\n const raw = c.getAttributeNS(W_NS, 'id') ?? c.getAttribute('w:id') ?? '';\n if (raw === idStr) victims.push(c);\n }\n for (const v of victims) {\n if (v.parentNode) v.parentNode.removeChild(v);\n }\n if (victims.length > 0) markDirty(part);\n }\n}\n\nfunction isRunEffectivelyEmpty(run: Element): boolean {\n const children = run.childNodes;\n for (let i = 0; i < children.length; i++) {\n const c = children[i];\n if (!c || c.nodeType !== 1) continue;\n if ((c as Element).localName === 'rPr') continue;\n return false;\n }\n return true;\n}\n\nfunction markStoryPartDirty(ctx: ExecutorContext, el: Element, opName: string): void {\n const story = findStoryFor(ctx.pkg, el);\n if (!story) {\n throw new WordError(\n 'PACKAGE_CORRUPT',\n `element not found in any story (op: ${opName})`,\n ctx.docId,\n { opName },\n );\n }\n const part = getPart(ctx.pkg, story.partPath);\n if (!part) {\n throw new WordError(\n 'PACKAGE_CORRUPT',\n `story part '${story.partPath}' not found (op: ${opName})`,\n ctx.docId,\n { opName, partPath: story.partPath },\n );\n }\n markDirty(part);\n}\n","/**\n * #190 占位图共享资源 —— PNG 字节 + 注入帮助。\n *\n * 设计:\n * - 全包共享一份 `word/media/placeholder.png`(200x150 灰度,内含中部 X 标记)\n * - 每个承载 drawing 的 part(`word/document.xml` / `word/header*.xml` 等)各自的\n * `.rels` 里**最多注入一条** image relationship → placeholder.png,后续替换复用\n * - [Content_Types].xml 首次时补 `<Default Extension=\"png\" ContentType=\"image/png\"/>`\n * (已有相同 Default 或同名 Override 时跳过)\n *\n * 视觉表达:PNG 内是灰底 + 边框 + 中部 X 标记(国际通用\"占位/图像缺失\"图标语义)。\n * 中文\"[图片占位]\"标注由替换 executor 写入 `wp:docPr/@descr`(screen reader / hover\n * tooltip 可见),避免在 PNG 内手工渲染中文字形。\n *\n * 字节来源:`scripts/gen-placeholder-png.mjs` 一次性生成,baked 进 placeholder-image-bytes.ts。\n */\nimport { parseXmlDocument } from 'slimdom';\nimport type { Package } from '../../pack/index.js';\nimport {\n createBinaryPart,\n createXmlPart,\n deletePart,\n getPart,\n hasPart,\n isBinaryPart,\n isXmlPart,\n listParts,\n markDirty,\n setPart,\n} from '../../pack/index.js';\nimport { PLACEHOLDER_PNG_BYTES } from './placeholder-image-bytes.js';\n\n// ─────────── 常量 ───────────\n\n/** 共享占位图在包内的路径 */\nexport const PLACEHOLDER_MEDIA_PATH = 'word/media/placeholder.png';\n/** PNG MIME content type */\nexport const PNG_CONTENT_TYPE = 'image/png';\n/** OOXML image relationship type(BLIP r:embed 的解析目标)*/\nexport const IMAGE_RELATIONSHIP_TYPE =\n 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/image';\n\n/** 中文标注文字 —— 由 executor 写到 wp:docPr/@descr / @title */\nexport const PLACEHOLDER_DESCR = '[图片占位]';\n\nconst CONTENT_TYPES_PATH = '[Content_Types].xml';\nconst CONTENT_TYPES_NS = 'http://schemas.openxmlformats.org/package/2006/content-types';\nconst RELS_NS = 'http://schemas.openxmlformats.org/package/2006/relationships';\n\n// ─────────── 公开 API ───────────\n\n/**\n * 确保 `word/media/placeholder.png` 存在;不存在时创建。\n *\n * 幂等:多次调用安全,首次创建后续 short-circuit。\n *\n * @returns 是否本次刚创建(供调用方决定是否标记 [Content_Types] 等 dirty)\n */\nexport function ensurePlaceholderMediaPart(pkg: Package): boolean {\n if (hasPart(pkg, PLACEHOLDER_MEDIA_PATH)) return false;\n const part = createBinaryPart({\n path: PLACEHOLDER_MEDIA_PATH,\n contentType: PNG_CONTENT_TYPE,\n bytes: PLACEHOLDER_PNG_BYTES,\n // 不传 originalBytes 让其默认 = bytes;但显式 markDirty 让 toZip 触发实际写入\n });\n setPart(pkg, part);\n // createBinaryPart 默认 _dirty=false(装载即终态语义);新建场景必须 markDirty 才会被 toZip 序列化\n markDirty(part);\n return true;\n}\n\n/**\n * 确保 [Content_Types].xml 中 PNG 类型可解析。\n *\n * 优先策略:补 `<Default Extension=\"png\" ContentType=\"image/png\"/>`。\n * - 若已有同 Extension 的 Default(无论 ContentType 是否一致)→ 不动\n * - 若有 `<Override PartName=\"/word/media/placeholder.png\" .../>` → 也算覆盖,不补 Default\n *\n * @returns 是否本次刚补\n */\nexport function ensurePngContentType(pkg: Package): boolean {\n const ctPart = getPart(pkg, CONTENT_TYPES_PATH);\n if (!ctPart || !isXmlPart(ctPart) || !ctPart.xmlDom) return false;\n\n const doc = ctPart.xmlDom;\n\n // 已有 Default Extension=\"png\" → skip\n const defaults = doc.getElementsByTagNameNS(CONTENT_TYPES_NS, 'Default');\n for (let i = 0; i < defaults.length; i++) {\n if (defaults[i]!.getAttribute('Extension')?.toLowerCase() === 'png') return false;\n }\n\n // 已有 Override 指向 placeholder.png → skip\n const overrides = doc.getElementsByTagNameNS(CONTENT_TYPES_NS, 'Override');\n for (let i = 0; i < overrides.length; i++) {\n if (overrides[i]!.getAttribute('PartName') === `/${PLACEHOLDER_MEDIA_PATH}`) return false;\n }\n\n // 补 Default\n const def = doc.createElementNS(CONTENT_TYPES_NS, 'Default');\n def.setAttribute('Extension', 'png');\n def.setAttribute('ContentType', PNG_CONTENT_TYPE);\n doc.documentElement.appendChild(def);\n markDirty(ctPart);\n return true;\n}\n\n/**\n * 确保指定 rels part 内有一条 image relationship 指向 placeholder.png;若已存在直接返回其 rId。\n *\n * @param pkg 包\n * @param relsPartPath 目标 rels part 路径,如 'word/_rels/document.xml.rels' / 'word/_rels/header1.xml.rels'\n * 不存在时会创建空 rels(场景:某 header part 原本没有 .rels)\n * @returns 复用或新分配的 rId(形如 'rId7')\n */\nexport function ensurePlaceholderRelInPart(pkg: Package, relsPartPath: string): string {\n let relsPart = getPart(pkg, relsPartPath);\n if (!relsPart) {\n // 新建空 rels:某些 header / footer 原本无图,装载后第一次注入图片需要建 rels\n const empty = `<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\\n<Relationships xmlns=\"${RELS_NS}\"/>`;\n const dom = parseXmlDocument(empty) as unknown as Document;\n relsPart = createXmlPart({\n path: relsPartPath,\n contentType: 'application/vnd.openxmlformats-package.relationships+xml',\n xmlDom: dom,\n // 不传 originalBytes → 默认 dirty=true(新建)\n });\n setPart(pkg, relsPart);\n }\n if (!isXmlPart(relsPart) || !relsPart.xmlDom) {\n throw new Error(`ensurePlaceholderRelInPart: '${relsPartPath}' is not an XML part`);\n }\n\n const doc = relsPart.xmlDom;\n const placeholderTarget = computeRelTarget(relsPartPath, PLACEHOLDER_MEDIA_PATH);\n\n // 已有指向 placeholder 的 image rel → 复用\n const rels = doc.getElementsByTagNameNS(RELS_NS, 'Relationship');\n let maxRId = 0;\n for (let i = 0; i < rels.length; i++) {\n const r = rels[i]!;\n const id = r.getAttribute('Id') ?? '';\n const m = /^rId(\\d+)$/.exec(id);\n if (m) {\n const n = parseInt(m[1]!, 10);\n if (n > maxRId) maxRId = n;\n }\n if (\n r.getAttribute('Type') === IMAGE_RELATIONSHIP_TYPE &&\n normalizeTarget(r.getAttribute('Target') ?? '') === placeholderTarget\n ) {\n return id;\n }\n }\n\n // 新增 rel\n const rId = `rId${maxRId + 1}`;\n const rel = doc.createElementNS(RELS_NS, 'Relationship');\n rel.setAttribute('Id', rId);\n rel.setAttribute('Type', IMAGE_RELATIONSHIP_TYPE);\n rel.setAttribute('Target', placeholderTarget);\n doc.documentElement.appendChild(rel);\n markDirty(relsPart);\n return rId;\n}\n\n/**\n * 把 .rels 文件内 `<Relationship>` 的 Target(相对路径)解析为包内绝对 part 路径。\n *\n * 规则:相对于宿主 part 的目录解析。\n * - 'word/_rels/document.xml.rels' 内 Target='media/x.png' → 'word/media/x.png'\n * - Target='/word/media/x.png'(以 '/' 开头的\"包根绝对路径\")→ 'word/media/x.png'\n * - 顶层 '_rels/.rels' base 为包根\n */\nexport function resolveRelTarget(relsPartPath: string, target: string): string {\n let t = target.trim();\n if (t.startsWith('/')) return t.slice(1);\n while (t.startsWith('./')) t = t.slice(2);\n const base = hostDirOfRelsPart(relsPartPath);\n if (base === '') return t;\n // 处理 '../' 回溯(尾随段累计)\n let pathParts = base.split('/').filter(Boolean);\n while (t.startsWith('../')) {\n pathParts = pathParts.slice(0, -1);\n t = t.slice(3);\n }\n return pathParts.length === 0 ? t : `${pathParts.join('/')}/${t}`;\n}\n\n/**\n * 统计 media part 路径在全包所有 .rels 中的引用数。\n *\n * 用于孤儿 media 清理:执行器删除一条 rels 条目后,该 Relationship.Target 对应的\n * media path 可能仍被其它 .rels 引用(同图被多 part / 多 drawing 共享场景),\n * 仅在全包归零时才可真正删除 binary part。\n */\nexport function countMediaReferences(pkg: Package, mediaPath: string): number {\n let count = 0;\n for (const part of listParts(pkg)) {\n if (!isXmlPart(part) || !part.xmlDom) continue;\n if (!part.path.endsWith('.rels')) continue;\n const rels = part.xmlDom.getElementsByTagNameNS(RELS_NS, 'Relationship');\n for (let i = 0; i < rels.length; i++) {\n const target = rels[i]!.getAttribute('Target');\n if (!target) continue;\n if (resolveRelTarget(part.path, target) === mediaPath) count++;\n }\n }\n return count;\n}\n\n/**\n * 把候选孤儿 media 路径过一遍,只在全包真正归零时才 deletePart。\n *\n * @returns 实际删除的 path 列表(便于日志 / 测试断言)\n */\nexport function sweepOrphanMediaParts(pkg: Package, candidates: Iterable<string>): string[] {\n const removed: string[] = [];\n for (const path of candidates) {\n const part = getPart(pkg, path);\n if (!part) continue;\n if (!isBinaryPart(part)) continue;\n if (countMediaReferences(pkg, path) > 0) continue;\n deletePart(pkg, path);\n removed.push(path);\n }\n return removed;\n}\n\n// ─────────── 内部 ───────────\n\n/**\n * 计算 rels 文件里 Relationship/@Target 应写的相对路径。\n *\n * OOXML rel Target 默认相对于宿主 part 的目录解析:\n * - 'word/document.xml' 的 rels → base 'word/'\n * - 'word/_rels/document.xml.rels' 内 Target='media/x.png' → 'word/media/x.png'\n *\n * 我们的 placeholder 在 'word/media/placeholder.png',对所有 'word/*.xml.rels' 来说\n * 都是 'media/placeholder.png'。对顶层 '_rels/.rels'(基 = 包根)需要 'word/media/placeholder.png'\n * —— 但 #190 的 drawing 不可能在顶层 rels 里出现,只保留兼容。\n */\nfunction computeRelTarget(relsPartPath: string, targetPartPath: string): string {\n // 把 rels part 路径转成 host part 路径,再取目录做 base\n // 'word/_rels/document.xml.rels' → host = 'word/document.xml' → base = 'word/'\n // '_rels/.rels' → host = '.rels' → base = ''\n const hostDir = hostDirOfRelsPart(relsPartPath);\n if (hostDir === '') return targetPartPath;\n if (targetPartPath.startsWith(`${hostDir}/`)) {\n return targetPartPath.slice(hostDir.length + 1);\n }\n // base 与目标不同前缀(罕见),退化为以 '../' 回溯。这里 #190 实际只走 word/ 前缀,\n // 简化处理:回 '/' 绝对路径形态(OOXML 允许)。\n return `/${targetPartPath}`;\n}\n\nfunction hostDirOfRelsPart(relsPath: string): string {\n // 找到 '/_rels/' 段:其前部 = host 所在目录\n const idx = relsPath.lastIndexOf('/_rels/');\n if (idx < 0) {\n // 如 '_rels/.rels' 形态:host 在包根\n return '';\n }\n return relsPath.slice(0, idx);\n}\n\n/** 标准化 Target 路径用于比较(去开头 './',统一斜杠,去重复斜杠)*/\nfunction normalizeTarget(t: string): string {\n let s = t.trim();\n while (s.startsWith('./')) s = s.slice(2);\n return s.replace(/\\\\/g, '/');\n}\n","// Generated by scripts/gen-placeholder-png.mjs — DO NOT edit manually.\n// 200x150 8-bit grayscale PNG, 839 bytes.\nexport const PLACEHOLDER_PNG_BYTES: Uint8Array = new Uint8Array([\n 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52,\n 0x00, 0x00, 0x00, 0xc8, 0x00, 0x00, 0x00, 0x96, 0x08, 0x00, 0x00, 0x00, 0x00, 0xbe, 0xb7, 0x98,\n 0xc5, 0x00, 0x00, 0x00, 0x28, 0x74, 0x45, 0x58, 0x74, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70,\n 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x43, 0x6f, 0x63, 0x6f, 0x4f, 0x66, 0x66, 0x69, 0x63, 0x65, 0x20,\n 0x49, 0x6d, 0x61, 0x67, 0x65, 0x20, 0x50, 0x6c, 0x61, 0x63, 0x65, 0x68, 0x6f, 0x6c, 0x64, 0x65,\n 0x72, 0xcb, 0xd8, 0x22, 0x04, 0x00, 0x00, 0x02, 0xda, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0xed,\n 0xdd, 0x0b, 0x72, 0x02, 0x21, 0x0c, 0x80, 0xe1, 0x1c, 0xbd, 0x47, 0xf5, 0x28, 0x9d, 0xa9, 0xb5,\n 0xba, 0xeb, 0x02, 0x49, 0x48, 0x78, 0xfc, 0xd5, 0x03, 0x90, 0x7c, 0x33, 0xea, 0xb2, 0x10, 0x82,\n 0x7c, 0x41, 0x3e, 0xc2, 0x82, 0xdc, 0xb6, 0xfe, 0x3c, 0x20, 0xb7, 0xbd, 0x29, 0x3f, 0xd9, 0xdf,\n 0x21, 0x5b, 0x4b, 0xee, 0xb9, 0xff, 0x42, 0x36, 0x96, 0xfc, 0x66, 0xfe, 0x80, 0xec, 0x4a, 0xf9,\n 0xcb, 0xfa, 0x09, 0xd9, 0x52, 0xf2, 0xcc, 0xf9, 0x05, 0xb2, 0xa1, 0xe4, 0x25, 0xe3, 0x57, 0xc8,\n 0x6e, 0x94, 0x43, 0xb6, 0x47, 0xc8, 0x56, 0x92, 0x63, 0xae, 0x27, 0xc8, 0x46, 0x92, 0x53, 0xa6,\n 0x67, 0xc8, 0x2e, 0x94, 0xb7, 0x2c, 0xdf, 0x21, 0x5b, 0x48, 0xde, 0x73, 0xbc, 0x80, 0x6c, 0x20,\n 0xb9, 0xc8, 0xf0, 0x0a, 0xb2, 0x3a, 0xe5, 0x32, 0xbb, 0x6b, 0xc8, 0xd2, 0x92, 0xeb, 0xdc, 0x0a,\n 0x90, 0x85, 0x25, 0x85, 0xcc, 0x4a, 0x90, 0x55, 0x29, 0xc5, 0xac, 0xca, 0x90, 0x25, 0x25, 0xe5,\n 0x9c, 0x2a, 0x90, 0x05, 0x25, 0x95, 0x8c, 0x6a, 0x90, 0xd5, 0x28, 0xd5, 0x6c, 0xea, 0x90, 0xa5,\n 0x24, 0xf5, 0x5c, 0x1a, 0x90, 0x85, 0x24, 0x8d, 0x4c, 0x5a, 0x90, 0x55, 0x28, 0xcd, 0x2c, 0xda,\n 0x90, 0x25, 0x24, 0xed, 0x1c, 0x14, 0x90, 0x05, 0x24, 0x8a, 0x0c, 0x34, 0x90, 0xd9, 0x14, 0x55,\n 0x74, 0x1d, 0x64, 0xaa, 0x44, 0x17, 0x5b, 0x09, 0x99, 0x28, 0x51, 0x46, 0xd6, 0x42, 0x66, 0x51,\n 0xd4, 0x51, 0xf5, 0x90, 0x29, 0x12, 0x7d, 0x4c, 0x03, 0x64, 0x82, 0xc4, 0x10, 0xd1, 0x02, 0x19,\n 0x4d, 0x31, 0x45, 0xb3, 0x41, 0x86, 0x4a, 0x6c, 0xb1, 0x8c, 0x90, 0x81, 0x12, 0x63, 0x24, 0x2b,\n 0x64, 0x14, 0xc5, 0x1c, 0xc5, 0x0e, 0x19, 0x22, 0xb1, 0xc7, 0x70, 0x40, 0x06, 0x48, 0x1c, 0x11,\n 0x3c, 0x90, 0x6c, 0x8a, 0x6b, 0x74, 0x1f, 0x24, 0x55, 0xe2, 0x1b, 0xdb, 0x09, 0x49, 0x94, 0x38,\n 0x47, 0xf6, 0x42, 0xb2, 0x28, 0xee, 0x51, 0xfd, 0x90, 0x14, 0x89, 0x7f, 0xcc, 0x0e, 0x48, 0x82,\n 0xa4, 0x63, 0xc4, 0x1e, 0x48, 0x34, 0xa5, 0x6b, 0xb4, 0x3e, 0x48, 0xa8, 0xa4, 0x6f, 0xac, 0x4e,\n 0x48, 0xa0, 0xa4, 0x73, 0xa4, 0x5e, 0x48, 0x14, 0xa5, 0x7b, 0x94, 0x7e, 0x48, 0x88, 0xa4, 0x7f,\n 0x8c, 0x00, 0x48, 0x48, 0x16, 0x01, 0x49, 0x48, 0xc0, 0x37, 0xa3, 0xf7, 0x77, 0x1a, 0x92, 0x82,\n 0xcc, 0xfe, 0x8a, 0x47, 0xfd, 0xc8, 0x42, 0x20, 0x5d, 0x8f, 0xe4, 0xa0, 0x04, 0x24, 0xe8, 0xff,\n 0xd3, 0x3b, 0x69, 0x0d, 0x0b, 0x2f, 0x33, 0x1f, 0x04, 0x91, 0x8f, 0xa1, 0x30, 0x88, 0xeb, 0xfd,\n 0x34, 0x30, 0xb8, 0x04, 0x4e, 0x97, 0xac, 0x2b, 0x38, 0xa1, 0xa1, 0x65, 0xd6, 0xbc, 0x2f, 0x7a,\n 0xc6, 0x19, 0x0a, 0x31, 0x2d, 0xd6, 0x06, 0x07, 0x96, 0xe0, 0x97, 0x0a, 0xed, 0x76, 0x46, 0x78,\n 0x58, 0x99, 0xf1, 0x76, 0x94, 0xf1, 0x4e, 0x16, 0x0e, 0x51, 0xed, 0x5c, 0x26, 0x04, 0x95, 0x84,\n 0x35, 0x84, 0xd6, 0xde, 0x7e, 0x4a, 0x48, 0x19, 0xbd, 0x18, 0x92, 0xb5, 0xfc, 0x92, 0x02, 0xa9,\n 0x96, 0xf1, 0x24, 0x05, 0x94, 0xa4, 0x95, 0xb6, 0x52, 0xa1, 0x5b, 0x5a, 0x38, 0x19, 0xb9, 0x64,\n 0x98, 0xb9, 0x40, 0x99, 0x06, 0xb9, 0xac, 0x69, 0x4d, 0x0c, 0x26, 0x89, 0x0b, 0xeb, 0xe7, 0xaa,\n 0xef, 0xd4, 0x50, 0x32, 0x6a, 0x87, 0x20, 0x7b, 0x2f, 0x22, 0x15, 0x72, 0x38, 0xe0, 0x91, 0x1c,\n 0x48, 0x92, 0xb7, 0x9f, 0x1e, 0x47, 0xa0, 0xd2, 0xc3, 0xc8, 0x88, 0x7d, 0xb4, 0x11, 0xbb, 0x75,\n 0xe9, 0x90, 0xdb, 0x08, 0xc7, 0x07, 0xf2, 0x0f, 0xbf, 0x5a, 0x90, 0x1f, 0x3b, 0xe5, 0xef, 0x97,\n 0xf2, 0x40, 0x84, 0x4c, 0x51, 0x28, 0x93, 0x46, 0xca, 0x34, 0x1e, 0xf2, 0x62, 0x45, 0x79, 0xd5,\n 0xa5, 0x2c, 0x3e, 0x40, 0x96, 0x83, 0x28, 0x0b, 0x74, 0x94, 0x25, 0x53, 0xc8, 0x22, 0x36, 0x65,\n 0x5b, 0x81, 0xb2, 0xd1, 0x03, 0xd9, 0x7a, 0xa3, 0x6c, 0x86, 0x52, 0xb6, 0xa7, 0x21, 0x05, 0x03,\n 0x94, 0x12, 0x0e, 0x4a, 0x51, 0x0d, 0xa4, 0xcc, 0x89, 0x52, 0x78, 0x46, 0x29, 0x05, 0x84, 0x14,\n 0x67, 0x52, 0xca, 0x65, 0x29, 0x05, 0xcc, 0x90, 0x92, 0x72, 0x4a, 0x91, 0x3f, 0xe5, 0xd8, 0x05,\n 0xe4, 0x20, 0x0c, 0xe5, 0x68, 0x12, 0xe5, 0xb0, 0x18, 0xe4, 0xf8, 0x1e, 0xe5, 0x40, 0x25, 0xe5,\n 0x88, 0x2b, 0xe4, 0xd0, 0x31, 0xe5, 0x18, 0x38, 0xe5, 0x60, 0x3e, 0xa4, 0x55, 0x02, 0xa5, 0x79,\n 0x05, 0xa5, 0x9d, 0x08, 0xa4, 0xc1, 0x0b, 0xa5, 0xe5, 0x0e, 0xa5, 0x09, 0x12, 0xa4, 0x2d, 0x15,\n 0xa5, 0x51, 0x18, 0xa5, 0x75, 0x1b, 0xa4, 0x99, 0x1e, 0xa5, 0xbd, 0x21, 0xa5, 0xe1, 0x24, 0xa4,\n 0x05, 0x28, 0xa5, 0x29, 0x2b, 0xa5, 0x4d, 0x2e, 0xa4, 0x71, 0x31, 0xa5, 0x95, 0x34, 0xa5, 0xb9,\n 0x37, 0xa4, 0xdd, 0x3a, 0xa5, 0x01, 0x3e, 0xe5, 0x4a, 0x02, 0xc8, 0x25, 0x11, 0x94, 0x6b, 0x3b,\n 0x28, 0x17, 0xa9, 0x40, 0xae, 0xb6, 0xa1, 0x5c, 0x36, 0x44, 0xb9, 0xfe, 0x09, 0x72, 0x21, 0x17,\n 0xe5, 0x8a, 0x34, 0xca, 0xa5, 0x75, 0x94, 0x6b, 0x04, 0x31, 0x17, 0x3b, 0x7e, 0xee, 0x0c, 0x5d,\n 0xea, 0xf3, 0x0d, 0xea, 0xe3, 0xd5, 0xbf, 0x92, 0xac, 0x76, 0x5c, 0x00, 0x00, 0x00, 0x00, 0x49,\n 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82,\n]);\n","/**\n * Drawing executor —— #190(replaceDrawingWithPlaceholder / deleteDrawing)+ #210\n * (replaceShapeInnerText)。\n *\n * 设计要点:\n * - 入口都是 `drawingId`(装载期分配的 'dr-NNNN',来源:`indices.drawingIdx`),不接\n * Element / paraId,避免调用方自己绕 DOM 反查。\n * - replaceDrawingWithPlaceholder:仅接受 kind='picture' 的 drawing,把 a:blip/@r:embed\n * 改指共享 placeholder。布局完全保留(wp:inline / wp:anchor / wp:extent / 环绕 / position)。\n * 非 picture 抛 UNSUPPORTED_OOXML_FEATURE(由调用方走 deleteDrawing 或 replaceShapeInnerText)。\n * - deleteDrawing:不限制 kind,物理删 w:drawing;承载 w:r 仅含该 drawing 时一并删除。\n * - replaceShapeInnerText:仅接受含 w:txbxContent 的 drawing(textBox / shape-with-text),\n * 保留 w:drawing 整个外壳,只重写 txbxContent 内部为单段单 run 占位文字,保留首段 jc,\n * 并**继承原首 run rPr**(字体 / 字号 / 颜色)——红头艺术字字段化时占位 / 实际机关名\n * 不丢红色样式(解除 #210 v1「占位走默认字体」限制)。\n * 非 txbxContent drawing 抛 UNSUPPORTED_OOXML_FEATURE。这是 #192 内容型保留的工程依赖。\n * - 旧 media / rels 引用计数清理:替换 / 删除后若旧 rId 在该 part 无其它引用,移除 rels\n * 条目;旧 media binary part 在全包无其它引用时一并删除。这是 #190 「原始图片二进制\n * 不出现在输出文档中」验收条件的保证。replaceShapeInnerText 同源清理 txbxContent\n * 内 hyperlink / 嵌套 picture 的 rId 引用。\n * - trackChanges=true 暂不支持(与 deleteTable / replaceTableCellWithSdt 一致)。\n */\nimport { getPart, isXmlPart, markDirty } from '../../pack/index.js';\nimport { findStoryFor } from '../stories.js';\nimport { A_NS, PIC_NS, R_NS, W_NS, W14_NS, WP_NS } from '../namespaces.js';\nimport { generateParaId } from '../para-id.js';\nimport type { Op } from '../plan.js';\nimport { WordError } from '../word-error.js';\nimport type { ExecutorContext } from './executor-context.js';\nimport {\n PLACEHOLDER_DESCR,\n ensurePlaceholderMediaPart,\n ensurePlaceholderRelInPart,\n ensurePngContentType,\n resolveRelTarget,\n} from './placeholder-image.js';\nimport { createT, createW, firstDirectChildW, pickFirstRunRPr } from './_shared.js';\n\nconst RELS_NS = 'http://schemas.openxmlformats.org/package/2006/relationships';\n\nconst PICTURE_GRAPHICDATA_URI = 'http://schemas.openxmlformats.org/drawingml/2006/picture';\n\n// ─────────── replaceDrawingWithPlaceholder(#190)───────────\n\nexport function executeReplaceDrawingWithPlaceholder(\n ctx: ExecutorContext,\n op: Extract<Op, { type: 'replaceDrawingWithPlaceholder' }>,\n): void {\n if (ctx.options.trackChanges) {\n throw new WordError(\n 'UNSUPPORTED_OOXML_FEATURE',\n 'replaceDrawingWithPlaceholder with trackChanges=true not yet implemented',\n ctx.docId,\n { opType: 'replaceDrawingWithPlaceholder', drawingId: op.drawingId },\n );\n }\n\n const dr = requireDrawing(ctx, op.drawingId, 'replaceDrawingWithPlaceholder');\n\n // kind 校验:仅 picture 走本路径,其它(chart / smartArt / shape / textBox / group /\n // canvas / other)直接 reject —— 调用方应走 deleteDrawing 或 #192 的 shape 路径。\n const kindCheck = checkPictureKind(dr);\n if (!kindCheck.isPicture) {\n throw new WordError(\n 'UNSUPPORTED_OOXML_FEATURE',\n `replaceDrawingWithPlaceholder only supports kind='picture' drawings; got ${\n kindCheck.reason\n }. Use deleteDrawing for chart/smartArt/shape/textBox.`,\n ctx.docId,\n {\n opType: 'replaceDrawingWithPlaceholder',\n drawingId: op.drawingId,\n kindCheckReason: kindCheck.reason,\n },\n );\n }\n\n // 定位宿主 part 与对应 .rels\n const story = findStoryFor(ctx.pkg, dr);\n if (!story) {\n throw new WordError(\n 'PACKAGE_CORRUPT',\n `drawing '${op.drawingId}' not found in any story`,\n ctx.docId,\n { drawingId: op.drawingId, opType: 'replaceDrawingWithPlaceholder' },\n );\n }\n const hostPart = getPart(ctx.pkg, story.partPath);\n if (!hostPart || !isXmlPart(hostPart)) {\n throw new WordError(\n 'PACKAGE_CORRUPT',\n `story part '${story.partPath}' missing or not XML (op: replaceDrawingWithPlaceholder)`,\n ctx.docId,\n { drawingId: op.drawingId, partPath: story.partPath },\n );\n }\n const relsPath = relsPathFor(story.partPath);\n\n // 收集本 drawing 内所有 a:blip(picture 通常 1 个,但允许多张时统一处理)。\n // 同时记录每个 blip 替换前的 r:embed,供 S4 引用计数清理使用。\n const blips = snapshot(dr.getElementsByTagNameNS(A_NS, 'blip'));\n if (blips.length === 0) {\n throw new WordError(\n 'PACKAGE_CORRUPT',\n `drawing '${op.drawingId}' has kind='picture' but contains no <a:blip>`,\n ctx.docId,\n { drawingId: op.drawingId, opType: 'replaceDrawingWithPlaceholder' },\n );\n }\n\n // 注入共享资源(幂等)\n const mediaCreated = ensurePlaceholderMediaPart(ctx.pkg);\n if (mediaCreated) ensurePngContentType(ctx.pkg);\n const placeholderRId = ensurePlaceholderRelInPart(ctx.pkg, relsPath);\n\n // 收集替换前的 r:embed / r:link,稍后由 S4 清理旧 media。\n // 当前 PR(S3):只做改写,清理路径占位,留 ctx 侧 channel 后续补。\n const oldRelIds: string[] = [];\n for (const blip of blips) {\n const oldEmbed = blip.getAttributeNS(R_NS, 'embed');\n const oldLink = blip.getAttributeNS(R_NS, 'link');\n if (oldEmbed) oldRelIds.push(oldEmbed);\n if (oldLink) oldRelIds.push(oldLink);\n // 移除 r:link(linked image 场景);只保留 r:embed 指向 placeholder\n if (oldLink !== null) blip.removeAttributeNS(R_NS, 'link');\n blip.setAttributeNS(R_NS, 'r:embed', placeholderRId);\n }\n\n // 写无障碍标注 wp:docPr/@descr(中文\"[图片占位]\"由此处体现)\n applyPlaceholderDescr(dr);\n\n markDirty(hostPart);\n\n // 旧 media 引用清理(S4)— 必须在 host part DOM 已经改完(blip 已重定向)之后再算引用数\n const relsPartObj = getPart(ctx.pkg, relsPath);\n if (relsPartObj && isXmlPart(relsPartObj)) {\n cleanupOrphanRels(ctx, hostPart, relsPartObj, relsPath, oldRelIds, placeholderRId);\n }\n}\n\n// ─────────── deleteDrawing(#190)───────────\n\nexport function executeDeleteDrawing(\n ctx: ExecutorContext,\n op: Extract<Op, { type: 'deleteDrawing' }>,\n): void {\n if (ctx.options.trackChanges) {\n throw new WordError(\n 'UNSUPPORTED_OOXML_FEATURE',\n 'deleteDrawing with trackChanges=true not yet implemented',\n ctx.docId,\n { opType: 'deleteDrawing', drawingId: op.drawingId },\n );\n }\n\n const dr = requireDrawing(ctx, op.drawingId, 'deleteDrawing');\n\n const story = findStoryFor(ctx.pkg, dr);\n if (!story) {\n throw new WordError(\n 'PACKAGE_CORRUPT',\n `drawing '${op.drawingId}' not found in any story`,\n ctx.docId,\n { drawingId: op.drawingId, opType: 'deleteDrawing' },\n );\n }\n const hostPart = getPart(ctx.pkg, story.partPath);\n if (!hostPart || !isXmlPart(hostPart)) {\n throw new WordError(\n 'PACKAGE_CORRUPT',\n `story part '${story.partPath}' missing or not XML (op: deleteDrawing)`,\n ctx.docId,\n { drawingId: op.drawingId, partPath: story.partPath },\n );\n }\n const relsPath = relsPathFor(story.partPath);\n\n // 1. 收集 drawing 子树里所有 rId(embed / link / id):删 drawing 后这些都可能成孤儿\n const referencedRelIds = collectRelIdsInSubtree(dr);\n\n // 2. 删 w:drawing 节点本身\n const parent = dr.parentNode;\n if (!parent) {\n throw new WordError(\n 'PACKAGE_CORRUPT',\n `drawing '${op.drawingId}' has no parentNode`,\n ctx.docId,\n { drawingId: op.drawingId, opType: 'deleteDrawing' },\n );\n }\n parent.removeChild(dr);\n\n // 3. 父 w:r 若只剩 rPr / 已无实质内容,整段删(避免悬空空 run)\n if (\n parent.nodeType === 1 &&\n (parent as Element).namespaceURI === W_NS &&\n (parent as Element).localName === 'r' &&\n isRunEffectivelyEmpty(parent as Element)\n ) {\n const grand = parent.parentNode;\n if (grand) grand.removeChild(parent);\n }\n\n // 4. 同步 drawingIdx\n ctx.indices.drawingIdx.delete(op.drawingId);\n\n markDirty(hostPart);\n\n // 5. rels 引用清理(无 placeholder rId 需保留,传空串占位 keepRelId 不命中任何条目)\n const relsPartObj = getPart(ctx.pkg, relsPath);\n if (relsPartObj && isXmlPart(relsPartObj)) {\n cleanupOrphanRels(ctx, hostPart, relsPartObj, relsPath, referencedRelIds, '');\n }\n}\n\n// ─────────── replaceShapeInnerText(#210)───────────\n\nexport function executeReplaceShapeInnerText(\n ctx: ExecutorContext,\n op: Extract<Op, { type: 'replaceShapeInnerText' }>,\n): void {\n if (ctx.options.trackChanges) {\n throw new WordError(\n 'UNSUPPORTED_OOXML_FEATURE',\n 'replaceShapeInnerText with trackChanges=true not yet implemented',\n ctx.docId,\n { opType: 'replaceShapeInnerText', drawingId: op.drawingId },\n );\n }\n\n const dr = requireDrawing(ctx, op.drawingId, 'replaceShapeInnerText');\n\n // kind 校验:必须含 w:txbxContent(textBox / shape-with-text)。\n // - 嵌套 textBox 罕见但合法 —— 取 first descendant 在文档顺序上是最外层 txbxContent,符合直觉。\n // - mc:Fallback 内的 drawing 在装载期 buildDrawingIndex 已过滤,这里看到的是 Choice 路径。\n const txbxList = dr.getElementsByTagNameNS(W_NS, 'txbxContent');\n const txbx = txbxList.length > 0 ? (txbxList[0] as Element) : null;\n if (!txbx) {\n // 信息性错误:告诉调用方该走哪个 op 替代\n const kindCheck = checkPictureKind(dr);\n const hint = kindCheck.isPicture\n ? 'kind=picture; use replaceDrawingWithPlaceholder instead'\n : 'no w:txbxContent (shape without text / chart / smartArt / group / canvas / other); use deleteDrawing instead';\n throw new WordError(\n 'UNSUPPORTED_OOXML_FEATURE',\n `replaceShapeInnerText only supports drawings containing w:txbxContent (textBox / shape-with-text); got ${hint}`,\n ctx.docId,\n { opType: 'replaceShapeInnerText', drawingId: op.drawingId, hint },\n );\n }\n\n // 定位宿主 part(同 #190 路径)\n const story = findStoryFor(ctx.pkg, dr);\n if (!story) {\n throw new WordError(\n 'PACKAGE_CORRUPT',\n `drawing '${op.drawingId}' not found in any story`,\n ctx.docId,\n { drawingId: op.drawingId, opType: 'replaceShapeInnerText' },\n );\n }\n const hostPart = getPart(ctx.pkg, story.partPath);\n if (!hostPart || !isXmlPart(hostPart)) {\n throw new WordError(\n 'PACKAGE_CORRUPT',\n `story part '${story.partPath}' missing or not XML (op: replaceShapeInnerText)`,\n ctx.docId,\n { drawingId: op.drawingId, partPath: story.partPath },\n );\n }\n const relsPath = relsPathFor(story.partPath);\n\n // 替换前收集 txbxContent 子树内的 rId 引用(hyperlink / 嵌套 picture):删除后用于孤儿清理。\n // 注意:只扫 txbxContent 内部,外层 spPr/blipFill(若有作为 shape 填充图)不动。\n const referencedRelIds = collectRelIdsInSubtree(txbx);\n const oldParaIds = snapshot(txbx.getElementsByTagNameNS(W_NS, 'p'))\n .map((p) => p.getAttributeNS(W14_NS, 'paraId'))\n .filter((id): id is string => Boolean(id));\n\n // 保留首段 w:jc(对齐维度,#192 分组键依赖)\n const firstP = firstDirectChildW(txbx, 'p');\n const firstPPr = firstP ? firstDirectChildW(firstP, 'pPr') : null;\n\n // 保留被替换文字的原首 run rPr(字体 / 字号 / 颜色)——红头艺术字字段化的关键:\n // 占位文字(及后续排版填入的实际机关名)继承原 run 样式,而非走默认字体(解除 #210 v1 限制)。\n // pickFirstRunRPr 取传入元素内首个后代 run 的 rPr 克隆(覆盖 hyperlink / SDT 等包裹),\n // run 无显式 rPr 时兜底取该元素**直属** pPr/rPr ——故必须传**首段 w:p**(firstP)而非 txbx:\n // pPr 是 w:p 的直属子,而 txbx 的直属子是 w:p,传 txbx 会让 pPr/rPr 兜底永远落空。\n // firstP 缺失(罕见,txbxContent 无段落)时退回 txbx,只能拿到后代 run 的 rPr(无 pPr/rPr 兜底)。\n // 两者都无 → undefined(裸 run,语义不变)。必须在清空 txbxContent 之前抓取。\n const firstRunRPr = pickFirstRunRPr(firstP ?? txbx);\n\n // 清空 txbxContent 全部子节点\n while (txbx.firstChild) txbx.removeChild(txbx.firstChild);\n for (const id of oldParaIds) ctx.indices.paraIdx.delete(id.toUpperCase());\n\n // 注入单段单 run 占位文字\n const doc = txbx.ownerDocument!;\n const p = createW(doc, 'p');\n const newParaId = generateParaId(new Set(ctx.indices.paraIdx.keys()));\n p.setAttributeNS(W14_NS, 'w14:paraId', newParaId);\n if (firstPPr) p.appendChild(firstPPr.cloneNode(true));\n const r = createW(doc, 'r');\n // 继承原 rPr(若有);rPr 必须是 run 首子(OOXML schema 要求 w:rPr 在 w:t 之前)\n if (firstRunRPr) r.appendChild(firstRunRPr);\n r.appendChild(createT(doc, op.placeholder));\n p.appendChild(r);\n txbx.appendChild(p);\n ctx.indices.paraIdx.set(newParaId, p);\n\n markDirty(hostPart);\n\n // rels 引用清理(同 #190):txbxContent 内若有 hyperlink/embed 的 rId,删后该 part 内归零则清 rels\n const relsPartObj = getPart(ctx.pkg, relsPath);\n if (relsPartObj && isXmlPart(relsPartObj)) {\n cleanupOrphanRels(ctx, hostPart, relsPartObj, relsPath, referencedRelIds, '');\n }\n}\n\n// ─────────── 内部 ───────────\n\nfunction requireDrawing(ctx: ExecutorContext, drawingId: string, opName: string): Element {\n const dr = ctx.indices.drawingIdx.get(drawingId);\n if (!dr) {\n throw new WordError(\n 'DRAWING_NOT_FOUND',\n `drawing with drawingId='${drawingId}' not found (op: ${opName})`,\n ctx.docId,\n { drawingId, opName },\n );\n }\n return dr;\n}\n\nfunction snapshot<T extends Element>(col: { length: number } & Record<number, T>): T[] {\n const out: T[] = [];\n for (let i = 0; i < col.length; i++) {\n const el = col[i];\n if (el) out.push(el);\n }\n return out;\n}\n\n/**\n * 判断 drawing 是否 kind='picture'。\n *\n * 与 list-drawings.ts 的判定逻辑对齐:看 a:graphicData @uri。这里独立实现一份\n * 避免反向依赖 list-drawings(那是只读 API,executor 走自己的轻量路径)。\n *\n * 进入路径:`w:drawing → wp:inline | wp:anchor → a:graphic → a:graphicData @uri`。\n * 若任一层缺失视为 corrupt(返回 reason=`malformed`),不当 picture 处理。\n */\nfunction checkPictureKind(drawing: Element): { isPicture: boolean; reason: string } {\n // wp:inline / wp:anchor 任一\n let container: Element | null = null;\n for (let i = 0; i < drawing.childNodes.length; i++) {\n const c = drawing.childNodes[i];\n if (!c || c.nodeType !== 1) continue;\n const el = c as Element;\n if (el.namespaceURI === WP_NS && (el.localName === 'inline' || el.localName === 'anchor')) {\n container = el;\n break;\n }\n }\n if (!container) return { isPicture: false, reason: 'malformed (no wp:inline / wp:anchor)' };\n\n // a:graphic → a:graphicData\n const graphic = firstChildNS(container, A_NS, 'graphic');\n if (!graphic) return { isPicture: false, reason: 'malformed (no a:graphic)' };\n const graphicData = firstChildNS(graphic, A_NS, 'graphicData');\n if (!graphicData) return { isPicture: false, reason: 'malformed (no a:graphicData)' };\n\n const uri = graphicData.getAttribute('uri');\n if (uri !== PICTURE_GRAPHICDATA_URI) {\n return { isPicture: false, reason: `kind=non-picture (a:graphicData/@uri='${uri ?? ''}')` };\n }\n\n // 进一步校验 pic:pic 存在(防御性:某些工具会用 picture URI 但内部嵌入非 pic:pic)\n const pic = firstChildNS(graphicData, PIC_NS, 'pic');\n if (!pic)\n return { isPicture: false, reason: 'malformed (graphicData/@uri=picture but no pic:pic)' };\n\n return { isPicture: true, reason: 'picture' };\n}\n\nfunction firstChildNS(parent: Element, ns: string, local: string): Element | null {\n for (let i = 0; i < parent.childNodes.length; i++) {\n const c = parent.childNodes[i];\n if (!c || c.nodeType !== 1) continue;\n const el = c as Element;\n if (el.namespaceURI === ns && el.localName === local) return el;\n }\n return null;\n}\n\n/**\n * 设置 drawing 的中文无障碍标注。\n *\n * 路径:wp:inline | wp:anchor → wp:docPr。docPr 是 OOXML 规范保证的元素(Word\n * 装载期会自动补;若缺失则视作 corrupt,但本函数容错地不抛 —— 静默跳过)。\n *\n * 同时设 @descr(screen reader / OS accessibility 读取)与 @title(hover tooltip)。\n */\nfunction applyPlaceholderDescr(drawing: Element): void {\n for (let i = 0; i < drawing.childNodes.length; i++) {\n const c = drawing.childNodes[i];\n if (!c || c.nodeType !== 1) continue;\n const container = c as Element;\n if (container.namespaceURI !== WP_NS) continue;\n if (container.localName !== 'inline' && container.localName !== 'anchor') continue;\n const docPr = firstChildNS(container, WP_NS, 'docPr');\n if (!docPr) return; // 罕见;不抛,保守跳过\n docPr.setAttribute('descr', PLACEHOLDER_DESCR);\n docPr.setAttribute('title', PLACEHOLDER_DESCR);\n return;\n }\n}\n\n/**\n * 把 part 路径转换为对应 .rels part 路径。\n *\n * 'word/document.xml' → 'word/_rels/document.xml.rels'\n * 'word/header1.xml' → 'word/_rels/header1.xml.rels'\n * '.rels' 顶层场景不出现在 #190 用例里(drawing 不会挂顶层 part)\n */\nfunction relsPathFor(partPath: string): string {\n const idx = partPath.lastIndexOf('/');\n if (idx < 0) return `_rels/${partPath}.rels`;\n const dir = partPath.slice(0, idx);\n const name = partPath.slice(idx + 1);\n return `${dir}/_rels/${name}.rels`;\n}\n\n/**\n * 旧 rels / media 引用计数清理(#190 S4)。\n *\n * 流程:\n * 1. 对每个 oldRelId,在宿主 part XML 内统计剩余引用数(r:embed / r:link / r:id 三种属性)\n * 2. 引用归零 → 删 rels DOM 中对应 `<Relationship>`,记录 Target → 候选 media path\n * 3. media path 加入 ctx.orphanMediaCandidates(由 kernel 在事务 commit 后统一 sweep)\n *\n * 为什么不在这里直接删 binary part:同一 media 可能被多 drawing 共享(其它 part 或同 part\n * 后续未处理 drawing),只在全包 rels 都不再引用时才安全。判定与删除延迟到 sweep 阶段。\n *\n * @param hostPart drawing 所在 XML part\n * @param relsPart 对应 .rels part(必须已 isXmlPart && xmlDom)\n * @param relsPath rels part 路径(用于 Target → 绝对 path 解析)\n * @param oldRelIds 替换前的 r:embed / r:link 列表(允许重复;函数内去重)\n * @param keepRelId 新写入的 placeholder rId,不要把它当孤儿\n */\nfunction cleanupOrphanRels(\n ctx: ExecutorContext,\n hostPart: { xmlDom?: Document },\n relsPart: { xmlDom?: Document },\n relsPath: string,\n oldRelIds: readonly string[],\n keepRelId: string,\n): void {\n if (oldRelIds.length === 0) return;\n if (!hostPart.xmlDom || !relsPart.xmlDom) return;\n\n const uniqueOld = new Set(oldRelIds.filter((id) => id && id !== keepRelId));\n if (uniqueOld.size === 0) return;\n\n // 1. 宿主 part 内仍引用 oldRelId 的次数(replace 已经把所有 a:blip 改了;但同 part\n // 内可能有其它 drawing / VML / chart 也用同名 rId,本步骤是防误删)\n const orphanRelIds: string[] = [];\n for (const oldId of uniqueOld) {\n if (countRelRefsInDoc(hostPart.xmlDom, oldId) === 0) orphanRelIds.push(oldId);\n }\n if (orphanRelIds.length === 0) return;\n\n // 2. 从 rels DOM 删 orphan <Relationship>,记录 media path\n const rels = snapshot(relsPart.xmlDom.getElementsByTagNameNS(RELS_NS, 'Relationship'));\n let relsTouched = false;\n for (const rel of rels) {\n const id = rel.getAttribute('Id') ?? '';\n if (!orphanRelIds.includes(id)) continue;\n const target = rel.getAttribute('Target') ?? '';\n if (target && ctx.orphanMediaCandidates) {\n const mediaPath = resolveRelTarget(relsPath, target);\n ctx.orphanMediaCandidates.add(mediaPath);\n }\n rel.parentNode?.removeChild(rel);\n relsTouched = true;\n }\n if (relsTouched) {\n const rp = getPart(ctx.pkg, relsPath);\n if (rp) markDirty(rp);\n }\n}\n\n/**\n * 统计文档内引用某个 rId 的次数。\n *\n * 扫所有元素,匹配 r:embed / r:link / r:id 三类属性(OOXML 中 rId 引用的全部形态)。\n * 性能:全文遍历一遍,对中小文档可接受;若未来发现热点可改成按已知 tag 名(a:blip /\n * v:imagedata / c:chart / w:hyperlink 等)定向扫描。\n */\nfunction countRelRefsInDoc(doc: Document, relId: string): number {\n let count = 0;\n const all = doc.getElementsByTagName('*');\n for (let i = 0; i < all.length; i++) {\n const el = all[i] as Element | undefined;\n if (!el) continue;\n if (el.getAttributeNS(R_NS, 'embed') === relId) count++;\n if (el.getAttributeNS(R_NS, 'link') === relId) count++;\n if (el.getAttributeNS(R_NS, 'id') === relId) count++;\n }\n return count;\n}\n\n/**\n * 收集 drawing 子树内所有 rId 引用(r:embed / r:link / r:id),返回去重列表。\n *\n * 覆盖范围:不仅是 a:blip 的 embed/link,也包括 chart 的 r:id、SmartArt 的 r:dm/r:lo/r:qs/r:cs\n * (这些都用 R_NS 的 id 属性引用 chart.xml / data1.xml / styles.xml 等关联 part)。\n *\n * 注意:删除 drawing 时这些子树内所有 rId 都\"可能\"成为孤儿;sweepOrphanMediaParts\n * 只会删 isBinaryPart 的部分,XML 关联 part(如 chart.xml)会被跳过留存,行为合理。\n */\nfunction collectRelIdsInSubtree(drawing: Element): string[] {\n const ids = new Set<string>();\n const all = drawing.getElementsByTagName('*');\n for (let i = 0; i < all.length; i++) {\n const el = all[i] as Element | undefined;\n if (!el) continue;\n const embed = el.getAttributeNS(R_NS, 'embed');\n if (embed) ids.add(embed);\n const link = el.getAttributeNS(R_NS, 'link');\n if (link) ids.add(link);\n const rid = el.getAttributeNS(R_NS, 'id');\n if (rid) ids.add(rid);\n }\n return [...ids];\n}\n\n/**\n * 判断 `<w:r>` 是否仅含 `<w:rPr>` 或无内容(即可安全删除)。\n *\n * 复用自 table-ops.ts 的 isRunEffectivelyEmpty 语义,这里就近实现避免跨文件 export\n * shared util。判定:除 w:rPr 外没有其它元素子节点 = 空。\n */\nfunction isRunEffectivelyEmpty(run: Element): boolean {\n for (let i = 0; i < run.childNodes.length; i++) {\n const c = run.childNodes[i];\n if (!c || c.nodeType !== 1) continue;\n const el = c as Element;\n if (el.namespaceURI === W_NS && el.localName === 'rPr') continue;\n return false;\n }\n return true;\n}\n","/**\n * insertImageAfter executor —— task-insert-image。\n *\n * 在 anchorParaId 段之后新插一个 <w:p>,段内含 inline 图片 <w:drawing>。\n *\n * 写链(8 步):\n * 1. anchor 定位(paraIdx → PARA_NOT_FOUND)\n * 2. 分配 media 文件名(image1..imageN.ext,无撞)\n * 3. 新建 binary part(createBinaryPart + setPart + markDirty)\n * 4. 加 image rel(rels 扫 max(rIdN)+1)\n * 5. 登记 content-type(ensureImageContentType)\n * 6. 构造 <w:drawing> DOM(inline picture 模板)\n * 7. 包 <w:r> + 新 <w:p>(含 w14:paraId 主动分配)\n * 8. markDirty\n *\n * 跨端:只用 Uint8Array,绝不碰 node fs/Buffer。\n */\nimport { parseXmlDocument } from 'slimdom';\nimport {\n createBinaryPart,\n createXmlPart,\n getPart,\n hasPart,\n isXmlPart,\n listParts,\n markDirty,\n setPart,\n type Package,\n} from '../../pack/index.js';\nimport { generateParaId } from '../para-id.js';\nimport { A_NS, PIC_NS, R_NS, W_NS, W14_NS, WP_NS } from '../namespaces.js';\nimport type { Op } from '../plan.js';\nimport { findStoryFor } from '../stories.js';\nimport { WordError } from '../word-error.js';\nimport type { ExecutorContext } from './executor-context.js';\n\nconst RELS_NS = 'http://schemas.openxmlformats.org/package/2006/relationships';\nconst CONTENT_TYPES_PATH = '[Content_Types].xml';\nconst CONTENT_TYPES_NS = 'http://schemas.openxmlformats.org/package/2006/content-types';\nconst IMAGE_RELATIONSHIP_TYPE =\n 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/image';\n\n/**\n * contentType → 文件扩展名。\n *\n * 含位图 5 种 + 矢量图 2 种(EMF/WMF)。\n *\n * EMF/WMF 是 Word 原生支持的矢量图格式(粘贴的 Office 图表/示意图、老文档插图常见),\n * 在 OOXML 里和位图一样走 a:blip/@r:embed 引用机制 —— blip 对图片格式一视同仁,\n * 矢量图 part 的扩展名是 .emf/.wmf、content-type 是 image/x-emf/image/x-wmf。\n * typeset 透传源文档已有的 EMF/WMF 图时(getImageBytes 读出原始字节 + contentType,\n * insertImageAfter 重新引用),白名单必须含这两种,否则真实文档(含矢量图)排版崩溃。\n */\nexport const CONTENT_TYPE_TO_EXT: Record<string, string> = {\n 'image/png': 'png',\n 'image/jpeg': 'jpeg',\n 'image/gif': 'gif',\n 'image/bmp': 'bmp',\n 'image/tiff': 'tiff',\n 'image/x-emf': 'emf',\n 'image/x-wmf': 'wmf',\n};\n\n// ─────────── executor ───────────\n\nexport function executeInsertImageAfter(\n ctx: ExecutorContext,\n op: Extract<Op, { type: 'insertImageAfter' }>,\n): void {\n if (ctx.options.trackChanges) {\n throw new WordError(\n 'UNSUPPORTED_OOXML_FEATURE',\n 'insertImageAfter with trackChanges=true not yet implemented',\n ctx.docId,\n { opType: 'insertImageAfter' },\n );\n }\n\n // contentType 校验\n const ext = CONTENT_TYPE_TO_EXT[op.contentType];\n if (!ext) {\n throw new WordError(\n 'UNSUPPORTED_OOXML_FEATURE',\n `insertImageAfter: unsupported contentType '${op.contentType}'. Supported: image/png, image/jpeg, image/gif, image/bmp, image/tiff, image/x-emf, image/x-wmf`,\n ctx.docId,\n { opType: 'insertImageAfter', contentType: op.contentType },\n );\n }\n\n // 1. anchor 定位\n const anchor = ctx.indices.paraIdx.get(op.anchorParaId.toUpperCase());\n if (!anchor) {\n throw new WordError(\n 'PARA_NOT_FOUND',\n `paragraph with paraId='${op.anchorParaId}' not found (op: insertImageAfter)`,\n ctx.docId,\n { paraId: op.anchorParaId, opName: 'insertImageAfter' },\n );\n }\n const story = findStoryFor(ctx.pkg, anchor);\n if (!story) {\n throw new WordError(\n 'PACKAGE_CORRUPT',\n `anchor paragraph '${op.anchorParaId}' not found in any story`,\n ctx.docId,\n { paraId: op.anchorParaId, opName: 'insertImageAfter' },\n );\n }\n const hostPartPath = story.partPath;\n const relsPath = relsPathFor(hostPartPath);\n\n // 2. 分配 media 文件名(image1..imageN.ext)\n const mediaPath = allocateMediaPath(ctx.pkg, ext);\n\n // 3. 新建 binary part\n const mediaPart = createBinaryPart({\n path: mediaPath,\n contentType: op.contentType,\n bytes: op.bytes,\n });\n setPart(ctx.pkg, mediaPart);\n markDirty(mediaPart);\n\n // 4. 加 image rel(rels 扫 max(rIdN)+1)\n const rId = addImageRel(ctx.pkg, relsPath, mediaPath);\n\n // 5. 登记 content-type\n ensureImageContentType(ctx.pkg, ext, op.contentType);\n\n // 6. 构造 <w:drawing> DOM\n const hostPart = getPart(ctx.pkg, hostPartPath);\n if (!hostPart || !isXmlPart(hostPart) || !hostPart.xmlDom) {\n throw new WordError(\n 'PACKAGE_CORRUPT',\n `host part '${hostPartPath}' missing or not XML`,\n ctx.docId,\n { opName: 'insertImageAfter' },\n );\n }\n const doc = hostPart.xmlDom;\n\n const docPrId = allocateDocPrId(doc);\n const drawing = buildInlineDrawing(doc, rId, docPrId, op.widthEmu, op.heightEmu);\n\n // 7. 新 <w:p>(含主动分配 w14:paraId)\n const seen = new Set(ctx.indices.paraIdx.keys());\n const newParaId = generateParaId(seen);\n\n const newPara = doc.createElementNS(W_NS, 'w:p');\n newPara.setAttributeNS(W14_NS, 'w14:paraId', newParaId);\n const run = doc.createElementNS(W_NS, 'w:r');\n run.appendChild(drawing);\n newPara.appendChild(run);\n\n // 插到 anchor 之后(insert-before anchor.nextSibling)\n const parent = anchor.parentNode;\n if (!parent) {\n throw new WordError(\n 'PACKAGE_CORRUPT',\n `anchor paragraph '${op.anchorParaId}' has no parentNode`,\n ctx.docId,\n { paraId: op.anchorParaId, opName: 'insertImageAfter' },\n );\n }\n parent.insertBefore(newPara, anchor.nextSibling);\n\n // 同步 paraIdx(保证同一 plan 内后续 op 可查到新段)\n ctx.indices.paraIdx.set(newParaId, newPara);\n\n // 8. markDirty\n markDirty(hostPart);\n const relsPart = getPart(ctx.pkg, relsPath);\n if (relsPart) markDirty(relsPart);\n const ctPart = getPart(ctx.pkg, CONTENT_TYPES_PATH);\n if (ctPart) markDirty(ctPart);\n}\n\n// ─────────── helpers ───────────\n\n/**\n * 分配唯一 media 文件名:扫 word/media/imageN.ext,取最大 N+1。\n * hasPart 二次校验防撞(理论不撞,保险用)。\n */\nexport function allocateMediaPath(pkg: Package, ext: string): string {\n let maxN = 0;\n for (const part of listParts(pkg)) {\n const m = /^word\\/media\\/image(\\d+)\\./i.exec(part.path);\n if (m) {\n const n = parseInt(m[1]!, 10);\n if (n > maxN) maxN = n;\n }\n }\n let candidate = `word/media/image${maxN + 1}.${ext}`;\n // 二次校验防撞(例如 image1.png 已存在但 image1.jpeg 也占了 N=1)\n while (hasPart(pkg, candidate)) {\n maxN++;\n candidate = `word/media/image${maxN + 1}.${ext}`;\n }\n return candidate;\n}\n\n/**\n * 在 relsPartPath 里新增一条 image relationship 指向 mediaPath,返回分配的 rId。\n * 若 rels part 不存在,先创建空 rels。\n */\nexport function addImageRelForHost(pkg: Package, relsPartPath: string, mediaPath: string): string {\n return addImageRel(pkg, relsPartPath, mediaPath);\n}\n\nfunction addImageRel(pkg: Package, relsPartPath: string, mediaPath: string): string {\n let relsPart = getPart(pkg, relsPartPath);\n if (!relsPart) {\n const empty = `<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\\n<Relationships xmlns=\"${RELS_NS}\"/>`;\n const dom = parseXmlDocument(empty) as unknown as Document;\n relsPart = createXmlPart({\n path: relsPartPath,\n contentType: 'application/vnd.openxmlformats-package.relationships+xml',\n xmlDom: dom,\n });\n setPart(pkg, relsPart);\n }\n if (!isXmlPart(relsPart) || !relsPart.xmlDom) {\n throw new Error(`addImageRel: '${relsPartPath}' is not an XML part`);\n }\n\n const doc = relsPart.xmlDom;\n const rels = doc.getElementsByTagNameNS(RELS_NS, 'Relationship');\n let maxRId = 0;\n for (let i = 0; i < rels.length; i++) {\n const id = rels[i]!.getAttribute('Id') ?? '';\n const m = /^rId(\\d+)$/.exec(id);\n if (m) {\n const n = parseInt(m[1]!, 10);\n if (n > maxRId) maxRId = n;\n }\n }\n\n const rId = `rId${maxRId + 1}`;\n // Target 相对于宿主 part 目录:word/document.xml → word/media/imageN.ext → media/imageN.ext\n const target = computeRelTarget(relsPartPath, mediaPath);\n const rel = doc.createElementNS(RELS_NS, 'Relationship');\n rel.setAttribute('Id', rId);\n rel.setAttribute('Type', IMAGE_RELATIONSHIP_TYPE);\n rel.setAttribute('Target', target);\n doc.documentElement.appendChild(rel);\n markDirty(relsPart);\n return rId;\n}\n\n/**\n * 登记 content-type Default:补 `<Default Extension=ext ContentType=ct/>`。\n * 已有同 Extension 的 Default → 跳过。\n */\nexport function ensureImageContentType(pkg: Package, ext: string, contentType: string): void {\n const ctPart = getPart(pkg, CONTENT_TYPES_PATH);\n if (!ctPart || !isXmlPart(ctPart) || !ctPart.xmlDom) return;\n const doc = ctPart.xmlDom;\n\n const defaults = doc.getElementsByTagNameNS(CONTENT_TYPES_NS, 'Default');\n for (let i = 0; i < defaults.length; i++) {\n if (defaults[i]!.getAttribute('Extension')?.toLowerCase() === ext.toLowerCase()) return;\n }\n\n const def = doc.createElementNS(CONTENT_TYPES_NS, 'Default');\n def.setAttribute('Extension', ext);\n def.setAttribute('ContentType', contentType);\n doc.documentElement.appendChild(def);\n markDirty(ctPart);\n}\n\n/**\n * 扫 document.xmlDom 里所有 wp:docPr/@id,取 max+1。\n */\nfunction allocateDocPrId(doc: Document): number {\n const docPrs = doc.getElementsByTagNameNS(WP_NS, 'docPr');\n let maxId = 0;\n for (let i = 0; i < docPrs.length; i++) {\n const raw = docPrs[i]!.getAttribute('id');\n if (!raw) continue;\n const n = parseInt(raw, 10);\n if (!isNaN(n) && n > maxId) maxId = n;\n }\n return maxId + 1;\n}\n\n/**\n * 构造 inline picture <w:drawing> DOM。\n *\n * 结构:\n * w:drawing\n * wp:inline(distT/B/L/R=0)\n * wp:extent(@cx @cy)\n * wp:docPr(@id @name)\n * wp:cNvGraphicFramePr > a:graphicFrameLocks(noChangeAspect=1)\n * a:graphic > a:graphicData(uri=PIC_NS)\n * pic:pic\n * pic:nvPicPr > pic:cNvPr(@id @name) + pic:cNvPicPr > a:picLocks(noChangeAspect=1)\n * pic:blipFill > a:blip(@r:embed) + a:stretch > a:fillRect\n * pic:spPr > a:xfrm > (a:off x=0 y=0 + a:ext @cx @cy) + a:prstGeom(prst=rect) > a:avLst\n */\nfunction buildInlineDrawing(\n doc: Document,\n rId: string,\n docPrId: number,\n widthEmu: number,\n heightEmu: number,\n): Element {\n const imgName = `image${docPrId}`;\n\n function ns(nsUri: string, local: string): Element {\n // Use prefixed form for non-W_NS elements to match real OOXML output\n const prefix = nsPrefixOf(nsUri);\n return doc.createElementNS(nsUri, prefix ? `${prefix}:${local}` : local);\n }\n\n // w:drawing\n const drawing = doc.createElementNS(W_NS, 'w:drawing');\n\n // wp:inline\n const inline = ns(WP_NS, 'inline');\n inline.setAttribute('distT', '0');\n inline.setAttribute('distB', '0');\n inline.setAttribute('distL', '0');\n inline.setAttribute('distR', '0');\n drawing.appendChild(inline);\n\n // wp:extent\n const extent = ns(WP_NS, 'extent');\n extent.setAttribute('cx', String(widthEmu));\n extent.setAttribute('cy', String(heightEmu));\n inline.appendChild(extent);\n\n // wp:effectExtent\n const effectExtent = ns(WP_NS, 'effectExtent');\n effectExtent.setAttribute('l', '0');\n effectExtent.setAttribute('t', '0');\n effectExtent.setAttribute('r', '0');\n effectExtent.setAttribute('b', '0');\n inline.appendChild(effectExtent);\n\n // wp:docPr\n const docPr = ns(WP_NS, 'docPr');\n docPr.setAttribute('id', String(docPrId));\n docPr.setAttribute('name', imgName);\n inline.appendChild(docPr);\n\n // wp:cNvGraphicFramePr\n const cNvGFP = ns(WP_NS, 'cNvGraphicFramePr');\n const gfLocks = doc.createElementNS(A_NS, 'a:graphicFrameLocks');\n gfLocks.setAttribute('noChangeAspect', '1');\n cNvGFP.appendChild(gfLocks);\n inline.appendChild(cNvGFP);\n\n // a:graphic > a:graphicData\n const graphic = doc.createElementNS(A_NS, 'a:graphic');\n const graphicData = doc.createElementNS(A_NS, 'a:graphicData');\n graphicData.setAttribute('uri', PIC_NS);\n graphic.appendChild(graphicData);\n inline.appendChild(graphic);\n\n // pic:pic\n const pic = doc.createElementNS(PIC_NS, 'pic:pic');\n graphicData.appendChild(pic);\n\n // pic:nvPicPr\n const nvPicPr = doc.createElementNS(PIC_NS, 'pic:nvPicPr');\n pic.appendChild(nvPicPr);\n\n const cNvPr = doc.createElementNS(PIC_NS, 'pic:cNvPr');\n cNvPr.setAttribute('id', String(docPrId));\n cNvPr.setAttribute('name', imgName);\n nvPicPr.appendChild(cNvPr);\n\n const cNvPicPr = doc.createElementNS(PIC_NS, 'pic:cNvPicPr');\n const picLocks = doc.createElementNS(A_NS, 'a:picLocks');\n picLocks.setAttribute('noChangeAspect', '1');\n cNvPicPr.appendChild(picLocks);\n nvPicPr.appendChild(cNvPicPr);\n\n // pic:blipFill\n const blipFill = doc.createElementNS(PIC_NS, 'pic:blipFill');\n pic.appendChild(blipFill);\n\n const blip = doc.createElementNS(A_NS, 'a:blip');\n blip.setAttributeNS(R_NS, 'r:embed', rId);\n blipFill.appendChild(blip);\n\n const stretch = doc.createElementNS(A_NS, 'a:stretch');\n const fillRect = doc.createElementNS(A_NS, 'a:fillRect');\n stretch.appendChild(fillRect);\n blipFill.appendChild(stretch);\n\n // pic:spPr\n const spPr = doc.createElementNS(PIC_NS, 'pic:spPr');\n pic.appendChild(spPr);\n\n const xfrm = doc.createElementNS(A_NS, 'a:xfrm');\n const off = doc.createElementNS(A_NS, 'a:off');\n off.setAttribute('x', '0');\n off.setAttribute('y', '0');\n xfrm.appendChild(off);\n const extEl = doc.createElementNS(A_NS, 'a:ext');\n extEl.setAttribute('cx', String(widthEmu));\n extEl.setAttribute('cy', String(heightEmu));\n xfrm.appendChild(extEl);\n spPr.appendChild(xfrm);\n\n const prstGeom = doc.createElementNS(A_NS, 'a:prstGeom');\n prstGeom.setAttribute('prst', 'rect');\n const avLst = doc.createElementNS(A_NS, 'a:avLst');\n prstGeom.appendChild(avLst);\n spPr.appendChild(prstGeom);\n\n return drawing;\n}\n\n/** namespace URI → prefix map(用于创建有正确前缀的元素,与真实 OOXML 匹配)*/\nfunction nsPrefixOf(nsUri: string): string {\n if (nsUri === WP_NS) return 'wp';\n if (nsUri === A_NS) return 'a';\n if (nsUri === PIC_NS) return 'pic';\n if (nsUri === R_NS) return 'r';\n return '';\n}\n\n/**\n * 把 rels part 路径转成宿主 part 所在目录,用于计算相对 Target。\n * 'word/_rels/document.xml.rels' → base='word'\n */\nfunction computeRelTarget(relsPartPath: string, targetPartPath: string): string {\n const idx = relsPartPath.lastIndexOf('/_rels/');\n if (idx < 0) return targetPartPath;\n const hostDir = relsPartPath.slice(0, idx);\n if (targetPartPath.startsWith(`${hostDir}/`)) {\n return targetPartPath.slice(hostDir.length + 1);\n }\n return `/${targetPartPath}`;\n}\n\n/**\n * 把 part 路径转换为对应 .rels part 路径。\n * 'word/document.xml' → 'word/_rels/document.xml.rels'\n */\nfunction relsPathFor(partPath: string): string {\n const idx = partPath.lastIndexOf('/');\n if (idx < 0) return `_rels/${partPath}.rels`;\n const dir = partPath.slice(0, idx);\n const name = partPath.slice(idx + 1);\n return `${dir}/_rels/${name}.rels`;\n}\n\n// ─────────── getImageBytes(内核侧同步实现,供 kernel.ts 调用)───────────\n\nexport interface ImageBytesResult {\n bytes: Uint8Array;\n contentType: string;\n extentEMU: { cx: number; cy: number };\n}\n\n/**\n * 读取 drawingId 对应 picture 的原始图片字节。\n * drawingId 不存在 / 非 picture / media 找不到 → 返回 null(不抛)。\n */\nexport function getImageBytesSync(\n pkg: Package,\n indices: { drawingIdx: Map<string, Element> },\n drawingId: string,\n): ImageBytesResult | null {\n // 1. drawingId → <w:drawing>\n const dr = indices.drawingIdx.get(drawingId);\n if (!dr) return null;\n\n // 2. <w:drawing> → a:blip/@r:embed\n const blips = dr.getElementsByTagNameNS(A_NS, 'blip');\n if (blips.length === 0) return null;\n const blip = blips[0]!;\n const rId = blip.getAttributeNS(R_NS, 'embed');\n if (!rId) return null;\n\n // 3. <w:drawing> → 宿主 part path\n const story = findStoryFor(pkg, dr);\n if (!story) return null;\n const hostPartPath = story.partPath;\n\n // 4. partPath → rels path\n const relsPath = relsPathFor(hostPartPath);\n\n // 5. rId → media path via rels\n const relsPart = getPart(pkg, relsPath);\n if (!relsPart || !isXmlPart(relsPart) || !relsPart.xmlDom) return null;\n const rels = relsPart.xmlDom.getElementsByTagNameNS(RELS_NS, 'Relationship');\n let mediaPath: string | null = null;\n for (let i = 0; i < rels.length; i++) {\n const r = rels[i]!;\n if (r.getAttribute('Id') === rId) {\n const target = r.getAttribute('Target') ?? '';\n // resolve relative target → absolute part path\n mediaPath = resolveTarget(relsPath, target);\n break;\n }\n }\n if (!mediaPath) return null;\n\n // 6. media path → bytes\n const mediaPart = getPart(pkg, mediaPath);\n if (!mediaPart) return null;\n // isBinaryPart check: has bytes field\n const bytes = (mediaPart as unknown as { bytes?: Uint8Array }).bytes;\n if (!bytes) return null;\n const contentType = mediaPart.contentType;\n\n // extentEMU: from wp:extent inside wp:inline / wp:anchor\n const extentEMU = readDrawingExtent(dr);\n\n return { bytes, contentType, extentEMU };\n}\n\n/** wp:extent @cx/@cy from wp:inline or wp:anchor child */\nfunction readDrawingExtent(drawing: Element): { cx: number; cy: number } {\n for (let i = 0; i < drawing.childNodes.length; i++) {\n const c = drawing.childNodes[i] as Element;\n if (!c || c.nodeType !== 1) continue;\n if (c.namespaceURI !== WP_NS) continue;\n if (c.localName !== 'inline' && c.localName !== 'anchor') continue;\n // find wp:extent child\n for (let j = 0; j < c.childNodes.length; j++) {\n const ext = c.childNodes[j] as Element;\n if (!ext || ext.nodeType !== 1) continue;\n if (ext.namespaceURI === WP_NS && ext.localName === 'extent') {\n const cx = parseInt(ext.getAttribute('cx') ?? '0', 10);\n const cy = parseInt(ext.getAttribute('cy') ?? '0', 10);\n return { cx: isNaN(cx) ? 0 : cx, cy: isNaN(cy) ? 0 : cy };\n }\n }\n }\n return { cx: 0, cy: 0 };\n}\n\n/** Resolve rels Target → absolute package path (mirrors resolveRelTarget in placeholder-image.ts) */\nfunction resolveTarget(relsPartPath: string, target: string): string {\n let t = target.trim();\n if (t.startsWith('/')) return t.slice(1);\n while (t.startsWith('./')) t = t.slice(2);\n const idx = relsPartPath.lastIndexOf('/_rels/');\n if (idx < 0) return t;\n const hostDir = relsPartPath.slice(0, idx);\n // handle '../' traversal\n let parts = hostDir.split('/').filter(Boolean);\n while (t.startsWith('../')) {\n parts = parts.slice(0, -1);\n t = t.slice(3);\n }\n return parts.length === 0 ? t : `${parts.join('/')}/${t}`;\n}\n\n// Re-export for kernel.ts convenience\nexport { relsPathFor as relsPathForImage };\n// Re-export for insert-table-ops.ts(跨文档搬表时算 host rels 路径)。\nexport { relsPathFor as relsPathForHost };\n","/**\n * insertTableFrom executor —— task-20260616-table-content-driven。\n *\n * 把一张**来自另一文档**的 `<w:tbl>`(已序列化为 XML 字符串)verbatim 搬进当前输出\n * 文档,插到 anchorParaId 段之后。与 insertImageAfter 同构(图按字节跨文档搬、表按\n * OOXML 子树跨文档搬),是\"数据表 = 内容块\"(§13.9)的底座 op。\n *\n * 为什么是「序列化 XML + 预解析图字节」而非「直接传 Element」:\n * - op 必须跨端安全(worker 模式下 op 经结构化克隆传输,绝不能带 foreign DOM 节点)。\n * - 调用方(typeset,inline 模式持有两个 doc)在源文档侧把 `<w:tbl>` 子树\n * `serializeToWellFormedString` 成字符串、把每个格内图按原 r:embed 反查出原始字节,\n * 打包成自包含 payload 传进来。executor 只吃 string + Uint8Array。\n *\n * 写链:\n * 1. anchor 定位(paraIdx → PARA_NOT_FOUND)。\n * 2. parseXmlFragment(tableXml) → importNode 到 host doc(命名空间随子树带入,已验证)。\n * 3. 校验根是 <w:tbl>(否则 INVALID_ARGUMENT,绝不把异物塞进文档)。\n * 4. 重映射格内图:遍历表内每个 <a:blip @r:embed>,按原 rId 找 op.images 里对应字节,\n * 在 host doc 新建 media part + image rel + content-type,把 embed 改写成新 rId。\n * 原 rId 在 op.images 里找不到 → 该 blip 的 embed 清掉 + warn(绝不留悬空引用致文档损坏;\n * 文字/结构仍 verbatim 保真,只这一张格内图降级丢失,调用方侧应保证 images 齐全)。\n * 5. 剥离表内锚点(书签/批注 5 类),重分配每个 <w:p> 的 paraId(全局唯一)。\n * 6. 样式归一(可选):op.styleTblPrXml 提供时,用它整体替换搬入表的 <w:tblPr>\n * (tblStyle / 边框 / tblLook / 宽度 → 归一到模板数据表样式,覆盖内容表自带样式)。\n * 7. 插到 anchor 之后,markDirty。\n *\n * 内容零丢红线:表的行/列/值/合并/嵌套表/格内图全部 verbatim 来自 op.tableXml(源原表),\n * executor 不重建、不裁剪、不对位——只搬运 + 重映射引用 + 套样式。\n */\nimport { parseXmlFragment } from 'slimdom';\nimport { createBinaryPart, getPart, isXmlPart, markDirty, setPart } from '../../pack/index.js';\nimport { generateParaId } from '../para-id.js';\nimport { A_NS, R_NS, W_NS, W14_NS } from '../namespaces.js';\nimport type { Op } from '../plan.js';\nimport { findStoryFor } from '../stories.js';\nimport { WordError } from '../word-error.js';\nimport type { ExecutorContext } from './executor-context.js';\nimport {\n addImageRelForHost,\n allocateMediaPath,\n CONTENT_TYPE_TO_EXT,\n ensureImageContentType,\n relsPathForHost,\n} from './insert-image-ops.js';\n\n/** 单张格内图的预解析字节(按源文档原始 r:embed rId 索引)。 */\nexport interface InsertTableImage {\n /** 源表 <a:blip @r:embed> 的原始 rId(host 内会被改写成新 rId)。 */\n originalRId: string;\n /** 原始图片字节(来自源文档 media part)。 */\n bytes: Uint8Array;\n /** 图片 content-type(image/png 等)。 */\n contentType: string;\n}\n\nexport function executeInsertTableFrom(\n ctx: ExecutorContext,\n op: Extract<Op, { type: 'insertTableFrom' }>,\n): void {\n if (ctx.options.trackChanges) {\n throw new WordError(\n 'UNSUPPORTED_OOXML_FEATURE',\n 'insertTableFrom with trackChanges=true not yet implemented',\n ctx.docId,\n { opType: 'insertTableFrom' },\n );\n }\n\n // 1. anchor 定位\n const anchor = ctx.indices.paraIdx.get(op.anchorParaId.toUpperCase());\n if (!anchor) {\n throw new WordError(\n 'PARA_NOT_FOUND',\n `paragraph with paraId='${op.anchorParaId}' not found (op: insertTableFrom)`,\n ctx.docId,\n { paraId: op.anchorParaId, opName: 'insertTableFrom' },\n );\n }\n const parent = anchor.parentNode;\n if (!parent) {\n throw new WordError(\n 'PACKAGE_CORRUPT',\n `anchor paragraph '${op.anchorParaId}' has no parentNode`,\n ctx.docId,\n { paraId: op.anchorParaId, opName: 'insertTableFrom' },\n );\n }\n\n const story = findStoryFor(ctx.pkg, anchor);\n if (!story) {\n throw new WordError(\n 'PACKAGE_CORRUPT',\n `anchor paragraph '${op.anchorParaId}' not in any story`,\n ctx.docId,\n { paraId: op.anchorParaId, opName: 'insertTableFrom' },\n );\n }\n const hostPartPath = story.partPath;\n\n // host doc(用于 importNode + createElementNS)\n const hostPart = getPart(ctx.pkg, hostPartPath);\n if (!hostPart || !isXmlPart(hostPart) || !hostPart.xmlDom) {\n throw new WordError(\n 'PACKAGE_CORRUPT',\n `host part '${hostPartPath}' missing or not XML`,\n ctx.docId,\n { opName: 'insertTableFrom' },\n );\n }\n const hostDoc = hostPart.xmlDom;\n\n // 2. 解析 + 导入表子树\n let imported: Element;\n try {\n const frag = parseXmlFragment(op.tableXml);\n // 取首个元素子节点(应是 <w:tbl>)\n let root: Element | null = null;\n for (let i = 0; i < frag.childNodes.length; i++) {\n const c = frag.childNodes[i] as Element;\n if (c && c.nodeType === 1) {\n root = c;\n break;\n }\n }\n if (!root) {\n throw new WordError(\n 'INVALID_ARGUMENT',\n 'insertTableFrom: tableXml has no element root',\n ctx.docId,\n { opName: 'insertTableFrom' },\n );\n }\n imported = hostDoc.importNode(root, true) as unknown as Element;\n } catch (e) {\n if (e instanceof WordError) throw e;\n throw new WordError(\n 'INVALID_ARGUMENT',\n `insertTableFrom: failed to parse/import tableXml: ${(e as Error).message}`,\n ctx.docId,\n { opName: 'insertTableFrom' },\n );\n }\n\n // 3. 校验根是 <w:tbl>\n if (imported.namespaceURI !== W_NS || imported.localName !== 'tbl') {\n throw new WordError(\n 'INVALID_ARGUMENT',\n `insertTableFrom: root element is '${imported.localName}', expected 'w:tbl'`,\n ctx.docId,\n { opName: 'insertTableFrom' },\n );\n }\n\n // 4. 重映射格内图 blip r:embed(跨文档:原 rId → host 新建 media + rel → 新 rId)\n const relsPath = relsPathForHost(hostPartPath);\n const imageByRId = new Map<string, InsertTableImage>();\n for (const img of op.images ?? []) imageByRId.set(img.originalRId, img);\n // 同一原 rId 在表里可能被多个 blip 引用,但语义上只该建一次 media;这里缓存原→新映射。\n const remapped = new Map<string, string>();\n let mediaCreated = false;\n\n const blips = imported.getElementsByTagNameNS(A_NS, 'blip');\n const blipSnapshot: Element[] = [];\n for (let i = 0; i < blips.length; i++) {\n const b = blips[i];\n if (b) blipSnapshot.push(b);\n }\n for (const blip of blipSnapshot) {\n const origRId = blip.getAttributeNS(R_NS, 'embed');\n if (!origRId) continue;\n let newRId = remapped.get(origRId);\n if (!newRId) {\n const img = imageByRId.get(origRId);\n if (!img) {\n // 调用方未提供该图字节 → 清掉悬空引用(绝不留无效 rId 致文档打不开),warn 记录降级。\n console.warn(\n `[word] insertTableFrom: cell image rId='${origRId}' not in op.images; ` +\n `dropping blip embed (degrade, docId: ${ctx.docId})`,\n );\n blip.removeAttributeNS(R_NS, 'embed');\n continue;\n }\n const ext = CONTENT_TYPE_TO_EXT[img.contentType];\n if (!ext) {\n console.warn(\n `[word] insertTableFrom: unsupported cell image contentType '${img.contentType}' ` +\n `(rId='${origRId}'); dropping blip embed (docId: ${ctx.docId})`,\n );\n blip.removeAttributeNS(R_NS, 'embed');\n continue;\n }\n const mediaPath = allocateMediaPath(ctx.pkg, ext);\n const mediaPart = createBinaryPart({\n path: mediaPath,\n contentType: img.contentType,\n bytes: img.bytes,\n });\n setPart(ctx.pkg, mediaPart);\n markDirty(mediaPart);\n newRId = addImageRelForHost(ctx.pkg, relsPath, mediaPath);\n ensureImageContentType(ctx.pkg, ext, img.contentType);\n remapped.set(origRId, newRId);\n mediaCreated = true;\n }\n blip.setAttributeNS(R_NS, 'r:embed', newRId);\n }\n\n // 5. 剥离锚点 + 重分配 paraId\n stripTableAnchors(imported);\n reassignClonedParaIds(ctx, imported);\n\n // 6. 样式归一(可选):用模板数据表的 <w:tblPr> 整体替换搬入表的 <w:tblPr>,\n // 把 tblStyle / 边框 / tblLook / 宽度归一到模板(覆盖内容表自带样式)。\n if (op.styleTblPrXml) {\n overrideTblPr(ctx, hostDoc, imported, op.styleTblPrXml);\n }\n\n // 7. 插到 anchor 之后\n parent.insertBefore(imported, anchor.nextSibling);\n\n // 同步 paraIdx + tblIdx(保证同 plan 内后续 op 可查到新段/新表)。\n syncIndicesAfterInsert(ctx, imported);\n\n // 8. markDirty\n markDirty(hostPart);\n if (mediaCreated) {\n const relsPart = getPart(ctx.pkg, relsPath);\n if (relsPart) markDirty(relsPart);\n }\n}\n\n// ─────────── helpers ───────────\n\n/**\n * 用模板 <w:tblPr> 替换搬入表的 <w:tblPr>(样式归一)。\n *\n * `<w:tblPr>` 持有 tblStyle(样式引用)/ tblBorders / tblLook / tblW(宽度)/ jc 等表级\n * 格式——整体替换即把内容表的表级外观换成模板数据表的外观。单元格字体随 tblStyle 引用走,\n * 故表级替换 + cell 自带 tcPr(保结构)已能让产物外观贴近模板。\n *\n * styleTblPrXml 解析失败 / 非 <w:tblPr> → 跳过(不崩,宁可保留内容表原样式也不丢内容/损坏)。\n */\nfunction overrideTblPr(\n ctx: ExecutorContext,\n hostDoc: Document,\n tbl: Element,\n styleTblPrXml: string,\n): void {\n let newTblPr: Element | null = null;\n try {\n const frag = parseXmlFragment(styleTblPrXml);\n for (let i = 0; i < frag.childNodes.length; i++) {\n const c = frag.childNodes[i] as Element;\n if (c && c.nodeType === 1 && c.namespaceURI === W_NS && c.localName === 'tblPr') {\n newTblPr = hostDoc.importNode(c, true) as unknown as Element;\n break;\n }\n }\n } catch (e) {\n console.warn(\n `[word] insertTableFrom: parse styleTblPrXml failed, keep original tblPr: ${(e as Error).message}`,\n );\n return;\n }\n if (!newTblPr) return;\n\n // 找搬入表的原 <w:tblPr>(必是 tbl 首个直属子;无则插到首位)。\n let oldTblPr: Element | null = null;\n for (let i = 0; i < tbl.childNodes.length; i++) {\n const c = tbl.childNodes[i] as Element;\n if (c && c.nodeType === 1 && c.namespaceURI === W_NS && c.localName === 'tblPr') {\n oldTblPr = c;\n break;\n }\n }\n if (oldTblPr) {\n tbl.replaceChild(newTblPr, oldTblPr);\n } else {\n tbl.insertBefore(newTblPr, tbl.firstChild);\n }\n void ctx;\n}\n\n/**\n * 同步 paraIdx + tblIdx:把搬入表内所有 <w:p> 与表自身登记进索引,\n * 保证同一 plan 内后续 op(如再对这张表填格/查段)能命中。\n *\n * 注:applyPlan finally 块会 buildIndices 全量重建,这里只为同 plan 内后续 op 的可见性。\n */\nfunction syncIndicesAfterInsert(ctx: ExecutorContext, tbl: Element): void {\n // <w:p> → paraIdx\n const paras = tbl.getElementsByTagNameNS(W_NS, 'p');\n for (let i = 0; i < paras.length; i++) {\n const p = paras[i];\n if (!p) continue;\n const pid = p.getAttributeNS(W14_NS, 'paraId');\n if (pid) ctx.indices.paraIdx.set(pid.toUpperCase(), p);\n }\n // 表自身 → tblIdx(分配下一个 tbl-NNNN,仅同 plan 内可见;finally 全量重建会规整)。\n let maxN = 0;\n for (const id of ctx.indices.tblIdx.keys()) {\n const m = /^tbl-(\\d+)$/.exec(id);\n if (m) {\n const n = parseInt(m[1]!, 10);\n if (n > maxN) maxN = n;\n }\n }\n ctx.indices.tblIdx.set(`tbl-${String(maxN + 1).padStart(4, '0')}`, tbl);\n}\n\n/**\n * 重分配子树内所有 `<w:p>` 的 paraId(全局唯一)。与 table-ops 的同名逻辑同构,\n * 但跨文档搬入的表 paraId 可能与 host 既有撞,故必须重分配。\n */\nfunction reassignClonedParaIds(ctx: ExecutorContext, node: Element): void {\n const seen = new Set(ctx.indices.paraIdx.keys());\n const paragraphs = node.getElementsByTagNameNS(W_NS, 'p');\n const snapshot: Element[] = [];\n for (let i = 0; i < paragraphs.length; i++) {\n const p = paragraphs[i];\n if (p) snapshot.push(p);\n }\n for (const p of snapshot) {\n const newId = generateParaId(seen);\n p.setAttributeNS(W14_NS, 'w14:paraId', newId);\n }\n}\n\n/**\n * 剥离表子树内所有锚点(书签/批注 5 类)。跨文档搬入的表里若带源文档的书签/批注引用,\n * 在 host 里是悬空引用(host 无对应 comments.xml 条目 / bookmarkIdx)→ 必须剥离,\n * 否则产物含无效锚点。与 table-ops.stripAnchorsFromClone 同构。\n */\nfunction stripTableAnchors(tbl: Element): void {\n const anchorLocals = [\n 'bookmarkStart',\n 'bookmarkEnd',\n 'commentRangeStart',\n 'commentRangeEnd',\n 'commentReference',\n ];\n for (const local of anchorLocals) {\n const list = tbl.getElementsByTagNameNS(W_NS, local);\n const toRemove: Element[] = [];\n for (let i = 0; i < list.length; i++) {\n const el = list[i];\n if (el) toRemove.push(el);\n }\n for (const el of toRemove) {\n if (el.parentNode) el.parentNode.removeChild(el);\n }\n }\n}\n","/**\n * Settings executor —— task-core-update-fields。\n *\n * 职责:\n * - `executeSetUpdateFields`:在 settings.xml 根 `<w:settings>` 写入/更新\n * `<w:updateFields w:val=\"true|false\"/>`,并把 settings part 标脏,\n * 确保 `toZip()` / `toFlatOpc()` 正确持久化。\n *\n * 设计要点:\n * - 按 contentType 定位 settings part(不硬编码路径),镜像 style-queries.ts 的 findStylesPart。\n * - settings part 不存在(非 B 场景边缘):抛 UNSUPPORTED_OOXML_FEATURE,留后续 follow-up。\n * - 幂等:已有 `<w:updateFields>` 则只改 `w:val`,不重复插入。\n * - CT_Settings schema 顺序:updateFields 较靠后(在 defaultTabStop/zoom 类之后、\n * footnotePr/endnotePr/compat/rsids 之前)。实现上追加到 `<w:settings>` 末尾;\n * Word 对 CT_Settings 子元素顺序宽容,追加安全。若已有则原地改值不移位。\n * - namespace:W_NS + setAttributeNS 写 `w:val`(与其他 ops 统一)。\n */\nimport { listParts, markDirty } from '../../pack/index.js';\nimport { W_NS } from '../namespaces.js';\nimport type { Op } from '../plan.js';\nimport { WordError } from '../word-error.js';\nimport type { ExecutorContext } from './executor-context.js';\n\n// ─────────── ContentType 常量 ───────────────────────────────────────────────\n\nconst SETTINGS_CONTENT_TYPE =\n 'application/vnd.openxmlformats-officedocument.wordprocessingml.settings+xml';\n\n// ─────────── 内部工具 ────────────────────────────────────────────────────────\n\n/**\n * 按 contentType 定位 settings part(不硬编码路径)。\n * 镜像 style-queries.ts 的 findStylesPart 模式。\n */\nfunction findSettingsPart(ctx: ExecutorContext): { xmlDom: Document; _dirty: boolean } | undefined {\n for (const part of listParts(ctx.pkg)) {\n if (part.contentType === SETTINGS_CONTENT_TYPE && part.xmlDom) {\n return part as { xmlDom: Document; _dirty: boolean };\n }\n }\n return undefined;\n}\n\n// ─────────── executeSetUpdateFields ──────────────────────────────────────────\n\nexport function executeSetUpdateFields(\n ctx: ExecutorContext,\n op: Extract<Op, { type: 'setUpdateFields' }>,\n): void {\n // ── Step 1: 定位 settings part ─────────────────────────────────────────────\n const settingsPart = findSettingsPart(ctx);\n if (!settingsPart) {\n // B 场景中 settings.xml 必然存在;此分支仅用于健壮性兜底。\n // 新建 settings part 需注册 ContentTypes Override + document.xml rels,\n // 基础设施成本较高,留后续 follow-up。\n throw new WordError(\n 'UNSUPPORTED_OOXML_FEATURE',\n 'setUpdateFields: settings.xml part not found in package. ' +\n 'Creating a new settings part is not yet implemented (follow-up task).',\n ctx.docId,\n { opType: 'setUpdateFields' },\n );\n }\n\n const xmlDom = settingsPart.xmlDom;\n\n // ── Step 2: 找根 <w:settings> ─────────────────────────────────────────────\n const settingsRoot = xmlDom.documentElement;\n if (!settingsRoot) {\n throw new WordError(\n 'PACKAGE_CORRUPT',\n 'setUpdateFields: settings.xml has no documentElement',\n ctx.docId,\n { opType: 'setUpdateFields' },\n );\n }\n\n // ── Step 3: 幂等 —— 查已有 <w:updateFields> ──────────────────────────────\n const existing = findFirstChildW(settingsRoot, 'updateFields');\n const valStr = op.enabled ? 'true' : 'false';\n\n if (existing) {\n // 已有:只改 w:val,不移位,不重复插入(幂等核心)\n existing.setAttributeNS(W_NS, 'w:val', valStr);\n } else {\n // 不存在:新建并追加到 <w:settings> 末尾\n // CT_Settings 顺序:updateFields 在较靠后位置,追加到末尾符合规范且 Word 宽容\n const newEl = xmlDom.createElementNS(W_NS, 'w:updateFields');\n newEl.setAttributeNS(W_NS, 'w:val', valStr);\n settingsRoot.appendChild(newEl);\n }\n\n // ── Step 4: 标脏 ──────────────────────────────────────────────────────────\n // settings part 不是 story part,直接通过 pkg 找到 Part 对象调 markDirty。\n for (const part of listParts(ctx.pkg)) {\n if (part.contentType === SETTINGS_CONTENT_TYPE && part.xmlDom) {\n markDirty(part);\n break;\n }\n }\n}\n\n// ─────────── 内部工具 ────────────────────────────────────────────────────────\n\n/** 找 el 的第一个 W_NS 直属子元素(localName 匹配)。 */\nfunction findFirstChildW(el: Element, localName: string): Element | null {\n const children = el.childNodes;\n for (let i = 0; i < children.length; i++) {\n const c = children[i];\n if (\n c &&\n c.nodeType === 1 &&\n (c as Element).namespaceURI === W_NS &&\n (c as Element).localName === localName\n ) {\n return c as Element;\n }\n }\n return null;\n}\n","/**\n * Plan executor dispatcher(#28 起)。\n *\n * WordPlan 提交的 op 队列走 `kernel.applyPlan` → `dispatchOp` → 具体 executor。\n * 每个 executor 一个文件:\n * - paragraph-ops.ts #28 replaceParagraph / replaceTextInParagraph\n * - paragraph-structure-ops.ts #29 insertParagraphBefore/After / deleteParagraph\n * - bookmark-ops.ts #34 createBookmark / deleteBookmark\n * - comment-ops.ts #35 addComment / deleteComment\n * - revision-ops.ts #31 trackChanges 包装 / #32 acceptRevisions / rejectRevisions\n *\n * **Executor 契约**(给后续 PR 照抄):\n * - 签名:`function executeXxx(ctx: ExecutorContext, op): void`\n * - 报错:throw `WordError`(对应 code:PARA_NOT_FOUND / TEXT_NOT_FOUND_IN_PARA /\n * ANCHOR_CONFLICT / UNSUPPORTED_OOXML_FEATURE / BOOKMARK_NAME_EXISTS 等);\n * docId 由外层 kernel.applyPlan 捕后重抛注入\n * - 产出:mutate `ctx.result` 累积 ApplyResult 字段(insertedParagraphs 等);\n * 不用 return 值\n * - 事务:外层已把所有 affected parts 包进 runTransaction;executor 只关心\n * 当前 op 的变更,抛错自动回滚\n * - markDirty:executor 负责在改完 part 后 `markDirty(pkg, partPath)`\n * - 索引同步:executor 自行维护 indices(paraIdx / bookmarkIdx / commentIdx)\n * 对简单 op(只改 `<w:p>` 内部),索引条目指向的 `<w:p>` Element 不变,\n * 不需动;涉及段落增删或书签/批注增删时必须同步\n */\nimport type { Op } from '../plan.js';\nimport { WordError } from '../word-error.js';\nimport type { ExecutorContext } from './executor-context.js';\nimport {\n executeFormatParagraph,\n executeFormatTextInParagraph,\n executeReplaceParagraph,\n executeReplaceTextInParagraph,\n} from './paragraph-ops.js';\nimport { executeCreateBookmark, executeDeleteBookmark } from './bookmark-ops.js';\nimport { executeAddComment, executeDeleteComment } from './comment-ops.js';\nimport {\n executeInsertParagraph,\n executeInsertParagraphAtBodyStart,\n executeDeleteParagraph,\n} from './paragraph-structure-ops.js';\nimport { executeAcceptRevisions, executeRejectRevisions } from './revision-ops.js';\nimport {\n executeAddTableComment,\n executeDeleteTable,\n executeReplaceTableCellWithSdt,\n executeReplaceTableCellText,\n executeFormatTableCell,\n executeInsertTableCellParagraph,\n executeDeleteTableRow,\n executeInsertTableRow,\n executeCloneTableAfter,\n executeSetTableColumnWidths,\n executeSetTableRowHeights,\n} from './table-ops.js';\nimport {\n executeReplaceDrawingWithPlaceholder,\n executeDeleteDrawing,\n executeReplaceShapeInnerText,\n} from './drawing-ops.js';\nimport { executeInsertImageAfter } from './insert-image-ops.js';\nimport { executeInsertTableFrom } from './insert-table-ops.js';\nimport { executeSetUpdateFields } from './settings-ops.js';\n\nexport type { ExecutorContext } from './executor-context.js';\n\n/**\n * 分发一个 op 到对应 executor。未实现的 op 类型抛 `UNSUPPORTED_OOXML_FEATURE`,\n * message 指向对应 issue。\n */\nexport function dispatchOp(op: Op, ctx: ExecutorContext): void {\n switch (op.type) {\n case 'replaceParagraph':\n executeReplaceParagraph(ctx, op);\n return;\n case 'replaceTextInParagraph':\n executeReplaceTextInParagraph(ctx, op);\n return;\n case 'formatTextInParagraph':\n executeFormatTextInParagraph(ctx, op);\n return;\n case 'formatParagraph':\n executeFormatParagraph(ctx, op);\n return;\n // #29\n case 'insertParagraphBefore':\n executeInsertParagraph(ctx, op, 'before');\n return;\n case 'insertParagraphAfter':\n executeInsertParagraph(ctx, op, 'after');\n return;\n case 'insertParagraphAtBodyStart':\n executeInsertParagraphAtBodyStart(ctx, op);\n return;\n case 'deleteParagraph':\n executeDeleteParagraph(ctx, op);\n return;\n // #34\n case 'createBookmark':\n executeCreateBookmark(ctx, op);\n return;\n case 'deleteBookmark':\n executeDeleteBookmark(ctx, op);\n return;\n // #35\n case 'addComment':\n executeAddComment(ctx, op);\n return;\n case 'deleteComment':\n executeDeleteComment(ctx, op);\n return;\n // #32\n case 'acceptRevisions':\n executeAcceptRevisions(ctx, op);\n return;\n case 'rejectRevisions':\n executeRejectRevisions(ctx, op);\n return;\n // #186\n case 'addTableComment':\n executeAddTableComment(ctx, op);\n return;\n case 'deleteTable':\n executeDeleteTable(ctx, op);\n return;\n // #188\n case 'replaceTableCellWithSdt':\n executeReplaceTableCellWithSdt(ctx, op);\n return;\n case 'replaceTableCellText':\n executeReplaceTableCellText(ctx, op);\n return;\n case 'formatTableCell':\n executeFormatTableCell(ctx, op);\n return;\n case 'insertTableCellParagraph':\n executeInsertTableCellParagraph(ctx, op);\n return;\n case 'deleteTableRow':\n executeDeleteTableRow(ctx, op);\n return;\n // #14\n case 'insertTableRow':\n executeInsertTableRow(ctx, op);\n return;\n // #15\n case 'cloneTableAfter':\n executeCloneTableAfter(ctx, op);\n return;\n // task-core-table-grid\n case 'setTableColumnWidths':\n executeSetTableColumnWidths(ctx, op);\n return;\n // task-core-table-rowheight\n case 'setTableRowHeights':\n executeSetTableRowHeights(ctx, op);\n return;\n // #190\n case 'replaceDrawingWithPlaceholder':\n executeReplaceDrawingWithPlaceholder(ctx, op);\n return;\n case 'deleteDrawing':\n executeDeleteDrawing(ctx, op);\n return;\n // #210\n case 'replaceShapeInnerText':\n executeReplaceShapeInnerText(ctx, op);\n return;\n // task-insert-image\n case 'insertImageAfter':\n executeInsertImageAfter(ctx, op);\n return;\n // task-20260616-table-content-driven\n case 'insertTableFrom':\n executeInsertTableFrom(ctx, op);\n return;\n // task-core-update-fields\n case 'setUpdateFields':\n executeSetUpdateFields(ctx, op);\n return;\n default: {\n // 类型穷尽兜底\n const _never: never = op;\n throw new WordError(\n 'UNSUPPORTED_OOXML_FEATURE',\n `unknown plan op type: ${JSON.stringify(_never)}`,\n ctx.docId,\n );\n }\n }\n}\n\n// notImplemented helper removed in #32 —— 所有 11 个 op 都已实现,无 stub 分支\n","/**\n * 跨 parts 事务 —— docs/03 §13.5 的落地。\n *\n * Plan.apply 的底层原语:在一组 part 上执行可能失败的 work,失败时回滚到 work 前状态。\n *\n * 设计:\n * - 进入事务前,对 `affectedPartPaths` 里每个已存在的 part 做深拷贝快照(xmlDom / bytes / _dirty)\n * - 记录哪些 path 在 work 开始时**不存在**(新建场景)\n * - work 内可自由变更 part(包括新增 / 删除 / 改 xmlDom)\n * - 抛错时:\n * * 原本存在的 part → 从快照恢复 xmlDom / bytes / _dirty\n * * 原本不存在但 work 新增的 part → 从 pkg 删除\n * - 成功时:保持 work 结束时的状态(work 自己负责 markDirty)\n *\n * 当前实现:deepClone 整个 xmlDom,在 10 万段落档上约 1-2s,优化(反向 op 记录)留后续 issue。\n */\nimport type { Package, Part } from '../pack/index.js';\nimport { createBinaryPart, createXmlPart, deletePart, getPart, setPart } from '../pack/index.js';\n\ninterface PartSnapshot {\n contentType: string;\n xmlDom: Document | undefined;\n bytes: Uint8Array | undefined;\n originalBytes: Uint8Array | undefined;\n dirty: boolean;\n}\n\n/**\n * 在 `pkg` 上执行可能失败的 `work`。事务作用域仅覆盖 `affectedPartPaths` 列出的 parts:\n * - work 抛错 → 被列出的 parts 回滚到进入事务前状态(xmlDom / bytes / _dirty),新增的 parts 删除\n * - work 成功 → 返回 work 的结果\n *\n * **调用方职责**:\n * - `affectedPartPaths` 必须包含 work 里**所有可能触达**的 part 路径(读 + 写 + 新增)\n * - 未在列表里的 part 即便被 work 改动,回滚时不会被恢复\n */\nexport async function runTransaction<T>(\n pkg: Package,\n affectedPartPaths: readonly string[],\n work: () => Promise<T> | T,\n): Promise<T> {\n const snapshots = new Map<string, PartSnapshot>();\n const existedBefore = new Set<string>();\n\n for (const path of affectedPartPaths) {\n if (!pkg.parts.has(path)) continue;\n existedBefore.add(path);\n const part = getPart(pkg, path)!;\n snapshots.set(path, cloneSnapshot(part));\n }\n\n try {\n return await Promise.resolve(work());\n } catch (err) {\n rollback(pkg, affectedPartPaths, existedBefore, snapshots);\n throw err;\n }\n}\n\nfunction cloneSnapshot(part: Part): PartSnapshot {\n return {\n contentType: part.contentType,\n xmlDom: part.xmlDom ? (part.xmlDom.cloneNode(true) as Document) : undefined,\n bytes: part.bytes ? new Uint8Array(part.bytes) : undefined,\n originalBytes: part._originalBytes ? new Uint8Array(part._originalBytes) : undefined,\n dirty: part._dirty,\n };\n}\n\nfunction rollback(\n pkg: Package,\n affectedPartPaths: readonly string[],\n existedBefore: Set<string>,\n snapshots: Map<string, PartSnapshot>,\n): void {\n for (const path of affectedPartPaths) {\n if (existedBefore.has(path)) {\n // 恢复到快照\n const part = getPart(pkg, path);\n const snap = snapshots.get(path)!;\n if (!part) {\n // 事务里把这个 part 删了 —— 用快照内 contentType + payload 重建。\n //\n // 这是 #190 引入的能力(占位图替换的旧 media 清理需要在事务内删 binary part)。\n // 用 createXmlPart / createBinaryPart 回填 readonly 字段,保持 Part 的\"择一\"约束。\n let restored: Part;\n if (snap.xmlDom) {\n restored = createXmlPart({\n path,\n contentType: snap.contentType,\n xmlDom: snap.xmlDom,\n ...(snap.originalBytes !== undefined ? { originalBytes: snap.originalBytes } : {}),\n });\n } else if (snap.bytes) {\n restored = createBinaryPart({\n path,\n contentType: snap.contentType,\n bytes: snap.bytes,\n ...(snap.originalBytes !== undefined ? { originalBytes: snap.originalBytes } : {}),\n });\n } else {\n throw new Error(\n `runTransaction rollback: snapshot for '${path}' has neither xmlDom nor bytes`,\n );\n }\n restored._dirty = snap.dirty;\n setPart(pkg, restored);\n continue;\n }\n part.xmlDom = snap.xmlDom;\n part.bytes = snap.bytes;\n part._dirty = snap.dirty;\n } else {\n // 事务里新建的 part(或从未存在过)→ 删除\n deletePart(pkg, path);\n }\n }\n}\n","/**\n * Section(节)查询(#211 / docs/03.1 §2)。\n *\n * 节边界由\"承载 `<w:sectPr>` 的段\"标定:\n * - 主 body 的最后一个 `<w:sectPr>` 是 body 直接子元素(不属于任何段),是最后一节\n * - 其余节的 sectPr 嵌在 `<w:p>/<w:pPr>/<w:sectPr>`,该段是节的最后一段\n *\n * 算法:遍历 body 直属节点(doc-order),收集 `<w:p>`,遇含 sectPr 的段闭合一节\n * (lastParaId = 该段 paraId);body 末尾的散 sectPr 闭合最后一节。\n *\n * 节信息字段(消费方主要诉求来自 skeleton #195 封面检测):\n * - sectionIndex / firstParaId / lastParaId:边界\n * - type:'nextPage' / 'continuous' / 'evenPage' / 'oddPage' / 'nextColumn'(缺省 = nextPage,OOXML 默认)\n * - headerRefs / footerRefs:resolve 到 partName,跨节比对页眉页脚是否相同\n * - titlePage:'首页不同' 设置(封面强信号)\n */\nimport type { Package } from '../pack/index.js';\nimport { listParts } from '../pack/index.js';\nimport { W_NS, W14_NS, R_NS } from './namespaces.js';\nimport { resolveRelTarget } from './plan-executors/placeholder-image.js';\nimport { listStories } from './stories.js';\n\nexport type SectionType = 'nextPage' | 'continuous' | 'evenPage' | 'oddPage' | 'nextColumn';\nexport type HeaderFooterType = 'default' | 'first' | 'even';\n\nexport interface HeaderFooterRef {\n type: HeaderFooterType;\n /** rels 目标 part 路径(如 'word/header1.xml') */\n partName: string;\n}\n\nexport interface SectionInfo {\n sectionIndex: number;\n firstParaId: string;\n /** 节末段的 paraId(承载 sectPr 的段;最后一节为 body 末尾散 sectPr 时回退到 body 最后段)*/\n lastParaId: string;\n type?: SectionType;\n headerRefs?: HeaderFooterRef[];\n footerRefs?: HeaderFooterRef[];\n /** w:sectPr/w:titlePg 存在 = 首页不同(封面强信号)*/\n titlePage?: boolean;\n}\n\nexport function listSections(pkg: Package): SectionInfo[] {\n const stories = listStories(pkg, { kinds: ['body'] });\n if (stories.length === 0) return [];\n const body = stories[0]!.root;\n const partPath = stories[0]!.partPath;\n const relsPath = relsPathFor(partPath);\n\n const out: SectionInfo[] = [];\n let sectionFirstParaId: string | undefined;\n let lastParaIdInBody: string | undefined;\n let sectionIndex = 0;\n\n // 遍历 body 直属子节点\n for (let i = 0; i < body.childNodes.length; i++) {\n const node = body.childNodes[i];\n if (!node || node.nodeType !== 1) continue;\n const el = node as Element;\n if (el.namespaceURI !== W_NS) continue;\n\n if (el.localName === 'p') {\n const paraId = el.getAttributeNS(W14_NS, 'paraId')?.toUpperCase() ?? '';\n if (paraId.length === 0) continue;\n if (sectionFirstParaId === undefined) sectionFirstParaId = paraId;\n lastParaIdInBody = paraId;\n\n // 该段是否承载 sectPr?\n const pPr = firstDirectChild(el, W_NS, 'pPr');\n const inlineSectPr = pPr ? firstDirectChild(pPr, W_NS, 'sectPr') : null;\n if (inlineSectPr) {\n out.push(\n buildSection(sectionIndex++, sectionFirstParaId, paraId, inlineSectPr, pkg, relsPath),\n );\n sectionFirstParaId = undefined;\n }\n } else if (el.localName === 'sectPr') {\n // body 末尾散 sectPr:最后一节,lastParaId 用 body 最后段\n if (sectionFirstParaId !== undefined && lastParaIdInBody !== undefined) {\n out.push(\n buildSection(sectionIndex++, sectionFirstParaId, lastParaIdInBody, el, pkg, relsPath),\n );\n sectionFirstParaId = undefined;\n }\n }\n // 其他节点(tbl 等)按 doc-order 跳过,不影响节边界\n }\n\n return out;\n}\n\n// ─────────── 内部 ───────────\n\nfunction buildSection(\n sectionIndex: number,\n firstParaId: string,\n lastParaId: string,\n sectPr: Element,\n pkg: Package,\n relsPath: string | undefined,\n): SectionInfo {\n const info: SectionInfo = { sectionIndex, firstParaId, lastParaId };\n\n // type\n const typeEl = firstDirectChild(sectPr, W_NS, 'type');\n if (typeEl) {\n const v = typeEl.getAttributeNS(W_NS, 'val');\n if (\n v === 'nextPage' ||\n v === 'continuous' ||\n v === 'evenPage' ||\n v === 'oddPage' ||\n v === 'nextColumn'\n ) {\n info.type = v;\n }\n }\n\n // header/footer references\n const headerRefs = collectRefs(sectPr, 'headerReference', pkg, relsPath);\n if (headerRefs.length > 0) info.headerRefs = headerRefs;\n const footerRefs = collectRefs(sectPr, 'footerReference', pkg, relsPath);\n if (footerRefs.length > 0) info.footerRefs = footerRefs;\n\n // titlePg\n if (firstDirectChild(sectPr, W_NS, 'titlePg')) info.titlePage = true;\n\n return info;\n}\n\nfunction collectRefs(\n sectPr: Element,\n localName: 'headerReference' | 'footerReference',\n pkg: Package,\n relsPath: string | undefined,\n): HeaderFooterRef[] {\n const refs: HeaderFooterRef[] = [];\n if (!relsPath) return refs;\n const relMap = loadRels(pkg, relsPath);\n if (!relMap) return refs;\n const nodes = sectPr.getElementsByTagNameNS(W_NS, localName);\n for (let i = 0; i < nodes.length; i++) {\n const el = nodes[i];\n if (!el || el.parentNode !== sectPr) continue;\n const typeAttr = el.getAttributeNS(W_NS, 'type');\n const rId = el.getAttributeNS(R_NS, 'id');\n if (!rId) continue;\n const target = relMap.get(rId);\n if (!target) continue;\n const partName = resolveRelTarget(relsPath, target);\n const type: HeaderFooterType =\n typeAttr === 'first' || typeAttr === 'even' ? typeAttr : 'default';\n refs.push({ type, partName });\n }\n return refs;\n}\n\nconst RELS_NS = 'http://schemas.openxmlformats.org/package/2006/relationships';\n\nfunction loadRels(pkg: Package, relsPath: string): Map<string, string> | null {\n for (const part of listParts(pkg)) {\n if (part.path !== relsPath) continue;\n if (!part.xmlDom) return null;\n const map = new Map<string, string>();\n const nodes = part.xmlDom.getElementsByTagNameNS(RELS_NS, 'Relationship');\n for (let i = 0; i < nodes.length; i++) {\n const el = nodes[i];\n if (!el) continue;\n const id = el.getAttribute('Id');\n const target = el.getAttribute('Target');\n if (id && target) map.set(id, target);\n }\n return map;\n }\n return null;\n}\n\nfunction relsPathFor(partPath: string): string | undefined {\n const lastSlash = partPath.lastIndexOf('/');\n const dir = lastSlash >= 0 ? partPath.slice(0, lastSlash) : '';\n const file = partPath.slice(lastSlash + 1);\n return dir.length > 0 ? `${dir}/_rels/${file}.rels` : `_rels/${file}.rels`;\n}\n\nfunction firstDirectChild(el: Element, ns: string, local: string): Element | null {\n for (let i = 0; i < el.childNodes.length; i++) {\n const c = el.childNodes[i];\n if (!c || c.nodeType !== 1) continue;\n const ce = c as Element;\n if (ce.namespaceURI === ns && ce.localName === local) return ce;\n }\n return null;\n}\n","/**\n * TOC 域查询(#197)。\n *\n * 识别文档中的 TOC(目录)域:\n * - complex field:`<w:fldChar w:fldCharType=\"begin\">` … `end`,depth 计数跳过嵌套子域\n * - simple field:`<w:fldSimple w:instr=\"TOC ...\">` 单段闭合\n *\n * 只识别域名前缀匹配 `/^TOC\\b/i` 的域,PAGEREF / HYPERLINK 等子域不收集。\n *\n * 嵌套处理:depth 计数器跟踪 fldChar 深度;instr 只在 depth=1(最外层)时收集。\n * complex TOC 的 firstParaId/lastParaId 是 begin/end fldChar 所在段;中间段也在区间内。\n */\nimport type { Package } from '../pack/index.js';\nimport { listStories } from './stories.js';\nimport { W_NS, W14_NS } from './namespaces.js';\n\nexport interface TocFieldRange {\n /** 文档顺序索引(0-based) */\n tocIndex: number;\n /** TOC 域第一段的 paraId(complex field = fldChar begin 段;simple field = fldSimple 段)*/\n firstParaId: string;\n /** TOC 域最后一段的 paraId(complex field = fldChar end 段;simple field = firstParaId)*/\n lastParaId: string;\n /**\n * 域指令文本(拼接所有 instrText / fldSimple@w:instr,trim 后)。\n * 示例:`'TOC \\\\o \"1-3\" \\\\h \\\\z \\\\u'`\n */\n instr: string;\n}\n\n/** 每个 body 直属 `<w:p>` 里所有有序节点事件(fldChar begin/end、instrText) */\ninterface ParaEvent {\n kind: 'begin' | 'end' | 'instr';\n text?: string; // instrText 的内容\n}\n\n/**\n * 按文档顺序产出 body 下的\"段级\" `<w:p>` —— **下钻 `<w:sdt>`/`<w:sdtContent>`,但不下钻 `<w:tbl>`**。\n *\n * root-cause(task-toc-leak,2026-06-14 坐实):Word 2016+ 默认把目录(TOC)整体包进一个\n * `<w:sdt>`(结构化文档标签 / content control,给\"更新目录\"按钮用)。真实文档\n * `sample-files.com-formatted-report.docx` 的 TOC begin 段祖先链是\n * `p > sdtContent > sdt > body`——深了两层。旧实现只遍历 `body.childNodes`(**直属**子节点),\n * 完全看不到 sdtContent 内的段 → fldChar begin/end/instrText 一个都收不到 → `listTocFields`\n * 返回 0 → 排版侧 inToc 全 false → TOC 14 条目泄漏成重复标题(标题数翻倍)。\n *\n * 修法:把\"直属 p 遍历\"改为这个生成器。它在 body 子树上按文档顺序递归:\n * - `<w:p>` → 产出(段级单元,complex/simple field 逻辑照旧按段处理);\n * - `<w:sdt>` → 下钻其 `<w:sdtContent>`(可嵌套 sdt),把里面的 p 当作同级段继续产出;\n * - `<w:sdtContent>` → 下钻(sdt 的直接子;也兼容直接遇到的情况);\n * - `<w:tbl>` → **跳过**(表格内段是独立的 cell 段流,跨进来会打乱段顺序、且表格内嵌 TOC\n * 极罕见,超本修范围);其余元素跳过。\n *\n * 不回归既有用例:无 sdt 的文档里,该生成器产出的序列与\"遍历 body 直属 p\"完全一致\n * (sectPr/其它非 p 非 sdt 元素本来就被跳过),simple/complex/嵌套子域/多域/跨节所有现有测试\n * 的段序、firstParaId/lastParaId 不变。\n */\nfunction* iterTocParas(root: Element): Generator<Element> {\n for (let i = 0; i < root.childNodes.length; i++) {\n const node = root.childNodes[i];\n if (!node || node.nodeType !== 1) continue;\n const el = node as Element;\n if (el.namespaceURI !== W_NS) continue;\n if (el.localName === 'p') {\n yield el;\n } else if (el.localName === 'sdt' || el.localName === 'sdtContent') {\n // 下钻 sdt(→ 找其 sdtContent → 内部 p)/ sdtContent(→ 内部 p),保持文档顺序。\n yield* iterTocParas(el);\n }\n // <w:tbl> 及其它元素:跳过(不下钻)。\n }\n}\n\nfunction collectParaEvents(para: Element): ParaEvent[] {\n const events: ParaEvent[] = [];\n // 按 DOM 文档顺序遍历段内所有 run\n const runs = para.getElementsByTagNameNS(W_NS, 'r');\n for (let ri = 0; ri < runs.length; ri++) {\n const run = runs[ri];\n if (!run) continue;\n\n // fldChar\n const fldChars = run.getElementsByTagNameNS(W_NS, 'fldChar');\n for (let fi = 0; fi < fldChars.length; fi++) {\n const fc = fldChars[fi];\n if (!fc) continue;\n const ct = fc.getAttributeNS(W_NS, 'fldCharType');\n if (ct === 'begin') events.push({ kind: 'begin' });\n else if (ct === 'end') events.push({ kind: 'end' });\n }\n\n // instrText\n const instrTexts = run.getElementsByTagNameNS(W_NS, 'instrText');\n for (let it = 0; it < instrTexts.length; it++) {\n const itEl = instrTexts[it];\n if (!itEl) continue;\n events.push({ kind: 'instr', text: itEl.textContent ?? '' });\n }\n }\n return events;\n}\n\nexport function listTocFields(pkg: Package): TocFieldRange[] {\n const stories = listStories(pkg, { kinds: ['body'] });\n if (stories.length === 0) return [];\n const body = stories[0]!.root;\n\n const out: TocFieldRange[] = [];\n let tocIndex = 0;\n\n // complex field state\n let depth = 0; // 全局 fldChar 嵌套深度(0 = 无活动域)\n let outerInstrParts: string[] = []; // depth=1 时收集的 instrText\n let outerFirstParaId: string | undefined; // begin 所在段\n let outerIsToc = false; // instrParts join 后匹配 TOC\n\n // 按文档顺序遍历 body 下的段级 p——下钻 sdt/sdtContent(覆盖被 content control 包裹的 TOC)。\n for (const el of iterTocParas(body)) {\n const paraId = (el.getAttributeNS(W14_NS, 'paraId') ?? '').toUpperCase();\n\n // ── simple field ──────────────────────────────────────────────\n // 只处理 depth=0 时遇到的 fldSimple(不在 complex field 内部)\n if (depth === 0) {\n const simples = el.getElementsByTagNameNS(W_NS, 'fldSimple');\n for (let si = 0; si < simples.length; si++) {\n const fs = simples[si];\n if (!fs) continue;\n const instr = (fs.getAttributeNS(W_NS, 'instr') ?? '').trim();\n if (/^TOC\\b/i.test(instr) && paraId.length > 0) {\n out.push({\n tocIndex: tocIndex++,\n firstParaId: paraId,\n lastParaId: paraId,\n instr,\n });\n }\n }\n }\n\n // ── complex field events ───────────────────────────────────────\n const events = collectParaEvents(el);\n\n // 若 depth > 0,当前段已是活动 TOC 域内的一段(begin 段已在之前处理过)\n // 只需在处理事件前记录\"当前段进入域\"\n const wasInDomain = depth > 0;\n void wasInDomain; // 仅用于语义说明\n\n for (const ev of events) {\n if (ev.kind === 'begin') {\n depth++;\n if (depth === 1) {\n // 开始最外层域\n outerFirstParaId = paraId.length > 0 ? paraId : undefined;\n outerInstrParts = [];\n outerIsToc = false;\n }\n } else if (ev.kind === 'end') {\n if (depth === 1) {\n // 关闭最外层域\n const fullInstr = outerInstrParts.join('').trim();\n const isToc = outerIsToc || /^TOC\\b/i.test(fullInstr);\n if (isToc && outerFirstParaId && paraId.length > 0) {\n out.push({\n tocIndex: tocIndex++,\n firstParaId: outerFirstParaId,\n lastParaId: paraId,\n instr: fullInstr,\n });\n }\n outerFirstParaId = undefined;\n outerInstrParts = [];\n outerIsToc = false;\n }\n if (depth > 0) depth--;\n } else if (ev.kind === 'instr' && depth === 1) {\n // 只收集最外层域的 instrText\n outerInstrParts.push(ev.text ?? '');\n if (!outerIsToc) {\n const joined = outerInstrParts.join('').trim();\n if (/^TOC\\b/i.test(joined)) outerIsToc = true;\n }\n }\n }\n }\n\n return out;\n}\n","/**\n * kernel-handlers —— RPC 方法到 Kernel 方法的分发表。\n *\n * 同一张表被 InlineTransport(主线程直接调)与 kernel-worker-entry(Worker 内通过\n * postMessage 触发)共用,保证语义一致。\n */\nimport type { BookmarkName, ListBookmarksOptions } from './bookmark-queries.js';\nimport type { CommentId } from './comment-queries.js';\nimport type { ContextSearchOptions } from './context-search.js';\nimport type { Kernel, KernelLoadParams, KernelProgress, SnapshotPartEntry } from './kernel.js';\nimport type { ListParagraphsOptions } from './list-paragraphs.js';\nimport type { ListTablesOptions } from './list-tables.js';\nimport type { ListDrawingsOptions } from './list-drawings.js';\nimport type { ApplyPlanParams } from './plan.js';\nimport type { ListRevisionsOptions } from './revision-queries.js';\nimport type { ListStylesOptions } from './style-queries.js';\n\nexport type KernelMethod =\n | 'load'\n | 'toZip'\n | 'toFlatOpc'\n | 'dispose'\n | 'serializeParts'\n | 'rebuildFromParts'\n // 读 namespace 方法(#92,docs/03.1 §2);dots 在字符串里没有歧义,见 sub-apis.ts\n | 'paragraphs.list'\n | 'paragraphs.get'\n | 'bookmarks.list'\n | 'bookmarks.get'\n | 'comments.list'\n | 'comments.get'\n | 'context.search'\n | 'revisions.list'\n | 'revisions.get'\n | 'styles.list'\n | 'styles.get'\n | 'tables.list'\n | 'tables.get'\n | 'tables.getVerbatim'\n | 'drawings.list'\n | 'drawings.get'\n | 'drawings.getImageBytes'\n | 'validatePlan'\n | 'sections.list'\n | 'tocFields.list'\n | 'applyPlan';\n\nexport interface KernelHandlerContext {\n kernel: Kernel;\n onProgress?: KernelProgress;\n}\n\n/** 每个 method 的 handler 签名:接 context + args,返 Promise<result> */\nexport type KernelHandler = (ctx: KernelHandlerContext, args: unknown[]) => Promise<unknown>;\n\nexport const kernelHandlers: Record<KernelMethod, KernelHandler> = {\n load: async ({ kernel, onProgress }, args) => {\n const [params] = args as [KernelLoadParams];\n await kernel.load(params, onProgress);\n // 返回装载后的可导出快照,便于主线程代理保留 docId / 初始字节等(为 worker 模式设计)\n return {\n docId: kernel.getDocId(),\n hasInitialBytes: kernel.getInitialBytes() !== undefined,\n hasInitialFlatOpc: kernel.getInitialFlatOpc() !== undefined,\n };\n },\n toZip: async ({ kernel }) => kernel.toZip(),\n toFlatOpc: async ({ kernel }) => kernel.toFlatOpc(),\n dispose: async ({ kernel }) => {\n kernel.dispose();\n },\n serializeParts: async ({ kernel }) => kernel.serializeParts(),\n rebuildFromParts: async ({ kernel, onProgress }, args) => {\n const [parts] = args as [readonly SnapshotPartEntry[]];\n kernel.rebuildFromParts(parts, onProgress);\n },\n 'paragraphs.list': async ({ kernel }, args) => {\n const [opts] = args as [ListParagraphsOptions | undefined];\n return kernel.listParagraphs(opts);\n },\n 'paragraphs.get': async ({ kernel }, args) => {\n const [paraId] = args as [string];\n return kernel.getParagraph(paraId);\n },\n 'bookmarks.list': async ({ kernel }, args) => {\n const [opts] = args as [ListBookmarksOptions | undefined];\n return kernel.listBookmarks(opts);\n },\n 'bookmarks.get': async ({ kernel }, args) => {\n const [name] = args as [BookmarkName];\n return kernel.getBookmark(name);\n },\n 'comments.list': async ({ kernel }) => kernel.listComments(),\n 'comments.get': async ({ kernel }, args) => {\n const [id] = args as [CommentId];\n return kernel.getComment(id);\n },\n 'context.search': async ({ kernel }, args) => {\n const [opts] = args as [ContextSearchOptions];\n return kernel.searchContext(opts);\n },\n 'revisions.list': async ({ kernel }, args) => {\n const [opts] = args as [ListRevisionsOptions | undefined];\n return kernel.listRevisions(opts);\n },\n 'revisions.get': async ({ kernel }, args) => {\n const [revId, opts] = args as [string, ListRevisionsOptions | undefined];\n return kernel.getRevision(revId, opts);\n },\n 'styles.list': async ({ kernel }, args) => {\n const [opts] = args as [ListStylesOptions | undefined];\n return kernel.listStyles(opts);\n },\n 'styles.get': async ({ kernel }, args) => {\n const [styleId] = args as [string];\n return kernel.getStyle(styleId);\n },\n 'tables.list': async ({ kernel }, args) => {\n const [opts] = args as [ListTablesOptions | undefined];\n return kernel.listTables(opts);\n },\n 'tables.get': async ({ kernel }, args) => {\n const [tableId] = args as [string];\n return kernel.getTable(tableId);\n },\n 'tables.getVerbatim': async ({ kernel }, args) => {\n const [tableId] = args as [string];\n return kernel.getTableVerbatim(tableId);\n },\n 'drawings.list': async ({ kernel }, args) => {\n const [opts] = args as [ListDrawingsOptions | undefined];\n return kernel.listDrawings(opts);\n },\n 'drawings.get': async ({ kernel }, args) => {\n const [drawingId] = args as [string];\n return kernel.getDrawing(drawingId);\n },\n 'drawings.getImageBytes': async ({ kernel }, args) => {\n const [drawingId] = args as [string];\n return kernel.getImageBytes(drawingId);\n },\n 'sections.list': async ({ kernel }) => kernel.listSections(),\n 'tocFields.list': async ({ kernel }) => kernel.listTocFields(),\n applyPlan: async ({ kernel }, args) => {\n const [params] = args as [ApplyPlanParams];\n // RPC 路径明确来源 'plan',对应 `doc.plan().apply()`(脚本路径走 script-execute,\n // 不进本 handler;那里 source 默认为 'script')。\n return kernel.applyPlan(params, { source: 'plan' });\n },\n validatePlan: async ({ kernel }, args) => {\n const [params] = args as [ApplyPlanParams];\n return kernel.validatePlan(params);\n },\n};\n","/**\n * Core-Word 读 API 的 namespace 子对象(#92,docs/03.1 §2)。\n *\n * 把 Phase B 原本平铺在 `WordDocument` 上的 7 个读方法按实体聚合为 4 个子 API:\n *\n * | 旧(平铺) | 新(namespace) |\n * |---|---|\n * | `doc.listParagraphs(opts)` | `doc.paragraphs.list(opts)` |\n * | `doc.getParagraph(id)` | `doc.paragraphs.get(id)` |\n * | `doc.listBookmarks(opts)` | `doc.bookmarks.list(opts)` |\n * | `doc.getBookmark(name)` | `doc.bookmarks.get(name)` |\n * | `doc.listComments()` | `doc.comments.list()` |\n * | `doc.getComment(id)` | `doc.comments.get(id)` |\n * | `doc.listRevisions(opts)` | `doc.revisions.list(opts)` |\n *\n * 动机:Phase F 起属性层(`format.*`)+ sections / tables / drawings / styles /\n * hyperlinks / fields 若继续平铺会让主类表面爆炸。namespace 聚合后新实体扩展只\n * 需往 `WordDocument` 加一个 `readonly` 字段(见 docs/03.1 §2 的 \"未来扩展\")。\n *\n * 命名规范(docs/03.1 §2.1):\n * - 子 API 方法用动词短命名 `list` / `get`,不重复实体名\n * - 过滤/分页选项保留顶层类型名(`ListParagraphsOptions` 不简化)\n * - 返回值类型名不变\n *\n * RPC method name 同步迁移:`paragraphs.list` / `paragraphs.get` / `bookmarks.list`\n * / `bookmarks.get` / `comments.list` / `comments.get` / `revisions.list`。协议\n * 版本不 bump —— 这是 method name rename,非协议结构变更。\n */\nimport type { BookmarkInfo, BookmarkName, ListBookmarksOptions } from './bookmark-queries.js';\nimport type { CommentId, CommentInfo } from './comment-queries.js';\nimport type { ContextSearchOptions, ContextSearchResult } from './context-search.js';\nimport type { ListParagraphsOptions, ListResult, ParagraphInfo } from './list-paragraphs.js';\nimport type {\n ListTablesOptions,\n RowHeight,\n TableCellBlockInfo,\n TableCellInfo,\n TableInfo,\n TableVerbatim,\n} from './list-tables.js';\nimport type { DrawingInfo, ListDrawingsOptions, TextBoxBlockInfo } from './list-drawings.js';\nimport type {\n ApplyResult,\n Op,\n ParaId,\n ParagraphDirectFormat,\n Range,\n TableCellDirectFormat,\n} from './plan.js';\nimport type { ListRevisionsOptions, RevisionInfo } from './revision-queries.js';\nimport type { SectionInfo } from './section-queries.js';\nimport type { TocFieldRange } from './toc-queries.js';\nimport type { ListStylesOptions, StyleInfo } from './style-queries.js';\nimport type { Transport } from './transport.js';\nimport { W_NS } from './namespaces.js';\n\n// ─────────── 接口(docs/03.1 §2)───────────\n\nexport interface ParagraphApi {\n /**\n * Lists paragraphs and returns live paragraph handles.\n */\n list(opts?: ListParagraphsOptions): Promise<ParagraphList>;\n /**\n * Gets one paragraph by `paraId`.\n *\n * Returns `null` when the paragraph no longer exists.\n */\n get(paraId: string): Promise<Paragraph | null>;\n}\n\nexport interface ParagraphList {\n paragraphs: Paragraph[];\n pagination: ListResult['pagination'];\n}\n\nexport interface LiveObjectWriteOptions {\n /**\n * Enables tracked-change markup for the write operation when supported.\n */\n trackChanges?: boolean;\n /**\n * Author metadata used by comments and tracked changes.\n */\n author?: string;\n /**\n * Date metadata used by comments and tracked changes.\n */\n date?: Date;\n}\n\nexport interface ContextApi {\n /**\n * Searches local document content and returns actionable context matches.\n */\n search(opts: ContextSearchOptions): Promise<ContextSearchResult>;\n}\n\nexport interface RevisionBulkOptions extends LiveObjectWriteOptions {\n /**\n * Bulk revision writes currently target all supported revisions.\n */\n scope?: 'all';\n}\n\nexport interface ParagraphDeleteOptions extends LiveObjectWriteOptions {\n /**\n * Controls what happens when deleting the paragraph would affect anchors such\n * as bookmarks or comments.\n */\n onAnchorConflict?: 'error' | 'drop';\n}\n\nexport interface ParagraphInsertOptions extends LiveObjectWriteOptions {\n /**\n * Controls the new paragraph's paragraph/run style source.\n */\n style?: 'inherit' | string;\n /**\n * Controls whether the new paragraph run inherits the anchor run format.\n */\n runFormat?: 'inherit' | 'default';\n}\n\nexport interface ParagraphReplaceOptions extends LiveObjectWriteOptions {\n /**\n * Controls what happens when replacing a paragraph would affect anchors such\n * as bookmarks or comments.\n */\n onAnchorConflict?: 'error' | 'drop';\n /**\n * Preserves inline drawings/objects while replacing text runs.\n */\n keepInlineGraphics?: boolean;\n}\n\nexport interface ParagraphInsertImageSpec {\n /** Image bytes. The SDK accepts browser-safe Uint8Array data. */\n bytes: Uint8Array;\n /** Image MIME type, for example `image/png` or `image/jpeg`. */\n contentType: string;\n /** Rendered width in EMU. 1 inch = 914400 EMU. */\n widthEmu: number;\n /** Rendered height in EMU. 1 inch = 914400 EMU. */\n heightEmu: number;\n}\n\nexport interface ParagraphInsertTableSpec {\n /**\n * Text matrix used to create a simple Word table. Missing cells in ragged\n * rows are created as empty cells.\n */\n rows: string[][];\n /** Column widths in twips. Defaults to 2400 twips for each column. */\n columnWidths?: number[];\n /** Optional Word table style id, written as `w:tblStyle`. */\n tableStyleId?: string;\n}\n\n/**\n * Live handle for one document paragraph.\n *\n * Snapshot fields such as `paraId` and `story` come from the read that created\n * the handle. Methods read or write the current document state.\n */\nexport interface Paragraph extends ParagraphInfo {\n /** Stable paragraph identifier. */\n readonly paraId: ParaId;\n /** Alias of `paraId`, kept for object-style APIs. */\n readonly id: ParaId;\n /** Document story that contains this paragraph. */\n readonly story: ParagraphInfo['story'];\n /**\n * Reads the current metadata for this paragraph.\n */\n getInfo(\n opts?: Pick<ListParagraphsOptions, 'includeFormat' | 'textFormat'>,\n ): Promise<ParagraphInfo | null>;\n /**\n * Reads the current plain text of this paragraph.\n */\n getText(): Promise<string | null>;\n /**\n * Replaces this paragraph with plain text.\n */\n replaceWith(text: string, opts?: ParagraphReplaceOptions): Promise<ApplyResult>;\n /**\n * Sets horizontal paragraph alignment.\n */\n setAlignment(\n value: NonNullable<ParagraphDirectFormat['alignment']>,\n opts?: LiveObjectWriteOptions,\n ): Promise<ApplyResult>;\n /**\n * Sets paragraph outline level. Values 0-8 correspond to heading levels 1-9.\n */\n setOutlineLevel(value: number, opts?: LiveObjectWriteOptions): Promise<ApplyResult>;\n /**\n * Sets whether this paragraph starts on a new page.\n */\n setPageBreakBefore(value: boolean, opts?: LiveObjectWriteOptions): Promise<ApplyResult>;\n /**\n * Sets paragraph indentation in twips.\n */\n setIndent(\n value: NonNullable<ParagraphDirectFormat['indent']>,\n opts?: LiveObjectWriteOptions,\n ): Promise<ApplyResult>;\n /**\n * Sets paragraph spacing in twips.\n */\n setSpacing(\n value: NonNullable<ParagraphDirectFormat['spacing']>,\n opts?: LiveObjectWriteOptions,\n ): Promise<ApplyResult>;\n /**\n * Inserts a new paragraph before this paragraph.\n */\n insertBefore(text: string, opts?: ParagraphInsertOptions): Promise<ApplyResult>;\n /**\n * Inserts a new paragraph after this paragraph.\n */\n insertAfter(text: string, opts?: ParagraphInsertOptions): Promise<ApplyResult>;\n /**\n * Inserts a new inline image paragraph after this paragraph.\n */\n insertImageAfter(\n spec: ParagraphInsertImageSpec,\n opts?: LiveObjectWriteOptions,\n ): Promise<ApplyResult>;\n /**\n * Inserts a simple text table after this paragraph.\n *\n * For high-fidelity table copy, use `table.getVerbatim()` with\n * `doc.plan().insertTableFrom(...)`.\n */\n insertTableAfter(\n spec: ParagraphInsertTableSpec,\n opts?: LiveObjectWriteOptions,\n ): Promise<ApplyResult>;\n /**\n * Deletes this paragraph from the document.\n */\n delete(opts?: ParagraphDeleteOptions): Promise<ApplyResult>;\n /**\n * Adds a comment to this whole paragraph.\n */\n addComment(text: string, opts?: LiveObjectWriteOptions): Promise<ApplyResult>;\n /**\n * Creates a bookmark around this whole paragraph.\n */\n createBookmark(name: BookmarkName, opts?: LiveObjectWriteOptions): Promise<ApplyResult>;\n /**\n * Creates a text range handle by searching inside this paragraph.\n *\n * The returned range is lazy: it resolves the search when a range method is\n * executed.\n */\n findText(search: string, opts?: { scope?: 'first' | 'all' }): TextRange;\n}\n\n/**\n * Live handle for text matched inside one paragraph.\n */\nexport interface TextRange {\n /**\n * Replaces the matched text with plain text.\n */\n replaceWith(text: string, opts?: LiveObjectWriteOptions): Promise<ApplyResult>;\n /**\n * Deletes the matched text.\n */\n delete(opts?: LiveObjectWriteOptions): Promise<ApplyResult>;\n /**\n * Sets bold formatting on the matched text.\n */\n setBold(value: boolean, opts?: LiveObjectWriteOptions): Promise<ApplyResult>;\n /**\n * Sets font color on the matched text.\n */\n setColor(value: string, opts?: LiveObjectWriteOptions): Promise<ApplyResult>;\n /**\n * Sets italic formatting on the matched text.\n */\n setItalic(value: boolean, opts?: LiveObjectWriteOptions): Promise<ApplyResult>;\n /**\n * Sets single underline on the matched text.\n */\n setUnderline(value: boolean, opts?: LiveObjectWriteOptions): Promise<ApplyResult>;\n /**\n * Sets Word highlight color on the matched text.\n */\n setHighlight(value: string, opts?: LiveObjectWriteOptions): Promise<ApplyResult>;\n /**\n * Sets font size in points on the matched text.\n */\n setFontSize(value: number, opts?: LiveObjectWriteOptions): Promise<ApplyResult>;\n /**\n * Sets font family on the matched text.\n */\n setFontFamily(value: string, opts?: LiveObjectWriteOptions): Promise<ApplyResult>;\n /**\n * Adds a comment to the matched text.\n */\n addComment(text: string, opts?: LiveObjectWriteOptions): Promise<ApplyResult>;\n /**\n * Creates a bookmark around the matched text.\n */\n createBookmark(name: BookmarkName, opts?: LiveObjectWriteOptions): Promise<ApplyResult>;\n}\n\nexport interface BookmarkApi {\n /**\n * Lists bookmarks and returns live bookmark handles.\n */\n list(opts?: ListBookmarksOptions): Promise<Bookmark[]>;\n /**\n * Gets one bookmark by name.\n *\n * Returns `null` when the bookmark no longer exists.\n */\n get(name: BookmarkName): Promise<Bookmark | null>;\n}\n\n/**\n * Live handle for one document bookmark.\n */\nexport interface Bookmark extends BookmarkInfo {\n /** Alias of `name`, kept for object-style APIs. */\n readonly id: BookmarkName;\n /**\n * Reads current metadata for this bookmark.\n */\n getInfo(): Promise<BookmarkInfo | null>;\n /**\n * Reads the current text covered by this bookmark when it can be expressed as\n * a paragraph or text range.\n */\n getText(): Promise<string | null>;\n /**\n * Returns the paragraph that contains this bookmark when available.\n */\n getParagraph(): Promise<Paragraph | null>;\n /**\n * Deletes this bookmark anchor pair.\n */\n delete(opts?: LiveObjectWriteOptions): Promise<ApplyResult>;\n}\n\nexport interface CommentApi {\n /**\n * Lists comments and returns live comment handles.\n */\n list(): Promise<Comment[]>;\n /**\n * Gets one comment by id.\n *\n * Returns `null` when the comment no longer exists.\n */\n get(id: CommentId): Promise<Comment | null>;\n}\n\n/**\n * Live handle for one document comment.\n */\nexport interface Comment extends CommentInfo {\n /**\n * Reads current metadata for this comment.\n */\n getInfo(): Promise<CommentInfo | null>;\n /**\n * Reads the current comment body text from `comments.xml`.\n */\n getText(): Promise<string | null>;\n /**\n * Reads the current document text covered by this comment anchor.\n */\n getAnchorText(): Promise<string | null>;\n /**\n * Returns the paragraph that contains this comment anchor when available.\n */\n getParagraph(): Promise<Paragraph | null>;\n /**\n * Deletes this comment body and its anchors.\n */\n delete(opts?: LiveObjectWriteOptions): Promise<ApplyResult>;\n}\n\nexport interface RevisionApi {\n /**\n * Lists revisions and returns live revision handles.\n */\n list(opts?: ListRevisionsOptions): Promise<Revision[]>;\n /**\n * Gets one revision by `revId`.\n *\n * Returns `null` when the revision no longer exists.\n */\n get(revId: RevisionInfo['revId'], opts?: ListRevisionsOptions): Promise<Revision | null>;\n /**\n * Accepts all supported revisions.\n */\n accept(opts?: RevisionBulkOptions): Promise<ApplyResult>;\n /**\n * Rejects all supported revisions.\n */\n reject(opts?: RevisionBulkOptions): Promise<ApplyResult>;\n}\n\n/**\n * Live handle for one document revision.\n *\n * `revision.accept/reject` operate on this single revision id. Use\n * `doc.revisions.accept/reject` for all supported revisions.\n */\nexport interface Revision extends RevisionInfo {\n /** Stable alias of `revId`, kept for object-style APIs. */\n readonly id: RevisionInfo['revId'];\n /**\n * Reads current metadata for this revision.\n */\n getInfo(opts?: ListRevisionsOptions): Promise<RevisionInfo | null>;\n /**\n * Reads the revision text when available.\n */\n getText(): Promise<string | null>;\n /**\n * Returns the paragraph that contains this revision when available.\n */\n getParagraph(): Promise<Paragraph | null>;\n /**\n * Accepts this revision.\n */\n accept(opts?: LiveObjectWriteOptions): Promise<ApplyResult>;\n /**\n * Rejects this revision.\n */\n reject(opts?: LiveObjectWriteOptions): Promise<ApplyResult>;\n}\n\nexport interface StylesApi {\n /**\n * 列出 styles.xml 中的所有样式(或按 type 过滤)。\n * styles.xml 不存在时返回空数组。\n */\n list(opts?: ListStylesOptions): Promise<StyleInfo[]>;\n /**\n * 按 styleId 精确查找,O(1)。\n * styleId 大小写敏感。不存在时返回 null。\n */\n get(styleId: string): Promise<StyleInfo | null>;\n}\n\nexport interface TablesApi {\n /**\n * 枚举文档表格(#185)。\n * - scope: 'body'(默认)只返回主文档 body 中的表格\n * - includeNested: false(默认)跳过嵌套在其他表格内的表格\n */\n /**\n * Lists tables in the document and returns live table handles.\n *\n * The returned `Table` values contain a snapshot of the table metadata at\n * list time, and also expose methods that can read fresh state or write back\n * to the same table.\n */\n list(opts?: ListTablesOptions): Promise<Table[]>;\n /**\n * 按 tableId 精确取单个表格,O(1)。不存在返回 null。\n */\n /**\n * Gets one table by `tableId`.\n *\n * Returns `null` when the table no longer exists.\n */\n get(tableId: string): Promise<Table | null>;\n /**\n * 按 tableId verbatim 取一张表的 OOXML 子树 + 格内图字节(自包含 payload)。\n * 供跨文档搬表 `plan.insertTableFrom(...)`(\"数据表 = 内容块\" §13.9)。不存在返回 null。\n */\n /**\n * Exports the raw OOXML subtree and related media for a table.\n *\n * This is an advanced API for high-fidelity table copying. Normal table\n * reads and writes should use `list`, `get`, and the methods on `Table`.\n */\n getVerbatim(tableId: string): Promise<TableVerbatim | null>;\n}\n\nexport interface TableDeleteOptions extends LiveObjectWriteOptions {\n /**\n * Controls what happens when deleting the table would affect anchors such as\n * bookmarks or comments.\n */\n onAnchorConflict?: 'error' | 'drop';\n}\n\nexport interface TableCellWriteOptions extends LiveObjectWriteOptions {\n /**\n * Controls what happens when replacing cell text would affect anchors such\n * as bookmarks or comments.\n */\n onAnchorConflict?: 'error' | 'drop';\n}\n\nexport interface TableRowDeleteOptions extends LiveObjectWriteOptions {\n /**\n * Controls what happens when deleting the row would affect anchors such as\n * bookmarks or comments.\n */\n onAnchorConflict?: 'error' | 'drop';\n}\n\n/**\n * Live handle for one document table.\n *\n * A `Table` is both a metadata snapshot and an operation handle:\n * snapshot fields such as `tableId`, `rowCount`, `colCount`, and `cells` come\n * from the read that created the handle, while methods such as `getInfo` and\n * `replaceCellText` read or write the current document state.\n */\nexport interface Table extends TableInfo {\n /** Stable alias of `tableId`, kept for object-style APIs. */\n readonly id: string;\n /**\n * Creates a live handle for one cell, addressed by zero-based row and column.\n */\n cell(row: number, col: number): TableCell;\n /**\n * Creates a live handle for one row, addressed by zero-based row index.\n */\n row(row: number): TableRow;\n /**\n * Creates a live handle for one column, addressed by zero-based column index.\n */\n column(col: number): TableColumn;\n /**\n * Reads the current metadata for this table.\n *\n * Use this after writes when you need fresh row, column, width, height, or\n * cell information.\n */\n getInfo(opts?: ListTablesOptions): Promise<TableInfo | null>;\n /**\n * Exports this table as raw OOXML plus related media.\n *\n * This is intended for high-fidelity copy/move flows, not routine editing.\n */\n getVerbatim(): Promise<TableVerbatim | null>;\n /**\n * Reads the current plain text of this table.\n *\n * Cell text is joined using tabs between columns and line breaks between\n * rows.\n */\n getText(opts?: ListTablesOptions): Promise<string | null>;\n /**\n * Reads the current table cell text as a two-dimensional array.\n *\n * Returns `null` when the table no longer exists.\n */\n getCells(opts?: ListTablesOptions): Promise<string[][] | null>;\n /** Adds a comment to the whole table range. */\n addComment(text: string, opts?: LiveObjectWriteOptions): Promise<ApplyResult>;\n /** Deletes this table from the document. */\n delete(opts?: TableDeleteOptions): Promise<ApplyResult>;\n /**\n * Replaces the text of one cell, addressed by zero-based row and column.\n */\n replaceCellText(\n row: number,\n col: number,\n text: string,\n opts?: TableCellWriteOptions,\n ): Promise<ApplyResult>;\n /** Deletes one row, addressed by zero-based row index. */\n deleteRow(row: number, opts?: TableRowDeleteOptions): Promise<ApplyResult>;\n /**\n * Inserts one row.\n *\n * `templateRow` is the zero-based source row used for row structure.\n * `position` is the zero-based insertion position, or `'end'`.\n */\n insertRow(\n spec: { templateRow: number; position: number | 'end'; cellTexts?: string[] },\n opts?: LiveObjectWriteOptions,\n ): Promise<ApplyResult>;\n /**\n * Sets table grid column widths in twips.\n *\n * The array length should match the table column count.\n */\n setColumnWidths(widths: number[], opts?: LiveObjectWriteOptions): Promise<ApplyResult>;\n /**\n * Sets row heights.\n *\n * Pass `null` for a row that should keep its current height.\n */\n setRowHeights(heights: (RowHeight | null)[], opts?: LiveObjectWriteOptions): Promise<ApplyResult>;\n}\n\n/**\n * Live handle for one table cell.\n */\nexport interface TableCell {\n /** Parent table id. */\n readonly tableId: string;\n /** Zero-based row index. */\n readonly row: number;\n /** Zero-based column index. */\n readonly col: number;\n /**\n * Reads the current cell metadata.\n */\n getInfo(opts?: ListTablesOptions): Promise<TableCellInfo | null>;\n /**\n * Reads direct content blocks in this cell, preserving cell content order.\n */\n getBlocks(opts?: ListTablesOptions): Promise<TableCellBlock[] | null>;\n /**\n * Reads live paragraph handles for direct paragraphs in this cell.\n */\n getParagraphs(opts?: ListTablesOptions): Promise<Paragraph[]>;\n /**\n * Reads the current plain text of this cell.\n */\n getText(opts?: ListTablesOptions): Promise<string | null>;\n /**\n * Creates a text range handle by searching inside this cell's paragraphs.\n */\n findText(search: string, opts?: { scope?: 'first' | 'all' }): CellTextRange;\n /**\n * Replaces this cell with plain text.\n */\n replaceWith(text: string, opts?: TableCellWriteOptions): Promise<ApplyResult>;\n /**\n * Inserts a new paragraph before the first direct content block in this cell.\n */\n insertParagraphAtStart(text: string, opts?: LiveObjectWriteOptions): Promise<ApplyResult>;\n /**\n * Inserts a new paragraph after the last direct content block in this cell.\n */\n insertParagraphAtEnd(text: string, opts?: LiveObjectWriteOptions): Promise<ApplyResult>;\n /**\n * Sets direct cell background shading fill color.\n */\n setShading(fill: string, opts?: LiveObjectWriteOptions): Promise<ApplyResult>;\n /**\n * Sets direct cell vertical alignment.\n */\n setVerticalAlignment(\n value: NonNullable<TableCellDirectFormat['verticalAlignment']>,\n opts?: LiveObjectWriteOptions,\n ): Promise<ApplyResult>;\n /**\n * Sets direct cell width in twips.\n */\n setWidth(width: number, opts?: LiveObjectWriteOptions): Promise<ApplyResult>;\n}\n\nexport type TableCellBlock =\n | {\n type: 'paragraph';\n paragraph: Paragraph;\n paraId: string;\n text: string;\n index: number;\n }\n | {\n type: 'drawing';\n drawing: Drawing | null;\n drawingId: string;\n paraId?: string;\n index: number;\n }\n | {\n type: 'table';\n table: Table | null;\n tableId: string;\n index: number;\n };\n\n/**\n * Live handle for text matched inside a table cell.\n */\nexport interface CellTextRange {\n replaceWith(text: string, opts?: LiveObjectWriteOptions): Promise<ApplyResult>;\n delete(opts?: LiveObjectWriteOptions): Promise<ApplyResult>;\n setBold(value: boolean, opts?: LiveObjectWriteOptions): Promise<ApplyResult>;\n setColor(value: string, opts?: LiveObjectWriteOptions): Promise<ApplyResult>;\n setItalic(value: boolean, opts?: LiveObjectWriteOptions): Promise<ApplyResult>;\n setUnderline(value: boolean, opts?: LiveObjectWriteOptions): Promise<ApplyResult>;\n setHighlight(value: string, opts?: LiveObjectWriteOptions): Promise<ApplyResult>;\n setFontSize(value: number, opts?: LiveObjectWriteOptions): Promise<ApplyResult>;\n setFontFamily(value: string, opts?: LiveObjectWriteOptions): Promise<ApplyResult>;\n addComment(text: string, opts?: LiveObjectWriteOptions): Promise<ApplyResult>;\n createBookmark(name: BookmarkName, opts?: LiveObjectWriteOptions): Promise<ApplyResult>;\n}\n\n/**\n * Live handle for one table row.\n */\nexport interface TableRow {\n /** Parent table id. */\n readonly tableId: string;\n /** Zero-based row index. */\n readonly index: number;\n /**\n * Reads the current cell texts for this row.\n */\n getCells(opts?: ListTablesOptions): Promise<string[] | null>;\n /**\n * Reads the current plain text of this row.\n *\n * Cell text is joined using tabs.\n */\n getText(opts?: ListTablesOptions): Promise<string | null>;\n /**\n * Deletes this row.\n */\n delete(opts?: TableRowDeleteOptions): Promise<ApplyResult>;\n /**\n * Inserts a row before this row, using this row as the structural template.\n */\n insertBefore(cellTexts?: string[], opts?: LiveObjectWriteOptions): Promise<ApplyResult>;\n /**\n * Inserts a row after this row, using this row as the structural template.\n */\n insertAfter(cellTexts?: string[], opts?: LiveObjectWriteOptions): Promise<ApplyResult>;\n /**\n * Sets the row height. Pass `null` to remove the explicit row height.\n */\n setHeight(height: RowHeight | null, opts?: LiveObjectWriteOptions): Promise<ApplyResult>;\n}\n\n/**\n * Live handle for one table column.\n */\nexport interface TableColumn {\n /** Parent table id. */\n readonly tableId: string;\n /** Zero-based column index. */\n readonly index: number;\n /**\n * Reads the current cell texts for this column.\n */\n getCells(opts?: ListTablesOptions): Promise<string[] | null>;\n /**\n * Reads the current plain text of this column.\n *\n * Cell text is joined using line breaks.\n */\n getText(opts?: ListTablesOptions): Promise<string | null>;\n /**\n * Sets this column width in twips.\n */\n setWidth(width: number, opts?: LiveObjectWriteOptions): Promise<ApplyResult>;\n}\n\nexport interface SectionsApi {\n /**\n * 列出主 body 的所有节(#211)。节按 doc-order 排序。\n * 无 body 或文档无 sectPr 时返回空数组。\n */\n list(): Promise<SectionInfo[]>;\n}\n\nexport interface TocFieldsApi {\n /**\n * 枚举主 body 中的所有 TOC 域(#197)。doc-order 排序。\n * 无 TOC 域时返回空数组。\n */\n list(): Promise<TocFieldRange[]>;\n}\n\nexport interface DrawingsApi {\n /**\n * 枚举文档 drawing 对象(#189)。\n * - scope: 'body'(默认)只返回主文档 body 内的 drawing\n * - scope: 'all' 包含 headers / footers / footnotes / endnotes / comments\n *\n * 本 API 只暴露形态信号(kind / extent / wrap / position / isInHeaderFooter 等),\n * 不下 A / B / C 业务分类结论 —— 那是 #191 / #192 的事。\n */\n list(opts?: ListDrawingsOptions): Promise<Drawing[]>;\n /**\n * Lists picture drawings only.\n *\n * Prefer this over filtering `list()` when the task is explicitly about\n * images.\n */\n listPictures(opts?: ListDrawingsOptions): Promise<PictureDrawing[]>;\n /**\n * Lists textbox drawings only.\n *\n * Prefer this when the task is explicitly about text boxes.\n */\n listTextBoxes(opts?: ListDrawingsOptions): Promise<TextBoxDrawing[]>;\n /**\n * Lists plain shape drawings only.\n *\n * This does not include pictures, text boxes, charts, SmartArt, groups, or\n * canvases.\n */\n listShapes(opts?: ListDrawingsOptions): Promise<ShapeDrawing[]>;\n /**\n * 按 drawingId 精确取单个 drawing,O(1)。不存在返回 null。\n */\n get(drawingId: string): Promise<Drawing | null>;\n}\n\nexport interface DrawingImageBytes {\n bytes: Uint8Array;\n contentType: string;\n extentEMU: { cx: number; cy: number };\n}\n\n/**\n * Live handle for one drawing object.\n */\nexport interface Drawing extends DrawingInfo {\n /** Stable alias of `drawingId`, kept for object-style APIs. */\n readonly id: string;\n /**\n * Reads current drawing metadata.\n */\n getInfo(): Promise<DrawingInfo | null>;\n /**\n * Reads original image bytes when this drawing is a picture.\n */\n getImageBytes(): Promise<DrawingImageBytes | null>;\n /**\n * Deletes this drawing.\n */\n delete(opts?: LiveObjectWriteOptions): Promise<ApplyResult>;\n /**\n * Replaces a picture drawing with the shared placeholder image.\n */\n replaceWithPlaceholder(opts?: LiveObjectWriteOptions): Promise<ApplyResult>;\n /**\n * Replaces text inside a shape/textbox drawing.\n */\n replaceShapeInnerText(placeholder: string, opts?: LiveObjectWriteOptions): Promise<ApplyResult>;\n}\n\n// ─────────── 工厂:持有 transport 引用 + dispose 检查 ───────────\n\n/** `WordDocument.assertNotDisposed` 的桥接签名;避免 sub-apis.ts 反向依赖 WordDocument */\n/**\n * Live handle for a picture drawing.\n */\nexport interface PictureDrawing extends Drawing {\n readonly kind: 'picture';\n /**\n * Reads original image bytes for this picture drawing.\n */\n getImageBytes(): Promise<DrawingImageBytes | null>;\n /**\n * Replaces this picture with the shared placeholder image while preserving layout.\n */\n replaceWithPlaceholder(opts?: LiveObjectWriteOptions): Promise<ApplyResult>;\n /**\n * Deletes this picture drawing.\n */\n delete(opts?: LiveObjectWriteOptions): Promise<ApplyResult>;\n}\n\n/**\n * Live handle for a textbox drawing.\n */\nexport interface TextBoxDrawing extends Drawing {\n readonly kind: 'textBox';\n /**\n * Reads the text currently inside this textbox.\n *\n * Returns `null` if the drawing no longer exists or is no longer a textbox.\n */\n getText(): Promise<string | null>;\n /**\n * Lists live paragraph handles inside this textbox.\n */\n getParagraphs(): Promise<Paragraph[]>;\n /**\n * Reads direct content blocks inside this textbox, preserving textbox content order.\n */\n getBlocks(): Promise<TextBoxBlock[]>;\n /**\n * Replaces all textbox content with a single paragraph containing `text`.\n */\n replaceText(text: string, opts?: LiveObjectWriteOptions): Promise<ApplyResult>;\n}\n\nexport type TextBoxBlock =\n | {\n type: 'paragraph';\n paragraph: Paragraph;\n paraId: string;\n text: string;\n index: number;\n }\n | {\n type: 'drawing';\n drawing: Drawing | null;\n drawingId: string;\n paraId?: string;\n index: number;\n }\n | {\n type: 'table';\n table: Table | null;\n tableId: string;\n index: number;\n };\n\n/**\n * Live handle for a plain shape drawing.\n */\nexport interface ShapeDrawing extends Drawing {\n readonly kind: 'shape';\n /**\n * Reads current plain-shape metadata such as border/fill and line hints.\n */\n getInfo(): Promise<(DrawingInfo & { kind: 'shape' }) | null>;\n /**\n * Deletes this plain shape drawing.\n */\n delete(opts?: LiveObjectWriteOptions): Promise<ApplyResult>;\n}\n\nexport type AssertNotDisposed = () => void;\n\nfunction liveObjectApplyOptions(opts: LiveObjectWriteOptions = {}): {\n trackChanges: boolean;\n author?: string;\n date?: string;\n} {\n return {\n trackChanges: opts.trackChanges ?? false,\n ...(opts.author !== undefined ? { author: opts.author } : {}),\n ...(opts.date !== undefined ? { date: opts.date.toISOString() } : {}),\n };\n}\n\nexport function createParagraphApi(\n transport: Transport,\n assertNotDisposed: AssertNotDisposed,\n): ParagraphApi {\n const createObject = (info: ParagraphInfo) =>\n new LiveParagraph(transport, assertNotDisposed, info);\n\n return {\n async list(opts) {\n assertNotDisposed();\n const result = await transport.call<ListResult>('paragraphs.list', [opts]);\n return {\n paragraphs: result.paragraphs.map(createObject),\n pagination: result.pagination,\n };\n },\n async get(paraId) {\n assertNotDisposed();\n const info = await transport.call<ParagraphInfo | null>('paragraphs.get', [paraId]);\n return info ? createObject(info) : null;\n },\n };\n}\n\nclass LiveParagraph implements Paragraph {\n readonly id: ParaId;\n readonly paraId!: ParaId;\n readonly story!: ParagraphInfo['story'];\n readonly text!: string;\n readonly truncated?: boolean;\n readonly styleId?: string;\n readonly hasRevisions?: boolean;\n readonly hasComments?: boolean;\n readonly hasBookmarks?: boolean;\n readonly hasMath?: boolean;\n readonly format?: ParagraphInfo['format'];\n readonly table?: ParagraphInfo['table'];\n\n constructor(\n private readonly transport: Transport,\n private readonly assertNotDisposed: AssertNotDisposed,\n infoOrParaId: ParagraphInfo | ParaId,\n story?: ParagraphInfo['story'],\n ) {\n const info =\n typeof infoOrParaId === 'string'\n ? ({ paraId: infoOrParaId, story: story!, text: '' } satisfies ParagraphInfo)\n : infoOrParaId;\n Object.assign(this, info);\n this.id = info.paraId;\n }\n\n async getInfo(\n opts?: Pick<ListParagraphsOptions, 'includeFormat' | 'textFormat'>,\n ): Promise<ParagraphInfo | null> {\n this.assertNotDisposed();\n if (opts?.includeFormat || opts?.textFormat) {\n const result = await this.transport.call<ListResult>('paragraphs.list', [\n {\n scope: [this.story],\n pagination: { mode: 'all' },\n ...opts,\n } satisfies ListParagraphsOptions,\n ]);\n return result.paragraphs.find((paragraph) => paragraph.paraId === this.paraId) ?? null;\n }\n return this.transport.call<ParagraphInfo | null>('paragraphs.get', [this.paraId]);\n }\n\n async getText(): Promise<string | null> {\n const info = await this.getInfo();\n return info?.text ?? null;\n }\n\n replaceWith(text: string, opts: ParagraphReplaceOptions = {}): Promise<ApplyResult> {\n return this.apply(\n [\n {\n type: 'replaceParagraph',\n paraId: this.paraId,\n text,\n onAnchorConflict: opts.onAnchorConflict ?? 'error',\n ...(opts.keepInlineGraphics !== undefined\n ? { keepInlineGraphics: opts.keepInlineGraphics }\n : {}),\n },\n ],\n opts,\n );\n }\n\n setAlignment(\n value: NonNullable<ParagraphDirectFormat['alignment']>,\n opts: LiveObjectWriteOptions = {},\n ): Promise<ApplyResult> {\n return this.applyParagraphFormat({ alignment: value }, opts);\n }\n\n setOutlineLevel(value: number, opts: LiveObjectWriteOptions = {}): Promise<ApplyResult> {\n return this.applyParagraphFormat({ outlineLevel: value }, opts);\n }\n\n setPageBreakBefore(value: boolean, opts: LiveObjectWriteOptions = {}): Promise<ApplyResult> {\n return this.applyParagraphFormat({ pageBreakBefore: value }, opts);\n }\n\n setIndent(\n value: NonNullable<ParagraphDirectFormat['indent']>,\n opts: LiveObjectWriteOptions = {},\n ): Promise<ApplyResult> {\n return this.applyParagraphFormat({ indent: value }, opts);\n }\n\n setSpacing(\n value: NonNullable<ParagraphDirectFormat['spacing']>,\n opts: LiveObjectWriteOptions = {},\n ): Promise<ApplyResult> {\n return this.applyParagraphFormat({ spacing: value }, opts);\n }\n\n insertBefore(text: string, opts: ParagraphInsertOptions = {}): Promise<ApplyResult> {\n return this.insertParagraph('insertParagraphBefore', text, opts);\n }\n\n insertAfter(text: string, opts: ParagraphInsertOptions = {}): Promise<ApplyResult> {\n return this.insertParagraph('insertParagraphAfter', text, opts);\n }\n\n insertImageAfter(\n spec: ParagraphInsertImageSpec,\n opts: LiveObjectWriteOptions = {},\n ): Promise<ApplyResult> {\n return this.apply(\n [\n {\n type: 'insertImageAfter',\n anchorParaId: this.paraId,\n bytes: spec.bytes,\n contentType: spec.contentType,\n widthEmu: spec.widthEmu,\n heightEmu: spec.heightEmu,\n },\n ],\n opts,\n );\n }\n\n insertTableAfter(\n spec: ParagraphInsertTableSpec,\n opts: LiveObjectWriteOptions = {},\n ): Promise<ApplyResult> {\n return this.apply(\n [\n {\n type: 'insertTableFrom',\n anchorParaId: this.paraId,\n tableXml: buildSimpleTableXml(spec),\n },\n ],\n opts,\n );\n }\n\n delete(opts: ParagraphDeleteOptions = {}): Promise<ApplyResult> {\n return this.apply(\n [\n {\n type: 'deleteParagraph',\n paraId: this.paraId,\n onAnchorConflict: opts.onAnchorConflict ?? 'error',\n },\n ],\n opts,\n );\n }\n\n addComment(text: string, opts: LiveObjectWriteOptions = {}): Promise<ApplyResult> {\n return this.apply([{ type: 'addComment', range: this.paragraphRange(), text }], opts);\n }\n\n createBookmark(name: BookmarkName, opts: LiveObjectWriteOptions = {}): Promise<ApplyResult> {\n return this.apply([{ type: 'createBookmark', name, range: this.paragraphRange() }], opts);\n }\n\n findText(search: string, opts: { scope?: 'first' | 'all' } = {}): TextRange {\n this.assertNotDisposed();\n return new LiveTextRange(\n this.transport,\n this.assertNotDisposed,\n this.paraId,\n search,\n opts.scope ?? 'first',\n );\n }\n\n private paragraphRange(): Range {\n return { paraId: this.paraId };\n }\n\n private applyParagraphFormat(\n format: ParagraphDirectFormat,\n opts: LiveObjectWriteOptions = {},\n ): Promise<ApplyResult> {\n return this.apply([{ type: 'formatParagraph', paraId: this.paraId, format }], opts);\n }\n\n private insertParagraph(\n type: 'insertParagraphBefore' | 'insertParagraphAfter',\n text: string,\n opts: ParagraphInsertOptions = {},\n ): Promise<ApplyResult> {\n const spec: Extract<Op, { type: typeof type }>['spec'] = { text };\n if (opts.style !== undefined) spec.style = opts.style;\n if (opts.runFormat !== undefined) spec.runFormat = opts.runFormat;\n return this.apply([{ type, anchorParaId: this.paraId, spec }], opts);\n }\n\n private apply(ops: Op[], opts: LiveObjectWriteOptions = {}): Promise<ApplyResult> {\n this.assertNotDisposed();\n return this.transport.call<ApplyResult>('applyPlan', [\n {\n ops,\n options: liveObjectApplyOptions(opts),\n },\n ]);\n }\n}\n\nexport function createContextApi(\n transport: Transport,\n assertNotDisposed: AssertNotDisposed,\n): ContextApi {\n return {\n search(opts) {\n assertNotDisposed();\n return transport.call<ContextSearchResult>('context.search', [opts]);\n },\n };\n}\n\nfunction buildSimpleTableXml(spec: ParagraphInsertTableSpec): string {\n const rows = spec.rows;\n if (rows.length === 0) {\n throw new Error('insertTableAfter requires at least one row');\n }\n\n const colCount = Math.max(...rows.map((row) => row.length));\n if (colCount === 0) {\n throw new Error('insertTableAfter requires at least one column');\n }\n\n const widths = Array.from({ length: colCount }, (_, index) =>\n normalizeTwips(spec.columnWidths?.[index] ?? 2400),\n );\n const grid = widths.map((width) => `<w:gridCol w:w=\"${width}\"/>`).join('');\n const style = spec.tableStyleId\n ? `<w:tblStyle w:val=\"${escapeXmlAttribute(spec.tableStyleId)}\"/>`\n : '';\n const body = rows\n .map((row) => {\n const cells = widths\n .map((width, index) => buildSimpleTableCell(row[index] ?? '', width))\n .join('');\n return `<w:tr>${cells}</w:tr>`;\n })\n .join('');\n\n return `<w:tbl xmlns:w=\"${W_NS}\"><w:tblPr>${style}<w:tblW w:w=\"0\" w:type=\"auto\"/></w:tblPr><w:tblGrid>${grid}</w:tblGrid>${body}</w:tbl>`;\n}\n\nfunction buildSimpleTableCell(text: string, width: number): string {\n const paragraph =\n text === ''\n ? '<w:p/>'\n : `<w:p><w:r><w:t xml:space=\"preserve\">${escapeXmlText(text)}</w:t></w:r></w:p>`;\n return `<w:tc><w:tcPr><w:tcW w:w=\"${width}\" w:type=\"dxa\"/></w:tcPr>${paragraph}</w:tc>`;\n}\n\nfunction normalizeTwips(value: number): number {\n if (!Number.isFinite(value) || value <= 0) {\n throw new Error('table column widths must be positive numbers');\n }\n return Math.round(value);\n}\n\nfunction escapeXmlText(value: string): string {\n return value.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');\n}\n\nfunction escapeXmlAttribute(value: string): string {\n return escapeXmlText(value).replace(/\"/g, '&quot;').replace(/'/g, '&apos;');\n}\n\nclass LiveTextRange implements TextRange {\n constructor(\n private readonly transport: Transport,\n private readonly assertNotDisposed: AssertNotDisposed,\n private readonly paraId: ParaId,\n private readonly search: string,\n private readonly scope: 'first' | 'all',\n ) {}\n\n replaceWith(text: string, opts: LiveObjectWriteOptions = {}): Promise<ApplyResult> {\n return this.apply(\n [\n {\n type: 'replaceTextInParagraph',\n paraId: this.paraId,\n search: this.search,\n replacement: text,\n scope: this.scope,\n },\n ],\n opts,\n );\n }\n\n delete(opts: LiveObjectWriteOptions = {}): Promise<ApplyResult> {\n return this.replaceWith('', opts);\n }\n\n setBold(value: boolean, opts: LiveObjectWriteOptions = {}): Promise<ApplyResult> {\n return this.applyTextFormat({ bold: value }, opts);\n }\n\n setColor(value: string, opts: LiveObjectWriteOptions = {}): Promise<ApplyResult> {\n return this.applyTextFormat({ color: value }, opts);\n }\n\n setItalic(value: boolean, opts: LiveObjectWriteOptions = {}): Promise<ApplyResult> {\n return this.applyTextFormat({ italic: value }, opts);\n }\n\n setUnderline(value: boolean, opts: LiveObjectWriteOptions = {}): Promise<ApplyResult> {\n return this.applyTextFormat({ underline: value }, opts);\n }\n\n setHighlight(value: string, opts: LiveObjectWriteOptions = {}): Promise<ApplyResult> {\n return this.applyTextFormat({ highlight: value }, opts);\n }\n\n setFontSize(value: number, opts: LiveObjectWriteOptions = {}): Promise<ApplyResult> {\n return this.applyTextFormat({ fontSize: value }, opts);\n }\n\n setFontFamily(value: string, opts: LiveObjectWriteOptions = {}): Promise<ApplyResult> {\n return this.applyTextFormat({ fontFamily: value }, opts);\n }\n\n private applyTextFormat(\n format: Extract<Op, { type: 'formatTextInParagraph' }>['format'],\n opts: LiveObjectWriteOptions = {},\n ): Promise<ApplyResult> {\n return this.apply(\n [\n {\n type: 'formatTextInParagraph',\n paraId: this.paraId,\n search: this.search,\n format,\n scope: this.scope,\n },\n ],\n opts,\n );\n }\n\n addComment(text: string, opts: LiveObjectWriteOptions = {}): Promise<ApplyResult> {\n return this.apply([{ type: 'addComment', range: this.toRangeDescriptor(), text }], opts);\n }\n\n createBookmark(name: BookmarkName, opts: LiveObjectWriteOptions = {}): Promise<ApplyResult> {\n return this.apply([{ type: 'createBookmark', name, range: this.toRangeDescriptor() }], opts);\n }\n\n private toRangeDescriptor(): Range {\n return { paraId: this.paraId, text: this.search, scope: this.scope };\n }\n\n private apply(ops: Op[], opts: LiveObjectWriteOptions = {}): Promise<ApplyResult> {\n this.assertNotDisposed();\n return this.transport.call<ApplyResult>('applyPlan', [\n {\n ops,\n options: liveObjectApplyOptions(opts),\n },\n ]);\n }\n}\n\nexport function createBookmarkApi(\n transport: Transport,\n assertNotDisposed: AssertNotDisposed,\n): BookmarkApi {\n const createObject = (info: BookmarkInfo) => new LiveBookmark(transport, assertNotDisposed, info);\n\n return {\n async list(opts) {\n assertNotDisposed();\n const result = await transport.call<BookmarkInfo[]>('bookmarks.list', [opts]);\n return result.map(createObject);\n },\n async get(name) {\n assertNotDisposed();\n const info = await transport.call<BookmarkInfo | null>('bookmarks.get', [name]);\n return info ? createObject(info) : null;\n },\n };\n}\n\nclass LiveBookmark implements Bookmark {\n readonly id: BookmarkName;\n readonly name!: BookmarkName;\n readonly story!: BookmarkInfo['story'];\n readonly rangeKind!: BookmarkInfo['rangeKind'];\n readonly paraId?: string;\n readonly text?: string;\n readonly hidden?: boolean;\n\n constructor(\n private readonly transport: Transport,\n private readonly assertNotDisposed: AssertNotDisposed,\n info: BookmarkInfo,\n ) {\n Object.assign(this, info);\n this.id = info.name;\n }\n\n getInfo(): Promise<BookmarkInfo | null> {\n this.assertNotDisposed();\n return this.transport.call<BookmarkInfo | null>('bookmarks.get', [this.name]);\n }\n\n async getText(): Promise<string | null> {\n const info = await this.getInfo();\n if (!info) return null;\n if (info.rangeKind === 'text') return info.text ?? '';\n if (!info.paraId) return null;\n const paragraph = await this.getParagraph();\n return paragraph?.getText() ?? null;\n }\n\n async getParagraph(): Promise<Paragraph | null> {\n const info = await this.getInfo();\n if (!info?.paraId) return null;\n const paragraph = await this.transport.call<ParagraphInfo | null>('paragraphs.get', [\n info.paraId,\n ]);\n return paragraph\n ? new LiveParagraph(this.transport, this.assertNotDisposed, paragraph.paraId, paragraph.story)\n : null;\n }\n\n delete(opts: LiveObjectWriteOptions = {}): Promise<ApplyResult> {\n this.assertNotDisposed();\n return this.transport.call<ApplyResult>('applyPlan', [\n {\n ops: [{ type: 'deleteBookmark', name: this.name }],\n options: liveObjectApplyOptions(opts),\n },\n ]);\n }\n}\n\nexport function createCommentApi(\n transport: Transport,\n assertNotDisposed: AssertNotDisposed,\n): CommentApi {\n const createObject = (info: CommentInfo) => new LiveComment(transport, assertNotDisposed, info);\n\n return {\n async list() {\n assertNotDisposed();\n const result = await transport.call<CommentInfo[]>('comments.list', []);\n return result.map(createObject);\n },\n async get(id) {\n assertNotDisposed();\n const info = await transport.call<CommentInfo | null>('comments.get', [id]);\n return info ? createObject(info) : null;\n },\n };\n}\n\nclass LiveComment implements Comment {\n readonly id!: CommentId;\n readonly author!: string;\n readonly date!: string;\n readonly text!: string;\n readonly rangeKind!: CommentInfo['rangeKind'];\n readonly paraId?: string;\n readonly anchorText?: string;\n\n constructor(\n private readonly transport: Transport,\n private readonly assertNotDisposed: AssertNotDisposed,\n info: CommentInfo,\n ) {\n Object.assign(this, info);\n }\n\n getInfo(): Promise<CommentInfo | null> {\n this.assertNotDisposed();\n return this.transport.call<CommentInfo | null>('comments.get', [this.id]);\n }\n\n async getText(): Promise<string | null> {\n return (await this.getInfo())?.text ?? null;\n }\n\n async getAnchorText(): Promise<string | null> {\n const info = await this.getInfo();\n if (!info) return null;\n if (info.rangeKind === 'text') return info.anchorText ?? '';\n if (!info.paraId) return null;\n const paragraph = await this.getParagraph();\n return paragraph?.getText() ?? null;\n }\n\n async getParagraph(): Promise<Paragraph | null> {\n const info = await this.getInfo();\n if (!info?.paraId) return null;\n const paragraph = await this.transport.call<ParagraphInfo | null>('paragraphs.get', [\n info.paraId,\n ]);\n return paragraph\n ? new LiveParagraph(this.transport, this.assertNotDisposed, paragraph.paraId, paragraph.story)\n : null;\n }\n\n delete(opts: LiveObjectWriteOptions = {}): Promise<ApplyResult> {\n this.assertNotDisposed();\n return this.transport.call<ApplyResult>('applyPlan', [\n {\n ops: [{ type: 'deleteComment', commentId: this.id }],\n options: liveObjectApplyOptions(opts),\n },\n ]);\n }\n}\n\nexport function createRevisionApi(\n transport: Transport,\n assertNotDisposed: AssertNotDisposed,\n): RevisionApi {\n const createObject = (info: RevisionInfo) => new LiveRevision(transport, assertNotDisposed, info);\n\n return {\n async list(opts) {\n assertNotDisposed();\n const result = await transport.call<RevisionInfo[]>('revisions.list', [opts]);\n return result.map(createObject);\n },\n async get(revId, opts) {\n assertNotDisposed();\n const info = await transport.call<RevisionInfo | null>('revisions.get', [revId, opts]);\n return info ? createObject(info) : null;\n },\n accept(opts = {}) {\n assertNotDisposed();\n return applyRevisionBulk(transport, 'acceptRevisions', opts);\n },\n reject(opts = {}) {\n assertNotDisposed();\n return applyRevisionBulk(transport, 'rejectRevisions', opts);\n },\n };\n}\n\nfunction applyRevisionBulk(\n transport: Transport,\n type: 'acceptRevisions' | 'rejectRevisions',\n opts: RevisionBulkOptions = {},\n): Promise<ApplyResult> {\n const op: Op = { type, scope: { scope: opts.scope ?? 'all' } };\n return transport.call<ApplyResult>('applyPlan', [\n {\n ops: [op],\n options: liveObjectApplyOptions(opts),\n },\n ]);\n}\n\nclass LiveRevision implements Revision {\n readonly id: RevisionInfo['revId'];\n readonly revId!: RevisionInfo['revId'];\n readonly kind!: RevisionInfo['kind'];\n readonly author!: string;\n readonly date!: string;\n readonly story!: RevisionInfo['story'];\n readonly paraId?: string;\n readonly text?: string;\n\n constructor(\n private readonly transport: Transport,\n private readonly assertNotDisposed: AssertNotDisposed,\n info: RevisionInfo,\n ) {\n Object.assign(this, info);\n this.id = info.revId;\n }\n\n getInfo(opts?: ListRevisionsOptions): Promise<RevisionInfo | null> {\n this.assertNotDisposed();\n return this.transport.call<RevisionInfo | null>('revisions.get', [this.revId, opts]);\n }\n\n async getText(): Promise<string | null> {\n return (await this.getInfo({ scope: 'all' }))?.text ?? null;\n }\n\n async getParagraph(): Promise<Paragraph | null> {\n const info = await this.getInfo({ scope: 'all' });\n if (!info?.paraId) return null;\n const paragraph = await this.transport.call<ParagraphInfo | null>('paragraphs.get', [\n info.paraId,\n ]);\n return paragraph\n ? new LiveParagraph(this.transport, this.assertNotDisposed, paragraph.paraId, paragraph.story)\n : null;\n }\n\n accept(opts: LiveObjectWriteOptions = {}): Promise<ApplyResult> {\n return this.applyRevision('acceptRevisions', opts);\n }\n\n reject(opts: LiveObjectWriteOptions = {}): Promise<ApplyResult> {\n return this.applyRevision('rejectRevisions', opts);\n }\n\n private applyRevision(\n type: 'acceptRevisions' | 'rejectRevisions',\n opts: LiveObjectWriteOptions = {},\n ): Promise<ApplyResult> {\n this.assertNotDisposed();\n const op: Op = { type, scope: { scope: 'revision', revId: this.revId } };\n return this.transport.call<ApplyResult>('applyPlan', [\n {\n ops: [op],\n options: liveObjectApplyOptions(opts),\n },\n ]);\n }\n}\n\nexport function createStylesApi(\n transport: Transport,\n assertNotDisposed: AssertNotDisposed,\n): StylesApi {\n return {\n async list(opts) {\n assertNotDisposed();\n return transport.call<StyleInfo[]>('styles.list', [opts]);\n },\n async get(styleId) {\n assertNotDisposed();\n return transport.call<StyleInfo | null>('styles.get', [styleId]);\n },\n };\n}\n\nexport function createSectionsApi(\n transport: Transport,\n assertNotDisposed: AssertNotDisposed,\n): SectionsApi {\n return {\n async list() {\n assertNotDisposed();\n return transport.call<SectionInfo[]>('sections.list', []);\n },\n };\n}\n\nexport function createTablesApi(\n transport: Transport,\n assertNotDisposed: AssertNotDisposed,\n): TablesApi {\n const createObject = (info: TableInfo) => new LiveTable(transport, assertNotDisposed, info);\n\n return {\n async list(opts) {\n assertNotDisposed();\n const result = await transport.call<TableInfo[]>('tables.list', [opts]);\n return result.map(createObject);\n },\n async get(tableId) {\n assertNotDisposed();\n const info = await transport.call<TableInfo | null>('tables.get', [tableId]);\n return info ? createObject(info) : null;\n },\n async getVerbatim(tableId) {\n assertNotDisposed();\n return transport.call<TableVerbatim | null>('tables.getVerbatim', [tableId]);\n },\n };\n}\n\nclass LiveTable implements Table {\n readonly id: string;\n readonly tableId!: string;\n readonly partPath!: string;\n readonly index!: number;\n readonly isNested!: boolean;\n readonly rowCount!: number;\n readonly colCount!: number;\n readonly hasMerge!: boolean;\n readonly tableStyleId?: string;\n readonly hasImages!: boolean;\n readonly hasNestedTables!: boolean;\n readonly prevParaId?: string;\n readonly nextParaId?: string;\n readonly columnWidths!: number[];\n readonly rowHeights!: (RowHeight | null)[];\n readonly cells?: string[][];\n readonly cellGrid?: TableInfo['cellGrid'];\n\n constructor(\n private readonly transport: Transport,\n private readonly assertNotDisposed: AssertNotDisposed,\n info: TableInfo,\n ) {\n Object.assign(this, info);\n this.id = info.tableId;\n }\n\n cell(row: number, col: number): TableCell {\n this.assertNotDisposed();\n return new LiveTableCell(this.transport, this.assertNotDisposed, this, row, col);\n }\n\n row(row: number): TableRow {\n this.assertNotDisposed();\n return new LiveTableRow(this, row);\n }\n\n column(col: number): TableColumn {\n this.assertNotDisposed();\n return new LiveTableColumn(this, col);\n }\n\n async getInfo(opts?: ListTablesOptions): Promise<TableInfo | null> {\n this.assertNotDisposed();\n if (!opts) {\n return this.transport.call<TableInfo | null>('tables.get', [this.tableId]);\n }\n const result = await this.transport.call<TableInfo[]>('tables.list', [\n {\n scope: 'all',\n includeNested: true,\n ...opts,\n } satisfies ListTablesOptions,\n ]);\n return result.find((table) => table.tableId === this.tableId) ?? null;\n }\n\n getVerbatim(): Promise<TableVerbatim | null> {\n this.assertNotDisposed();\n return this.transport.call<TableVerbatim | null>('tables.getVerbatim', [this.tableId]);\n }\n\n async getText(opts?: ListTablesOptions): Promise<string | null> {\n const cells = await this.getCells(opts);\n return cells?.map((row) => row.join('\\t')).join('\\n') ?? null;\n }\n\n async getCells(opts?: ListTablesOptions): Promise<string[][] | null> {\n const info = await this.getInfo({\n scope: 'all',\n includeNested: true,\n ...opts,\n includeCellTexts: true,\n });\n return info?.cells ?? null;\n }\n\n addComment(text: string, opts: LiveObjectWriteOptions = {}): Promise<ApplyResult> {\n return this.apply([{ type: 'addTableComment', tableId: this.tableId, text }], opts);\n }\n\n delete(opts: TableDeleteOptions = {}): Promise<ApplyResult> {\n return this.apply(\n [\n {\n type: 'deleteTable',\n tableId: this.tableId,\n onAnchorConflict: opts.onAnchorConflict ?? 'error',\n },\n ],\n opts,\n );\n }\n\n replaceCellText(\n row: number,\n col: number,\n text: string,\n opts: TableCellWriteOptions = {},\n ): Promise<ApplyResult> {\n return this.apply(\n [\n {\n type: 'replaceTableCellText',\n tableId: this.tableId,\n row,\n col,\n text,\n onAnchorConflict: opts.onAnchorConflict ?? 'error',\n },\n ],\n opts,\n );\n }\n\n deleteRow(row: number, opts: TableRowDeleteOptions = {}): Promise<ApplyResult> {\n return this.apply(\n [\n {\n type: 'deleteTableRow',\n tableId: this.tableId,\n row,\n onAnchorConflict: opts.onAnchorConflict ?? 'error',\n },\n ],\n opts,\n );\n }\n\n insertRow(\n spec: { templateRow: number; position: number | 'end'; cellTexts?: string[] },\n opts: LiveObjectWriteOptions = {},\n ): Promise<ApplyResult> {\n return this.apply(\n [\n {\n type: 'insertTableRow',\n tableId: this.tableId,\n templateRow: spec.templateRow,\n position: spec.position,\n cellTexts: spec.cellTexts,\n },\n ],\n opts,\n );\n }\n\n setColumnWidths(widths: number[], opts: LiveObjectWriteOptions = {}): Promise<ApplyResult> {\n return this.apply([{ type: 'setTableColumnWidths', tableId: this.tableId, widths }], opts);\n }\n\n setRowHeights(\n heights: (RowHeight | null)[],\n opts: LiveObjectWriteOptions = {},\n ): Promise<ApplyResult> {\n return this.apply([{ type: 'setTableRowHeights', tableId: this.tableId, heights }], opts);\n }\n\n private apply(ops: Op[], opts: LiveObjectWriteOptions = {}): Promise<ApplyResult> {\n this.assertNotDisposed();\n return this.transport.call<ApplyResult>('applyPlan', [\n {\n ops,\n options: liveObjectApplyOptions(opts),\n },\n ]);\n }\n}\n\nclass LiveTableCell implements TableCell {\n readonly tableId: string;\n\n constructor(\n private readonly transport: Transport,\n private readonly assertNotDisposed: AssertNotDisposed,\n private readonly table: Table,\n readonly row: number,\n readonly col: number,\n ) {\n this.tableId = table.tableId;\n }\n\n async getInfo(opts?: ListTablesOptions): Promise<TableCellInfo | null> {\n const info = await this.table.getInfo({\n scope: 'all',\n includeNested: true,\n ...opts,\n includeCellTexts: true,\n });\n return info?.cellGrid?.[this.row]?.[this.col] ?? null;\n }\n\n async getBlocks(opts?: ListTablesOptions): Promise<TableCellBlock[] | null> {\n const info = await this.getInfo(opts);\n if (!info) return null;\n const blocks: TableCellBlock[] = [];\n for (let index = 0; index < info.blocks.length; index++) {\n const block = info.blocks[index]!;\n const mapped = await this.toLiveBlock(block, index);\n if (mapped) blocks.push(mapped);\n }\n return blocks;\n }\n\n async getParagraphs(opts?: ListTablesOptions): Promise<Paragraph[]> {\n const info = await this.getInfo(opts);\n if (!info) return [];\n const paragraphs = await Promise.all(\n info.paragraphIds.map((paraId) =>\n this.transport.call<ParagraphInfo | null>('paragraphs.get', [paraId]),\n ),\n );\n return paragraphs\n .filter((paragraph): paragraph is ParagraphInfo => paragraph !== null)\n .map(\n (paragraph) =>\n new LiveParagraph(\n this.transport,\n this.assertNotDisposed,\n paragraph.paraId,\n paragraph.story,\n ),\n );\n }\n\n async getText(opts?: ListTablesOptions): Promise<string | null> {\n return (await this.getInfo(opts))?.text ?? null;\n }\n\n findText(search: string, opts: { scope?: 'first' | 'all' } = {}): CellTextRange {\n this.assertNotDisposed();\n return new LiveCellTextRange(this, search, opts.scope ?? 'first');\n }\n\n replaceWith(text: string, opts?: TableCellWriteOptions): Promise<ApplyResult> {\n return this.table.replaceCellText(this.row, this.col, text, opts);\n }\n\n insertParagraphAtStart(text: string, opts?: LiveObjectWriteOptions): Promise<ApplyResult> {\n return this.insertParagraph(text, 'start', opts);\n }\n\n insertParagraphAtEnd(text: string, opts?: LiveObjectWriteOptions): Promise<ApplyResult> {\n return this.insertParagraph(text, 'end', opts);\n }\n\n setShading(fill: string, opts?: LiveObjectWriteOptions): Promise<ApplyResult> {\n return this.applyCellFormat({ shading: { fill } }, opts);\n }\n\n setVerticalAlignment(\n value: NonNullable<TableCellDirectFormat['verticalAlignment']>,\n opts?: LiveObjectWriteOptions,\n ): Promise<ApplyResult> {\n return this.applyCellFormat({ verticalAlignment: value }, opts);\n }\n\n setWidth(width: number, opts?: LiveObjectWriteOptions): Promise<ApplyResult> {\n return this.applyCellFormat({ width }, opts);\n }\n\n private async toLiveBlock(\n block: TableCellBlockInfo,\n index: number,\n ): Promise<TableCellBlock | null> {\n if (block.type === 'drawing') {\n const info = await this.transport.call<DrawingInfo | null>('drawings.get', [block.drawingId]);\n const drawing = info ? new LiveDrawing(this.transport, this.assertNotDisposed, info) : null;\n return 'paraId' in block && block.paraId\n ? { type: 'drawing', drawing, drawingId: block.drawingId, paraId: block.paraId, index }\n : { type: 'drawing', drawing, drawingId: block.drawingId, index };\n }\n if (block.type === 'table') {\n const info = await this.transport.call<TableInfo | null>('tables.get', [block.tableId]);\n return {\n type: 'table',\n tableId: block.tableId,\n table: info ? new LiveTable(this.transport, this.assertNotDisposed, info) : null,\n index,\n };\n }\n\n const info = await this.transport.call<ParagraphInfo | null>('paragraphs.get', [block.paraId]);\n if (!info) return null;\n return {\n type: 'paragraph',\n paragraph: new LiveParagraph(this.transport, this.assertNotDisposed, info.paraId, info.story),\n paraId: block.paraId,\n text: block.text,\n index,\n };\n }\n\n private applyCellFormat(\n format: TableCellDirectFormat,\n opts: LiveObjectWriteOptions = {},\n ): Promise<ApplyResult> {\n return this.apply(\n [\n {\n type: 'formatTableCell',\n tableId: this.tableId,\n row: this.row,\n col: this.col,\n format,\n },\n ],\n opts,\n );\n }\n\n private insertParagraph(\n text: string,\n position: 'start' | 'end',\n opts: LiveObjectWriteOptions = {},\n ): Promise<ApplyResult> {\n return this.apply(\n [\n {\n type: 'insertTableCellParagraph',\n tableId: this.tableId,\n row: this.row,\n col: this.col,\n text,\n position,\n },\n ],\n opts,\n );\n }\n\n private apply(ops: Op[], opts: LiveObjectWriteOptions = {}): Promise<ApplyResult> {\n this.assertNotDisposed();\n return this.transport.call<ApplyResult>('applyPlan', [\n {\n ops,\n options: liveObjectApplyOptions(opts),\n },\n ]);\n }\n}\n\nclass LiveCellTextRange implements CellTextRange {\n constructor(\n private readonly cell: TableCell,\n private readonly search: string,\n private readonly scope: 'first' | 'all',\n ) {}\n\n async replaceWith(text: string, opts?: LiveObjectWriteOptions): Promise<ApplyResult> {\n return this.apply((range) => range.replaceWith(text, opts));\n }\n\n async delete(opts?: LiveObjectWriteOptions): Promise<ApplyResult> {\n return this.replaceWith('', opts);\n }\n\n async setBold(value: boolean, opts?: LiveObjectWriteOptions): Promise<ApplyResult> {\n return this.apply((range) => range.setBold(value, opts));\n }\n\n async setColor(value: string, opts?: LiveObjectWriteOptions): Promise<ApplyResult> {\n return this.apply((range) => range.setColor(value, opts));\n }\n\n async setItalic(value: boolean, opts?: LiveObjectWriteOptions): Promise<ApplyResult> {\n return this.apply((range) => range.setItalic(value, opts));\n }\n\n async setUnderline(value: boolean, opts?: LiveObjectWriteOptions): Promise<ApplyResult> {\n return this.apply((range) => range.setUnderline(value, opts));\n }\n\n async setHighlight(value: string, opts?: LiveObjectWriteOptions): Promise<ApplyResult> {\n return this.apply((range) => range.setHighlight(value, opts));\n }\n\n async setFontSize(value: number, opts?: LiveObjectWriteOptions): Promise<ApplyResult> {\n return this.apply((range) => range.setFontSize(value, opts));\n }\n\n async setFontFamily(value: string, opts?: LiveObjectWriteOptions): Promise<ApplyResult> {\n return this.apply((range) => range.setFontFamily(value, opts));\n }\n\n async addComment(text: string, opts?: LiveObjectWriteOptions): Promise<ApplyResult> {\n return this.apply((range) => range.addComment(text, opts));\n }\n\n async createBookmark(name: BookmarkName, opts?: LiveObjectWriteOptions): Promise<ApplyResult> {\n return this.apply((range) => range.createBookmark(name, opts));\n }\n\n private async apply(op: (range: TextRange) => Promise<ApplyResult>): Promise<ApplyResult> {\n const paragraphs = await this.cell.getParagraphs();\n const matched: Paragraph[] = [];\n for (const paragraph of paragraphs) {\n const text = await paragraph.getText();\n if (text?.includes(this.search)) {\n matched.push(paragraph);\n if (this.scope === 'first') break;\n }\n }\n if (matched.length === 0) {\n throw new Error(\n `cell.findText: text '${this.search}' not found in table '${this.cell.tableId}' cell (${this.cell.row}, ${this.cell.col})`,\n );\n }\n\n let last: ApplyResult | undefined;\n for (const paragraph of matched) {\n last = await op(paragraph.findText(this.search, { scope: this.scope }));\n }\n return last!;\n }\n}\n\nclass LiveTableRow implements TableRow {\n readonly tableId: string;\n\n constructor(\n private readonly table: Table,\n readonly index: number,\n ) {\n this.tableId = table.tableId;\n }\n\n async getCells(opts?: ListTablesOptions): Promise<string[] | null> {\n const cells = await this.table.getCells(opts);\n return cells?.[this.index] ?? null;\n }\n\n async getText(opts?: ListTablesOptions): Promise<string | null> {\n const cells = await this.getCells(opts);\n return cells?.join('\\t') ?? null;\n }\n\n delete(opts?: TableRowDeleteOptions): Promise<ApplyResult> {\n return this.table.deleteRow(this.index, opts);\n }\n\n insertBefore(cellTexts?: string[], opts?: LiveObjectWriteOptions): Promise<ApplyResult> {\n return this.table.insertRow({ templateRow: this.index, position: this.index, cellTexts }, opts);\n }\n\n insertAfter(cellTexts?: string[], opts?: LiveObjectWriteOptions): Promise<ApplyResult> {\n return this.table.insertRow(\n { templateRow: this.index, position: this.index + 1, cellTexts },\n opts,\n );\n }\n\n async setHeight(height: RowHeight | null, opts?: LiveObjectWriteOptions): Promise<ApplyResult> {\n const info = await this.table.getInfo();\n const heights = (info?.rowHeights ?? this.table.rowHeights).slice();\n heights[this.index] = height;\n return this.table.setRowHeights(heights, opts);\n }\n}\n\nclass LiveTableColumn implements TableColumn {\n readonly tableId: string;\n\n constructor(\n private readonly table: Table,\n readonly index: number,\n ) {\n this.tableId = table.tableId;\n }\n\n async getCells(opts?: ListTablesOptions): Promise<string[] | null> {\n const cells = await this.table.getCells(opts);\n if (!cells) return null;\n return cells.map((row) => row[this.index] ?? '');\n }\n\n async getText(opts?: ListTablesOptions): Promise<string | null> {\n const cells = await this.getCells(opts);\n return cells?.join('\\n') ?? null;\n }\n\n async setWidth(width: number, opts?: LiveObjectWriteOptions): Promise<ApplyResult> {\n const info = await this.table.getInfo();\n const widths = (info?.columnWidths ?? this.table.columnWidths).slice();\n widths[this.index] = width;\n return this.table.setColumnWidths(widths, opts);\n }\n}\n\nexport function createDrawingsApi(\n transport: Transport,\n assertNotDisposed: AssertNotDisposed,\n): DrawingsApi {\n const createObject = (info: DrawingInfo) => new LiveDrawing(transport, assertNotDisposed, info);\n const listAll = async (opts?: ListDrawingsOptions): Promise<Drawing[]> => {\n assertNotDisposed();\n const drawings = await transport.call<DrawingInfo[]>('drawings.list', [opts]);\n return drawings.map(createObject);\n };\n\n return {\n list: listAll,\n async listPictures(opts) {\n const drawings = await listAll(opts);\n return drawings.filter((drawing): drawing is PictureDrawing => drawing.kind === 'picture');\n },\n async listTextBoxes(opts) {\n const drawings = await listAll(opts);\n return drawings.filter((drawing): drawing is TextBoxDrawing => drawing.kind === 'textBox');\n },\n async listShapes(opts) {\n const drawings = await listAll(opts);\n return drawings.filter((drawing): drawing is ShapeDrawing => drawing.kind === 'shape');\n },\n async get(drawingId) {\n assertNotDisposed();\n const info = await transport.call<DrawingInfo | null>('drawings.get', [drawingId]);\n return info ? createObject(info) : null;\n },\n };\n}\n\nclass LiveDrawing implements Drawing {\n readonly id: string;\n readonly drawingId!: string;\n readonly partPath!: string;\n readonly index!: number;\n readonly anchoringMode!: DrawingInfo['anchoringMode'];\n readonly kind!: DrawingInfo['kind'];\n readonly extentEMU!: DrawingInfo['extentEMU'];\n readonly isInHeaderFooter!: boolean;\n readonly hasPicReference!: boolean;\n\n constructor(\n private readonly transport: Transport,\n private readonly assertNotDisposed: AssertNotDisposed,\n info: DrawingInfo,\n ) {\n Object.assign(this, info);\n this.id = info.drawingId;\n }\n\n getInfo(): Promise<DrawingInfo | null> {\n this.assertNotDisposed();\n return this.transport.call<DrawingInfo | null>('drawings.get', [this.drawingId]);\n }\n\n getImageBytes(): Promise<DrawingImageBytes | null> {\n this.assertNotDisposed();\n return this.transport.call<DrawingImageBytes | null>('drawings.getImageBytes', [\n this.drawingId,\n ]);\n }\n\n delete(opts: LiveObjectWriteOptions = {}): Promise<ApplyResult> {\n return this.apply([{ type: 'deleteDrawing', drawingId: this.drawingId }], opts);\n }\n\n replaceWithPlaceholder(opts: LiveObjectWriteOptions = {}): Promise<ApplyResult> {\n return this.apply([{ type: 'replaceDrawingWithPlaceholder', drawingId: this.drawingId }], opts);\n }\n\n replaceShapeInnerText(\n placeholder: string,\n opts: LiveObjectWriteOptions = {},\n ): Promise<ApplyResult> {\n return this.apply(\n [{ type: 'replaceShapeInnerText', drawingId: this.drawingId, placeholder }],\n opts,\n );\n }\n\n async getText(): Promise<string | null> {\n const info = await this.getInfo();\n if (!info || info.kind !== 'textBox') return null;\n return info.innerText ?? '';\n }\n\n async getParagraphs(): Promise<Paragraph[]> {\n const info = await this.getInfo();\n if (!info || info.kind !== 'textBox') return [];\n const paragraphs: Paragraph[] = [];\n for (const paraId of info.innerParagraphIds ?? []) {\n const paragraphInfo = await this.transport.call<ParagraphInfo | null>('paragraphs.get', [\n paraId,\n ]);\n if (paragraphInfo) {\n paragraphs.push(\n new LiveParagraph(\n this.transport,\n this.assertNotDisposed,\n paragraphInfo.paraId,\n paragraphInfo.story,\n ),\n );\n }\n }\n return paragraphs;\n }\n\n async getBlocks(): Promise<TextBoxBlock[]> {\n const info = await this.getInfo();\n if (!info || info.kind !== 'textBox') return [];\n const blocks: TextBoxBlock[] = [];\n for (let index = 0; index < (info.innerBlocks ?? []).length; index++) {\n const block = info.innerBlocks![index]!;\n const mapped = await this.toLiveTextBoxBlock(block, index);\n if (mapped) blocks.push(mapped);\n }\n return blocks;\n }\n\n replaceText(text: string, opts: LiveObjectWriteOptions = {}): Promise<ApplyResult> {\n return this.apply(\n [{ type: 'replaceShapeInnerText', drawingId: this.drawingId, placeholder: text }],\n opts,\n );\n }\n\n private async toLiveTextBoxBlock(\n block: TextBoxBlockInfo,\n index: number,\n ): Promise<TextBoxBlock | null> {\n if (block.type === 'drawing') {\n const info = await this.transport.call<DrawingInfo | null>('drawings.get', [block.drawingId]);\n const drawing = info ? new LiveDrawing(this.transport, this.assertNotDisposed, info) : null;\n return 'paraId' in block && block.paraId\n ? { type: 'drawing', drawing, drawingId: block.drawingId, paraId: block.paraId, index }\n : { type: 'drawing', drawing, drawingId: block.drawingId, index };\n }\n\n if (block.type === 'table') {\n const info = await this.transport.call<TableInfo | null>('tables.get', [block.tableId]);\n return {\n type: 'table',\n tableId: block.tableId,\n table: info ? new LiveTable(this.transport, this.assertNotDisposed, info) : null,\n index,\n };\n }\n\n const info = await this.transport.call<ParagraphInfo | null>('paragraphs.get', [block.paraId]);\n if (!info) return null;\n return {\n type: 'paragraph',\n paragraph: new LiveParagraph(this.transport, this.assertNotDisposed, info.paraId, info.story),\n paraId: block.paraId,\n text: block.text,\n index,\n };\n }\n\n private apply(ops: Op[], opts: LiveObjectWriteOptions = {}): Promise<ApplyResult> {\n this.assertNotDisposed();\n return this.transport.call<ApplyResult>('applyPlan', [\n {\n ops,\n options: liveObjectApplyOptions(opts),\n },\n ]);\n }\n}\n\nexport function createTocFieldsApi(\n transport: Transport,\n assertNotDisposed: AssertNotDisposed,\n): TocFieldsApi {\n return {\n async list() {\n assertNotDisposed();\n return transport.call<TocFieldRange[]>('tocFields.list', []);\n },\n };\n}\n","/**\n * sandbox-doc —— 在 sandbox 内构造与主线程 `WordDocument` 同形态的 `doc` 注入对象(#159)。\n *\n * 04.2 §6.1 声明沙箱内的 `doc` 与主线程 `WordDocument` 同名签名。本模块复用\n * `sub-apis.ts` 与 `WordPlanImpl` 的工厂(它们均 transport-agnostic),只额外\n * 提供一个最小的 sandbox transport —— 把 namespace / plan 的 RPC 调用转发到本\n * 进程内已存在的 Kernel,不经过 worker 边界。\n *\n * 注入的 `doc` 形态:\n * - `doc.docId: string`\n * - `doc.paragraphs.list(opts) / get(id)`\n * - `doc.bookmarks.list(opts) / get(name)`\n * - `doc.comments.list() / get(id)`\n * - `doc.revisions.list(opts)`\n * - `doc.plan(opts).<op>().apply()`\n *\n * 不暴露:\n * - `doc.executeCode`(沙箱内递归执行无意义)\n * - 旧的平铺 / kernel-direct 形态(`doc.applyPlan` / `doc.listParagraphs` 等):\n * #159 决定一次性切换,不保留 backward-compat。\n */\nimport { kernelHandlers, type KernelMethod } from './kernel-handlers.js';\nimport type { Kernel, KernelProgress } from './kernel.js';\nimport { WordPlanImpl, type ApplyPlanParams, type PlanOptions, type WordPlan } from './plan.js';\nimport {\n createBookmarkApi,\n createCommentApi,\n createParagraphApi,\n createRevisionApi,\n createTablesApi,\n type BookmarkApi,\n type CommentApi,\n type ParagraphApi,\n type RevisionApi,\n type TablesApi,\n} from './sub-apis.js';\nimport type { Transport } from './transport.js';\nimport { WordError } from './word-error.js';\n\nexport interface SandboxDoc {\n readonly docId: string;\n readonly paragraphs: ParagraphApi;\n readonly bookmarks: BookmarkApi;\n readonly comments: CommentApi;\n readonly revisions: RevisionApi;\n readonly tables: TablesApi;\n plan(opts?: PlanOptions): WordPlan;\n}\n\n/**\n * 构造 sandbox 用的最小 transport:只实现 `call` —— 把 RPC method 直接路由到\n * 已存在 kernel 的 handler。其它 Transport 能力(executeScript / dispose /\n * onChange)在 sandbox 内不需要也不应触发。\n *\n * `applyPlan` 特殊化:`kernelHandlers.applyPlan` 硬编码 `source: 'plan'`(主线程\n * `doc.plan().apply()` 路径),但脚本里 `doc.plan().apply()` 应当标 `source: 'script'`\n * —— 故 sandbox transport 直接调 `kernel.applyPlan(params, { source: 'script' })`,\n * 绕过 handler 默认值。\n */\nfunction createSandboxTransport(kernel: Kernel): Transport {\n return {\n async call<T>(method: KernelMethod, args: unknown[], onProgress?: KernelProgress): Promise<T> {\n if (method === 'applyPlan') {\n const [params] = args as [ApplyPlanParams];\n const result = await kernel.applyPlan(params, { source: 'script' });\n return result as T;\n }\n const handler = kernelHandlers[method];\n const result = await handler({ kernel, onProgress }, args);\n return result as T;\n },\n executeScript() {\n return Promise.reject(\n new Error('nested executeScript is not supported inside script sandbox'),\n );\n },\n dispose() {\n return Promise.resolve();\n },\n onChange() {\n return () => {};\n },\n };\n}\n\n/**\n * 把 kernel 包成与主线程 `WordDocument` 同形态的 sandbox `doc`。\n *\n * 复用 sub-apis.ts 的 namespace 工厂 + WordPlanImpl —— 这两者只通过\n * `transport.call(method, args)` 访问 kernel,与主线程走同一条路径。\n *\n * 不做 `assertNotDisposed` 检查:sandbox 内 kernel 由宿主管理,脚本生命周期\n * 短于 kernel,disposed 状态不会出现。\n */\nexport function createSandboxDoc(kernel: Kernel): SandboxDoc {\n const docId = kernel.getDocId();\n if (!docId) {\n throw new WordError(\n 'PACKAGE_UNSUPPORTED_FORMAT',\n 'createSandboxDoc: kernel not loaded (docId is undefined)',\n '',\n );\n }\n const transport = createSandboxTransport(kernel);\n const noop = () => {};\n return {\n docId,\n paragraphs: createParagraphApi(transport, noop),\n bookmarks: createBookmarkApi(transport, noop),\n comments: createCommentApi(transport, noop),\n revisions: createRevisionApi(transport, noop),\n tables: createTablesApi(transport, noop),\n plan(opts?: PlanOptions): WordPlan {\n const resolved: PlanOptions = {\n trackChanges: opts?.trackChanges ?? false,\n };\n if (opts?.author !== undefined) resolved.author = opts.author;\n if (opts?.date !== undefined) resolved.date = opts.date;\n return new WordPlanImpl({ docId, transport, options: resolved });\n },\n };\n}\n","/**\n * script-execute —— 在 worker / inline 内执行用户脚本(04.2 §六冻结的运行时环境)。\n *\n * 入口:\n * `executeScript(kernel, code, args, timeoutMs)`\n *\n * 执行形态:\n * `new Function('doc', 'args', 'fs', wrappedBody)(doc, args, fs)`\n * wrappedBody 把用户 code 包进 async IIFE,允许顶层 await。\n *\n * 安全 / 隔离:\n * - v1 不开启沙箱;脚本能访问 worker 全局(setTimeout / fetch 等 worker 原生能力)\n * - 不暴露 require / 动态 import(由 `new Function` 隔离作用域天然不可见)\n * - 错误穿过 worker 边界时序列化(由 worker-entry 处理)\n *\n * Timeout 简化实施(v1):\n * - `timeoutMs > 0`:Promise.race 超时拒绝;**脚本本身继续运行**(setTimeout 不能终止\n * 运行中代码),Worker kill+reload 由 04.2 §四 留给后续 issue\n * - `timeoutMs === 0`:不设超时\n *\n * doc 的形态(04.2 §6.1,#159 落地):\n * - 注入与主线程 `WordDocument` **同形态**的 `doc`:`doc.paragraphs.list()` /\n * `doc.bookmarks` / `doc.comments` / `doc.revisions` / `doc.plan().xxx().apply()` /\n * `doc.docId`\n * - 不暴露旧的平铺 / kernel-direct 形态(`doc.applyPlan` / `doc.listParagraphs` 等)\n * - 不暴露 `doc.executeCode`(沙箱内递归无意义)\n * - 实现细节见 sandbox-doc.ts —— 复用 namespace 工厂与 WordPlanImpl,加一层\n * 最小 sandbox transport,直接路由到本进程 kernel\n *\n * @see docs/04.2-脚本执行-Tool设计.md §二 §六\n */\n\nimport type { Kernel } from './kernel.js';\nimport { createSandboxDoc } from './sandbox-doc.js';\n\n/**\n * 在当前线程内执行一段用户脚本,返回脚本顶层 return 的值。\n *\n * @param kernel 当前 worker / inline 的 Kernel 实例,作为脚本 `doc` 暴露\n * @param code 用户提供的 JS 源码;函数体形态(可以包含顶层 await / return)\n * @param args 传给脚本的参数,经 structured clone 过 worker 边界\n * @param timeoutMs 超时毫秒数;0 = 不超时\n * @param signal 可选 AbortSignal(#151):\n * - InlineTransport 调本函数时透传:abort 触发 → race 拒绝(主线程立即返回,\n * 但脚本仍在后台跑直到自然结束 —— inline 无 worker 可 terminate)\n * - WorkerTransport 在主线程侧用 signal 触发 \\`worker.terminate()\\`,worker 内\n * 的 executeScript 不直接收 signal(传 \\`undefined\\` 即可)\n *\n * @throws 脚本本身抛出的错误 / 语法错误 / 超时 / abort\n */\nexport async function executeScript(\n kernel: Kernel,\n code: string,\n args: Record<string, unknown> | undefined,\n timeoutMs: number,\n signal?: AbortSignal,\n): Promise<unknown> {\n // 用户 code 可能包含顶层 return / await。包进 async IIFE,\n // 既保留 return 语义也允许 await。\n const wrappedBody = `return (async () => { ${code} })()`;\n\n let scriptFn: (doc: unknown, args: unknown, fs: unknown) => Promise<unknown>;\n try {\n scriptFn = new Function('doc', 'args', 'fs', wrappedBody) as (\n doc: unknown,\n args: unknown,\n fs: unknown,\n ) => Promise<unknown>;\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n throw new Error(`script syntax error: ${msg}`);\n }\n\n // doc = 与主线程 WordDocument 同形态的 facade(#159);见 sandbox-doc.ts。\n // fs 在 worker 内**不**注入(04.2 §6.1:\"仅当宿主注入时存在\",worker 边界外的\n // FileSystemPort 在 v1 内不跨边界传递 —— 主线程 plugin 的 fs 在加载脚本前已用过)。\n const doc = createSandboxDoc(kernel);\n const scriptPromise = (async () => scriptFn(doc, args, undefined))();\n\n // 提前触发的 abort:不启动脚本(实际上脚本已构造但 race 立即拒绝)\n if (signal?.aborted) {\n throw new Error('script aborted');\n }\n\n // 收集需要 race 的 promises:scriptPromise / timeout / abort\n const racers: Promise<unknown>[] = [scriptPromise];\n let timeoutHandle: ReturnType<typeof setTimeout> | undefined;\n let abortHandler: (() => void) | undefined;\n const cleanups: (() => void)[] = [];\n\n if (timeoutMs > 0) {\n racers.push(\n new Promise<never>((_, reject) => {\n timeoutHandle = setTimeout(() => {\n reject(new Error(`script timeout after ${timeoutMs}ms`));\n }, timeoutMs);\n }),\n );\n cleanups.push(() => {\n if (timeoutHandle) clearTimeout(timeoutHandle);\n });\n }\n\n if (signal) {\n racers.push(\n new Promise<never>((_, reject) => {\n abortHandler = () => reject(new Error('script aborted'));\n signal.addEventListener('abort', abortHandler, { once: true });\n }),\n );\n cleanups.push(() => {\n if (abortHandler) signal.removeEventListener('abort', abortHandler);\n });\n }\n\n try {\n return await Promise.race(racers);\n } finally {\n for (const cleanup of cleanups) cleanup();\n }\n}\n","/**\n * kernel-worker-shared —— Worker bootstrap 的环境无关核心。\n *\n * Node `worker_threads` 与浏览器 `Worker` 的差异只在 IO 层(`parentPort.on('message')`\n * vs `self.onmessage`,`parentPort.postMessage` vs `self.postMessage`)。本模块把 RPC\n * dispatch 抽出来,Node entry / 浏览器 entry 都注入一个 `post` 函数即可复用。\n *\n * 不在 public API 暴露,仅供 `kernel-worker-entry.ts`(Node)/`kernel-worker-browser-entry.ts`\n * 引用。\n */\nimport { WORD_CHANGE_EVENT } from './change-events.js';\nimport { Kernel } from './kernel.js';\nimport { kernelHandlers, type KernelMethod } from './kernel-handlers.js';\nimport type {\n RpcError,\n RpcEvent,\n RpcMessage,\n RpcProgress,\n RpcRequest,\n RpcResponse,\n SerializableError,\n} from './rpc-protocol.js';\nimport { executeScript } from './script-execute.js';\nimport { WordError } from './word-error.js';\n\n/** 独立 RPC method —— 不进 KernelMethod 联合(04.2 §六)。 */\nconst SCRIPT_EXECUTE_METHOD = 'script.execute';\n\n/** 由调用方注入,把消息回投给主线程。 */\nexport type PostFn = (data: unknown) => void;\n\n/**\n * 创建一个 dispatcher 闭包,内部持单例 Kernel。每次收到 raw 消息调用即可。\n *\n * 调用方负责:\n * - 用环境对应的事件机制把 raw 消息送进来\n * - 提供 `post` 把 dispatcher 产出的 response/error/progress 回投给主线程\n */\nexport function createKernelDispatcher(post: PostFn): (raw: unknown) => Promise<void> {\n const kernel = new Kernel();\n\n // 把 worker 内的 change 事件 post 到主线程,主线程 WorkerTransport.handleIncoming\n // 在 RpcEvent 分支里 fan-out 给 WordDocument 的订阅者。每次 worker 实例只挂一次,\n // worker 生命周期内不取消(dispatcher 自身没有 dispose 入口;worker terminate 时\n // kernel 引用也释放,listener 不再被调用)。\n kernel.onChange((ev) => {\n post({ kind: 'event', event: WORD_CHANGE_EVENT, payload: ev } satisfies RpcEvent);\n });\n\n return async function dispatch(raw: unknown): Promise<void> {\n // 防御 host 投来非 RpcMessage 的 garbage(主线程库 bug / 浏览器 worker 兼容性消息等)\n if (raw === null || typeof raw !== 'object') return;\n const msg = raw as RpcMessage;\n if (msg.kind !== 'request') return;\n const req = msg as RpcRequest;\n\n // script.execute 走独立分支(04.2 §六),不进 kernelHandlers\n if (req.method === SCRIPT_EXECUTE_METHOD) {\n try {\n const [code, args, timeoutMs] = req.args as [\n string,\n Record<string, unknown> | undefined,\n number,\n ];\n const result = await executeScript(kernel, code, args, timeoutMs);\n post({ kind: 'response', id: req.id, result } satisfies RpcResponse);\n } catch (e) {\n post({ kind: 'error', id: req.id, error: serializeError(e) } satisfies RpcError);\n }\n return;\n }\n\n const handler = kernelHandlers[req.method as KernelMethod];\n if (!handler) {\n post({\n kind: 'error',\n id: req.id,\n error: { message: `unknown kernel method: ${req.method}` },\n } satisfies RpcError);\n return;\n }\n\n try {\n const result = await handler(\n {\n kernel,\n onProgress: (phase, pct) => {\n post({ kind: 'progress', id: req.id, phase, pct } satisfies RpcProgress);\n },\n },\n req.args,\n );\n post({ kind: 'response', id: req.id, result } satisfies RpcResponse);\n } catch (e) {\n post({ kind: 'error', id: req.id, error: serializeError(e) } satisfies RpcError);\n }\n };\n}\n\nexport function serializeError(e: unknown): SerializableError {\n if (e instanceof WordError) {\n return {\n code: e.code,\n message: e.message,\n docId: e.docId,\n details: e.details,\n name: e.name,\n };\n }\n const err = e as Error | null | undefined;\n return {\n message: err?.message ?? String(e),\n name: err?.name,\n stack: err?.stack,\n };\n}\n","/**\n * kernel-worker-browser-entry —— Worker 的启动 bootstrap(浏览器 `Worker` 场景)。\n *\n * tsup 单独打成 `dist/kernel-worker-browser.{js,cjs}`。消费方在主线程用 `new Worker(url,\n * { type: 'module' })` 加载,通过 `WordDocument.setWorkerFactory()` 注入到 SDK。\n *\n * 与 Node entry 唯一区别在 IO 层:`self.onmessage` / `self.postMessage`。dispatch 逻辑、\n * Kernel 单例、错误序列化全部走 `kernel-worker-shared.ts`。\n *\n * 运行时基线:WPS Chromium 104(项目最低支持版本)。不依赖 Chrome 105+ 新 API。\n */\nimport { createKernelDispatcher } from './kernel-worker-shared.js';\n\n// `self` 在 DedicatedWorkerGlobalScope 里就是 worker 自身;不在 worker 上下文则报错\n// (例如有人在主线程误 import 这个 entry)。\nconst ctx = self as unknown as DedicatedWorkerGlobalScope;\nif (typeof ctx.postMessage !== 'function' || typeof ctx.addEventListener !== 'function') {\n throw new Error('kernel-worker-browser-entry must run inside a DedicatedWorkerGlobalScope');\n}\n\nconst dispatch = createKernelDispatcher((data) => {\n ctx.postMessage(data);\n});\n\nctx.addEventListener('message', (e: MessageEvent): void => {\n void dispatch(e.data);\n});\n"],"mappings":"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AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAC1F;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAC1F;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAC1F;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAC1F;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAC1F;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAC1F;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAC1F;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAC1F;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAC1F;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAC1F;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAC1F;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAC1F;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAC1F;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAC1F;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAC1F;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAC1F;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAC1F;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAC1F;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAC1F;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAC1F;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAC1F;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAC1F;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAC1F;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAC1F;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAC1F;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAC1F;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAC1F;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAC1F;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAC1F;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAC1F;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAC1F;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAC1F;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAC1F;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAC1F;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAC1F;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAC1F;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAC1F;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAC1F;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAC1F;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAC1F;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAC1F;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAC1F;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAC1F;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAC1F;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAC1F;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAC1F;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAC1F;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAC1F;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAC1F;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAC1F;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAC1F;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAC1F;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AACtC,CAAC;;;ADrBM,IAAM,yBAAyB;AAE/B,IAAM,mBAAmB;AAEzB,IAAM,0BACX;AAGK,IAAM,oBAAoB;AAEjC,IAAMC,sBAAqB;AAC3B,IAAMC,oBAAmB;AACzB,IAAMC,WAAU;AAWT,SAAS,2BAA2B,KAAuB;AAChE,MAAI,QAAQ,KAAK,sBAAsB,EAAG,QAAO;AACjD,QAAM,OAAO,iBAAiB;AAAA,IAC5B,MAAM;AAAA,IACN,aAAa;AAAA,IACb,OAAO;AAAA;AAAA,EAET,CAAC;AACD,UAAQ,KAAK,IAAI;AAEjB,YAAU,IAAI;AACd,SAAO;AACT;AAZgB;AAuBT,SAAS,qBAAqB,KAAuB;AAjF5D;AAkFE,QAAM,SAAS,QAAQ,KAAKF,mBAAkB;AAC9C,MAAI,CAAC,UAAU,CAAC,UAAU,MAAM,KAAK,CAAC,OAAO,OAAQ,QAAO;AAE5D,QAAM,MAAM,OAAO;AAGnB,QAAM,WAAW,IAAI,uBAAuBC,mBAAkB,SAAS;AACvE,WAAS,IAAI,GAAG,IAAI,SAAS,QAAQ,KAAK;AACxC,UAAI,cAAS,CAAC,EAAG,aAAa,WAAW,MAArC,mBAAwC,mBAAkB,MAAO,QAAO;AAAA,EAC9E;AAGA,QAAM,YAAY,IAAI,uBAAuBA,mBAAkB,UAAU;AACzE,WAAS,IAAI,GAAG,IAAI,UAAU,QAAQ,KAAK;AACzC,QAAI,UAAU,CAAC,EAAG,aAAa,UAAU,MAAM,IAAI,sBAAsB,GAAI,QAAO;AAAA,EACtF;AAGA,QAAM,MAAM,IAAI,gBAAgBA,mBAAkB,SAAS;AAC3D,MAAI,aAAa,aAAa,KAAK;AACnC,MAAI,aAAa,eAAe,gBAAgB;AAChD,MAAI,gBAAgB,YAAY,GAAG;AACnC,YAAU,MAAM;AAChB,SAAO;AACT;AAzBgB;AAmCT,SAAS,2BAA2B,KAAc,cAA8B;AApHvF;AAqHE,MAAI,WAAW,QAAQ,KAAK,YAAY;AACxC,MAAI,CAAC,UAAU;AAEb,UAAM,QAAQ;AAAA,wBAAkFC,QAAO;AACvG,UAAM,MAAMC,kBAAiB,KAAK;AAClC,eAAW,cAAc;AAAA,MACvB,MAAM;AAAA,MACN,aAAa;AAAA,MACb,QAAQ;AAAA;AAAA,IAEV,CAAC;AACD,YAAQ,KAAK,QAAQ;AAAA,EACvB;AACA,MAAI,CAAC,UAAU,QAAQ,KAAK,CAAC,SAAS,QAAQ;AAC5C,UAAM,IAAI,MAAM,gCAAgC,YAAY,sBAAsB;AAAA,EACpF;AAEA,QAAM,MAAM,SAAS;AACrB,QAAM,oBAAoB,iBAAiB,cAAc,sBAAsB;AAG/E,QAAM,OAAO,IAAI,uBAAuBD,UAAS,cAAc;AAC/D,MAAI,SAAS;AACb,WAAS,IAAI,GAAG,IAAI,KAAK,QAAQ,KAAK;AACpC,UAAM,IAAI,KAAK,CAAC;AAChB,UAAM,MAAK,OAAE,aAAa,IAAI,MAAnB,YAAwB;AACnC,UAAM,IAAI,aAAa,KAAK,EAAE;AAC9B,QAAI,GAAG;AACL,YAAM,IAAI,SAAS,EAAE,CAAC,GAAI,EAAE;AAC5B,UAAI,IAAI,OAAQ,UAAS;AAAA,IAC3B;AACA,QACE,EAAE,aAAa,MAAM,MAAM,2BAC3B,iBAAgB,OAAE,aAAa,QAAQ,MAAvB,YAA4B,EAAE,MAAM,mBACpD;AACA,aAAO;AAAA,IACT;AAAA,EACF;AAGA,QAAM,MAAM,MAAM,SAAS,CAAC;AAC5B,QAAM,MAAM,IAAI,gBAAgBA,UAAS,cAAc;AACvD,MAAI,aAAa,MAAM,GAAG;AAC1B,MAAI,aAAa,QAAQ,uBAAuB;AAChD,MAAI,aAAa,UAAU,iBAAiB;AAC5C,MAAI,gBAAgB,YAAY,GAAG;AACnC,YAAU,QAAQ;AAClB,SAAO;AACT;AAjDgB;AA2DT,SAASE,kBAAiB,cAAsB,QAAwB;AAC7E,MAAI,IAAI,OAAO,KAAK;AACpB,MAAI,EAAE,WAAW,GAAG,EAAG,QAAO,EAAE,MAAM,CAAC;AACvC,SAAO,EAAE,WAAW,IAAI,EAAG,KAAI,EAAE,MAAM,CAAC;AACxC,QAAM,OAAO,kBAAkB,YAAY;AAC3C,MAAI,SAAS,GAAI,QAAO;AAExB,MAAI,YAAY,KAAK,MAAM,GAAG,EAAE,OAAO,OAAO;AAC9C,SAAO,EAAE,WAAW,KAAK,GAAG;AAC1B,gBAAY,UAAU,MAAM,GAAG,EAAE;AACjC,QAAI,EAAE,MAAM,CAAC;AAAA,EACf;AACA,SAAO,UAAU,WAAW,IAAI,IAAI,GAAG,UAAU,KAAK,GAAG,CAAC,IAAI,CAAC;AACjE;AAbgB,OAAAA,mBAAA;AAsBT,SAAS,qBAAqB,KAAc,WAA2B;AAC5E,MAAI,QAAQ;AACZ,aAAW,QAAQ,UAAU,GAAG,GAAG;AACjC,QAAI,CAAC,UAAU,IAAI,KAAK,CAAC,KAAK,OAAQ;AACtC,QAAI,CAAC,KAAK,KAAK,SAAS,OAAO,EAAG;AAClC,UAAM,OAAO,KAAK,OAAO,uBAAuBF,UAAS,cAAc;AACvE,aAAS,IAAI,GAAG,IAAI,KAAK,QAAQ,KAAK;AACpC,YAAM,SAAS,KAAK,CAAC,EAAG,aAAa,QAAQ;AAC7C,UAAI,CAAC,OAAQ;AACb,UAAIE,kBAAiB,KAAK,MAAM,MAAM,MAAM,UAAW;AAAA,IACzD;AAAA,EACF;AACA,SAAO;AACT;AAbgB;AAoBT,SAAS,sBAAsB,KAAc,YAAwC;AAC1F,QAAM,UAAoB,CAAC;AAC3B,aAAW,QAAQ,YAAY;AAC7B,UAAM,OAAO,QAAQ,KAAK,IAAI;AAC9B,QAAI,CAAC,KAAM;AACX,QAAI,CAAC,aAAa,IAAI,EAAG;AACzB,QAAI,qBAAqB,KAAK,IAAI,IAAI,EAAG;AACzC,eAAW,KAAK,IAAI;AACpB,YAAQ,KAAK,IAAI;AAAA,EACnB;AACA,SAAO;AACT;AAXgB;AA0BhB,SAAS,iBAAiB,cAAsB,gBAAgC;AAI9E,QAAM,UAAU,kBAAkB,YAAY;AAC9C,MAAI,YAAY,GAAI,QAAO;AAC3B,MAAI,eAAe,WAAW,GAAG,OAAO,GAAG,GAAG;AAC5C,WAAO,eAAe,MAAM,QAAQ,SAAS,CAAC;AAAA,EAChD;AAGA,SAAO,IAAI,cAAc;AAC3B;AAZS;AAcT,SAAS,kBAAkB,UAA0B;AAEnD,QAAM,MAAM,SAAS,YAAY,SAAS;AAC1C,MAAI,MAAM,GAAG;AAEX,WAAO;AAAA,EACT;AACA,SAAO,SAAS,MAAM,GAAG,GAAG;AAC9B;AARS;AAWT,SAAS,gBAAgB,GAAmB;AAC1C,MAAI,IAAI,EAAE,KAAK;AACf,SAAO,EAAE,WAAW,IAAI,EAAG,KAAI,EAAE,MAAM,CAAC;AACxC,SAAO,EAAE,QAAQ,OAAO,GAAG;AAC7B;AAJS;;;AEtOT,IAAMC,WAAU;AAEhB,IAAM,0BAA0B;AAIzB,SAAS,qCACdC,MACA,IACM;AACN,MAAIA,KAAI,QAAQ,cAAc;AAC5B,UAAM,IAAI;AAAA,MACR;AAAA,MACA;AAAA,MACAA,KAAI;AAAA,MACJ,EAAE,QAAQ,iCAAiC,WAAW,GAAG,UAAU;AAAA,IACrE;AAAA,EACF;AAEA,QAAM,KAAK,eAAeA,MAAK,GAAG,WAAW,+BAA+B;AAI5E,QAAM,YAAY,iBAAiB,EAAE;AACrC,MAAI,CAAC,UAAU,WAAW;AACxB,UAAM,IAAI;AAAA,MACR;AAAA,MACA,4EACE,UAAU,MACZ;AAAA,MACAA,KAAI;AAAA,MACJ;AAAA,QACE,QAAQ;AAAA,QACR,WAAW,GAAG;AAAA,QACd,iBAAiB,UAAU;AAAA,MAC7B;AAAA,IACF;AAAA,EACF;AAGA,QAAM,QAAQ,aAAaA,KAAI,KAAK,EAAE;AACtC,MAAI,CAAC,OAAO;AACV,UAAM,IAAI;AAAA,MACR;AAAA,MACA,YAAY,GAAG,SAAS;AAAA,MACxBA,KAAI;AAAA,MACJ,EAAE,WAAW,GAAG,WAAW,QAAQ,gCAAgC;AAAA,IACrE;AAAA,EACF;AACA,QAAM,WAAW,QAAQA,KAAI,KAAK,MAAM,QAAQ;AAChD,MAAI,CAAC,YAAY,CAAC,UAAU,QAAQ,GAAG;AACrC,UAAM,IAAI;AAAA,MACR;AAAA,MACA,eAAe,MAAM,QAAQ;AAAA,MAC7BA,KAAI;AAAA,MACJ,EAAE,WAAW,GAAG,WAAW,UAAU,MAAM,SAAS;AAAA,IACtD;AAAA,EACF;AACA,QAAM,WAAWC,aAAY,MAAM,QAAQ;AAI3C,QAAM,QAAQC,UAAS,GAAG,uBAAuB,MAAM,MAAM,CAAC;AAC9D,MAAI,MAAM,WAAW,GAAG;AACtB,UAAM,IAAI;AAAA,MACR;AAAA,MACA,YAAY,GAAG,SAAS;AAAA,MACxBF,KAAI;AAAA,MACJ,EAAE,WAAW,GAAG,WAAW,QAAQ,gCAAgC;AAAA,IACrE;AAAA,EACF;AAGA,QAAM,eAAe,2BAA2BA,KAAI,GAAG;AACvD,MAAI,aAAc,sBAAqBA,KAAI,GAAG;AAC9C,QAAM,iBAAiB,2BAA2BA,KAAI,KAAK,QAAQ;AAInE,QAAM,YAAsB,CAAC;AAC7B,aAAW,QAAQ,OAAO;AACxB,UAAM,WAAW,KAAK,eAAe,MAAM,OAAO;AAClD,UAAM,UAAU,KAAK,eAAe,MAAM,MAAM;AAChD,QAAI,SAAU,WAAU,KAAK,QAAQ;AACrC,QAAI,QAAS,WAAU,KAAK,OAAO;AAEnC,QAAI,YAAY,KAAM,MAAK,kBAAkB,MAAM,MAAM;AACzD,SAAK,eAAe,MAAM,WAAW,cAAc;AAAA,EACrD;AAGA,wBAAsB,EAAE;AAExB,YAAU,QAAQ;AAGlB,QAAM,cAAc,QAAQA,KAAI,KAAK,QAAQ;AAC7C,MAAI,eAAe,UAAU,WAAW,GAAG;AACzC,sBAAkBA,MAAK,UAAU,aAAa,UAAU,WAAW,cAAc;AAAA,EACnF;AACF;AA9FgB;AAkGT,SAAS,qBACdA,MACA,IACM;AACN,MAAIA,KAAI,QAAQ,cAAc;AAC5B,UAAM,IAAI;AAAA,MACR;AAAA,MACA;AAAA,MACAA,KAAI;AAAA,MACJ,EAAE,QAAQ,iBAAiB,WAAW,GAAG,UAAU;AAAA,IACrD;AAAA,EACF;AAEA,QAAM,KAAK,eAAeA,MAAK,GAAG,WAAW,eAAe;AAE5D,QAAM,QAAQ,aAAaA,KAAI,KAAK,EAAE;AACtC,MAAI,CAAC,OAAO;AACV,UAAM,IAAI;AAAA,MACR;AAAA,MACA,YAAY,GAAG,SAAS;AAAA,MACxBA,KAAI;AAAA,MACJ,EAAE,WAAW,GAAG,WAAW,QAAQ,gBAAgB;AAAA,IACrD;AAAA,EACF;AACA,QAAM,WAAW,QAAQA,KAAI,KAAK,MAAM,QAAQ;AAChD,MAAI,CAAC,YAAY,CAAC,UAAU,QAAQ,GAAG;AACrC,UAAM,IAAI;AAAA,MACR;AAAA,MACA,eAAe,MAAM,QAAQ;AAAA,MAC7BA,KAAI;AAAA,MACJ,EAAE,WAAW,GAAG,WAAW,UAAU,MAAM,SAAS;AAAA,IACtD;AAAA,EACF;AACA,QAAM,WAAWC,aAAY,MAAM,QAAQ;AAG3C,QAAM,mBAAmB,uBAAuB,EAAE;AAGlD,QAAM,SAAS,GAAG;AAClB,MAAI,CAAC,QAAQ;AACX,UAAM,IAAI;AAAA,MACR;AAAA,MACA,YAAY,GAAG,SAAS;AAAA,MACxBD,KAAI;AAAA,MACJ,EAAE,WAAW,GAAG,WAAW,QAAQ,gBAAgB;AAAA,IACrD;AAAA,EACF;AACA,SAAO,YAAY,EAAE;AAGrB,MACE,OAAO,aAAa,KACnB,OAAmB,iBAAiB,QACpC,OAAmB,cAAc,OAClCG,uBAAsB,MAAiB,GACvC;AACA,UAAM,QAAQ,OAAO;AACrB,QAAI,MAAO,OAAM,YAAY,MAAM;AAAA,EACrC;AAGA,EAAAH,KAAI,QAAQ,WAAW,OAAO,GAAG,SAAS;AAE1C,YAAU,QAAQ;AAGlB,QAAM,cAAc,QAAQA,KAAI,KAAK,QAAQ;AAC7C,MAAI,eAAe,UAAU,WAAW,GAAG;AACzC,sBAAkBA,MAAK,UAAU,aAAa,UAAU,kBAAkB,EAAE;AAAA,EAC9E;AACF;AAvEgB;AA2ET,SAAS,6BACdA,MACA,IACM;AACN,MAAIA,KAAI,QAAQ,cAAc;AAC5B,UAAM,IAAI;AAAA,MACR;AAAA,MACA;AAAA,MACAA,KAAI;AAAA,MACJ,EAAE,QAAQ,yBAAyB,WAAW,GAAG,UAAU;AAAA,IAC7D;AAAA,EACF;AAEA,QAAM,KAAK,eAAeA,MAAK,GAAG,WAAW,uBAAuB;AAKpE,QAAM,WAAW,GAAG,uBAAuB,MAAM,aAAa;AAC9D,QAAM,OAAO,SAAS,SAAS,IAAK,SAAS,CAAC,IAAgB;AAC9D,MAAI,CAAC,MAAM;AAET,UAAM,YAAY,iBAAiB,EAAE;AACrC,UAAM,OAAO,UAAU,YACnB,4DACA;AACJ,UAAM,IAAI;AAAA,MACR;AAAA,MACA,0GAA0G,IAAI;AAAA,MAC9GA,KAAI;AAAA,MACJ,EAAE,QAAQ,yBAAyB,WAAW,GAAG,WAAW,KAAK;AAAA,IACnE;AAAA,EACF;AAGA,QAAM,QAAQ,aAAaA,KAAI,KAAK,EAAE;AACtC,MAAI,CAAC,OAAO;AACV,UAAM,IAAI;AAAA,MACR;AAAA,MACA,YAAY,GAAG,SAAS;AAAA,MACxBA,KAAI;AAAA,MACJ,EAAE,WAAW,GAAG,WAAW,QAAQ,wBAAwB;AAAA,IAC7D;AAAA,EACF;AACA,QAAM,WAAW,QAAQA,KAAI,KAAK,MAAM,QAAQ;AAChD,MAAI,CAAC,YAAY,CAAC,UAAU,QAAQ,GAAG;AACrC,UAAM,IAAI;AAAA,MACR;AAAA,MACA,eAAe,MAAM,QAAQ;AAAA,MAC7BA,KAAI;AAAA,MACJ,EAAE,WAAW,GAAG,WAAW,UAAU,MAAM,SAAS;AAAA,IACtD;AAAA,EACF;AACA,QAAM,WAAWC,aAAY,MAAM,QAAQ;AAI3C,QAAM,mBAAmB,uBAAuB,IAAI;AACpD,QAAM,aAAaC,UAAS,KAAK,uBAAuB,MAAM,GAAG,CAAC,EAC/D,IAAI,CAACE,OAAMA,GAAE,eAAe,QAAQ,QAAQ,CAAC,EAC7C,OAAO,CAAC,OAAqB,QAAQ,EAAE,CAAC;AAG3C,QAAM,SAASC,mBAAkB,MAAM,GAAG;AAC1C,QAAM,WAAW,SAASA,mBAAkB,QAAQ,KAAK,IAAI;AAS7D,QAAM,cAAc,gBAAgB,0BAAU,IAAI;AAGlD,SAAO,KAAK,WAAY,MAAK,YAAY,KAAK,UAAU;AACxD,aAAW,MAAM,WAAY,CAAAL,KAAI,QAAQ,QAAQ,OAAO,GAAG,YAAY,CAAC;AAGxE,QAAM,MAAM,KAAK;AACjB,QAAM,IAAI,QAAQ,KAAK,GAAG;AAC1B,QAAM,YAAY,eAAe,IAAI,IAAIA,KAAI,QAAQ,QAAQ,KAAK,CAAC,CAAC;AACpE,IAAE,eAAe,QAAQ,cAAc,SAAS;AAChD,MAAI,SAAU,GAAE,YAAY,SAAS,UAAU,IAAI,CAAC;AACpD,QAAM,IAAI,QAAQ,KAAK,GAAG;AAE1B,MAAI,YAAa,GAAE,YAAY,WAAW;AAC1C,IAAE,YAAY,QAAQ,KAAK,GAAG,WAAW,CAAC;AAC1C,IAAE,YAAY,CAAC;AACf,OAAK,YAAY,CAAC;AAClB,EAAAA,KAAI,QAAQ,QAAQ,IAAI,WAAW,CAAC;AAEpC,YAAU,QAAQ;AAGlB,QAAM,cAAc,QAAQA,KAAI,KAAK,QAAQ;AAC7C,MAAI,eAAe,UAAU,WAAW,GAAG;AACzC,sBAAkBA,MAAK,UAAU,aAAa,UAAU,kBAAkB,EAAE;AAAA,EAC9E;AACF;AApGgB;AAwGhB,SAAS,eAAeA,MAAsB,WAAmB,QAAyB;AACxF,QAAM,KAAKA,KAAI,QAAQ,WAAW,IAAI,SAAS;AAC/C,MAAI,CAAC,IAAI;AACP,UAAM,IAAI;AAAA,MACR;AAAA,MACA,2BAA2B,SAAS,oBAAoB,MAAM;AAAA,MAC9DA,KAAI;AAAA,MACJ,EAAE,WAAW,OAAO;AAAA,IACtB;AAAA,EACF;AACA,SAAO;AACT;AAXS;AAaT,SAASE,UAA4B,KAAkD;AACrF,QAAM,MAAW,CAAC;AAClB,WAAS,IAAI,GAAG,IAAI,IAAI,QAAQ,KAAK;AACnC,UAAM,KAAK,IAAI,CAAC;AAChB,QAAI,GAAI,KAAI,KAAK,EAAE;AAAA,EACrB;AACA,SAAO;AACT;AAPS,OAAAA,WAAA;AAkBT,SAAS,iBAAiB,SAA0D;AAElF,MAAI,YAA4B;AAChC,WAAS,IAAI,GAAG,IAAI,QAAQ,WAAW,QAAQ,KAAK;AAClD,UAAM,IAAI,QAAQ,WAAW,CAAC;AAC9B,QAAI,CAAC,KAAK,EAAE,aAAa,EAAG;AAC5B,UAAM,KAAK;AACX,QAAI,GAAG,iBAAiB,UAAU,GAAG,cAAc,YAAY,GAAG,cAAc,WAAW;AACzF,kBAAY;AACZ;AAAA,IACF;AAAA,EACF;AACA,MAAI,CAAC,UAAW,QAAO,EAAE,WAAW,OAAO,QAAQ,uCAAuC;AAG1F,QAAM,UAAU,aAAa,WAAW,MAAM,SAAS;AACvD,MAAI,CAAC,QAAS,QAAO,EAAE,WAAW,OAAO,QAAQ,2BAA2B;AAC5E,QAAM,cAAc,aAAa,SAAS,MAAM,aAAa;AAC7D,MAAI,CAAC,YAAa,QAAO,EAAE,WAAW,OAAO,QAAQ,+BAA+B;AAEpF,QAAM,MAAM,YAAY,aAAa,KAAK;AAC1C,MAAI,QAAQ,yBAAyB;AACnC,WAAO,EAAE,WAAW,OAAO,QAAQ,yCAAyC,oBAAO,EAAE,KAAK;AAAA,EAC5F;AAGA,QAAM,MAAM,aAAa,aAAa,QAAQ,KAAK;AACnD,MAAI,CAAC;AACH,WAAO,EAAE,WAAW,OAAO,QAAQ,sDAAsD;AAE3F,SAAO,EAAE,WAAW,MAAM,QAAQ,UAAU;AAC9C;AA/BS;AAiCT,SAAS,aAAa,QAAiB,IAAY,OAA+B;AAChF,WAAS,IAAI,GAAG,IAAI,OAAO,WAAW,QAAQ,KAAK;AACjD,UAAM,IAAI,OAAO,WAAW,CAAC;AAC7B,QAAI,CAAC,KAAK,EAAE,aAAa,EAAG;AAC5B,UAAM,KAAK;AACX,QAAI,GAAG,iBAAiB,MAAM,GAAG,cAAc,MAAO,QAAO;AAAA,EAC/D;AACA,SAAO;AACT;AARS;AAkBT,SAAS,sBAAsB,SAAwB;AACrD,WAAS,IAAI,GAAG,IAAI,QAAQ,WAAW,QAAQ,KAAK;AAClD,UAAM,IAAI,QAAQ,WAAW,CAAC;AAC9B,QAAI,CAAC,KAAK,EAAE,aAAa,EAAG;AAC5B,UAAM,YAAY;AAClB,QAAI,UAAU,iBAAiB,MAAO;AACtC,QAAI,UAAU,cAAc,YAAY,UAAU,cAAc,SAAU;AAC1E,UAAM,QAAQ,aAAa,WAAW,OAAO,OAAO;AACpD,QAAI,CAAC,MAAO;AACZ,UAAM,aAAa,SAAS,iBAAiB;AAC7C,UAAM,aAAa,SAAS,iBAAiB;AAC7C;AAAA,EACF;AACF;AAbS;AAsBT,SAASD,aAAY,UAA0B;AAC7C,QAAM,MAAM,SAAS,YAAY,GAAG;AACpC,MAAI,MAAM,EAAG,QAAO,SAAS,QAAQ;AACrC,QAAM,MAAM,SAAS,MAAM,GAAG,GAAG;AACjC,QAAM,OAAO,SAAS,MAAM,MAAM,CAAC;AACnC,SAAO,GAAG,GAAG,UAAU,IAAI;AAC7B;AANS,OAAAA,cAAA;AAyBT,SAAS,kBACPD,MACA,UACA,UACA,UACA,WACA,WACM;AAzcR;AA0cE,MAAI,UAAU,WAAW,EAAG;AAC5B,MAAI,CAAC,SAAS,UAAU,CAAC,SAAS,OAAQ;AAE1C,QAAM,YAAY,IAAI,IAAI,UAAU,OAAO,CAAC,OAAO,MAAM,OAAO,SAAS,CAAC;AAC1E,MAAI,UAAU,SAAS,EAAG;AAI1B,QAAM,eAAyB,CAAC;AAChC,aAAW,SAAS,WAAW;AAC7B,QAAI,kBAAkB,SAAS,QAAQ,KAAK,MAAM,EAAG,cAAa,KAAK,KAAK;AAAA,EAC9E;AACA,MAAI,aAAa,WAAW,EAAG;AAG/B,QAAM,OAAOE,UAAS,SAAS,OAAO,uBAAuBH,UAAS,cAAc,CAAC;AACrF,MAAI,cAAc;AAClB,aAAW,OAAO,MAAM;AACtB,UAAM,MAAK,SAAI,aAAa,IAAI,MAArB,YAA0B;AACrC,QAAI,CAAC,aAAa,SAAS,EAAE,EAAG;AAChC,UAAM,UAAS,SAAI,aAAa,QAAQ,MAAzB,YAA8B;AAC7C,QAAI,UAAUC,KAAI,uBAAuB;AACvC,YAAM,YAAYM,kBAAiB,UAAU,MAAM;AACnD,MAAAN,KAAI,sBAAsB,IAAI,SAAS;AAAA,IACzC;AACA,cAAI,eAAJ,mBAAgB,YAAY;AAC5B,kBAAc;AAAA,EAChB;AACA,MAAI,aAAa;AACf,UAAM,KAAK,QAAQA,KAAI,KAAK,QAAQ;AACpC,QAAI,GAAI,WAAU,EAAE;AAAA,EACtB;AACF;AAxCS;AAiDT,SAAS,kBAAkB,KAAe,OAAuB;AAC/D,MAAI,QAAQ;AACZ,QAAM,MAAM,IAAI,qBAAqB,GAAG;AACxC,WAAS,IAAI,GAAG,IAAI,IAAI,QAAQ,KAAK;AACnC,UAAM,KAAK,IAAI,CAAC;AAChB,QAAI,CAAC,GAAI;AACT,QAAI,GAAG,eAAe,MAAM,OAAO,MAAM,MAAO;AAChD,QAAI,GAAG,eAAe,MAAM,MAAM,MAAM,MAAO;AAC/C,QAAI,GAAG,eAAe,MAAM,IAAI,MAAM,MAAO;AAAA,EAC/C;AACA,SAAO;AACT;AAXS;AAsBT,SAAS,uBAAuB,SAA4B;AAC1D,QAAM,MAAM,oBAAI,IAAY;AAC5B,QAAM,MAAM,QAAQ,qBAAqB,GAAG;AAC5C,WAAS,IAAI,GAAG,IAAI,IAAI,QAAQ,KAAK;AACnC,UAAM,KAAK,IAAI,CAAC;AAChB,QAAI,CAAC,GAAI;AACT,UAAM,QAAQ,GAAG,eAAe,MAAM,OAAO;AAC7C,QAAI,MAAO,KAAI,IAAI,KAAK;AACxB,UAAM,OAAO,GAAG,eAAe,MAAM,MAAM;AAC3C,QAAI,KAAM,KAAI,IAAI,IAAI;AACtB,UAAM,MAAM,GAAG,eAAe,MAAM,IAAI;AACxC,QAAI,IAAK,KAAI,IAAI,GAAG;AAAA,EACtB;AACA,SAAO,CAAC,GAAG,GAAG;AAChB;AAdS;AAsBT,SAASG,uBAAsB,KAAuB;AACpD,WAAS,IAAI,GAAG,IAAI,IAAI,WAAW,QAAQ,KAAK;AAC9C,UAAM,IAAI,IAAI,WAAW,CAAC;AAC1B,QAAI,CAAC,KAAK,EAAE,aAAa,EAAG;AAC5B,UAAM,KAAK;AACX,QAAI,GAAG,iBAAiB,QAAQ,GAAG,cAAc,MAAO;AACxD,WAAO;AAAA,EACT;AACA,SAAO;AACT;AATS,OAAAA,wBAAA;;;AC9gBT,SAAS,oBAAAI,yBAAwB;AAmBjC,IAAMC,WAAU;AAChB,IAAMC,sBAAqB;AAC3B,IAAMC,oBAAmB;AACzB,IAAMC,2BACJ;AAaK,IAAM,sBAA8C;AAAA,EACzD,aAAa;AAAA,EACb,cAAc;AAAA,EACd,aAAa;AAAA,EACb,aAAa;AAAA,EACb,cAAc;AAAA,EACd,eAAe;AAAA,EACf,eAAe;AACjB;AAIO,SAAS,wBACdC,MACA,IACM;AACN,MAAIA,KAAI,QAAQ,cAAc;AAC5B,UAAM,IAAI;AAAA,MACR;AAAA,MACA;AAAA,MACAA,KAAI;AAAA,MACJ,EAAE,QAAQ,mBAAmB;AAAA,IAC/B;AAAA,EACF;AAGA,QAAM,MAAM,oBAAoB,GAAG,WAAW;AAC9C,MAAI,CAAC,KAAK;AACR,UAAM,IAAI;AAAA,MACR;AAAA,MACA,8CAA8C,GAAG,WAAW;AAAA,MAC5DA,KAAI;AAAA,MACJ,EAAE,QAAQ,oBAAoB,aAAa,GAAG,YAAY;AAAA,IAC5D;AAAA,EACF;AAGA,QAAM,SAASA,KAAI,QAAQ,QAAQ,IAAI,GAAG,aAAa,YAAY,CAAC;AACpE,MAAI,CAAC,QAAQ;AACX,UAAM,IAAI;AAAA,MACR;AAAA,MACA,0BAA0B,GAAG,YAAY;AAAA,MACzCA,KAAI;AAAA,MACJ,EAAE,QAAQ,GAAG,cAAc,QAAQ,mBAAmB;AAAA,IACxD;AAAA,EACF;AACA,QAAM,QAAQ,aAAaA,KAAI,KAAK,MAAM;AAC1C,MAAI,CAAC,OAAO;AACV,UAAM,IAAI;AAAA,MACR;AAAA,MACA,qBAAqB,GAAG,YAAY;AAAA,MACpCA,KAAI;AAAA,MACJ,EAAE,QAAQ,GAAG,cAAc,QAAQ,mBAAmB;AAAA,IACxD;AAAA,EACF;AACA,QAAM,eAAe,MAAM;AAC3B,QAAM,WAAWC,aAAY,YAAY;AAGzC,QAAM,YAAY,kBAAkBD,KAAI,KAAK,GAAG;AAGhD,QAAM,YAAY,iBAAiB;AAAA,IACjC,MAAM;AAAA,IACN,aAAa,GAAG;AAAA,IAChB,OAAO,GAAG;AAAA,EACZ,CAAC;AACD,UAAQA,KAAI,KAAK,SAAS;AAC1B,YAAU,SAAS;AAGnB,QAAM,MAAM,YAAYA,KAAI,KAAK,UAAU,SAAS;AAGpD,yBAAuBA,KAAI,KAAK,KAAK,GAAG,WAAW;AAGnD,QAAM,WAAW,QAAQA,KAAI,KAAK,YAAY;AAC9C,MAAI,CAAC,YAAY,CAAC,UAAU,QAAQ,KAAK,CAAC,SAAS,QAAQ;AACzD,UAAM,IAAI;AAAA,MACR;AAAA,MACA,cAAc,YAAY;AAAA,MAC1BA,KAAI;AAAA,MACJ,EAAE,QAAQ,mBAAmB;AAAA,IAC/B;AAAA,EACF;AACA,QAAM,MAAM,SAAS;AAErB,QAAM,UAAU,gBAAgB,GAAG;AACnC,QAAM,UAAU,mBAAmB,KAAK,KAAK,SAAS,GAAG,UAAU,GAAG,SAAS;AAG/E,QAAM,OAAO,IAAI,IAAIA,KAAI,QAAQ,QAAQ,KAAK,CAAC;AAC/C,QAAM,YAAY,eAAe,IAAI;AAErC,QAAM,UAAU,IAAI,gBAAgB,MAAM,KAAK;AAC/C,UAAQ,eAAe,QAAQ,cAAc,SAAS;AACtD,QAAM,MAAM,IAAI,gBAAgB,MAAM,KAAK;AAC3C,MAAI,YAAY,OAAO;AACvB,UAAQ,YAAY,GAAG;AAGvB,QAAM,SAAS,OAAO;AACtB,MAAI,CAAC,QAAQ;AACX,UAAM,IAAI;AAAA,MACR;AAAA,MACA,qBAAqB,GAAG,YAAY;AAAA,MACpCA,KAAI;AAAA,MACJ,EAAE,QAAQ,GAAG,cAAc,QAAQ,mBAAmB;AAAA,IACxD;AAAA,EACF;AACA,SAAO,aAAa,SAAS,OAAO,WAAW;AAG/C,EAAAA,KAAI,QAAQ,QAAQ,IAAI,WAAW,OAAO;AAG1C,YAAU,QAAQ;AAClB,QAAM,WAAW,QAAQA,KAAI,KAAK,QAAQ;AAC1C,MAAI,SAAU,WAAU,QAAQ;AAChC,QAAM,SAAS,QAAQA,KAAI,KAAKH,mBAAkB;AAClD,MAAI,OAAQ,WAAU,MAAM;AAC9B;AA9GgB;AAsHT,SAAS,kBAAkB,KAAc,KAAqB;AACnE,MAAI,OAAO;AACX,aAAW,QAAQ,UAAU,GAAG,GAAG;AACjC,UAAM,IAAI,8BAA8B,KAAK,KAAK,IAAI;AACtD,QAAI,GAAG;AACL,YAAM,IAAI,SAAS,EAAE,CAAC,GAAI,EAAE;AAC5B,UAAI,IAAI,KAAM,QAAO;AAAA,IACvB;AAAA,EACF;AACA,MAAI,YAAY,mBAAmB,OAAO,CAAC,IAAI,GAAG;AAElD,SAAO,QAAQ,KAAK,SAAS,GAAG;AAC9B;AACA,gBAAY,mBAAmB,OAAO,CAAC,IAAI,GAAG;AAAA,EAChD;AACA,SAAO;AACT;AAhBgB;AAsBT,SAAS,mBAAmB,KAAc,cAAsB,WAA2B;AAChG,SAAO,YAAY,KAAK,cAAc,SAAS;AACjD;AAFgB;AAIhB,SAAS,YAAY,KAAc,cAAsB,WAA2B;AAjNpF;AAkNE,MAAI,WAAW,QAAQ,KAAK,YAAY;AACxC,MAAI,CAAC,UAAU;AACb,UAAM,QAAQ;AAAA,wBAAkFD,QAAO;AACvG,UAAM,MAAMM,kBAAiB,KAAK;AAClC,eAAW,cAAc;AAAA,MACvB,MAAM;AAAA,MACN,aAAa;AAAA,MACb,QAAQ;AAAA,IACV,CAAC;AACD,YAAQ,KAAK,QAAQ;AAAA,EACvB;AACA,MAAI,CAAC,UAAU,QAAQ,KAAK,CAAC,SAAS,QAAQ;AAC5C,UAAM,IAAI,MAAM,iBAAiB,YAAY,sBAAsB;AAAA,EACrE;AAEA,QAAM,MAAM,SAAS;AACrB,QAAM,OAAO,IAAI,uBAAuBN,UAAS,cAAc;AAC/D,MAAI,SAAS;AACb,WAAS,IAAI,GAAG,IAAI,KAAK,QAAQ,KAAK;AACpC,UAAM,MAAK,UAAK,CAAC,EAAG,aAAa,IAAI,MAA1B,YAA+B;AAC1C,UAAM,IAAI,aAAa,KAAK,EAAE;AAC9B,QAAI,GAAG;AACL,YAAM,IAAI,SAAS,EAAE,CAAC,GAAI,EAAE;AAC5B,UAAI,IAAI,OAAQ,UAAS;AAAA,IAC3B;AAAA,EACF;AAEA,QAAM,MAAM,MAAM,SAAS,CAAC;AAE5B,QAAM,SAASO,kBAAiB,cAAc,SAAS;AACvD,QAAM,MAAM,IAAI,gBAAgBP,UAAS,cAAc;AACvD,MAAI,aAAa,MAAM,GAAG;AAC1B,MAAI,aAAa,QAAQG,wBAAuB;AAChD,MAAI,aAAa,UAAU,MAAM;AACjC,MAAI,gBAAgB,YAAY,GAAG;AACnC,YAAU,QAAQ;AAClB,SAAO;AACT;AAtCS;AA4CF,SAAS,uBAAuB,KAAc,KAAa,aAA2B;AA7P7F;AA8PE,QAAM,SAAS,QAAQ,KAAKF,mBAAkB;AAC9C,MAAI,CAAC,UAAU,CAAC,UAAU,MAAM,KAAK,CAAC,OAAO,OAAQ;AACrD,QAAM,MAAM,OAAO;AAEnB,QAAM,WAAW,IAAI,uBAAuBC,mBAAkB,SAAS;AACvE,WAAS,IAAI,GAAG,IAAI,SAAS,QAAQ,KAAK;AACxC,UAAI,cAAS,CAAC,EAAG,aAAa,WAAW,MAArC,mBAAwC,mBAAkB,IAAI,YAAY,EAAG;AAAA,EACnF;AAEA,QAAM,MAAM,IAAI,gBAAgBA,mBAAkB,SAAS;AAC3D,MAAI,aAAa,aAAa,GAAG;AACjC,MAAI,aAAa,eAAe,WAAW;AAC3C,MAAI,gBAAgB,YAAY,GAAG;AACnC,YAAU,MAAM;AAClB;AAfgB;AAoBhB,SAAS,gBAAgB,KAAuB;AAC9C,QAAM,SAAS,IAAI,uBAAuB,OAAO,OAAO;AACxD,MAAI,QAAQ;AACZ,WAAS,IAAI,GAAG,IAAI,OAAO,QAAQ,KAAK;AACtC,UAAM,MAAM,OAAO,CAAC,EAAG,aAAa,IAAI;AACxC,QAAI,CAAC,IAAK;AACV,UAAM,IAAI,SAAS,KAAK,EAAE;AAC1B,QAAI,CAAC,MAAM,CAAC,KAAK,IAAI,MAAO,SAAQ;AAAA,EACtC;AACA,SAAO,QAAQ;AACjB;AAVS;AA2BT,SAAS,mBACP,KACA,KACA,SACA,UACA,WACS;AACT,QAAM,UAAU,QAAQ,OAAO;AAE/B,WAAS,GAAG,OAAe,OAAwB;AAEjD,UAAM,SAAS,WAAW,KAAK;AAC/B,WAAO,IAAI,gBAAgB,OAAO,SAAS,GAAG,MAAM,IAAI,KAAK,KAAK,KAAK;AAAA,EACzE;AAJS;AAOT,QAAM,UAAU,IAAI,gBAAgB,MAAM,WAAW;AAGrD,QAAM,SAAS,GAAG,OAAO,QAAQ;AACjC,SAAO,aAAa,SAAS,GAAG;AAChC,SAAO,aAAa,SAAS,GAAG;AAChC,SAAO,aAAa,SAAS,GAAG;AAChC,SAAO,aAAa,SAAS,GAAG;AAChC,UAAQ,YAAY,MAAM;AAG1B,QAAM,SAAS,GAAG,OAAO,QAAQ;AACjC,SAAO,aAAa,MAAM,OAAO,QAAQ,CAAC;AAC1C,SAAO,aAAa,MAAM,OAAO,SAAS,CAAC;AAC3C,SAAO,YAAY,MAAM;AAGzB,QAAM,eAAe,GAAG,OAAO,cAAc;AAC7C,eAAa,aAAa,KAAK,GAAG;AAClC,eAAa,aAAa,KAAK,GAAG;AAClC,eAAa,aAAa,KAAK,GAAG;AAClC,eAAa,aAAa,KAAK,GAAG;AAClC,SAAO,YAAY,YAAY;AAG/B,QAAM,QAAQ,GAAG,OAAO,OAAO;AAC/B,QAAM,aAAa,MAAM,OAAO,OAAO,CAAC;AACxC,QAAM,aAAa,QAAQ,OAAO;AAClC,SAAO,YAAY,KAAK;AAGxB,QAAM,SAAS,GAAG,OAAO,mBAAmB;AAC5C,QAAM,UAAU,IAAI,gBAAgB,MAAM,qBAAqB;AAC/D,UAAQ,aAAa,kBAAkB,GAAG;AAC1C,SAAO,YAAY,OAAO;AAC1B,SAAO,YAAY,MAAM;AAGzB,QAAM,UAAU,IAAI,gBAAgB,MAAM,WAAW;AACrD,QAAM,cAAc,IAAI,gBAAgB,MAAM,eAAe;AAC7D,cAAY,aAAa,OAAO,MAAM;AACtC,UAAQ,YAAY,WAAW;AAC/B,SAAO,YAAY,OAAO;AAG1B,QAAM,MAAM,IAAI,gBAAgB,QAAQ,SAAS;AACjD,cAAY,YAAY,GAAG;AAG3B,QAAM,UAAU,IAAI,gBAAgB,QAAQ,aAAa;AACzD,MAAI,YAAY,OAAO;AAEvB,QAAM,QAAQ,IAAI,gBAAgB,QAAQ,WAAW;AACrD,QAAM,aAAa,MAAM,OAAO,OAAO,CAAC;AACxC,QAAM,aAAa,QAAQ,OAAO;AAClC,UAAQ,YAAY,KAAK;AAEzB,QAAM,WAAW,IAAI,gBAAgB,QAAQ,cAAc;AAC3D,QAAM,WAAW,IAAI,gBAAgB,MAAM,YAAY;AACvD,WAAS,aAAa,kBAAkB,GAAG;AAC3C,WAAS,YAAY,QAAQ;AAC7B,UAAQ,YAAY,QAAQ;AAG5B,QAAM,WAAW,IAAI,gBAAgB,QAAQ,cAAc;AAC3D,MAAI,YAAY,QAAQ;AAExB,QAAM,OAAO,IAAI,gBAAgB,MAAM,QAAQ;AAC/C,OAAK,eAAe,MAAM,WAAW,GAAG;AACxC,WAAS,YAAY,IAAI;AAEzB,QAAM,UAAU,IAAI,gBAAgB,MAAM,WAAW;AACrD,QAAM,WAAW,IAAI,gBAAgB,MAAM,YAAY;AACvD,UAAQ,YAAY,QAAQ;AAC5B,WAAS,YAAY,OAAO;AAG5B,QAAM,OAAO,IAAI,gBAAgB,QAAQ,UAAU;AACnD,MAAI,YAAY,IAAI;AAEpB,QAAM,OAAO,IAAI,gBAAgB,MAAM,QAAQ;AAC/C,QAAM,MAAM,IAAI,gBAAgB,MAAM,OAAO;AAC7C,MAAI,aAAa,KAAK,GAAG;AACzB,MAAI,aAAa,KAAK,GAAG;AACzB,OAAK,YAAY,GAAG;AACpB,QAAM,QAAQ,IAAI,gBAAgB,MAAM,OAAO;AAC/C,QAAM,aAAa,MAAM,OAAO,QAAQ,CAAC;AACzC,QAAM,aAAa,MAAM,OAAO,SAAS,CAAC;AAC1C,OAAK,YAAY,KAAK;AACtB,OAAK,YAAY,IAAI;AAErB,QAAM,WAAW,IAAI,gBAAgB,MAAM,YAAY;AACvD,WAAS,aAAa,QAAQ,MAAM;AACpC,QAAM,QAAQ,IAAI,gBAAgB,MAAM,SAAS;AACjD,WAAS,YAAY,KAAK;AAC1B,OAAK,YAAY,QAAQ;AAEzB,SAAO;AACT;AAlHS;AAqHT,SAAS,WAAW,OAAuB;AACzC,MAAI,UAAU,MAAO,QAAO;AAC5B,MAAI,UAAU,KAAM,QAAO;AAC3B,MAAI,UAAU,OAAQ,QAAO;AAC7B,MAAI,UAAU,KAAM,QAAO;AAC3B,SAAO;AACT;AANS;AAYT,SAASK,kBAAiB,cAAsB,gBAAgC;AAC9E,QAAM,MAAM,aAAa,YAAY,SAAS;AAC9C,MAAI,MAAM,EAAG,QAAO;AACpB,QAAM,UAAU,aAAa,MAAM,GAAG,GAAG;AACzC,MAAI,eAAe,WAAW,GAAG,OAAO,GAAG,GAAG;AAC5C,WAAO,eAAe,MAAM,QAAQ,SAAS,CAAC;AAAA,EAChD;AACA,SAAO,IAAI,cAAc;AAC3B;AARS,OAAAA,mBAAA;AAcT,SAASF,aAAY,UAA0B;AAC7C,QAAM,MAAM,SAAS,YAAY,GAAG;AACpC,MAAI,MAAM,EAAG,QAAO,SAAS,QAAQ;AACrC,QAAM,MAAM,SAAS,MAAM,GAAG,GAAG;AACjC,QAAM,OAAO,SAAS,MAAM,MAAM,CAAC;AACnC,SAAO,GAAG,GAAG,UAAU,IAAI;AAC7B;AANS,OAAAA,cAAA;AAoBF,SAAS,kBACd,KACA,SACA,WACyB;AAnd3B;AAqdE,QAAM,KAAK,QAAQ,WAAW,IAAI,SAAS;AAC3C,MAAI,CAAC,GAAI,QAAO;AAGhB,QAAM,QAAQ,GAAG,uBAAuB,MAAM,MAAM;AACpD,MAAI,MAAM,WAAW,EAAG,QAAO;AAC/B,QAAM,OAAO,MAAM,CAAC;AACpB,QAAM,MAAM,KAAK,eAAe,MAAM,OAAO;AAC7C,MAAI,CAAC,IAAK,QAAO;AAGjB,QAAM,QAAQ,aAAa,KAAK,EAAE;AAClC,MAAI,CAAC,MAAO,QAAO;AACnB,QAAM,eAAe,MAAM;AAG3B,QAAM,WAAWA,aAAY,YAAY;AAGzC,QAAM,WAAW,QAAQ,KAAK,QAAQ;AACtC,MAAI,CAAC,YAAY,CAAC,UAAU,QAAQ,KAAK,CAAC,SAAS,OAAQ,QAAO;AAClE,QAAM,OAAO,SAAS,OAAO,uBAAuBL,UAAS,cAAc;AAC3E,MAAI,YAA2B;AAC/B,WAAS,IAAI,GAAG,IAAI,KAAK,QAAQ,KAAK;AACpC,UAAM,IAAI,KAAK,CAAC;AAChB,QAAI,EAAE,aAAa,IAAI,MAAM,KAAK;AAChC,YAAM,UAAS,OAAE,aAAa,QAAQ,MAAvB,YAA4B;AAE3C,kBAAY,cAAc,UAAU,MAAM;AAC1C;AAAA,IACF;AAAA,EACF;AACA,MAAI,CAAC,UAAW,QAAO;AAGvB,QAAM,YAAY,QAAQ,KAAK,SAAS;AACxC,MAAI,CAAC,UAAW,QAAO;AAEvB,QAAM,QAAS,UAAgD;AAC/D,MAAI,CAAC,MAAO,QAAO;AACnB,QAAM,cAAc,UAAU;AAG9B,QAAM,YAAY,kBAAkB,EAAE;AAEtC,SAAO,EAAE,OAAO,aAAa,UAAU;AACzC;AApDgB;AAuDhB,SAAS,kBAAkB,SAA8C;AAtgBzE;AAugBE,WAAS,IAAI,GAAG,IAAI,QAAQ,WAAW,QAAQ,KAAK;AAClD,UAAM,IAAI,QAAQ,WAAW,CAAC;AAC9B,QAAI,CAAC,KAAK,EAAE,aAAa,EAAG;AAC5B,QAAI,EAAE,iBAAiB,MAAO;AAC9B,QAAI,EAAE,cAAc,YAAY,EAAE,cAAc,SAAU;AAE1D,aAAS,IAAI,GAAG,IAAI,EAAE,WAAW,QAAQ,KAAK;AAC5C,YAAM,MAAM,EAAE,WAAW,CAAC;AAC1B,UAAI,CAAC,OAAO,IAAI,aAAa,EAAG;AAChC,UAAI,IAAI,iBAAiB,SAAS,IAAI,cAAc,UAAU;AAC5D,cAAM,KAAK,UAAS,SAAI,aAAa,IAAI,MAArB,YAA0B,KAAK,EAAE;AACrD,cAAM,KAAK,UAAS,SAAI,aAAa,IAAI,MAArB,YAA0B,KAAK,EAAE;AACrD,eAAO,EAAE,IAAI,MAAM,EAAE,IAAI,IAAI,IAAI,IAAI,MAAM,EAAE,IAAI,IAAI,GAAG;AAAA,MAC1D;AAAA,IACF;AAAA,EACF;AACA,SAAO,EAAE,IAAI,GAAG,IAAI,EAAE;AACxB;AAlBS;AAqBT,SAAS,cAAc,cAAsB,QAAwB;AACnE,MAAI,IAAI,OAAO,KAAK;AACpB,MAAI,EAAE,WAAW,GAAG,EAAG,QAAO,EAAE,MAAM,CAAC;AACvC,SAAO,EAAE,WAAW,IAAI,EAAG,KAAI,EAAE,MAAM,CAAC;AACxC,QAAM,MAAM,aAAa,YAAY,SAAS;AAC9C,MAAI,MAAM,EAAG,QAAO;AACpB,QAAM,UAAU,aAAa,MAAM,GAAG,GAAG;AAEzC,MAAI,QAAQ,QAAQ,MAAM,GAAG,EAAE,OAAO,OAAO;AAC7C,SAAO,EAAE,WAAW,KAAK,GAAG;AAC1B,YAAQ,MAAM,MAAM,GAAG,EAAE;AACzB,QAAI,EAAE,MAAM,CAAC;AAAA,EACf;AACA,SAAO,MAAM,WAAW,IAAI,IAAI,GAAG,MAAM,KAAK,GAAG,CAAC,IAAI,CAAC;AACzD;AAdS;;;AC9fT,SAAS,wBAAwB;AA0B1B,SAAS,uBACdQ,MACA,IACM;AA1DR;AA2DE,MAAIA,KAAI,QAAQ,cAAc;AAC5B,UAAM,IAAI;AAAA,MACR;AAAA,MACA;AAAA,MACAA,KAAI;AAAA,MACJ,EAAE,QAAQ,kBAAkB;AAAA,IAC9B;AAAA,EACF;AAGA,QAAM,SAASA,KAAI,QAAQ,QAAQ,IAAI,GAAG,aAAa,YAAY,CAAC;AACpE,MAAI,CAAC,QAAQ;AACX,UAAM,IAAI;AAAA,MACR;AAAA,MACA,0BAA0B,GAAG,YAAY;AAAA,MACzCA,KAAI;AAAA,MACJ,EAAE,QAAQ,GAAG,cAAc,QAAQ,kBAAkB;AAAA,IACvD;AAAA,EACF;AACA,QAAM,SAAS,OAAO;AACtB,MAAI,CAAC,QAAQ;AACX,UAAM,IAAI;AAAA,MACR;AAAA,MACA,qBAAqB,GAAG,YAAY;AAAA,MACpCA,KAAI;AAAA,MACJ,EAAE,QAAQ,GAAG,cAAc,QAAQ,kBAAkB;AAAA,IACvD;AAAA,EACF;AAEA,QAAM,QAAQ,aAAaA,KAAI,KAAK,MAAM;AAC1C,MAAI,CAAC,OAAO;AACV,UAAM,IAAI;AAAA,MACR;AAAA,MACA,qBAAqB,GAAG,YAAY;AAAA,MACpCA,KAAI;AAAA,MACJ,EAAE,QAAQ,GAAG,cAAc,QAAQ,kBAAkB;AAAA,IACvD;AAAA,EACF;AACA,QAAM,eAAe,MAAM;AAG3B,QAAM,WAAW,QAAQA,KAAI,KAAK,YAAY;AAC9C,MAAI,CAAC,YAAY,CAAC,UAAU,QAAQ,KAAK,CAAC,SAAS,QAAQ;AACzD,UAAM,IAAI;AAAA,MACR;AAAA,MACA,cAAc,YAAY;AAAA,MAC1BA,KAAI;AAAA,MACJ,EAAE,QAAQ,kBAAkB;AAAA,IAC9B;AAAA,EACF;AACA,QAAM,UAAU,SAAS;AAGzB,MAAI;AACJ,MAAI;AACF,UAAM,OAAO,iBAAiB,GAAG,QAAQ;AAEzC,QAAI,OAAuB;AAC3B,aAAS,IAAI,GAAG,IAAI,KAAK,WAAW,QAAQ,KAAK;AAC/C,YAAM,IAAI,KAAK,WAAW,CAAC;AAC3B,UAAI,KAAK,EAAE,aAAa,GAAG;AACzB,eAAO;AACP;AAAA,MACF;AAAA,IACF;AACA,QAAI,CAAC,MAAM;AACT,YAAM,IAAI;AAAA,QACR;AAAA,QACA;AAAA,QACAA,KAAI;AAAA,QACJ,EAAE,QAAQ,kBAAkB;AAAA,MAC9B;AAAA,IACF;AACA,eAAW,QAAQ,WAAW,MAAM,IAAI;AAAA,EAC1C,SAAS,GAAG;AACV,QAAI,aAAa,UAAW,OAAM;AAClC,UAAM,IAAI;AAAA,MACR;AAAA,MACA,qDAAsD,EAAY,OAAO;AAAA,MACzEA,KAAI;AAAA,MACJ,EAAE,QAAQ,kBAAkB;AAAA,IAC9B;AAAA,EACF;AAGA,MAAI,SAAS,iBAAiB,QAAQ,SAAS,cAAc,OAAO;AAClE,UAAM,IAAI;AAAA,MACR;AAAA,MACA,qCAAqC,SAAS,SAAS;AAAA,MACvDA,KAAI;AAAA,MACJ,EAAE,QAAQ,kBAAkB;AAAA,IAC9B;AAAA,EACF;AAGA,QAAM,WAAWC,aAAgB,YAAY;AAC7C,QAAM,aAAa,oBAAI,IAA8B;AACrD,aAAW,QAAO,QAAG,WAAH,YAAa,CAAC,EAAG,YAAW,IAAI,IAAI,aAAa,GAAG;AAEtE,QAAM,WAAW,oBAAI,IAAoB;AACzC,MAAI,eAAe;AAEnB,QAAM,QAAQ,SAAS,uBAAuB,MAAM,MAAM;AAC1D,QAAM,eAA0B,CAAC;AACjC,WAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;AACrC,UAAM,IAAI,MAAM,CAAC;AACjB,QAAI,EAAG,cAAa,KAAK,CAAC;AAAA,EAC5B;AACA,aAAW,QAAQ,cAAc;AAC/B,UAAM,UAAU,KAAK,eAAe,MAAM,OAAO;AACjD,QAAI,CAAC,QAAS;AACd,QAAI,SAAS,SAAS,IAAI,OAAO;AACjC,QAAI,CAAC,QAAQ;AACX,YAAM,MAAM,WAAW,IAAI,OAAO;AAClC,UAAI,CAAC,KAAK;AAER,gBAAQ;AAAA,UACN,2CAA2C,OAAO,4DACRD,KAAI,KAAK;AAAA,QACrD;AACA,aAAK,kBAAkB,MAAM,OAAO;AACpC;AAAA,MACF;AACA,YAAM,MAAM,oBAAoB,IAAI,WAAW;AAC/C,UAAI,CAAC,KAAK;AACR,gBAAQ;AAAA,UACN,+DAA+D,IAAI,WAAW,WACnE,OAAO,mCAAmCA,KAAI,KAAK;AAAA,QAChE;AACA,aAAK,kBAAkB,MAAM,OAAO;AACpC;AAAA,MACF;AACA,YAAM,YAAY,kBAAkBA,KAAI,KAAK,GAAG;AAChD,YAAM,YAAY,iBAAiB;AAAA,QACjC,MAAM;AAAA,QACN,aAAa,IAAI;AAAA,QACjB,OAAO,IAAI;AAAA,MACb,CAAC;AACD,cAAQA,KAAI,KAAK,SAAS;AAC1B,gBAAU,SAAS;AACnB,eAAS,mBAAmBA,KAAI,KAAK,UAAU,SAAS;AACxD,6BAAuBA,KAAI,KAAK,KAAK,IAAI,WAAW;AACpD,eAAS,IAAI,SAAS,MAAM;AAC5B,qBAAe;AAAA,IACjB;AACA,SAAK,eAAe,MAAM,WAAW,MAAM;AAAA,EAC7C;AAGA,oBAAkB,QAAQ;AAC1B,EAAAE,uBAAsBF,MAAK,QAAQ;AAInC,MAAI,GAAG,eAAe;AACpB,kBAAcA,MAAK,SAAS,UAAU,GAAG,aAAa;AAAA,EACxD;AAGA,SAAO,aAAa,UAAU,OAAO,WAAW;AAGhD,yBAAuBA,MAAK,QAAQ;AAGpC,YAAU,QAAQ;AAClB,MAAI,cAAc;AAChB,UAAM,WAAW,QAAQA,KAAI,KAAK,QAAQ;AAC1C,QAAI,SAAU,WAAU,QAAQ;AAAA,EAClC;AACF;AA9KgB;AA2LhB,SAAS,cACPA,MACA,SACA,KACA,eACM;AACN,MAAI,WAA2B;AAC/B,MAAI;AACF,UAAM,OAAO,iBAAiB,aAAa;AAC3C,aAAS,IAAI,GAAG,IAAI,KAAK,WAAW,QAAQ,KAAK;AAC/C,YAAM,IAAI,KAAK,WAAW,CAAC;AAC3B,UAAI,KAAK,EAAE,aAAa,KAAK,EAAE,iBAAiB,QAAQ,EAAE,cAAc,SAAS;AAC/E,mBAAW,QAAQ,WAAW,GAAG,IAAI;AACrC;AAAA,MACF;AAAA,IACF;AAAA,EACF,SAAS,GAAG;AACV,YAAQ;AAAA,MACN,4EAA6E,EAAY,OAAO;AAAA,IAClG;AACA;AAAA,EACF;AACA,MAAI,CAAC,SAAU;AAGf,MAAI,WAA2B;AAC/B,WAAS,IAAI,GAAG,IAAI,IAAI,WAAW,QAAQ,KAAK;AAC9C,UAAM,IAAI,IAAI,WAAW,CAAC;AAC1B,QAAI,KAAK,EAAE,aAAa,KAAK,EAAE,iBAAiB,QAAQ,EAAE,cAAc,SAAS;AAC/E,iBAAW;AACX;AAAA,IACF;AAAA,EACF;AACA,MAAI,UAAU;AACZ,QAAI,aAAa,UAAU,QAAQ;AAAA,EACrC,OAAO;AACL,QAAI,aAAa,UAAU,IAAI,UAAU;AAAA,EAC3C;AACA,OAAKA;AACP;AAvCS;AA+CT,SAAS,uBAAuBA,MAAsB,KAAoB;AAExE,QAAM,QAAQ,IAAI,uBAAuB,MAAM,GAAG;AAClD,WAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;AACrC,UAAM,IAAI,MAAM,CAAC;AACjB,QAAI,CAAC,EAAG;AACR,UAAM,MAAM,EAAE,eAAe,QAAQ,QAAQ;AAC7C,QAAI,IAAK,CAAAA,KAAI,QAAQ,QAAQ,IAAI,IAAI,YAAY,GAAG,CAAC;AAAA,EACvD;AAEA,MAAI,OAAO;AACX,aAAW,MAAMA,KAAI,QAAQ,OAAO,KAAK,GAAG;AAC1C,UAAM,IAAI,cAAc,KAAK,EAAE;AAC/B,QAAI,GAAG;AACL,YAAM,IAAI,SAAS,EAAE,CAAC,GAAI,EAAE;AAC5B,UAAI,IAAI,KAAM,QAAO;AAAA,IACvB;AAAA,EACF;AACA,EAAAA,KAAI,QAAQ,OAAO,IAAI,OAAO,OAAO,OAAO,CAAC,EAAE,SAAS,GAAG,GAAG,CAAC,IAAI,GAAG;AACxE;AAnBS;AAyBT,SAASE,uBAAsBF,MAAsB,MAAqB;AACxE,QAAM,OAAO,IAAI,IAAIA,KAAI,QAAQ,QAAQ,KAAK,CAAC;AAC/C,QAAM,aAAa,KAAK,uBAAuB,MAAM,GAAG;AACxD,QAAMG,YAAsB,CAAC;AAC7B,WAAS,IAAI,GAAG,IAAI,WAAW,QAAQ,KAAK;AAC1C,UAAM,IAAI,WAAW,CAAC;AACtB,QAAI,EAAG,CAAAA,UAAS,KAAK,CAAC;AAAA,EACxB;AACA,aAAW,KAAKA,WAAU;AACxB,UAAM,QAAQ,eAAe,IAAI;AACjC,MAAE,eAAe,QAAQ,cAAc,KAAK;AAAA,EAC9C;AACF;AAZS,OAAAD,wBAAA;AAmBT,SAAS,kBAAkB,KAAoB;AAC7C,QAAM,eAAe;AAAA,IACnB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACA,aAAW,SAAS,cAAc;AAChC,UAAM,OAAO,IAAI,uBAAuB,MAAM,KAAK;AACnD,UAAM,WAAsB,CAAC;AAC7B,aAAS,IAAI,GAAG,IAAI,KAAK,QAAQ,KAAK;AACpC,YAAM,KAAK,KAAK,CAAC;AACjB,UAAI,GAAI,UAAS,KAAK,EAAE;AAAA,IAC1B;AACA,eAAW,MAAM,UAAU;AACzB,UAAI,GAAG,WAAY,IAAG,WAAW,YAAY,EAAE;AAAA,IACjD;AAAA,EACF;AACF;AAnBS;;;ACpTT,IAAM,wBACJ;AAQF,SAAS,iBAAiBE,MAAyE;AACjG,aAAW,QAAQ,UAAUA,KAAI,GAAG,GAAG;AACrC,QAAI,KAAK,gBAAgB,yBAAyB,KAAK,QAAQ;AAC7D,aAAO;AAAA,IACT;AAAA,EACF;AACA,SAAO;AACT;AAPS;AAWF,SAAS,uBACdA,MACA,IACM;AAEN,QAAM,eAAe,iBAAiBA,IAAG;AACzC,MAAI,CAAC,cAAc;AAIjB,UAAM,IAAI;AAAA,MACR;AAAA,MACA;AAAA,MAEAA,KAAI;AAAA,MACJ,EAAE,QAAQ,kBAAkB;AAAA,IAC9B;AAAA,EACF;AAEA,QAAM,SAAS,aAAa;AAG5B,QAAM,eAAe,OAAO;AAC5B,MAAI,CAAC,cAAc;AACjB,UAAM,IAAI;AAAA,MACR;AAAA,MACA;AAAA,MACAA,KAAI;AAAA,MACJ,EAAE,QAAQ,kBAAkB;AAAA,IAC9B;AAAA,EACF;AAGA,QAAM,WAAW,gBAAgB,cAAc,cAAc;AAC7D,QAAM,SAAS,GAAG,UAAU,SAAS;AAErC,MAAI,UAAU;AAEZ,aAAS,eAAe,MAAM,SAAS,MAAM;AAAA,EAC/C,OAAO;AAGL,UAAM,QAAQ,OAAO,gBAAgB,MAAM,gBAAgB;AAC3D,UAAM,eAAe,MAAM,SAAS,MAAM;AAC1C,iBAAa,YAAY,KAAK;AAAA,EAChC;AAIA,aAAW,QAAQ,UAAUA,KAAI,GAAG,GAAG;AACrC,QAAI,KAAK,gBAAgB,yBAAyB,KAAK,QAAQ;AAC7D,gBAAU,IAAI;AACd;AAAA,IACF;AAAA,EACF;AACF;AAvDgB;AA4DhB,SAAS,gBAAgB,IAAa,WAAmC;AACvE,QAAM,WAAW,GAAG;AACpB,WAAS,IAAI,GAAG,IAAI,SAAS,QAAQ,KAAK;AACxC,UAAM,IAAI,SAAS,CAAC;AACpB,QACE,KACA,EAAE,aAAa,KACd,EAAc,iBAAiB,QAC/B,EAAc,cAAc,WAC7B;AACA,aAAO;AAAA,IACT;AAAA,EACF;AACA,SAAO;AACT;AAdS;;;ACnCF,SAAS,WAAW,IAAQC,MAA4B;AAC7D,UAAQ,GAAG,MAAM;AAAA,IACf,KAAK;AACH,8BAAwBA,MAAK,EAAE;AAC/B;AAAA,IACF,KAAK;AACH,oCAA8BA,MAAK,EAAE;AACrC;AAAA,IACF,KAAK;AACH,mCAA6BA,MAAK,EAAE;AACpC;AAAA,IACF,KAAK;AACH,6BAAuBA,MAAK,EAAE;AAC9B;AAAA;AAAA,IAEF,KAAK;AACH,6BAAuBA,MAAK,IAAI,QAAQ;AACxC;AAAA,IACF,KAAK;AACH,6BAAuBA,MAAK,IAAI,OAAO;AACvC;AAAA,IACF,KAAK;AACH,wCAAkCA,MAAK,EAAE;AACzC;AAAA,IACF,KAAK;AACH,6BAAuBA,MAAK,EAAE;AAC9B;AAAA;AAAA,IAEF,KAAK;AACH,4BAAsBA,MAAK,EAAE;AAC7B;AAAA,IACF,KAAK;AACH,4BAAsBA,MAAK,EAAE;AAC7B;AAAA;AAAA,IAEF,KAAK;AACH,wBAAkBA,MAAK,EAAE;AACzB;AAAA,IACF,KAAK;AACH,2BAAqBA,MAAK,EAAE;AAC5B;AAAA;AAAA,IAEF,KAAK;AACH,6BAAuBA,MAAK,EAAE;AAC9B;AAAA,IACF,KAAK;AACH,6BAAuBA,MAAK,EAAE;AAC9B;AAAA;AAAA,IAEF,KAAK;AACH,6BAAuBA,MAAK,EAAE;AAC9B;AAAA,IACF,KAAK;AACH,yBAAmBA,MAAK,EAAE;AAC1B;AAAA;AAAA,IAEF,KAAK;AACH,qCAA+BA,MAAK,EAAE;AACtC;AAAA,IACF,KAAK;AACH,kCAA4BA,MAAK,EAAE;AACnC;AAAA,IACF,KAAK;AACH,6BAAuBA,MAAK,EAAE;AAC9B;AAAA,IACF,KAAK;AACH,sCAAgCA,MAAK,EAAE;AACvC;AAAA,IACF,KAAK;AACH,4BAAsBA,MAAK,EAAE;AAC7B;AAAA;AAAA,IAEF,KAAK;AACH,4BAAsBA,MAAK,EAAE;AAC7B;AAAA;AAAA,IAEF,KAAK;AACH,6BAAuBA,MAAK,EAAE;AAC9B;AAAA;AAAA,IAEF,KAAK;AACH,kCAA4BA,MAAK,EAAE;AACnC;AAAA;AAAA,IAEF,KAAK;AACH,gCAA0BA,MAAK,EAAE;AACjC;AAAA;AAAA,IAEF,KAAK;AACH,2CAAqCA,MAAK,EAAE;AAC5C;AAAA,IACF,KAAK;AACH,2BAAqBA,MAAK,EAAE;AAC5B;AAAA;AAAA,IAEF,KAAK;AACH,mCAA6BA,MAAK,EAAE;AACpC;AAAA;AAAA,IAEF,KAAK;AACH,8BAAwBA,MAAK,EAAE;AAC/B;AAAA;AAAA,IAEF,KAAK;AACH,6BAAuBA,MAAK,EAAE;AAC9B;AAAA;AAAA,IAEF,KAAK;AACH,6BAAuBA,MAAK,EAAE;AAC9B;AAAA,IACF,SAAS;AAEP,YAAM,SAAgB;AACtB,YAAM,IAAI;AAAA,QACR;AAAA,QACA,yBAAyB,KAAK,UAAU,MAAM,CAAC;AAAA,QAC/CA,KAAI;AAAA,MACN;AAAA,IACF;AAAA,EACF;AACF;AAxHgB;;;AClChB,eAAsB,eACpB,KACA,mBACA,MACY;AACZ,QAAM,YAAY,oBAAI,IAA0B;AAChD,QAAM,gBAAgB,oBAAI,IAAY;AAEtC,aAAW,QAAQ,mBAAmB;AACpC,QAAI,CAAC,IAAI,MAAM,IAAI,IAAI,EAAG;AAC1B,kBAAc,IAAI,IAAI;AACtB,UAAM,OAAO,QAAQ,KAAK,IAAI;AAC9B,cAAU,IAAI,MAAM,cAAc,IAAI,CAAC;AAAA,EACzC;AAEA,MAAI;AACF,WAAO,MAAM,QAAQ,QAAQ,KAAK,CAAC;AAAA,EACrC,SAAS,KAAK;AACZ,aAAS,KAAK,mBAAmB,eAAe,SAAS;AACzD,UAAM;AAAA,EACR;AACF;AArBsB;AAuBtB,SAAS,cAAc,MAA0B;AAC/C,SAAO;AAAA,IACL,aAAa,KAAK;AAAA,IAClB,QAAQ,KAAK,SAAU,KAAK,OAAO,UAAU,IAAI,IAAiB;AAAA,IAClE,OAAO,KAAK,QAAQ,IAAI,WAAW,KAAK,KAAK,IAAI;AAAA,IACjD,eAAe,KAAK,iBAAiB,IAAI,WAAW,KAAK,cAAc,IAAI;AAAA,IAC3E,OAAO,KAAK;AAAA,EACd;AACF;AARS;AAUT,SAAS,SACP,KACA,mBACA,eACA,WACM;AACN,aAAW,QAAQ,mBAAmB;AACpC,QAAI,cAAc,IAAI,IAAI,GAAG;AAE3B,YAAM,OAAO,QAAQ,KAAK,IAAI;AAC9B,YAAM,OAAO,UAAU,IAAI,IAAI;AAC/B,UAAI,CAAC,MAAM;AAKT,YAAI;AACJ,YAAI,KAAK,QAAQ;AACf,qBAAW,cAAc;AAAA,YACvB;AAAA,YACA,aAAa,KAAK;AAAA,YAClB,QAAQ,KAAK;AAAA,aACT,KAAK,kBAAkB,SAAY,EAAE,eAAe,KAAK,cAAc,IAAI,CAAC,EACjF;AAAA,QACH,WAAW,KAAK,OAAO;AACrB,qBAAW,iBAAiB;AAAA,YAC1B;AAAA,YACA,aAAa,KAAK;AAAA,YAClB,OAAO,KAAK;AAAA,aACR,KAAK,kBAAkB,SAAY,EAAE,eAAe,KAAK,cAAc,IAAI,CAAC,EACjF;AAAA,QACH,OAAO;AACL,gBAAM,IAAI;AAAA,YACR,0CAA0C,IAAI;AAAA,UAChD;AAAA,QACF;AACA,iBAAS,SAAS,KAAK;AACvB,gBAAQ,KAAK,QAAQ;AACrB;AAAA,MACF;AACA,WAAK,SAAS,KAAK;AACnB,WAAK,QAAQ,KAAK;AAClB,WAAK,SAAS,KAAK;AAAA,IACrB,OAAO;AAEL,iBAAW,KAAK,IAAI;AAAA,IACtB;AAAA,EACF;AACF;AAhDS;;;AC1BF,SAAS,aAAa,KAA6B;AA3C1D;AA4CE,QAAM,UAAU,YAAY,KAAK,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC;AACpD,MAAI,QAAQ,WAAW,EAAG,QAAO,CAAC;AAClC,QAAM,OAAO,QAAQ,CAAC,EAAG;AACzB,QAAM,WAAW,QAAQ,CAAC,EAAG;AAC7B,QAAM,WAAWC,aAAY,QAAQ;AAErC,QAAM,MAAqB,CAAC;AAC5B,MAAI;AACJ,MAAI;AACJ,MAAI,eAAe;AAGnB,WAAS,IAAI,GAAG,IAAI,KAAK,WAAW,QAAQ,KAAK;AAC/C,UAAM,OAAO,KAAK,WAAW,CAAC;AAC9B,QAAI,CAAC,QAAQ,KAAK,aAAa,EAAG;AAClC,UAAM,KAAK;AACX,QAAI,GAAG,iBAAiB,KAAM;AAE9B,QAAI,GAAG,cAAc,KAAK;AACxB,YAAM,UAAS,cAAG,eAAe,QAAQ,QAAQ,MAAlC,mBAAqC,kBAArC,YAAsD;AACrE,UAAI,OAAO,WAAW,EAAG;AACzB,UAAI,uBAAuB,OAAW,sBAAqB;AAC3D,yBAAmB;AAGnB,YAAM,MAAMC,kBAAiB,IAAI,MAAM,KAAK;AAC5C,YAAM,eAAe,MAAMA,kBAAiB,KAAK,MAAM,QAAQ,IAAI;AACnE,UAAI,cAAc;AAChB,YAAI;AAAA,UACF,aAAa,gBAAgB,oBAAoB,QAAQ,cAAc,KAAK,QAAQ;AAAA,QACtF;AACA,6BAAqB;AAAA,MACvB;AAAA,IACF,WAAW,GAAG,cAAc,UAAU;AAEpC,UAAI,uBAAuB,UAAa,qBAAqB,QAAW;AACtE,YAAI;AAAA,UACF,aAAa,gBAAgB,oBAAoB,kBAAkB,IAAI,KAAK,QAAQ;AAAA,QACtF;AACA,6BAAqB;AAAA,MACvB;AAAA,IACF;AAAA,EAEF;AAEA,SAAO;AACT;AA/CgB;AAmDhB,SAAS,aACP,cACA,aACA,YACA,QACA,KACA,UACa;AACb,QAAM,OAAoB,EAAE,cAAc,aAAa,WAAW;AAGlE,QAAM,SAASA,kBAAiB,QAAQ,MAAM,MAAM;AACpD,MAAI,QAAQ;AACV,UAAM,IAAI,OAAO,eAAe,MAAM,KAAK;AAC3C,QACE,MAAM,cACN,MAAM,gBACN,MAAM,cACN,MAAM,aACN,MAAM,cACN;AACA,WAAK,OAAO;AAAA,IACd;AAAA,EACF;AAGA,QAAM,aAAa,YAAY,QAAQ,mBAAmB,KAAK,QAAQ;AACvE,MAAI,WAAW,SAAS,EAAG,MAAK,aAAa;AAC7C,QAAM,aAAa,YAAY,QAAQ,mBAAmB,KAAK,QAAQ;AACvE,MAAI,WAAW,SAAS,EAAG,MAAK,aAAa;AAG7C,MAAIA,kBAAiB,QAAQ,MAAM,SAAS,EAAG,MAAK,YAAY;AAEhE,SAAO;AACT;AAnCS;AAqCT,SAAS,YACP,QACA,WACA,KACA,UACmB;AACnB,QAAM,OAA0B,CAAC;AACjC,MAAI,CAAC,SAAU,QAAO;AACtB,QAAM,SAAS,SAAS,KAAK,QAAQ;AACrC,MAAI,CAAC,OAAQ,QAAO;AACpB,QAAM,QAAQ,OAAO,uBAAuB,MAAM,SAAS;AAC3D,WAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;AACrC,UAAM,KAAK,MAAM,CAAC;AAClB,QAAI,CAAC,MAAM,GAAG,eAAe,OAAQ;AACrC,UAAM,WAAW,GAAG,eAAe,MAAM,MAAM;AAC/C,UAAM,MAAM,GAAG,eAAe,MAAM,IAAI;AACxC,QAAI,CAAC,IAAK;AACV,UAAM,SAAS,OAAO,IAAI,GAAG;AAC7B,QAAI,CAAC,OAAQ;AACb,UAAM,WAAWC,kBAAiB,UAAU,MAAM;AAClD,UAAM,OACJ,aAAa,WAAW,aAAa,SAAS,WAAW;AAC3D,SAAK,KAAK,EAAE,MAAM,SAAS,CAAC;AAAA,EAC9B;AACA,SAAO;AACT;AAzBS;AA2BT,IAAMC,WAAU;AAEhB,SAAS,SAAS,KAAc,UAA8C;AAC5E,aAAW,QAAQ,UAAU,GAAG,GAAG;AACjC,QAAI,KAAK,SAAS,SAAU;AAC5B,QAAI,CAAC,KAAK,OAAQ,QAAO;AACzB,UAAM,MAAM,oBAAI,IAAoB;AACpC,UAAM,QAAQ,KAAK,OAAO,uBAAuBA,UAAS,cAAc;AACxE,aAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;AACrC,YAAM,KAAK,MAAM,CAAC;AAClB,UAAI,CAAC,GAAI;AACT,YAAM,KAAK,GAAG,aAAa,IAAI;AAC/B,YAAM,SAAS,GAAG,aAAa,QAAQ;AACvC,UAAI,MAAM,OAAQ,KAAI,IAAI,IAAI,MAAM;AAAA,IACtC;AACA,WAAO;AAAA,EACT;AACA,SAAO;AACT;AAhBS;AAkBT,SAASH,aAAY,UAAsC;AACzD,QAAM,YAAY,SAAS,YAAY,GAAG;AAC1C,QAAM,MAAM,aAAa,IAAI,SAAS,MAAM,GAAG,SAAS,IAAI;AAC5D,QAAM,OAAO,SAAS,MAAM,YAAY,CAAC;AACzC,SAAO,IAAI,SAAS,IAAI,GAAG,GAAG,UAAU,IAAI,UAAU,SAAS,IAAI;AACrE;AALS,OAAAA,cAAA;AAOT,SAASC,kBAAiB,IAAa,IAAY,OAA+B;AAChF,WAAS,IAAI,GAAG,IAAI,GAAG,WAAW,QAAQ,KAAK;AAC7C,UAAM,IAAI,GAAG,WAAW,CAAC;AACzB,QAAI,CAAC,KAAK,EAAE,aAAa,EAAG;AAC5B,UAAM,KAAK;AACX,QAAI,GAAG,iBAAiB,MAAM,GAAG,cAAc,MAAO,QAAO;AAAA,EAC/D;AACA,SAAO;AACT;AARS,OAAAA,mBAAA;;;AChIT,UAAU,aAAa,MAAmC;AACxD,WAAS,IAAI,GAAG,IAAI,KAAK,WAAW,QAAQ,KAAK;AAC/C,UAAM,OAAO,KAAK,WAAW,CAAC;AAC9B,QAAI,CAAC,QAAQ,KAAK,aAAa,EAAG;AAClC,UAAM,KAAK;AACX,QAAI,GAAG,iBAAiB,KAAM;AAC9B,QAAI,GAAG,cAAc,KAAK;AACxB,YAAM;AAAA,IACR,WAAW,GAAG,cAAc,SAAS,GAAG,cAAc,cAAc;AAElE,yBAAO,aAAa,EAAE;AAAA,IACxB;AAAA,EAEF;AACF;AAdU;AAgBV,SAAS,kBAAkB,MAA4B;AAzEvD;AA0EE,QAAM,SAAsB,CAAC;AAE7B,QAAM,OAAO,KAAK,uBAAuB,MAAM,GAAG;AAClD,WAAS,KAAK,GAAG,KAAK,KAAK,QAAQ,MAAM;AACvC,UAAM,MAAM,KAAK,EAAE;AACnB,QAAI,CAAC,IAAK;AAGV,UAAM,WAAW,IAAI,uBAAuB,MAAM,SAAS;AAC3D,aAAS,KAAK,GAAG,KAAK,SAAS,QAAQ,MAAM;AAC3C,YAAM,KAAK,SAAS,EAAE;AACtB,UAAI,CAAC,GAAI;AACT,YAAM,KAAK,GAAG,eAAe,MAAM,aAAa;AAChD,UAAI,OAAO,QAAS,QAAO,KAAK,EAAE,MAAM,QAAQ,CAAC;AAAA,eACxC,OAAO,MAAO,QAAO,KAAK,EAAE,MAAM,MAAM,CAAC;AAAA,IACpD;AAGA,UAAM,aAAa,IAAI,uBAAuB,MAAM,WAAW;AAC/D,aAAS,KAAK,GAAG,KAAK,WAAW,QAAQ,MAAM;AAC7C,YAAM,OAAO,WAAW,EAAE;AAC1B,UAAI,CAAC,KAAM;AACX,aAAO,KAAK,EAAE,MAAM,SAAS,OAAM,UAAK,gBAAL,YAAoB,GAAG,CAAC;AAAA,IAC7D;AAAA,EACF;AACA,SAAO;AACT;AA3BS;AA6BF,SAAS,cAAc,KAA+B;AAtG7D;AAuGE,QAAM,UAAU,YAAY,KAAK,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC;AACpD,MAAI,QAAQ,WAAW,EAAG,QAAO,CAAC;AAClC,QAAM,OAAO,QAAQ,CAAC,EAAG;AAEzB,QAAM,MAAuB,CAAC;AAC9B,MAAI,WAAW;AAGf,MAAI,QAAQ;AACZ,MAAI,kBAA4B,CAAC;AACjC,MAAI;AACJ,MAAI,aAAa;AAGjB,aAAW,MAAM,aAAa,IAAI,GAAG;AACnC,UAAM,WAAU,QAAG,eAAe,QAAQ,QAAQ,MAAlC,YAAuC,IAAI,YAAY;AAIvE,QAAI,UAAU,GAAG;AACf,YAAM,UAAU,GAAG,uBAAuB,MAAM,WAAW;AAC3D,eAAS,KAAK,GAAG,KAAK,QAAQ,QAAQ,MAAM;AAC1C,cAAM,KAAK,QAAQ,EAAE;AACrB,YAAI,CAAC,GAAI;AACT,cAAM,UAAS,QAAG,eAAe,MAAM,OAAO,MAA/B,YAAoC,IAAI,KAAK;AAC5D,YAAI,UAAU,KAAK,KAAK,KAAK,OAAO,SAAS,GAAG;AAC9C,cAAI,KAAK;AAAA,YACP,UAAU;AAAA,YACV,aAAa;AAAA,YACb,YAAY;AAAA,YACZ;AAAA,UACF,CAAC;AAAA,QACH;AAAA,MACF;AAAA,IACF;AAGA,UAAM,SAAS,kBAAkB,EAAE;AAInC,UAAM,cAAc,QAAQ;AAC5B,SAAK;AAEL,eAAW,MAAM,QAAQ;AACvB,UAAI,GAAG,SAAS,SAAS;AACvB;AACA,YAAI,UAAU,GAAG;AAEf,6BAAmB,OAAO,SAAS,IAAI,SAAS;AAChD,4BAAkB,CAAC;AACnB,uBAAa;AAAA,QACf;AAAA,MACF,WAAW,GAAG,SAAS,OAAO;AAC5B,YAAI,UAAU,GAAG;AAEf,gBAAM,YAAY,gBAAgB,KAAK,EAAE,EAAE,KAAK;AAChD,gBAAM,QAAQ,cAAc,UAAU,KAAK,SAAS;AACpD,cAAI,SAAS,oBAAoB,OAAO,SAAS,GAAG;AAClD,gBAAI,KAAK;AAAA,cACP,UAAU;AAAA,cACV,aAAa;AAAA,cACb,YAAY;AAAA,cACZ,OAAO;AAAA,YACT,CAAC;AAAA,UACH;AACA,6BAAmB;AACnB,4BAAkB,CAAC;AACnB,uBAAa;AAAA,QACf;AACA,YAAI,QAAQ,EAAG;AAAA,MACjB,WAAW,GAAG,SAAS,WAAW,UAAU,GAAG;AAE7C,wBAAgB,MAAK,QAAG,SAAH,YAAW,EAAE;AAClC,YAAI,CAAC,YAAY;AACf,gBAAM,SAAS,gBAAgB,KAAK,EAAE,EAAE,KAAK;AAC7C,cAAI,UAAU,KAAK,MAAM,EAAG,cAAa;AAAA,QAC3C;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;AApFgB;;;ArC+BT,IAAM,UAAN,MAAM,QAAO;AAAA,EAAb;AACL,wBAAQ;AACR,wBAAQ;AACR,wBAAQ;AACR,wBAAQ;AACR,wBAAQ;AACR,wBAAQ,YAAW;AACnB,wBAAiB,eAAc,IAAI,gBAAgB;AASnD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,wBAAiB,mBAAkB,oBAAI,IAAqC;AAiB5E;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,wBAAQ,mBAAiC,QAAQ,QAAQ;AAAA;AAAA;AAAA,EAIzD,MAAM,KAAK,QAA0B,YAA4C;AAC/E,SAAK,kBAAkB;AACvB,UAAM,EAAE,QAAQ,MAAM,IAAI;AAE1B,6CAAa,SAAS;AACtB,QAAI;AACJ,QAAI;AACF,UAAI,OAAO,SAAS,OAAO;AACzB,cAAM,MAAM,QAAW,OAAO,KAAK;AACnC,aAAK,eAAe,OAAO;AAAA,MAC7B,OAAO;AACL,cAAM,YAAe,OAAO,GAAG;AAC/B,aAAK,iBAAiB,OAAO;AAAA,MAC/B;AAAA,IACF,SAAS,GAAG;AACV,YAAM,QAAQ,OAAO,SAAS,QAAQ,YAAY;AAClD,YAAM,iBAAiB,GAAG,OAAO,KAAK;AAAA,IACxC;AAEA,6CAAa,aAAa;AAC1B,kBAAc,GAAG;AACjB,QAAI;AACF,WAAK,UAAU,aAAa,GAAG;AAAA,IACjC,SAAS,GAAG;AACV,UAAI,aAAa,mBAAmB;AAClC,cAAM,IAAI,UAAU,EAAE,MAAM,EAAE,SAAS,OAAO,EAAE,OAAO;AAAA,MACzD;AACA,YAAM,iBAAiB,GAAG,OAAO,WAAW;AAAA,IAC9C;AACA,6CAAa,aAAa;AAE1B,SAAK,MAAM;AACX,SAAK,QAAQ;AACb,SAAK,YAAY,MAAM;AAAA,EACzB;AAAA;AAAA,EAIA,MAAM,QAA6B;AACjC,SAAK,aAAa;AAClB,QAAI;AACF,aAAO,MAAM,MAAS,KAAK,GAAI;AAAA,IACjC,SAAS,GAAG;AACV,YAAM,iBAAiB,GAAG,KAAK,OAAQ,OAAO;AAAA,IAChD;AAAA,EACF;AAAA,EAEA,MAAM,YAA6B;AACjC,SAAK,aAAa;AAClB,QAAI;AACF,aAAO,UAAa,KAAK,GAAI;AAAA,IAC/B,SAAS,GAAG;AACV,YAAM,iBAAiB,GAAG,KAAK,OAAQ,WAAW;AAAA,IACpD;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAcA,eAAe,MAA0C;AACvD,SAAK,aAAa;AAClB,QAAI;AACF,YAAM,SAAS,KAAK,YAAY,WAAW;AAAA,QAAiB;AAAA,QAAM,MAChE,eAAmB,KAAK,KAAM,IAAI;AAAA,MACpC;AACA,UAAI,OAAQ,QAAO;AACnB,aAAO,eAAmB,KAAK,KAAM,IAAI;AAAA,IAC3C,SAAS,GAAG;AACV,UAAI,aAAa,UAAW,OAAM;AAClC,YAAM,MAAM,aAAa,QAAQ,EAAE,UAAU,OAAO,CAAC;AAGrD,YAAM,IAAI,UAAU,6BAA6B,KAAK,KAAK,KAAM;AAAA,IACnE;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,aAAa,QAAsC;AACjD,SAAK,aAAa;AAClB,WAAO,KAAK,YAAY,WAAW;AAAA,MAAa;AAAA,MAAQ,MACtD,qBAAqB,KAAK,KAAM,KAAK,SAAU,MAAM;AAAA,IACvD;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,cAAc,MAA6C;AACzD,SAAK,aAAa;AAClB,WAAO,cAAkB,KAAK,KAAM,KAAK,SAAU,IAAI;AAAA,EACzD;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,YAAY,MAAyC;AACnD,SAAK,aAAa;AAClB,WAAO,YAAgB,KAAK,KAAM,KAAK,SAAU,IAAI;AAAA,EACvD;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,eAA8B;AAC5B,SAAK,aAAa;AAClB,WAAO,aAAiB,KAAK,OAAQ;AAAA,EACvC;AAAA;AAAA;AAAA;AAAA,EAKA,WAAW,IAAmC;AAC5C,SAAK,aAAa;AAClB,WAAO,WAAe,KAAK,SAAU,EAAE;AAAA,EACzC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,cAAc,MAA6C;AACzD,SAAK,aAAa;AAClB,QAAI;AACF,aAAO,cAAkB,KAAK,KAAM,IAAI;AAAA,IAC1C,SAAS,GAAG;AAEV,UAAI,aAAa,aAAa,EAAE,UAAU,IAAI;AAC5C,cAAM,IAAI,UAAU,EAAE,MAAM,EAAE,SAAS,KAAK,OAAQ,EAAE,OAAO;AAAA,MAC/D;AACA,YAAM;AAAA,IACR;AAAA,EACF;AAAA,EAEA,YAAY,OAAe,MAAkD;AArU/E;AAsUI,YAAO,UAAK,cAAc,IAAI,EAAE,KAAK,CAAC,aAAa,SAAS,UAAU,KAAK,MAApE,YAAyE;AAAA,EAClF;AAAA,EAEA,cAAc,MAAiD;AAC7D,SAAK,aAAa;AAClB,WAAO,cAAkB,KAAK,KAAM,KAAK,SAAU,IAAI;AAAA,EACzD;AAAA;AAAA;AAAA,EAKA,WAAW,MAAuC;AAChD,SAAK,aAAa;AAClB,WAAO,WAAe,KAAK,QAAS,WAAW,IAAI;AAAA,EACrD;AAAA;AAAA,EAGA,SAAS,SAAmC;AAC1C,SAAK,aAAa;AAClB,WAAO,aAAiB,KAAK,QAAS,WAAW,OAAO;AAAA,EAC1D;AAAA;AAAA;AAAA,EAKA,WAAW,MAAuC;AAChD,SAAK,aAAa;AAClB,UAAM,SAAS,KAAK,YAAY,OAAO;AAAA,MAAiB;AAAA,MAAM,MAC5D,WAAe,KAAK,KAAM,KAAK,SAAU,IAAI;AAAA,IAC/C;AACA,QAAI,OAAQ,QAAO;AACnB,WAAO,WAAe,KAAK,KAAM,KAAK,SAAU,IAAI;AAAA,EACtD;AAAA;AAAA,EAGA,SAAS,SAAmC;AAC1C,SAAK,aAAa;AAClB,WAAO,KAAK,YAAY,OAAO;AAAA,MAAS;AAAA,MAAS,MAC/C,aAAiB,KAAK,KAAM,KAAK,SAAU,OAAO;AAAA,IACpD;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,iBAAiB,SAAuC;AACtD,SAAK,aAAa;AAClB,WAAO,iBAAqB,KAAK,KAAM,KAAK,SAAU,OAAO;AAAA,EAC/D;AAAA;AAAA;AAAA,EAKA,aAAa,MAA2C;AACtD,SAAK,aAAa;AAClB,WAAO,aAAiB,KAAK,KAAM,KAAK,SAAU,IAAI;AAAA,EACxD;AAAA;AAAA,EAGA,WAAW,WAAuC;AAChD,SAAK,aAAa;AAClB,WAAO,eAAmB,KAAK,KAAM,KAAK,SAAU,SAAS;AAAA,EAC/D;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,cAAc,WAA4C;AACxD,SAAK,aAAa;AAClB,WAAO,kBAAkB,KAAK,KAAM,KAAK,SAAU,SAAS;AAAA,EAC9D;AAAA;AAAA,EAGA,eAA8B;AAC5B,SAAK,aAAa;AAClB,WAAO,aAAiB,KAAK,GAAI;AAAA,EACnC;AAAA;AAAA,EAGA,gBAAiC;AAC/B,SAAK,aAAa;AAClB,WAAO,cAAkB,KAAK,GAAI;AAAA,EACpC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EA4BA,MAAM,UACJ,QACA,OAAuC,CAAC,GAClB;AACtB,SAAK,aAAa;AAClB,QAAI,OAAO,IAAI,WAAW,EAAG,QAAO,iBAAiB,kBAAkB;AAIvE,UAAM,OAAO,KAAK;AAClB,QAAI;AACJ,SAAK,kBAAkB,IAAI,QAAc,CAAC,YAAY;AACpD,gBAAU;AAAA,IACZ,CAAC;AACD,UAAM;AACN,QAAI;AACF,aAAO,MAAM,KAAK,gBAAgB,QAAQ,IAAI;AAAA,IAChD,UAAE;AACA,cAAQ;AAAA,IACV;AAAA,EACF;AAAA,EAEA,MAAM,aAAa,QAAyB;AAC1C,SAAK,aAAa;AAClB,UAAM,KAAK;AACX,WAAO,gBAAgB,QAAQ,KAAK,OAAQ;AAAA,EAC9C;AAAA,EAEA,MAAc,gBACZ,QACA,OAAuC,CAAC,GAClB;AAtd1B;AAudI,UAAM,UAAsC;AAAA,MAC1C,eAAc,YAAO,QAAQ,iBAAf,YAA+B;AAAA,MAC7C,SAAQ,YAAO,QAAQ,WAAf,YAAyB;AAAA,MACjC,MAAM,OAAO,QAAQ,OAAO,IAAI,KAAK,OAAO,QAAQ,IAAI,IAAI,oBAAI,KAAK;AAAA,IACvE;AACA,UAAM,kBAAkB,KAAK,IAAI;AACjC,UAAM,gCAAgC,KAAK,IAAI;AAC/C,UAAM,kBAAkB,yBAAyB,MAAM,OAAO,GAAG;AACjE,UAAM,gBAAgB,gBAAgB;AACtC,UAAM,yBAAyB,KAAK,IAAI,IAAI;AAC5C,UAAM,SAAS,iBAAiB,kBAAkB;AAClD,UAAMG,OAAuB;AAAA,MAC3B,KAAK,KAAK;AAAA,MACV,SAAS,KAAK;AAAA,MACd;AAAA,MACA;AAAA,MACA,SAAS;AAAA,MACT,OAAO,KAAK;AAAA,MACZ,uBAAuB,oBAAI,IAAY;AAAA,IACzC;AACA,UAAM,UAAU,wBAAC,OAAuB,GAAG,KAAK,MAAM,KAAK,GAAG,IAAI,EAAE,KAApD;AAChB,UAAM,UAAU,oBAAI,IAA2C;AAC/D,UAAM,iBAAiB,KAAK,IAAI;AAChC,QAAI,cAAc;AAClB,QAAI,mBAAmB;AAEvB,QAAI,cAAc;AAClB,QAAI;AACF,YAAM,cAAc,KAAK,IAAI;AAC7B,YAAM,eAAe,KAAK,KAAM,eAAe,MAAM;AApf3D,YAAAC;AAqfQ,iBAAS,IAAI,GAAG,IAAI,OAAO,IAAI,QAAQ,KAAK;AAC1C,UAAAD,KAAI,UAAU;AACd,gBAAM,KAAK,OAAO,IAAI,CAAC;AACvB,gBAAM,cAAc,KAAK,IAAI;AAC7B,qBAAW,IAAIA,IAAG;AAClB,gBAAM,QAAOC,MAAA,QAAQ,IAAI,GAAG,IAAI,MAAnB,OAAAA,MAAwB,EAAE,OAAO,GAAG,IAAI,EAAE;AACvD,eAAK;AACL,eAAK,MAAM,KAAK,IAAI,IAAI;AACxB,kBAAQ,IAAI,GAAG,MAAM,IAAI;AAAA,QAC3B;AAAA,MACF,CAAC;AACD,oBAAc,KAAK,IAAI,IAAI;AAC3B,oBAAc;AAAA,IAChB,UAAE;AAUA,UAAI,eAAeD,KAAI,yBAAyBA,KAAI,sBAAsB,OAAO,GAAG;AAClF,YAAI;AACF,gCAAsB,KAAK,KAAMA,KAAI,qBAAqB;AAAA,QAC5D,SAAS,GAAG;AACV,kBAAQ;AAAA,YACN,iDAAiD,aAAa,QAAQ,EAAE,UAAU,OAAO,CAAC,CAAC;AAAA,UAC7F;AAAA,QACF;AAAA,MACF;AASA,YAAM,mBAAmB,KAAK,IAAI;AAClC,UAAI;AACF,aAAK,UAAU,aAAa,KAAK,GAAI;AAAA,MACvC,SAAS,GAAG;AACV,YAAI,aAAa,mBAAmB;AAClC,kBAAQ;AAAA,YACN,0DAA0D,EAAE,IAAI,IAAI,EAAE,OAAO;AAAA,UAC/E;AAAA,QACF,OAAO;AACL,kBAAQ,KAAK,0DAA0D,OAAO,CAAC,CAAC,EAAE;AAAA,QACpF;AAAA,MACF;AACA,yBAAmB,KAAK,IAAI,IAAI;AAChC,YAAM,YAAY,MAAM,KAAK,QAAQ,QAAQ,CAAC,EAC3C,IAAI,CAAC,CAAC,MAAM,IAAI,MAAM,GAAG,IAAI,KAAK,KAAK,KAAK,IAAI,QAAQ,KAAK,EAAE,CAAC,EAAE,EAClE,KAAK,IAAI;AACZ,aAAO,cAAc;AAAA,QACnB,KAAK,OAAO,IAAI;AAAA,QAChB,eAAe,cAAc;AAAA,QAC7B;AAAA,QACA,kBAAkB,gBAAgB,OAAO;AAAA,QACzC,qBAAqB,gBAAgB,OAAO;AAAA,QAC5C,sBAAsB,gBAAgB,OAAO;AAAA,QAC7C,eAAe,gBAAgB,OAAO;AAAA,QACtC,eAAe;AAAA,QACf,WAAW;AAAA,QACX,SAAS,KAAK,IAAI,IAAI;AAAA,QACtB,UAAU,KAAK,IAAI,IAAI;AAAA,QACvB,QAAQ,MAAM,KAAK,QAAQ,QAAQ,CAAC,EAAE,IAAI,CAAC,CAAC,MAAM,IAAI,OAAO;AAAA,UAC3D;AAAA,UACA,OAAO,KAAK;AAAA,UACZ,IAAI,KAAK;AAAA,QACX,EAAE;AAAA,MACJ;AACA,YAAM,iBAAiB,gBAAgB,OAAO,OAC3C;AAAA,QACC,CAAC,UACC,GAAG,MAAM,IAAI,KAAK,MAAM,KAAK,IAAI,QAAQ,MAAM,EAAE,CAAC,UAAU,MAAM,YAAY,IAAI,QAAQ,MAAM,aAAa,CAAC;AAAA,MAClH,EACC,KAAK,IAAI;AACZ,cAAQ;AAAA,QACN,iCAAiC,OAAO,IAAI,MAAM,mBAAmB,cAAc,MAAM,0BAA0B,QAAQ,sBAAsB,CAAC,oBAAoB,QAAQ,gBAAgB,OAAO,SAAS,CAAC,kBAAkB,gBAAgB,OAAO,YAAY,IAAI,QAAQ,gBAAgB,OAAO,aAAa,CAAC,QAAQ,QAAQ,WAAW,CAAC,aAAa,QAAQ,gBAAgB,CAAC,WAAW,QAAQ,KAAK,IAAI,IAAI,cAAc,CAAC,YAAY,QAAQ,KAAK,IAAI,IAAI,eAAe,CAAC,GAAG,YAAY,KAAK,SAAS,KAAK,EAAE,GAAG,iBAAiB,oBAAoB,cAAc,KAAK,EAAE;AAAA,MAC1jB;AAAA,IACF;AAKA,SAAK,YAAY,qBAAqB,OAAO,GAAG;AAChD,SAAK,WAAW;AAAA,MACd,KAAK,OAAO;AAAA,MACZ;AAAA,MACA,SAAQ,UAAK,WAAL,YAAe;AAAA,IACzB,CAAC;AAED,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,SAAS,UAAuD;AAC9D,SAAK,gBAAgB,IAAI,QAAQ;AACjC,WAAO,MAAM;AACX,WAAK,gBAAgB,OAAO,QAAQ;AAAA,IACtC;AAAA,EACF;AAAA,EAEQ,WAAW,IAA6B;AAC9C,eAAW,YAAY,KAAK,iBAAiB;AAC3C,UAAI;AACF,iBAAS,EAAE;AAAA,MACb,SAAQ;AAAA,MAER;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,iBAAsC;AACpC,SAAK,aAAa;AAClB,UAAM,MAA2B,CAAC;AAClC,eAAW,QAAQ,UAAU,KAAK,GAAI,GAAG;AACvC,UAAI,KAAK;AAAA,QACP,MAAM,KAAK;AAAA,QACX,aAAa,KAAK;AAAA,QAClB,OAAOE,aAAY,IAAI;AAAA,MACzB,CAAC;AAAA,IACH;AACA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaA,iBAAiB,OAAqC,YAAmC;AAjpB3F;AAkpBI,SAAK,kBAAkB;AACvB,UAAM,MAAM,cAAc;AAC1B,UAAM,QAAQ,MAAM;AACpB,QAAI,YAAY;AAEhB,6CAAa,SAAS;AACtB,eAAW,SAAS,OAAO;AACzB,UAAIC,kBAAiB,MAAM,WAAW,GAAG;AACvC,cAAM,OAAO,IAAI,YAAY,EAAE,OAAO,MAAM,KAAK;AACjD,cAAM,MAAMC,kBAAiB,IAAI;AACjC;AAAA,UACE;AAAA,UACA,cAAc;AAAA,YACZ,MAAM,MAAM;AAAA,YACZ,aAAa,MAAM;AAAA,YACnB,QAAQ;AAAA,YACR,eAAe,MAAM;AAAA,UACvB,CAAC;AAAA,QACH;AAAA,MACF,OAAO;AACL;AAAA,UACE;AAAA,UACA,iBAAiB;AAAA,YACf,MAAM,MAAM;AAAA,YACZ,aAAa,MAAM;AAAA,YACnB,OAAO,MAAM;AAAA,UACf,CAAC;AAAA,QACH;AAAA,MACF;AACA;AACA,YAAM,MAAM,QAAQ,IAAI,KAAK,MAAO,YAAY,QAAS,GAAG,IAAI;AAChE,+CAAa,SAAS;AAAA,IACxB;AAGA,kBAAc,GAAG;AACjB,6CAAa,iBAAiB;AAC9B,QAAI;AACF,WAAK,UAAU,aAAa,GAAG;AAAA,IACjC,SAAS,GAAG;AACV,UAAI,aAAa,mBAAmB;AAClC,cAAM,IAAI,UAAU,EAAE,MAAM,EAAE,UAAS,UAAK,UAAL,YAAc,IAAI,EAAE,OAAO;AAAA,MACpE;AACA,YAAM;AAAA,IACR;AACA,SAAK,MAAM;AACX,SAAK,YAAY,MAAM;AACvB,6CAAa,QAAQ;AAAA,EACvB;AAAA;AAAA,EAIA,UAAgB;AACd,SAAK,WAAW;AAEhB,SAAK,MAAM;AACX,SAAK,UAAU;AACf,SAAK,eAAe;AACpB,SAAK,iBAAiB;AACtB,SAAK,YAAY,MAAM;AAAA,EACzB;AAAA;AAAA;AAAA,EAKA,WAA+B;AAC7B,WAAO,KAAK;AAAA,EACd;AAAA;AAAA,EAGA,aAAkC;AAChC,WAAO,KAAK;AAAA,EACd;AAAA;AAAA,EAGA,aAAyC;AACvC,WAAO,KAAK;AAAA,EACd;AAAA;AAAA,EAGA,kBAA0C;AACxC,WAAO,KAAK;AAAA,EACd;AAAA;AAAA,EAGA,oBAAwC;AACtC,WAAO,KAAK;AAAA,EACd;AAAA;AAAA,EAGA,aAAsB;AACpB,WAAO,KAAK;AAAA,EACd;AAAA;AAAA,EAGA,qBAA8C;AAC5C,WAAO,KAAK,YAAY,SAAS;AAAA,EACnC;AAAA;AAAA,EAGA,qBAAqB,SAA0B,OAAO,SAAS,SAAe;AAC5E,SAAK,YAAY,WAAW,QAAQ,MAAM;AAAA,EAC5C;AAAA,EAEQ,eAAqB;AA1vB/B;AA2vBI,SAAK,kBAAkB;AACvB,QAAI,CAAC,KAAK,OAAO,CAAC,KAAK,OAAO;AAC5B,YAAM,IAAI,UAAU,8BAA8B,sBAAqB,UAAK,UAAL,YAAc,EAAE;AAAA,IACzF;AAAA,EACF;AAAA,EAEQ,oBAA0B;AAjwBpC;AAkwBI,QAAI,KAAK,UAAU;AACjB,YAAM,IAAI;AAAA,QACR;AAAA,QACA;AAAA,SACA,UAAK,UAAL,YAAc;AAAA,MAChB;AAAA,IACF;AAAA,EACF;AACF;AAroBoB;AAAb,IAAM,SAAN;AA6oBP,SAAS,yBACP,QACA,KACgC;AArxBlC;AAsxBE,QAAM,QAAQ,oBAAI,IAAY;AAC9B,QAAM,UAAU,OAAO,WAAW;AAClC,QAAM,MAAM,OAAO,WAAW;AAC9B,QAAM,cAA6C;AAAA,IACjD,WAAW;AAAA,IACX,cAAc;AAAA,IACd,eAAe;AAAA,IACf,QAAQ,CAAC;AAAA,EACX;AACA,MAAI,CAAC,WAAW,CAAC,IAAK,QAAO,EAAE,OAAO,CAAC,GAAG,QAAQ,YAAY;AAE9D,QAAM,mBAAmB,KAAK,IAAI;AAClC,QAAM,UAAU,YAAY,GAAG;AAC/B,QAAM,SAAwC;AAAA,IAC5C,WAAW,KAAK,IAAI,IAAI;AAAA,IACxB,cAAc;AAAA,IACd,eAAe;AAAA,IACf,QAAQ,CAAC;AAAA,EACX;AACA,QAAM,SAAS,oBAAI,IAGjB;AACF,MAAI,cAMO;AACX,QAAM,uBAAuB,wBAAC,OAA+B;AApzB/D,QAAAH;AAqzBI,UAAM,YAAY,KAAK,IAAI;AAC3B,QAAI,QAAsB;AAC1B,eAAW,SAAS,SAAS;AAC3B,UAAI,MAAM,KAAK,SAAS,EAAqB,GAAG;AAC9C,gBAAQ;AACR;AAAA,MACF;AAAA,IACF;AACA,UAAM,KAAK,KAAK,IAAI,IAAI;AACxB,WAAO;AACP,WAAO,iBAAiB;AACxB,QAAI,aAAa;AACf,kBAAY;AACZ,kBAAY,iBAAiB;AAAA,IAC/B;AACA,YAAOA,MAAA,+BAAO,aAAP,OAAAA,MAAmB;AAAA,EAC5B,GAjB6B;AAqB7B,MAAI,kBAAiC;AACrC,aAAW,MAAM,KAAK;AACpB,UAAM,QAAO,YAAO,IAAI,GAAG,IAAI,MAAlB,YAAuB;AAAA,MAClC,MAAM,GAAG;AAAA,MACT,OAAO;AAAA,MACP,IAAI;AAAA,MACJ,cAAc;AAAA,MACd,eAAe;AAAA,IACjB;AACA,SAAK;AACL,WAAO,IAAI,GAAG,MAAM,IAAI;AACxB,kBAAc;AACd,UAAM,cAAc,KAAK,IAAI;AAC7B,QAAI;AACF,cAAQ,GAAG,MAAM;AAAA,QACf,KAAK;AAAA,QACL,KAAK;AAAA,QACL,KAAK;AAAA,QACL,KAAK;AAAA,QACL,KAAK;AAAA,QACL,KAAK,wBAAwB;AAC3B,gBAAM,SACJ,GAAG,SAAS,2BAA2B,GAAG,SAAS,yBAC/C,GAAG,eACH,GAAG;AACT,gBAAM,IAAI,QAAQ,QAAQ,IAAI,OAAO,YAAY,CAAC;AAClD,cAAI,GAAG;AACL,kBAAM,WAAW,qBAAqB,CAAC;AACvC,gBAAI,SAAU,OAAM,IAAI,QAAQ;AAAA,UAClC;AACA;AAAA,QACF;AAAA,QACA,KAAK,8BAA8B;AAEjC,gBAAM,CAAC,SAAS,IAAI,YAAY,KAAK,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC;AACxD,cAAI,UAAW,OAAM,IAAI,UAAU,QAAQ;AAC3C;AAAA,QACF;AAAA,QACA,KAAK,mBAAmB;AACtB,gBAAM,IAAI,QAAQ,QAAQ,IAAI,GAAG,OAAO,YAAY,CAAC;AACrD,cAAI,GAAG;AACL,kBAAM,WAAW,qBAAqB,CAAC;AACvC,gBAAI,SAAU,OAAM,IAAI,QAAQ;AAAA,UAClC;AAGA,cAAI,GAAG,qBAAqB,QAAQ;AAClC,kBAAM,IAAI,mBAAmB;AAC7B,kBAAM,IAAI,qBAAqB;AAC/B,kBAAM,IAAI,8BAA8B;AAAA,UAC1C;AACA;AAAA,QACF;AAAA;AAAA;AAAA,QAGA,KAAK,kBAAkB;AACrB,gBAAM,IAAI,QAAQ,QAAQ,IAAI,GAAG,MAAM,OAAO,YAAY,CAAC;AAC3D,cAAI,GAAG;AACL,kBAAM,WAAW,qBAAqB,CAAC;AACvC,gBAAI,SAAU,OAAM,IAAI,QAAQ;AAAA,UAClC;AACA;AAAA,QACF;AAAA,QACA,KAAK,kBAAkB;AACrB,gBAAM,QAAQ,QAAQ,YAAY,IAAI,GAAG,IAAI;AAC7C,cAAI,MAAO,OAAM,IAAI,MAAM,QAAQ;AACnC;AAAA,QACF;AAAA;AAAA,QAEA,KAAK,cAAc;AACjB,gBAAM,IAAI,QAAQ,QAAQ,IAAI,GAAG,MAAM,OAAO,YAAY,CAAC;AAC3D,cAAI,GAAG;AACL,kBAAM,WAAW,qBAAqB,CAAC;AACvC,gBAAI,SAAU,OAAM,IAAI,QAAQ;AAAA,UAClC;AAEA,gBAAM,IAAI,mBAAmB;AAC7B,gBAAM,IAAI,qBAAqB;AAC/B,gBAAM,IAAI,8BAA8B;AACxC;AAAA,QACF;AAAA;AAAA;AAAA,QAGA,KAAK,iBAAiB;AACpB,gBAAM,QAAQ,QAAQ,WAAW,IAAI,GAAG,SAAS;AACjD,cAAI,OAAO;AACT,kBAAM,YAAW,iBAAM,QAAQ,UAAd,YAAuB,MAAM,QAAQ,QAArC,YAA4C,MAAM,QAAQ;AAC3E,gBAAI,UAAU;AACZ,oBAAM,WAAW,qBAAqB,QAAQ;AAC9C,kBAAI,SAAU,OAAM,IAAI,QAAQ;AAAA,YAClC;AAAA,UACF;AACA,gBAAM,IAAI,mBAAmB;AAC7B,gBAAM,IAAI,qBAAqB;AAC/B,gBAAM,IAAI,8BAA8B;AACxC;AAAA,QACF;AAAA;AAAA,QAEA,KAAK,mBAAmB;AACtB,gBAAM,MAAM,QAAQ,OAAO,IAAI,GAAG,OAAO;AACzC,cAAI,KAAK;AACP,kBAAM,WAAW,qBAAqB,GAAG;AACzC,gBAAI,SAAU,OAAM,IAAI,QAAQ;AAAA,UAClC;AACA,gBAAM,IAAI,mBAAmB;AAC7B,gBAAM,IAAI,qBAAqB;AAC/B,gBAAM,IAAI,8BAA8B;AACxC;AAAA,QACF;AAAA;AAAA,QAEA,KAAK,eAAe;AAClB,gBAAM,MAAM,QAAQ,OAAO,IAAI,GAAG,OAAO;AACzC,cAAI,KAAK;AACP,kBAAM,WAAW,qBAAqB,GAAG;AACzC,gBAAI,SAAU,OAAM,IAAI,QAAQ;AAAA,UAClC;AACA,cAAI,GAAG,qBAAqB,QAAQ;AAClC,kBAAM,IAAI,mBAAmB;AAC7B,kBAAM,IAAI,qBAAqB;AAC/B,kBAAM,IAAI,8BAA8B;AAAA,UAC1C;AACA;AAAA,QACF;AAAA;AAAA,QAEA,KAAK,kBAAkB;AACrB,gBAAM,MAAM,QAAQ,OAAO,IAAI,GAAG,OAAO;AACzC,cAAI,KAAK;AACP,kBAAM,WAAW,qBAAqB,GAAG;AACzC,gBAAI,SAAU,OAAM,IAAI,QAAQ;AAAA,UAClC;AACA,cAAI,GAAG,qBAAqB,QAAQ;AAClC,kBAAM,IAAI,mBAAmB;AAC7B,kBAAM,IAAI,qBAAqB;AAC/B,kBAAM,IAAI,8BAA8B;AAAA,UAC1C;AACA;AAAA,QACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAQA,KAAK,mBAAmB;AACtB,gBAAM,MAAM,QAAQ,OAAO,IAAI,GAAG,OAAO;AACzC,cAAI,KAAK;AACP,kBAAM,WAAW,qBAAqB,GAAG;AACzC,gBAAI,SAAU,OAAM,IAAI,QAAQ;AAAA,UAClC;AACA;AAAA,QACF;AAAA,QACA,KAAK,4BAA4B;AAC/B,gBAAM,MAAM,QAAQ,OAAO,IAAI,GAAG,OAAO;AACzC,cAAI,KAAK;AACP,kBAAM,WAAW,qBAAqB,GAAG;AACzC,gBAAI,SAAU,OAAM,IAAI,QAAQ;AAAA,UAClC;AACA;AAAA,QACF;AAAA,QACA,KAAK;AAAA,QACL,KAAK;AAAA,QACL,KAAK,yBAAyB;AAC5B,gBAAM,KAAK,QAAQ,WAAW,IAAI,GAAG,SAAS;AAC9C,cAAI,IAAI;AACN,kBAAM,WAAW,qBAAqB,EAAE;AACxC,gBAAI,UAAU;AACZ,oBAAM,IAAI,QAAQ;AAClB,oBAAM,IAAII,aAAY,QAAQ,CAAC;AAAA,YACjC;AAAA,UACF;AACA,cAAI,GAAG,SAAS,iCAAiC;AAC/C,kBAAM,IAAI,4BAA4B;AACtC,kBAAM,IAAI,qBAAqB;AAAA,UACjC;AACA;AAAA,QACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAYA,KAAK,oBAAoB;AACvB,gBAAM,WAAW,QAAQ,QAAQ,IAAI,GAAG,aAAa,YAAY,CAAC;AAClE,cAAI,UAAU;AACZ,kBAAM,WAAW,qBAAqB,QAAQ;AAC9C,gBAAI,UAAU;AACZ,oBAAM,IAAI,QAAQ;AAClB,oBAAM,IAAIA,aAAY,QAAQ,CAAC;AAAA,YACjC;AAAA,UACF;AACA,gBAAM,IAAI,qBAAqB;AAC/B;AACE,kBAAM,MAAM,iBAAiB,GAAG,WAAW;AAC3C,gBAAI,KAAK;AAEP,kBAAI,CAAC,iBAAiB;AACpB,kCAAkB;AAClB,2BAAW,QAAQ,UAAU,GAAG,GAAG;AACjC,wBAAM,IAAI,8BAA8B,KAAK,KAAK,IAAI;AACtD,sBAAI,GAAG;AACL,0BAAM,IAAI,SAAS,EAAE,CAAC,GAAI,EAAE;AAC5B,wBAAI,IAAI,gBAAiB,mBAAkB;AAAA,kBAC7C;AAAA,gBACF;AAAA,cACF;AAEA;AAEA,qBAAO,IAAI,MAAM,IAAI,mBAAmB,eAAe,IAAI,GAAG,EAAE,GAAG;AACjE;AAAA,cACF;AACA,oBAAM,IAAI,mBAAmB,eAAe,IAAI,GAAG,EAAE;AAAA,YACvD;AAAA,UACF;AACA;AAAA,QACF;AAAA;AAAA,QAEA,KAAK;AAAA,QACL,KAAK,mBAAmB;AACtB,cAAI,GAAG,MAAM,UAAU,aAAa;AAClC,kBAAM,IAAI,QAAQ,QAAQ,IAAI,GAAG,MAAM,OAAO,YAAY,CAAC;AAC3D,gBAAI,GAAG;AACL,oBAAM,WAAW,qBAAqB,CAAC;AACvC,kBAAI,SAAU,OAAM,IAAI,QAAQ;AAAA,YAClC;AAAA,UACF,OAAO;AAGL,uBAAW,QAAQ,UAAU,GAAG,GAAG;AACjC,kBAAI,UAAU,IAAI,KAAK,KAAK,QAAQ;AAClC,sBAAM,KAAK,KAAK;AAChB,oBACE,GAAG,SAAS,kBAAkB,KAC9B,GAAG,SAAS,WAAW,KACvB,GAAG,SAAS,aAAa,KACzB,GAAG,SAAS,aAAa,KACzB,GAAG,SAAS,gBAAgB,KAC5B,GAAG,SAAS,eAAe,KAC3B,GAAG,SAAS,eAAe,GAC3B;AACA,wBAAM,IAAI,KAAK,IAAI;AAAA,gBACrB;AAAA,cACF;AAAA,YACF;AAAA,UACF;AACA;AAAA,QACF;AAAA,QACA;AACE;AAAA,MACJ;AAAA,IACF,UAAE;AACA,WAAK,MAAM,KAAK,IAAI,IAAI;AACxB,oBAAc;AAAA,IAChB;AAAA,EACF;AACA,SAAO,SAAS,MAAM,KAAK,OAAO,OAAO,CAAC;AAC1C,SAAO,EAAE,OAAO,CAAC,GAAG,KAAK,GAAG,OAAO;AACrC;AA/TS;AA2UT,SAASA,aAAY,UAA0B;AAC7C,QAAM,MAAM,SAAS,YAAY,GAAG;AACpC,MAAI,MAAM,EAAG,QAAO,SAAS,QAAQ;AACrC,QAAM,MAAM,SAAS,MAAM,GAAG,GAAG;AACjC,QAAM,OAAO,SAAS,MAAM,MAAM,CAAC;AACnC,SAAO,GAAG,GAAG,UAAU,IAAI;AAC7B;AANS,OAAAA,cAAA;AAST,SAAS,iBAAiB,IAA2B;AAtmCrD;AAumCE,QAAM,MAA8B;AAAA,IAClC,aAAa;AAAA,IACb,cAAc;AAAA,IACd,aAAa;AAAA,IACb,aAAa;AAAA,IACb,cAAc;AAAA,EAChB;AACA,UAAO,SAAI,EAAE,MAAN,YAAW;AACpB;AATS;AAYT,SAAS,iBAAiB,GAA6B;AACrD,SAAO;AAAA,IACL,oBAAoB,EAAE,mBAAmB,MAAM;AAAA,IAC/C,0BAA0B,EAAE,yBAAyB,MAAM;AAAA,IAC3D,iBAAiB,EAAE,gBAAgB,MAAM;AAAA,IACzC,kBAAkB,EAAE,iBAAiB,MAAM;AAAA,IAC3C,mBAAmB,EAAE;AAAA,IACrB,mBAAmB,EAAE;AAAA,IACrB,oBAAoB,EAAE;AAAA,KAClB,EAAE,gBAAgB,SAAY,EAAE,aAAa,EAAE,YAAY,IAAI,CAAC;AAExE;AAXS;AAaT,SAAS,iBAAiB,KAAc,OAAe,OAA0B;AAC/E,MAAI,eAAe,UAAW,QAAO;AACrC,QAAM,MAAM,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAC3D,SAAO,IAAI,UAAU,mBAAmB,GAAG,KAAK,YAAY,GAAG,IAAI,OAAO,EAAE,MAAM,CAAC;AACrF;AAJS;AAaT,SAASF,kBAAiB,IAAqB;AAC7C,SAAO,GAAG,SAAS,MAAM,KAAK,OAAO,qBAAqB,OAAO;AACnE;AAFS,OAAAA,mBAAA;AAIT,SAASD,aAAY,MAAwB;AAE3C,MAAI,CAAC,KAAK,UAAU,KAAK,gBAAgB;AACvC,WAAO,KAAK;AAAA,EACd;AACA,MAAI,UAAU,IAAI,GAAG;AACnB,QAAI,CAAC,KAAK,QAAQ;AAChB,YAAM,IAAI,MAAM,0BAA0B,KAAK,IAAI,kBAAkB;AAAA,IACvE;AACA,UAAM,OAAOI,6BAA4B,KAAK,MAAe;AAC7D,WAAO,IAAI,YAAY,EAAE,OAAO,IAAI;AAAA,EACtC;AAEA,MAAI,KAAK,MAAO,QAAO,KAAK;AAC5B,MAAI,KAAK,eAAgB,QAAO,KAAK;AACrC,QAAM,IAAI,MAAM,6BAA6B,KAAK,IAAI,gBAAgB;AACxE;AAhBS,OAAAJ,cAAA;;;AsCzlCF,IAAM,iBAAsD;AAAA,EACjE,MAAM,8BAAO,EAAE,QAAQ,WAAW,GAAG,SAAS;AAC5C,UAAM,CAAC,MAAM,IAAI;AACjB,UAAM,OAAO,KAAK,QAAQ,UAAU;AAEpC,WAAO;AAAA,MACL,OAAO,OAAO,SAAS;AAAA,MACvB,iBAAiB,OAAO,gBAAgB,MAAM;AAAA,MAC9C,mBAAmB,OAAO,kBAAkB,MAAM;AAAA,IACpD;AAAA,EACF,GATM;AAAA,EAUN,OAAO,8BAAO,EAAE,OAAO,MAAM,OAAO,MAAM,GAAnC;AAAA,EACP,WAAW,8BAAO,EAAE,OAAO,MAAM,OAAO,UAAU,GAAvC;AAAA,EACX,SAAS,8BAAO,EAAE,OAAO,MAAM;AAC7B,WAAO,QAAQ;AAAA,EACjB,GAFS;AAAA,EAGT,gBAAgB,8BAAO,EAAE,OAAO,MAAM,OAAO,eAAe,GAA5C;AAAA,EAChB,kBAAkB,8BAAO,EAAE,QAAQ,WAAW,GAAG,SAAS;AACxD,UAAM,CAAC,KAAK,IAAI;AAChB,WAAO,iBAAiB,OAAO,UAAU;AAAA,EAC3C,GAHkB;AAAA,EAIlB,mBAAmB,8BAAO,EAAE,OAAO,GAAG,SAAS;AAC7C,UAAM,CAAC,IAAI,IAAI;AACf,WAAO,OAAO,eAAe,IAAI;AAAA,EACnC,GAHmB;AAAA,EAInB,kBAAkB,8BAAO,EAAE,OAAO,GAAG,SAAS;AAC5C,UAAM,CAAC,MAAM,IAAI;AACjB,WAAO,OAAO,aAAa,MAAM;AAAA,EACnC,GAHkB;AAAA,EAIlB,kBAAkB,8BAAO,EAAE,OAAO,GAAG,SAAS;AAC5C,UAAM,CAAC,IAAI,IAAI;AACf,WAAO,OAAO,cAAc,IAAI;AAAA,EAClC,GAHkB;AAAA,EAIlB,iBAAiB,8BAAO,EAAE,OAAO,GAAG,SAAS;AAC3C,UAAM,CAAC,IAAI,IAAI;AACf,WAAO,OAAO,YAAY,IAAI;AAAA,EAChC,GAHiB;AAAA,EAIjB,iBAAiB,8BAAO,EAAE,OAAO,MAAM,OAAO,aAAa,GAA1C;AAAA,EACjB,gBAAgB,8BAAO,EAAE,OAAO,GAAG,SAAS;AAC1C,UAAM,CAAC,EAAE,IAAI;AACb,WAAO,OAAO,WAAW,EAAE;AAAA,EAC7B,GAHgB;AAAA,EAIhB,kBAAkB,8BAAO,EAAE,OAAO,GAAG,SAAS;AAC5C,UAAM,CAAC,IAAI,IAAI;AACf,WAAO,OAAO,cAAc,IAAI;AAAA,EAClC,GAHkB;AAAA,EAIlB,kBAAkB,8BAAO,EAAE,OAAO,GAAG,SAAS;AAC5C,UAAM,CAAC,IAAI,IAAI;AACf,WAAO,OAAO,cAAc,IAAI;AAAA,EAClC,GAHkB;AAAA,EAIlB,iBAAiB,8BAAO,EAAE,OAAO,GAAG,SAAS;AAC3C,UAAM,CAAC,OAAO,IAAI,IAAI;AACtB,WAAO,OAAO,YAAY,OAAO,IAAI;AAAA,EACvC,GAHiB;AAAA,EAIjB,eAAe,8BAAO,EAAE,OAAO,GAAG,SAAS;AACzC,UAAM,CAAC,IAAI,IAAI;AACf,WAAO,OAAO,WAAW,IAAI;AAAA,EAC/B,GAHe;AAAA,EAIf,cAAc,8BAAO,EAAE,OAAO,GAAG,SAAS;AACxC,UAAM,CAAC,OAAO,IAAI;AAClB,WAAO,OAAO,SAAS,OAAO;AAAA,EAChC,GAHc;AAAA,EAId,eAAe,8BAAO,EAAE,OAAO,GAAG,SAAS;AACzC,UAAM,CAAC,IAAI,IAAI;AACf,WAAO,OAAO,WAAW,IAAI;AAAA,EAC/B,GAHe;AAAA,EAIf,cAAc,8BAAO,EAAE,OAAO,GAAG,SAAS;AACxC,UAAM,CAAC,OAAO,IAAI;AAClB,WAAO,OAAO,SAAS,OAAO;AAAA,EAChC,GAHc;AAAA,EAId,sBAAsB,8BAAO,EAAE,OAAO,GAAG,SAAS;AAChD,UAAM,CAAC,OAAO,IAAI;AAClB,WAAO,OAAO,iBAAiB,OAAO;AAAA,EACxC,GAHsB;AAAA,EAItB,iBAAiB,8BAAO,EAAE,OAAO,GAAG,SAAS;AAC3C,UAAM,CAAC,IAAI,IAAI;AACf,WAAO,OAAO,aAAa,IAAI;AAAA,EACjC,GAHiB;AAAA,EAIjB,gBAAgB,8BAAO,EAAE,OAAO,GAAG,SAAS;AAC1C,UAAM,CAAC,SAAS,IAAI;AACpB,WAAO,OAAO,WAAW,SAAS;AAAA,EACpC,GAHgB;AAAA,EAIhB,0BAA0B,8BAAO,EAAE,OAAO,GAAG,SAAS;AACpD,UAAM,CAAC,SAAS,IAAI;AACpB,WAAO,OAAO,cAAc,SAAS;AAAA,EACvC,GAH0B;AAAA,EAI1B,iBAAiB,8BAAO,EAAE,OAAO,MAAM,OAAO,aAAa,GAA1C;AAAA,EACjB,kBAAkB,8BAAO,EAAE,OAAO,MAAM,OAAO,cAAc,GAA3C;AAAA,EAClB,WAAW,8BAAO,EAAE,OAAO,GAAG,SAAS;AACrC,UAAM,CAAC,MAAM,IAAI;AAGjB,WAAO,OAAO,UAAU,QAAQ,EAAE,QAAQ,OAAO,CAAC;AAAA,EACpD,GALW;AAAA,EAMX,cAAc,8BAAO,EAAE,OAAO,GAAG,SAAS;AACxC,UAAM,CAAC,MAAM,IAAI;AACjB,WAAO,OAAO,aAAa,MAAM;AAAA,EACnC,GAHc;AAIhB;;;AC0wBA,SAAS,uBAAuB,OAA+B,CAAC,GAI9D;AAv6BF;AAw6BE,SAAO;AAAA,IACL,eAAc,UAAK,iBAAL,YAAqB;AAAA,KAC/B,KAAK,WAAW,SAAY,EAAE,QAAQ,KAAK,OAAO,IAAI,CAAC,IACvD,KAAK,SAAS,SAAY,EAAE,MAAM,KAAK,KAAK,YAAY,EAAE,IAAI,CAAC;AAEvE;AAVS;AAYF,SAAS,mBACd,WACA,mBACc;AACd,QAAM,eAAe,wBAAC,SACpB,IAAI,cAAc,WAAW,mBAAmB,IAAI,GADjC;AAGrB,SAAO;AAAA,IACL,MAAM,KAAK,MAAM;AACf,wBAAkB;AAClB,YAAM,SAAS,MAAM,UAAU,KAAiB,mBAAmB,CAAC,IAAI,CAAC;AACzE,aAAO;AAAA,QACL,YAAY,OAAO,WAAW,IAAI,YAAY;AAAA,QAC9C,YAAY,OAAO;AAAA,MACrB;AAAA,IACF;AAAA,IACA,MAAM,IAAI,QAAQ;AAChB,wBAAkB;AAClB,YAAM,OAAO,MAAM,UAAU,KAA2B,kBAAkB,CAAC,MAAM,CAAC;AAClF,aAAO,OAAO,aAAa,IAAI,IAAI;AAAA,IACrC;AAAA,EACF;AACF;AAtBgB;AAwBhB,IAAM,iBAAN,MAAM,eAAmC;AAAA,EAcvC,YACmB,WACA,mBACjB,cACA,OACA;AAJiB;AACA;AAfnB,wBAAS;AACT,wBAAS;AACT,wBAAS;AACT,wBAAS;AACT,wBAAS;AACT,wBAAS;AACT,wBAAS;AACT,wBAAS;AACT,wBAAS;AACT,wBAAS;AACT,wBAAS;AACT,wBAAS;AAQP,UAAM,OACJ,OAAO,iBAAiB,WACnB,EAAE,QAAQ,cAAc,OAAe,MAAM,GAAG,IACjD;AACN,WAAO,OAAO,MAAM,IAAI;AACxB,SAAK,KAAK,KAAK;AAAA,EACjB;AAAA,EAEA,MAAM,QACJ,MAC+B;AAr+BnC;AAs+BI,SAAK,kBAAkB;AACvB,SAAI,6BAAM,mBAAiB,6BAAM,aAAY;AAC3C,YAAM,SAAS,MAAM,KAAK,UAAU,KAAiB,mBAAmB;AAAA,QACtE;AAAA,UACE,OAAO,CAAC,KAAK,KAAK;AAAA,UAClB,YAAY,EAAE,MAAM,MAAM;AAAA,WACvB;AAAA,MAEP,CAAC;AACD,cAAO,YAAO,WAAW,KAAK,CAAC,cAAc,UAAU,WAAW,KAAK,MAAM,MAAtE,YAA2E;AAAA,IACpF;AACA,WAAO,KAAK,UAAU,KAA2B,kBAAkB,CAAC,KAAK,MAAM,CAAC;AAAA,EAClF;AAAA,EAEA,MAAM,UAAkC;AAp/B1C;AAq/BI,UAAM,OAAO,MAAM,KAAK,QAAQ;AAChC,YAAO,kCAAM,SAAN,YAAc;AAAA,EACvB;AAAA,EAEA,YAAY,MAAc,OAAgC,CAAC,GAAyB;AAz/BtF;AA0/BI,WAAO,KAAK;AAAA,MACV;AAAA,QACE;AAAA,UACE,MAAM;AAAA,UACN,QAAQ,KAAK;AAAA,UACb;AAAA,UACA,mBAAkB,UAAK,qBAAL,YAAyB;AAAA,WACvC,KAAK,uBAAuB,SAC5B,EAAE,oBAAoB,KAAK,mBAAmB,IAC9C,CAAC;AAAA,MAET;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA,EAEA,aACE,OACA,OAA+B,CAAC,GACV;AACtB,WAAO,KAAK,qBAAqB,EAAE,WAAW,MAAM,GAAG,IAAI;AAAA,EAC7D;AAAA,EAEA,gBAAgB,OAAe,OAA+B,CAAC,GAAyB;AACtF,WAAO,KAAK,qBAAqB,EAAE,cAAc,MAAM,GAAG,IAAI;AAAA,EAChE;AAAA,EAEA,mBAAmB,OAAgB,OAA+B,CAAC,GAAyB;AAC1F,WAAO,KAAK,qBAAqB,EAAE,iBAAiB,MAAM,GAAG,IAAI;AAAA,EACnE;AAAA,EAEA,UACE,OACA,OAA+B,CAAC,GACV;AACtB,WAAO,KAAK,qBAAqB,EAAE,QAAQ,MAAM,GAAG,IAAI;AAAA,EAC1D;AAAA,EAEA,WACE,OACA,OAA+B,CAAC,GACV;AACtB,WAAO,KAAK,qBAAqB,EAAE,SAAS,MAAM,GAAG,IAAI;AAAA,EAC3D;AAAA,EAEA,aAAa,MAAc,OAA+B,CAAC,GAAyB;AAClF,WAAO,KAAK,gBAAgB,yBAAyB,MAAM,IAAI;AAAA,EACjE;AAAA,EAEA,YAAY,MAAc,OAA+B,CAAC,GAAyB;AACjF,WAAO,KAAK,gBAAgB,wBAAwB,MAAM,IAAI;AAAA,EAChE;AAAA,EAEA,iBACE,MACA,OAA+B,CAAC,GACV;AACtB,WAAO,KAAK;AAAA,MACV;AAAA,QACE;AAAA,UACE,MAAM;AAAA,UACN,cAAc,KAAK;AAAA,UACnB,OAAO,KAAK;AAAA,UACZ,aAAa,KAAK;AAAA,UAClB,UAAU,KAAK;AAAA,UACf,WAAW,KAAK;AAAA,QAClB;AAAA,MACF;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA,EAEA,iBACE,MACA,OAA+B,CAAC,GACV;AACtB,WAAO,KAAK;AAAA,MACV;AAAA,QACE;AAAA,UACE,MAAM;AAAA,UACN,cAAc,KAAK;AAAA,UACnB,UAAU,oBAAoB,IAAI;AAAA,QACpC;AAAA,MACF;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA,EAEA,OAAO,OAA+B,CAAC,GAAyB;AAllClE;AAmlCI,WAAO,KAAK;AAAA,MACV;AAAA,QACE;AAAA,UACE,MAAM;AAAA,UACN,QAAQ,KAAK;AAAA,UACb,mBAAkB,UAAK,qBAAL,YAAyB;AAAA,QAC7C;AAAA,MACF;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA,EAEA,WAAW,MAAc,OAA+B,CAAC,GAAyB;AAChF,WAAO,KAAK,MAAM,CAAC,EAAE,MAAM,cAAc,OAAO,KAAK,eAAe,GAAG,KAAK,CAAC,GAAG,IAAI;AAAA,EACtF;AAAA,EAEA,eAAe,MAAoB,OAA+B,CAAC,GAAyB;AAC1F,WAAO,KAAK,MAAM,CAAC,EAAE,MAAM,kBAAkB,MAAM,OAAO,KAAK,eAAe,EAAE,CAAC,GAAG,IAAI;AAAA,EAC1F;AAAA,EAEA,SAAS,QAAgB,OAAoC,CAAC,GAAc;AAvmC9E;AAwmCI,SAAK,kBAAkB;AACvB,WAAO,IAAI;AAAA,MACT,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,MACL;AAAA,OACA,UAAK,UAAL,YAAc;AAAA,IAChB;AAAA,EACF;AAAA,EAEQ,iBAAwB;AAC9B,WAAO,EAAE,QAAQ,KAAK,OAAO;AAAA,EAC/B;AAAA,EAEQ,qBACN,QACA,OAA+B,CAAC,GACV;AACtB,WAAO,KAAK,MAAM,CAAC,EAAE,MAAM,mBAAmB,QAAQ,KAAK,QAAQ,OAAO,CAAC,GAAG,IAAI;AAAA,EACpF;AAAA,EAEQ,gBACN,MACA,MACA,OAA+B,CAAC,GACV;AACtB,UAAM,OAAmD,EAAE,KAAK;AAChE,QAAI,KAAK,UAAU,OAAW,MAAK,QAAQ,KAAK;AAChD,QAAI,KAAK,cAAc,OAAW,MAAK,YAAY,KAAK;AACxD,WAAO,KAAK,MAAM,CAAC,EAAE,MAAM,cAAc,KAAK,QAAQ,KAAK,CAAC,GAAG,IAAI;AAAA,EACrE;AAAA,EAEQ,MAAM,KAAW,OAA+B,CAAC,GAAyB;AAChF,SAAK,kBAAkB;AACvB,WAAO,KAAK,UAAU,KAAkB,aAAa;AAAA,MACnD;AAAA,QACE;AAAA,QACA,SAAS,uBAAuB,IAAI;AAAA,MACtC;AAAA,IACF,CAAC;AAAA,EACH;AACF;AA1MyC;AAAzC,IAAM,gBAAN;AAwNA,SAAS,oBAAoB,MAAwC;AACnE,QAAM,OAAO,KAAK;AAClB,MAAI,KAAK,WAAW,GAAG;AACrB,UAAM,IAAI,MAAM,4CAA4C;AAAA,EAC9D;AAEA,QAAM,WAAW,KAAK,IAAI,GAAG,KAAK,IAAI,CAAC,QAAQ,IAAI,MAAM,CAAC;AAC1D,MAAI,aAAa,GAAG;AAClB,UAAM,IAAI,MAAM,+CAA+C;AAAA,EACjE;AAEA,QAAM,SAAS,MAAM;AAAA,IAAK,EAAE,QAAQ,SAAS;AAAA,IAAG,CAAC,GAAG,UAAO;AA1qC7D;AA2qCI,6BAAe,gBAAK,iBAAL,mBAAoB,WAApB,YAA8B,IAAI;AAAA;AAAA,EACnD;AACA,QAAM,OAAO,OAAO,IAAI,CAAC,UAAU,mBAAmB,KAAK,KAAK,EAAE,KAAK,EAAE;AACzE,QAAM,QAAQ,KAAK,eACf,sBAAsB,mBAAmB,KAAK,YAAY,CAAC,QAC3D;AACJ,QAAM,OAAO,KACV,IAAI,CAAC,QAAQ;AACZ,UAAM,QAAQ,OACX,IAAI,CAAC,OAAO,UAAO;AAprC5B;AAorC+B,mCAAqB,SAAI,KAAK,MAAT,YAAc,IAAI,KAAK;AAAA,KAAC,EACnE,KAAK,EAAE;AACV,WAAO,SAAS,KAAK;AAAA,EACvB,CAAC,EACA,KAAK,EAAE;AAEV,SAAO,mBAAmB,IAAI,cAAc,KAAK,uDAAuD,IAAI,eAAe,IAAI;AACjI;AA5BS;AA8BT,SAAS,qBAAqB,MAAc,OAAuB;AACjE,QAAM,YACJ,SAAS,KACL,WACA,uCAAuC,cAAc,IAAI,CAAC;AAChE,SAAO,6BAA6B,KAAK,4BAA4B,SAAS;AAChF;AANS;AAQT,SAAS,eAAe,OAAuB;AAC7C,MAAI,CAAC,OAAO,SAAS,KAAK,KAAK,SAAS,GAAG;AACzC,UAAM,IAAI,MAAM,8CAA8C;AAAA,EAChE;AACA,SAAO,KAAK,MAAM,KAAK;AACzB;AALS;AAOT,SAAS,cAAc,OAAuB;AAC5C,SAAO,MAAM,QAAQ,MAAM,OAAO,EAAE,QAAQ,MAAM,MAAM,EAAE,QAAQ,MAAM,MAAM;AAChF;AAFS;AAIT,SAAS,mBAAmB,OAAuB;AACjD,SAAO,cAAc,KAAK,EAAE,QAAQ,MAAM,QAAQ,EAAE,QAAQ,MAAM,QAAQ;AAC5E;AAFS;AAIT,IAAM,iBAAN,MAAM,eAAmC;AAAA,EACvC,YACmB,WACA,mBACA,QACA,QACA,OACjB;AALiB;AACA;AACA;AACA;AACA;AAAA,EAChB;AAAA,EAEH,YAAY,MAAc,OAA+B,CAAC,GAAyB;AACjF,WAAO,KAAK;AAAA,MACV;AAAA,QACE;AAAA,UACE,MAAM;AAAA,UACN,QAAQ,KAAK;AAAA,UACb,QAAQ,KAAK;AAAA,UACb,aAAa;AAAA,UACb,OAAO,KAAK;AAAA,QACd;AAAA,MACF;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA,EAEA,OAAO,OAA+B,CAAC,GAAyB;AAC9D,WAAO,KAAK,YAAY,IAAI,IAAI;AAAA,EAClC;AAAA,EAEA,QAAQ,OAAgB,OAA+B,CAAC,GAAyB;AAC/E,WAAO,KAAK,gBAAgB,EAAE,MAAM,MAAM,GAAG,IAAI;AAAA,EACnD;AAAA,EAEA,SAAS,OAAe,OAA+B,CAAC,GAAyB;AAC/E,WAAO,KAAK,gBAAgB,EAAE,OAAO,MAAM,GAAG,IAAI;AAAA,EACpD;AAAA,EAEA,UAAU,OAAgB,OAA+B,CAAC,GAAyB;AACjF,WAAO,KAAK,gBAAgB,EAAE,QAAQ,MAAM,GAAG,IAAI;AAAA,EACrD;AAAA,EAEA,aAAa,OAAgB,OAA+B,CAAC,GAAyB;AACpF,WAAO,KAAK,gBAAgB,EAAE,WAAW,MAAM,GAAG,IAAI;AAAA,EACxD;AAAA,EAEA,aAAa,OAAe,OAA+B,CAAC,GAAyB;AACnF,WAAO,KAAK,gBAAgB,EAAE,WAAW,MAAM,GAAG,IAAI;AAAA,EACxD;AAAA,EAEA,YAAY,OAAe,OAA+B,CAAC,GAAyB;AAClF,WAAO,KAAK,gBAAgB,EAAE,UAAU,MAAM,GAAG,IAAI;AAAA,EACvD;AAAA,EAEA,cAAc,OAAe,OAA+B,CAAC,GAAyB;AACpF,WAAO,KAAK,gBAAgB,EAAE,YAAY,MAAM,GAAG,IAAI;AAAA,EACzD;AAAA,EAEQ,gBACN,QACA,OAA+B,CAAC,GACV;AACtB,WAAO,KAAK;AAAA,MACV;AAAA,QACE;AAAA,UACE,MAAM;AAAA,UACN,QAAQ,KAAK;AAAA,UACb,QAAQ,KAAK;AAAA,UACb;AAAA,UACA,OAAO,KAAK;AAAA,QACd;AAAA,MACF;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA,EAEA,WAAW,MAAc,OAA+B,CAAC,GAAyB;AAChF,WAAO,KAAK,MAAM,CAAC,EAAE,MAAM,cAAc,OAAO,KAAK,kBAAkB,GAAG,KAAK,CAAC,GAAG,IAAI;AAAA,EACzF;AAAA,EAEA,eAAe,MAAoB,OAA+B,CAAC,GAAyB;AAC1F,WAAO,KAAK,MAAM,CAAC,EAAE,MAAM,kBAAkB,MAAM,OAAO,KAAK,kBAAkB,EAAE,CAAC,GAAG,IAAI;AAAA,EAC7F;AAAA,EAEQ,oBAA2B;AACjC,WAAO,EAAE,QAAQ,KAAK,QAAQ,MAAM,KAAK,QAAQ,OAAO,KAAK,MAAM;AAAA,EACrE;AAAA,EAEQ,MAAM,KAAW,OAA+B,CAAC,GAAyB;AAChF,SAAK,kBAAkB;AACvB,WAAO,KAAK,UAAU,KAAkB,aAAa;AAAA,MACnD;AAAA,QACE;AAAA,QACA,SAAS,uBAAuB,IAAI;AAAA,MACtC;AAAA,IACF,CAAC;AAAA,EACH;AACF;AA/FyC;AAAzC,IAAM,gBAAN;AAiGO,SAAS,kBACd,WACA,mBACa;AACb,QAAM,eAAe,wBAAC,SAAuB,IAAI,aAAa,WAAW,mBAAmB,IAAI,GAA3E;AAErB,SAAO;AAAA,IACL,MAAM,KAAK,MAAM;AACf,wBAAkB;AAClB,YAAM,SAAS,MAAM,UAAU,KAAqB,kBAAkB,CAAC,IAAI,CAAC;AAC5E,aAAO,OAAO,IAAI,YAAY;AAAA,IAChC;AAAA,IACA,MAAM,IAAI,MAAM;AACd,wBAAkB;AAClB,YAAM,OAAO,MAAM,UAAU,KAA0B,iBAAiB,CAAC,IAAI,CAAC;AAC9E,aAAO,OAAO,aAAa,IAAI,IAAI;AAAA,IACrC;AAAA,EACF;AACF;AAlBgB;AAoBhB,IAAM,gBAAN,MAAM,cAAiC;AAAA,EASrC,YACmB,WACA,mBACjB,MACA;AAHiB;AACA;AAVnB,wBAAS;AACT,wBAAS;AACT,wBAAS;AACT,wBAAS;AACT,wBAAS;AACT,wBAAS;AACT,wBAAS;AAOP,WAAO,OAAO,MAAM,IAAI;AACxB,SAAK,KAAK,KAAK;AAAA,EACjB;AAAA,EAEA,UAAwC;AACtC,SAAK,kBAAkB;AACvB,WAAO,KAAK,UAAU,KAA0B,iBAAiB,CAAC,KAAK,IAAI,CAAC;AAAA,EAC9E;AAAA,EAEA,MAAM,UAAkC;AAh2C1C;AAi2CI,UAAM,OAAO,MAAM,KAAK,QAAQ;AAChC,QAAI,CAAC,KAAM,QAAO;AAClB,QAAI,KAAK,cAAc,OAAQ,SAAO,UAAK,SAAL,YAAa;AACnD,QAAI,CAAC,KAAK,OAAQ,QAAO;AACzB,UAAM,YAAY,MAAM,KAAK,aAAa;AAC1C,YAAO,4CAAW,cAAX,YAAwB;AAAA,EACjC;AAAA,EAEA,MAAM,eAA0C;AAC9C,UAAM,OAAO,MAAM,KAAK,QAAQ;AAChC,QAAI,EAAC,6BAAM,QAAQ,QAAO;AAC1B,UAAM,YAAY,MAAM,KAAK,UAAU,KAA2B,kBAAkB;AAAA,MAClF,KAAK;AAAA,IACP,CAAC;AACD,WAAO,YACH,IAAI,cAAc,KAAK,WAAW,KAAK,mBAAmB,UAAU,QAAQ,UAAU,KAAK,IAC3F;AAAA,EACN;AAAA,EAEA,OAAO,OAA+B,CAAC,GAAyB;AAC9D,SAAK,kBAAkB;AACvB,WAAO,KAAK,UAAU,KAAkB,aAAa;AAAA,MACnD;AAAA,QACE,KAAK,CAAC,EAAE,MAAM,kBAAkB,MAAM,KAAK,KAAK,CAAC;AAAA,QACjD,SAAS,uBAAuB,IAAI;AAAA,MACtC;AAAA,IACF,CAAC;AAAA,EACH;AACF;AApDuC;AAAvC,IAAM,eAAN;AAsDO,SAAS,iBACd,WACA,mBACY;AACZ,QAAM,eAAe,wBAAC,SAAsB,IAAI,YAAY,WAAW,mBAAmB,IAAI,GAAzE;AAErB,SAAO;AAAA,IACL,MAAM,OAAO;AACX,wBAAkB;AAClB,YAAM,SAAS,MAAM,UAAU,KAAoB,iBAAiB,CAAC,CAAC;AACtE,aAAO,OAAO,IAAI,YAAY;AAAA,IAChC;AAAA,IACA,MAAM,IAAI,IAAI;AACZ,wBAAkB;AAClB,YAAM,OAAO,MAAM,UAAU,KAAyB,gBAAgB,CAAC,EAAE,CAAC;AAC1E,aAAO,OAAO,aAAa,IAAI,IAAI;AAAA,IACrC;AAAA,EACF;AACF;AAlBgB;AAoBhB,IAAM,eAAN,MAAM,aAA+B;AAAA,EASnC,YACmB,WACA,mBACjB,MACA;AAHiB;AACA;AAVnB,wBAAS;AACT,wBAAS;AACT,wBAAS;AACT,wBAAS;AACT,wBAAS;AACT,wBAAS;AACT,wBAAS;AAOP,WAAO,OAAO,MAAM,IAAI;AAAA,EAC1B;AAAA,EAEA,UAAuC;AACrC,SAAK,kBAAkB;AACvB,WAAO,KAAK,UAAU,KAAyB,gBAAgB,CAAC,KAAK,EAAE,CAAC;AAAA,EAC1E;AAAA,EAEA,MAAM,UAAkC;AAz6C1C;AA06CI,YAAQ,iBAAM,KAAK,QAAQ,MAAnB,mBAAuB,SAAvB,YAA+B;AAAA,EACzC;AAAA,EAEA,MAAM,gBAAwC;AA76ChD;AA86CI,UAAM,OAAO,MAAM,KAAK,QAAQ;AAChC,QAAI,CAAC,KAAM,QAAO;AAClB,QAAI,KAAK,cAAc,OAAQ,SAAO,UAAK,eAAL,YAAmB;AACzD,QAAI,CAAC,KAAK,OAAQ,QAAO;AACzB,UAAM,YAAY,MAAM,KAAK,aAAa;AAC1C,YAAO,4CAAW,cAAX,YAAwB;AAAA,EACjC;AAAA,EAEA,MAAM,eAA0C;AAC9C,UAAM,OAAO,MAAM,KAAK,QAAQ;AAChC,QAAI,EAAC,6BAAM,QAAQ,QAAO;AAC1B,UAAM,YAAY,MAAM,KAAK,UAAU,KAA2B,kBAAkB;AAAA,MAClF,KAAK;AAAA,IACP,CAAC;AACD,WAAO,YACH,IAAI,cAAc,KAAK,WAAW,KAAK,mBAAmB,UAAU,QAAQ,UAAU,KAAK,IAC3F;AAAA,EACN;AAAA,EAEA,OAAO,OAA+B,CAAC,GAAyB;AAC9D,SAAK,kBAAkB;AACvB,WAAO,KAAK,UAAU,KAAkB,aAAa;AAAA,MACnD;AAAA,QACE,KAAK,CAAC,EAAE,MAAM,iBAAiB,WAAW,KAAK,GAAG,CAAC;AAAA,QACnD,SAAS,uBAAuB,IAAI;AAAA,MACtC;AAAA,IACF,CAAC;AAAA,EACH;AACF;AAvDqC;AAArC,IAAM,cAAN;AAyDO,SAAS,kBACd,WACA,mBACa;AACb,QAAM,eAAe,wBAAC,SAAuB,IAAI,aAAa,WAAW,mBAAmB,IAAI,GAA3E;AAErB,SAAO;AAAA,IACL,MAAM,KAAK,MAAM;AACf,wBAAkB;AAClB,YAAM,SAAS,MAAM,UAAU,KAAqB,kBAAkB,CAAC,IAAI,CAAC;AAC5E,aAAO,OAAO,IAAI,YAAY;AAAA,IAChC;AAAA,IACA,MAAM,IAAI,OAAO,MAAM;AACrB,wBAAkB;AAClB,YAAM,OAAO,MAAM,UAAU,KAA0B,iBAAiB,CAAC,OAAO,IAAI,CAAC;AACrF,aAAO,OAAO,aAAa,IAAI,IAAI;AAAA,IACrC;AAAA,IACA,OAAO,OAAO,CAAC,GAAG;AAChB,wBAAkB;AAClB,aAAO,kBAAkB,WAAW,mBAAmB,IAAI;AAAA,IAC7D;AAAA,IACA,OAAO,OAAO,CAAC,GAAG;AAChB,wBAAkB;AAClB,aAAO,kBAAkB,WAAW,mBAAmB,IAAI;AAAA,IAC7D;AAAA,EACF;AACF;AA1BgB;AA4BhB,SAAS,kBACP,WACA,MACA,OAA4B,CAAC,GACP;AA5+CxB;AA6+CE,QAAM,KAAS,EAAE,MAAM,OAAO,EAAE,QAAO,UAAK,UAAL,YAAc,MAAM,EAAE;AAC7D,SAAO,UAAU,KAAkB,aAAa;AAAA,IAC9C;AAAA,MACE,KAAK,CAAC,EAAE;AAAA,MACR,SAAS,uBAAuB,IAAI;AAAA,IACtC;AAAA,EACF,CAAC;AACH;AAZS;AAcT,IAAM,gBAAN,MAAM,cAAiC;AAAA,EAUrC,YACmB,WACA,mBACjB,MACA;AAHiB;AACA;AAXnB,wBAAS;AACT,wBAAS;AACT,wBAAS;AACT,wBAAS;AACT,wBAAS;AACT,wBAAS;AACT,wBAAS;AACT,wBAAS;AAOP,WAAO,OAAO,MAAM,IAAI;AACxB,SAAK,KAAK,KAAK;AAAA,EACjB;AAAA,EAEA,QAAQ,MAA2D;AACjE,SAAK,kBAAkB;AACvB,WAAO,KAAK,UAAU,KAA0B,iBAAiB,CAAC,KAAK,OAAO,IAAI,CAAC;AAAA,EACrF;AAAA,EAEA,MAAM,UAAkC;AA9gD1C;AA+gDI,YAAQ,iBAAM,KAAK,QAAQ,EAAE,OAAO,MAAM,CAAC,MAAnC,mBAAuC,SAAvC,YAA+C;AAAA,EACzD;AAAA,EAEA,MAAM,eAA0C;AAC9C,UAAM,OAAO,MAAM,KAAK,QAAQ,EAAE,OAAO,MAAM,CAAC;AAChD,QAAI,EAAC,6BAAM,QAAQ,QAAO;AAC1B,UAAM,YAAY,MAAM,KAAK,UAAU,KAA2B,kBAAkB;AAAA,MAClF,KAAK;AAAA,IACP,CAAC;AACD,WAAO,YACH,IAAI,cAAc,KAAK,WAAW,KAAK,mBAAmB,UAAU,QAAQ,UAAU,KAAK,IAC3F;AAAA,EACN;AAAA,EAEA,OAAO,OAA+B,CAAC,GAAyB;AAC9D,WAAO,KAAK,cAAc,mBAAmB,IAAI;AAAA,EACnD;AAAA,EAEA,OAAO,OAA+B,CAAC,GAAyB;AAC9D,WAAO,KAAK,cAAc,mBAAmB,IAAI;AAAA,EACnD;AAAA,EAEQ,cACN,MACA,OAA+B,CAAC,GACV;AACtB,SAAK,kBAAkB;AACvB,UAAM,KAAS,EAAE,MAAM,OAAO,EAAE,OAAO,YAAY,OAAO,KAAK,MAAM,EAAE;AACvE,WAAO,KAAK,UAAU,KAAkB,aAAa;AAAA,MACnD;AAAA,QACE,KAAK,CAAC,EAAE;AAAA,QACR,SAAS,uBAAuB,IAAI;AAAA,MACtC;AAAA,IACF,CAAC;AAAA,EACH;AACF;AA5DuC;AAAvC,IAAM,eAAN;AA0FO,SAAS,gBACd,WACA,mBACW;AACX,QAAM,eAAe,wBAAC,SAAoB,IAAI,UAAU,WAAW,mBAAmB,IAAI,GAArE;AAErB,SAAO;AAAA,IACL,MAAM,KAAK,MAAM;AACf,wBAAkB;AAClB,YAAM,SAAS,MAAM,UAAU,KAAkB,eAAe,CAAC,IAAI,CAAC;AACtE,aAAO,OAAO,IAAI,YAAY;AAAA,IAChC;AAAA,IACA,MAAM,IAAI,SAAS;AACjB,wBAAkB;AAClB,YAAM,OAAO,MAAM,UAAU,KAAuB,cAAc,CAAC,OAAO,CAAC;AAC3E,aAAO,OAAO,aAAa,IAAI,IAAI;AAAA,IACrC;AAAA,IACA,MAAM,YAAY,SAAS;AACzB,wBAAkB;AAClB,aAAO,UAAU,KAA2B,sBAAsB,CAAC,OAAO,CAAC;AAAA,IAC7E;AAAA,EACF;AACF;AAtBgB;AAwBhB,IAAM,aAAN,MAAM,WAA2B;AAAA,EAmB/B,YACmB,WACA,mBACjB,MACA;AAHiB;AACA;AApBnB,wBAAS;AACT,wBAAS;AACT,wBAAS;AACT,wBAAS;AACT,wBAAS;AACT,wBAAS;AACT,wBAAS;AACT,wBAAS;AACT,wBAAS;AACT,wBAAS;AACT,wBAAS;AACT,wBAAS;AACT,wBAAS;AACT,wBAAS;AACT,wBAAS;AACT,wBAAS;AACT,wBAAS;AAOP,WAAO,OAAO,MAAM,IAAI;AACxB,SAAK,KAAK,KAAK;AAAA,EACjB;AAAA,EAEA,KAAK,KAAa,KAAwB;AACxC,SAAK,kBAAkB;AACvB,WAAO,IAAI,cAAc,KAAK,WAAW,KAAK,mBAAmB,MAAM,KAAK,GAAG;AAAA,EACjF;AAAA,EAEA,IAAI,KAAuB;AACzB,SAAK,kBAAkB;AACvB,WAAO,IAAI,aAAa,MAAM,GAAG;AAAA,EACnC;AAAA,EAEA,OAAO,KAA0B;AAC/B,SAAK,kBAAkB;AACvB,WAAO,IAAI,gBAAgB,MAAM,GAAG;AAAA,EACtC;AAAA,EAEA,MAAM,QAAQ,MAAqD;AAnpDrE;AAopDI,SAAK,kBAAkB;AACvB,QAAI,CAAC,MAAM;AACT,aAAO,KAAK,UAAU,KAAuB,cAAc,CAAC,KAAK,OAAO,CAAC;AAAA,IAC3E;AACA,UAAM,SAAS,MAAM,KAAK,UAAU,KAAkB,eAAe;AAAA,MACnE;AAAA,QACE,OAAO;AAAA,QACP,eAAe;AAAA,SACZ;AAAA,IAEP,CAAC;AACD,YAAO,YAAO,KAAK,CAAC,UAAU,MAAM,YAAY,KAAK,OAAO,MAArD,YAA0D;AAAA,EACnE;AAAA,EAEA,cAA6C;AAC3C,SAAK,kBAAkB;AACvB,WAAO,KAAK,UAAU,KAA2B,sBAAsB,CAAC,KAAK,OAAO,CAAC;AAAA,EACvF;AAAA,EAEA,MAAM,QAAQ,MAAkD;AAvqDlE;AAwqDI,UAAM,QAAQ,MAAM,KAAK,SAAS,IAAI;AACtC,YAAO,oCAAO,IAAI,CAAC,QAAQ,IAAI,KAAK,GAAI,GAAG,KAAK,UAAzC,YAAkD;AAAA,EAC3D;AAAA,EAEA,MAAM,SAAS,MAAsD;AA5qDvE;AA6qDI,UAAM,OAAO,MAAM,KAAK,QAAQ;AAAA,MAC9B,OAAO;AAAA,MACP,eAAe;AAAA,OACZ,OAH2B;AAAA,MAI9B,kBAAkB;AAAA,IACpB,EAAC;AACD,YAAO,kCAAM,UAAN,YAAe;AAAA,EACxB;AAAA,EAEA,WAAW,MAAc,OAA+B,CAAC,GAAyB;AAChF,WAAO,KAAK,MAAM,CAAC,EAAE,MAAM,mBAAmB,SAAS,KAAK,SAAS,KAAK,CAAC,GAAG,IAAI;AAAA,EACpF;AAAA,EAEA,OAAO,OAA2B,CAAC,GAAyB;AA1rD9D;AA2rDI,WAAO,KAAK;AAAA,MACV;AAAA,QACE;AAAA,UACE,MAAM;AAAA,UACN,SAAS,KAAK;AAAA,UACd,mBAAkB,UAAK,qBAAL,YAAyB;AAAA,QAC7C;AAAA,MACF;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA,EAEA,gBACE,KACA,KACA,MACA,OAA8B,CAAC,GACT;AA5sD1B;AA6sDI,WAAO,KAAK;AAAA,MACV;AAAA,QACE;AAAA,UACE,MAAM;AAAA,UACN,SAAS,KAAK;AAAA,UACd;AAAA,UACA;AAAA,UACA;AAAA,UACA,mBAAkB,UAAK,qBAAL,YAAyB;AAAA,QAC7C;AAAA,MACF;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA,EAEA,UAAU,KAAa,OAA8B,CAAC,GAAyB;AA5tDjF;AA6tDI,WAAO,KAAK;AAAA,MACV;AAAA,QACE;AAAA,UACE,MAAM;AAAA,UACN,SAAS,KAAK;AAAA,UACd;AAAA,UACA,mBAAkB,UAAK,qBAAL,YAAyB;AAAA,QAC7C;AAAA,MACF;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA,EAEA,UACE,MACA,OAA+B,CAAC,GACV;AACtB,WAAO,KAAK;AAAA,MACV;AAAA,QACE;AAAA,UACE,MAAM;AAAA,UACN,SAAS,KAAK;AAAA,UACd,aAAa,KAAK;AAAA,UAClB,UAAU,KAAK;AAAA,UACf,WAAW,KAAK;AAAA,QAClB;AAAA,MACF;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA,EAEA,gBAAgB,QAAkB,OAA+B,CAAC,GAAyB;AACzF,WAAO,KAAK,MAAM,CAAC,EAAE,MAAM,wBAAwB,SAAS,KAAK,SAAS,OAAO,CAAC,GAAG,IAAI;AAAA,EAC3F;AAAA,EAEA,cACE,SACA,OAA+B,CAAC,GACV;AACtB,WAAO,KAAK,MAAM,CAAC,EAAE,MAAM,sBAAsB,SAAS,KAAK,SAAS,QAAQ,CAAC,GAAG,IAAI;AAAA,EAC1F;AAAA,EAEQ,MAAM,KAAW,OAA+B,CAAC,GAAyB;AAChF,SAAK,kBAAkB;AACvB,WAAO,KAAK,UAAU,KAAkB,aAAa;AAAA,MACnD;AAAA,QACE;AAAA,QACA,SAAS,uBAAuB,IAAI;AAAA,MACtC;AAAA,IACF,CAAC;AAAA,EACH;AACF;AAxKiC;AAAjC,IAAM,YAAN;AA0KA,IAAM,iBAAN,MAAM,eAAmC;AAAA,EAGvC,YACmB,WACA,mBACA,OACR,KACA,KACT;AALiB;AACA;AACA;AACR;AACA;AAPX,wBAAS;AASP,SAAK,UAAU,MAAM;AAAA,EACvB;AAAA,EAEA,MAAM,QAAQ,MAAyD;AA/xDzE;AAgyDI,UAAM,OAAO,MAAM,KAAK,MAAM,QAAQ;AAAA,MACpC,OAAO;AAAA,MACP,eAAe;AAAA,OACZ,OAHiC;AAAA,MAIpC,kBAAkB;AAAA,IACpB,EAAC;AACD,YAAO,8CAAM,aAAN,mBAAiB,KAAK,SAAtB,mBAA6B,KAAK,SAAlC,YAA0C;AAAA,EACnD;AAAA,EAEA,MAAM,UAAU,MAA4D;AAC1E,UAAM,OAAO,MAAM,KAAK,QAAQ,IAAI;AACpC,QAAI,CAAC,KAAM,QAAO;AAClB,UAAM,SAA2B,CAAC;AAClC,aAAS,QAAQ,GAAG,QAAQ,KAAK,OAAO,QAAQ,SAAS;AACvD,YAAM,QAAQ,KAAK,OAAO,KAAK;AAC/B,YAAM,SAAS,MAAM,KAAK,YAAY,OAAO,KAAK;AAClD,UAAI,OAAQ,QAAO,KAAK,MAAM;AAAA,IAChC;AACA,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,cAAc,MAAgD;AAClE,UAAM,OAAO,MAAM,KAAK,QAAQ,IAAI;AACpC,QAAI,CAAC,KAAM,QAAO,CAAC;AACnB,UAAM,aAAa,MAAM,QAAQ;AAAA,MAC/B,KAAK,aAAa;AAAA,QAAI,CAAC,WACrB,KAAK,UAAU,KAA2B,kBAAkB,CAAC,MAAM,CAAC;AAAA,MACtE;AAAA,IACF;AACA,WAAO,WACJ,OAAO,CAAC,cAA0C,cAAc,IAAI,EACpE;AAAA,MACC,CAAC,cACC,IAAI;AAAA,QACF,KAAK;AAAA,QACL,KAAK;AAAA,QACL,UAAU;AAAA,QACV,UAAU;AAAA,MACZ;AAAA,IACJ;AAAA,EACJ;AAAA,EAEA,MAAM,QAAQ,MAAkD;AA10DlE;AA20DI,YAAQ,iBAAM,KAAK,QAAQ,IAAI,MAAvB,mBAA2B,SAA3B,YAAmC;AAAA,EAC7C;AAAA,EAEA,SAAS,QAAgB,OAAoC,CAAC,GAAkB;AA90DlF;AA+0DI,SAAK,kBAAkB;AACvB,WAAO,IAAI,kBAAkB,MAAM,SAAQ,UAAK,UAAL,YAAc,OAAO;AAAA,EAClE;AAAA,EAEA,YAAY,MAAc,MAAoD;AAC5E,WAAO,KAAK,MAAM,gBAAgB,KAAK,KAAK,KAAK,KAAK,MAAM,IAAI;AAAA,EAClE;AAAA,EAEA,uBAAuB,MAAc,MAAqD;AACxF,WAAO,KAAK,gBAAgB,MAAM,SAAS,IAAI;AAAA,EACjD;AAAA,EAEA,qBAAqB,MAAc,MAAqD;AACtF,WAAO,KAAK,gBAAgB,MAAM,OAAO,IAAI;AAAA,EAC/C;AAAA,EAEA,WAAW,MAAc,MAAqD;AAC5E,WAAO,KAAK,gBAAgB,EAAE,SAAS,EAAE,KAAK,EAAE,GAAG,IAAI;AAAA,EACzD;AAAA,EAEA,qBACE,OACA,MACsB;AACtB,WAAO,KAAK,gBAAgB,EAAE,mBAAmB,MAAM,GAAG,IAAI;AAAA,EAChE;AAAA,EAEA,SAAS,OAAe,MAAqD;AAC3E,WAAO,KAAK,gBAAgB,EAAE,MAAM,GAAG,IAAI;AAAA,EAC7C;AAAA,EAEA,MAAc,YACZ,OACA,OACgC;AAChC,QAAI,MAAM,SAAS,WAAW;AAC5B,YAAMK,QAAO,MAAM,KAAK,UAAU,KAAyB,gBAAgB,CAAC,MAAM,SAAS,CAAC;AAC5F,YAAM,UAAUA,QAAO,IAAI,YAAY,KAAK,WAAW,KAAK,mBAAmBA,KAAI,IAAI;AACvF,aAAO,YAAY,SAAS,MAAM,SAC9B,EAAE,MAAM,WAAW,SAAS,WAAW,MAAM,WAAW,QAAQ,MAAM,QAAQ,MAAM,IACpF,EAAE,MAAM,WAAW,SAAS,WAAW,MAAM,WAAW,MAAM;AAAA,IACpE;AACA,QAAI,MAAM,SAAS,SAAS;AAC1B,YAAMA,QAAO,MAAM,KAAK,UAAU,KAAuB,cAAc,CAAC,MAAM,OAAO,CAAC;AACtF,aAAO;AAAA,QACL,MAAM;AAAA,QACN,SAAS,MAAM;AAAA,QACf,OAAOA,QAAO,IAAI,UAAU,KAAK,WAAW,KAAK,mBAAmBA,KAAI,IAAI;AAAA,QAC5E;AAAA,MACF;AAAA,IACF;AAEA,UAAM,OAAO,MAAM,KAAK,UAAU,KAA2B,kBAAkB,CAAC,MAAM,MAAM,CAAC;AAC7F,QAAI,CAAC,KAAM,QAAO;AAClB,WAAO;AAAA,MACL,MAAM;AAAA,MACN,WAAW,IAAI,cAAc,KAAK,WAAW,KAAK,mBAAmB,KAAK,QAAQ,KAAK,KAAK;AAAA,MAC5F,QAAQ,MAAM;AAAA,MACd,MAAM,MAAM;AAAA,MACZ;AAAA,IACF;AAAA,EACF;AAAA,EAEQ,gBACN,QACA,OAA+B,CAAC,GACV;AACtB,WAAO,KAAK;AAAA,MACV;AAAA,QACE;AAAA,UACE,MAAM;AAAA,UACN,SAAS,KAAK;AAAA,UACd,KAAK,KAAK;AAAA,UACV,KAAK,KAAK;AAAA,UACV;AAAA,QACF;AAAA,MACF;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA,EAEQ,gBACN,MACA,UACA,OAA+B,CAAC,GACV;AACtB,WAAO,KAAK;AAAA,MACV;AAAA,QACE;AAAA,UACE,MAAM;AAAA,UACN,SAAS,KAAK;AAAA,UACd,KAAK,KAAK;AAAA,UACV,KAAK,KAAK;AAAA,UACV;AAAA,UACA;AAAA,QACF;AAAA,MACF;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA,EAEQ,MAAM,KAAW,OAA+B,CAAC,GAAyB;AAChF,SAAK,kBAAkB;AACvB,WAAO,KAAK,UAAU,KAAkB,aAAa;AAAA,MACnD;AAAA,QACE;AAAA,QACA,SAAS,uBAAuB,IAAI;AAAA,MACtC;AAAA,IACF,CAAC;AAAA,EACH;AACF;AA3KyC;AAAzC,IAAM,gBAAN;AA6KA,IAAM,qBAAN,MAAM,mBAA2C;AAAA,EAC/C,YACmB,MACA,QACA,OACjB;AAHiB;AACA;AACA;AAAA,EAChB;AAAA,EAEH,MAAM,YAAY,MAAc,MAAqD;AACnF,WAAO,KAAK,MAAM,CAAC,UAAU,MAAM,YAAY,MAAM,IAAI,CAAC;AAAA,EAC5D;AAAA,EAEA,MAAM,OAAO,MAAqD;AAChE,WAAO,KAAK,YAAY,IAAI,IAAI;AAAA,EAClC;AAAA,EAEA,MAAM,QAAQ,OAAgB,MAAqD;AACjF,WAAO,KAAK,MAAM,CAAC,UAAU,MAAM,QAAQ,OAAO,IAAI,CAAC;AAAA,EACzD;AAAA,EAEA,MAAM,SAAS,OAAe,MAAqD;AACjF,WAAO,KAAK,MAAM,CAAC,UAAU,MAAM,SAAS,OAAO,IAAI,CAAC;AAAA,EAC1D;AAAA,EAEA,MAAM,UAAU,OAAgB,MAAqD;AACnF,WAAO,KAAK,MAAM,CAAC,UAAU,MAAM,UAAU,OAAO,IAAI,CAAC;AAAA,EAC3D;AAAA,EAEA,MAAM,aAAa,OAAgB,MAAqD;AACtF,WAAO,KAAK,MAAM,CAAC,UAAU,MAAM,aAAa,OAAO,IAAI,CAAC;AAAA,EAC9D;AAAA,EAEA,MAAM,aAAa,OAAe,MAAqD;AACrF,WAAO,KAAK,MAAM,CAAC,UAAU,MAAM,aAAa,OAAO,IAAI,CAAC;AAAA,EAC9D;AAAA,EAEA,MAAM,YAAY,OAAe,MAAqD;AACpF,WAAO,KAAK,MAAM,CAAC,UAAU,MAAM,YAAY,OAAO,IAAI,CAAC;AAAA,EAC7D;AAAA,EAEA,MAAM,cAAc,OAAe,MAAqD;AACtF,WAAO,KAAK,MAAM,CAAC,UAAU,MAAM,cAAc,OAAO,IAAI,CAAC;AAAA,EAC/D;AAAA,EAEA,MAAM,WAAW,MAAc,MAAqD;AAClF,WAAO,KAAK,MAAM,CAAC,UAAU,MAAM,WAAW,MAAM,IAAI,CAAC;AAAA,EAC3D;AAAA,EAEA,MAAM,eAAe,MAAoB,MAAqD;AAC5F,WAAO,KAAK,MAAM,CAAC,UAAU,MAAM,eAAe,MAAM,IAAI,CAAC;AAAA,EAC/D;AAAA,EAEA,MAAc,MAAM,IAAsE;AACxF,UAAM,aAAa,MAAM,KAAK,KAAK,cAAc;AACjD,UAAM,UAAuB,CAAC;AAC9B,eAAW,aAAa,YAAY;AAClC,YAAM,OAAO,MAAM,UAAU,QAAQ;AACrC,UAAI,6BAAM,SAAS,KAAK,SAAS;AAC/B,gBAAQ,KAAK,SAAS;AACtB,YAAI,KAAK,UAAU,QAAS;AAAA,MAC9B;AAAA,IACF;AACA,QAAI,QAAQ,WAAW,GAAG;AACxB,YAAM,IAAI;AAAA,QACR,wBAAwB,KAAK,MAAM,yBAAyB,KAAK,KAAK,OAAO,WAAW,KAAK,KAAK,GAAG,KAAK,KAAK,KAAK,GAAG;AAAA,MACzH;AAAA,IACF;AAEA,QAAI;AACJ,eAAW,aAAa,SAAS;AAC/B,aAAO,MAAM,GAAG,UAAU,SAAS,KAAK,QAAQ,EAAE,OAAO,KAAK,MAAM,CAAC,CAAC;AAAA,IACxE;AACA,WAAO;AAAA,EACT;AACF;AAzEiD;AAAjD,IAAM,oBAAN;AA2EA,IAAM,gBAAN,MAAM,cAAiC;AAAA,EAGrC,YACmB,OACR,OACT;AAFiB;AACR;AAJX,wBAAS;AAMP,SAAK,UAAU,MAAM;AAAA,EACvB;AAAA,EAEA,MAAM,SAAS,MAAoD;AAphErE;AAqhEI,UAAM,QAAQ,MAAM,KAAK,MAAM,SAAS,IAAI;AAC5C,YAAO,oCAAQ,KAAK,WAAb,YAAuB;AAAA,EAChC;AAAA,EAEA,MAAM,QAAQ,MAAkD;AAzhElE;AA0hEI,UAAM,QAAQ,MAAM,KAAK,SAAS,IAAI;AACtC,YAAO,oCAAO,KAAK,SAAZ,YAAqB;AAAA,EAC9B;AAAA,EAEA,OAAO,MAAoD;AACzD,WAAO,KAAK,MAAM,UAAU,KAAK,OAAO,IAAI;AAAA,EAC9C;AAAA,EAEA,aAAa,WAAsB,MAAqD;AACtF,WAAO,KAAK,MAAM,UAAU,EAAE,aAAa,KAAK,OAAO,UAAU,KAAK,OAAO,UAAU,GAAG,IAAI;AAAA,EAChG;AAAA,EAEA,YAAY,WAAsB,MAAqD;AACrF,WAAO,KAAK,MAAM;AAAA,MAChB,EAAE,aAAa,KAAK,OAAO,UAAU,KAAK,QAAQ,GAAG,UAAU;AAAA,MAC/D;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAM,UAAU,QAA0B,MAAqD;AA7iEjG;AA8iEI,UAAM,OAAO,MAAM,KAAK,MAAM,QAAQ;AACtC,UAAM,YAAW,kCAAM,eAAN,YAAoB,KAAK,MAAM,YAAY,MAAM;AAClE,YAAQ,KAAK,KAAK,IAAI;AACtB,WAAO,KAAK,MAAM,cAAc,SAAS,IAAI;AAAA,EAC/C;AACF;AAzCuC;AAAvC,IAAM,eAAN;AA2CA,IAAM,mBAAN,MAAM,iBAAuC;AAAA,EAG3C,YACmB,OACR,OACT;AAFiB;AACR;AAJX,wBAAS;AAMP,SAAK,UAAU,MAAM;AAAA,EACvB;AAAA,EAEA,MAAM,SAAS,MAAoD;AACjE,UAAM,QAAQ,MAAM,KAAK,MAAM,SAAS,IAAI;AAC5C,QAAI,CAAC,MAAO,QAAO;AACnB,WAAO,MAAM,IAAI,CAAC,QAAK;AAlkE3B;AAkkE8B,uBAAI,KAAK,KAAK,MAAd,YAAmB;AAAA,KAAE;AAAA,EACjD;AAAA,EAEA,MAAM,QAAQ,MAAkD;AArkElE;AAskEI,UAAM,QAAQ,MAAM,KAAK,SAAS,IAAI;AACtC,YAAO,oCAAO,KAAK,UAAZ,YAAqB;AAAA,EAC9B;AAAA,EAEA,MAAM,SAAS,OAAe,MAAqD;AA1kErF;AA2kEI,UAAM,OAAO,MAAM,KAAK,MAAM,QAAQ;AACtC,UAAM,WAAU,kCAAM,iBAAN,YAAsB,KAAK,MAAM,cAAc,MAAM;AACrE,WAAO,KAAK,KAAK,IAAI;AACrB,WAAO,KAAK,MAAM,gBAAgB,QAAQ,IAAI;AAAA,EAChD;AACF;AA3B6C;AAA7C,IAAM,kBAAN;AA8DA,IAAM,eAAN,MAAM,aAA+B;AAAA,EAWnC,YACmB,WACA,mBACjB,MACA;AAHiB;AACA;AAZnB,wBAAS;AACT,wBAAS;AACT,wBAAS;AACT,wBAAS;AACT,wBAAS;AACT,wBAAS;AACT,wBAAS;AACT,wBAAS;AACT,wBAAS;AAOP,WAAO,OAAO,MAAM,IAAI;AACxB,SAAK,KAAK,KAAK;AAAA,EACjB;AAAA,EAEA,UAAuC;AACrC,SAAK,kBAAkB;AACvB,WAAO,KAAK,UAAU,KAAyB,gBAAgB,CAAC,KAAK,SAAS,CAAC;AAAA,EACjF;AAAA,EAEA,gBAAmD;AACjD,SAAK,kBAAkB;AACvB,WAAO,KAAK,UAAU,KAA+B,0BAA0B;AAAA,MAC7E,KAAK;AAAA,IACP,CAAC;AAAA,EACH;AAAA,EAEA,OAAO,OAA+B,CAAC,GAAyB;AAC9D,WAAO,KAAK,MAAM,CAAC,EAAE,MAAM,iBAAiB,WAAW,KAAK,UAAU,CAAC,GAAG,IAAI;AAAA,EAChF;AAAA,EAEA,uBAAuB,OAA+B,CAAC,GAAyB;AAC9E,WAAO,KAAK,MAAM,CAAC,EAAE,MAAM,iCAAiC,WAAW,KAAK,UAAU,CAAC,GAAG,IAAI;AAAA,EAChG;AAAA,EAEA,sBACE,aACA,OAA+B,CAAC,GACV;AACtB,WAAO,KAAK;AAAA,MACV,CAAC,EAAE,MAAM,yBAAyB,WAAW,KAAK,WAAW,YAAY,CAAC;AAAA,MAC1E;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAM,UAAkC;AArqE1C;AAsqEI,UAAM,OAAO,MAAM,KAAK,QAAQ;AAChC,QAAI,CAAC,QAAQ,KAAK,SAAS,UAAW,QAAO;AAC7C,YAAO,UAAK,cAAL,YAAkB;AAAA,EAC3B;AAAA,EAEA,MAAM,gBAAsC;AA3qE9C;AA4qEI,UAAM,OAAO,MAAM,KAAK,QAAQ;AAChC,QAAI,CAAC,QAAQ,KAAK,SAAS,UAAW,QAAO,CAAC;AAC9C,UAAM,aAA0B,CAAC;AACjC,eAAW,WAAU,UAAK,sBAAL,YAA0B,CAAC,GAAG;AACjD,YAAM,gBAAgB,MAAM,KAAK,UAAU,KAA2B,kBAAkB;AAAA,QACtF;AAAA,MACF,CAAC;AACD,UAAI,eAAe;AACjB,mBAAW;AAAA,UACT,IAAI;AAAA,YACF,KAAK;AAAA,YACL,KAAK;AAAA,YACL,cAAc;AAAA,YACd,cAAc;AAAA,UAChB;AAAA,QACF;AAAA,MACF;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,YAAqC;AAjsE7C;AAksEI,UAAM,OAAO,MAAM,KAAK,QAAQ;AAChC,QAAI,CAAC,QAAQ,KAAK,SAAS,UAAW,QAAO,CAAC;AAC9C,UAAM,SAAyB,CAAC;AAChC,aAAS,QAAQ,GAAG,UAAS,UAAK,gBAAL,YAAoB,CAAC,GAAG,QAAQ,SAAS;AACpE,YAAM,QAAQ,KAAK,YAAa,KAAK;AACrC,YAAM,SAAS,MAAM,KAAK,mBAAmB,OAAO,KAAK;AACzD,UAAI,OAAQ,QAAO,KAAK,MAAM;AAAA,IAChC;AACA,WAAO;AAAA,EACT;AAAA,EAEA,YAAY,MAAc,OAA+B,CAAC,GAAyB;AACjF,WAAO,KAAK;AAAA,MACV,CAAC,EAAE,MAAM,yBAAyB,WAAW,KAAK,WAAW,aAAa,KAAK,CAAC;AAAA,MAChF;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAc,mBACZ,OACA,OAC8B;AAC9B,QAAI,MAAM,SAAS,WAAW;AAC5B,YAAMC,QAAO,MAAM,KAAK,UAAU,KAAyB,gBAAgB,CAAC,MAAM,SAAS,CAAC;AAC5F,YAAM,UAAUA,QAAO,IAAI,aAAY,KAAK,WAAW,KAAK,mBAAmBA,KAAI,IAAI;AACvF,aAAO,YAAY,SAAS,MAAM,SAC9B,EAAE,MAAM,WAAW,SAAS,WAAW,MAAM,WAAW,QAAQ,MAAM,QAAQ,MAAM,IACpF,EAAE,MAAM,WAAW,SAAS,WAAW,MAAM,WAAW,MAAM;AAAA,IACpE;AAEA,QAAI,MAAM,SAAS,SAAS;AAC1B,YAAMA,QAAO,MAAM,KAAK,UAAU,KAAuB,cAAc,CAAC,MAAM,OAAO,CAAC;AACtF,aAAO;AAAA,QACL,MAAM;AAAA,QACN,SAAS,MAAM;AAAA,QACf,OAAOA,QAAO,IAAI,UAAU,KAAK,WAAW,KAAK,mBAAmBA,KAAI,IAAI;AAAA,QAC5E;AAAA,MACF;AAAA,IACF;AAEA,UAAM,OAAO,MAAM,KAAK,UAAU,KAA2B,kBAAkB,CAAC,MAAM,MAAM,CAAC;AAC7F,QAAI,CAAC,KAAM,QAAO;AAClB,WAAO;AAAA,MACL,MAAM;AAAA,MACN,WAAW,IAAI,cAAc,KAAK,WAAW,KAAK,mBAAmB,KAAK,QAAQ,KAAK,KAAK;AAAA,MAC5F,QAAQ,MAAM;AAAA,MACd,MAAM,MAAM;AAAA,MACZ;AAAA,IACF;AAAA,EACF;AAAA,EAEQ,MAAM,KAAW,OAA+B,CAAC,GAAyB;AAChF,SAAK,kBAAkB;AACvB,WAAO,KAAK,UAAU,KAAkB,aAAa;AAAA,MACnD;AAAA,QACE;AAAA,QACA,SAAS,uBAAuB,IAAI;AAAA,MACtC;AAAA,IACF,CAAC;AAAA,EACH;AACF;AA3IqC;AAArC,IAAM,cAAN;;;ACxjEA,SAAS,uBAAuB,QAA2B;AACzD,SAAO;AAAA,IACL,MAAM,KAAQ,QAAsB,MAAiB,YAAyC;AAC5F,UAAI,WAAW,aAAa;AAC1B,cAAM,CAAC,MAAM,IAAI;AACjB,cAAMC,UAAS,MAAM,OAAO,UAAU,QAAQ,EAAE,QAAQ,SAAS,CAAC;AAClE,eAAOA;AAAA,MACT;AACA,YAAM,UAAU,eAAe,MAAM;AACrC,YAAM,SAAS,MAAM,QAAQ,EAAE,QAAQ,WAAW,GAAG,IAAI;AACzD,aAAO;AAAA,IACT;AAAA,IACA,gBAAgB;AACd,aAAO,QAAQ;AAAA,QACb,IAAI,MAAM,6DAA6D;AAAA,MACzE;AAAA,IACF;AAAA,IACA,UAAU;AACR,aAAO,QAAQ,QAAQ;AAAA,IACzB;AAAA,IACA,WAAW;AACT,aAAO,MAAM;AAAA,MAAC;AAAA,IAChB;AAAA,EACF;AACF;AAxBS;AAmCF,SAAS,iBAAiB,QAA4B;AAC3D,QAAM,QAAQ,OAAO,SAAS;AAC9B,MAAI,CAAC,OAAO;AACV,UAAM,IAAI;AAAA,MACR;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACA,QAAM,YAAY,uBAAuB,MAAM;AAC/C,QAAM,OAAO,6BAAM;AAAA,EAAC,GAAP;AACb,SAAO;AAAA,IACL;AAAA,IACA,YAAY,mBAAmB,WAAW,IAAI;AAAA,IAC9C,WAAW,kBAAkB,WAAW,IAAI;AAAA,IAC5C,UAAU,iBAAiB,WAAW,IAAI;AAAA,IAC1C,WAAW,kBAAkB,WAAW,IAAI;AAAA,IAC5C,QAAQ,gBAAgB,WAAW,IAAI;AAAA,IACvC,KAAK,MAA8B;AAhHvC;AAiHM,YAAM,WAAwB;AAAA,QAC5B,eAAc,kCAAM,iBAAN,YAAsB;AAAA,MACtC;AACA,WAAI,6BAAM,YAAW,OAAW,UAAS,SAAS,KAAK;AACvD,WAAI,6BAAM,UAAS,OAAW,UAAS,OAAO,KAAK;AACnD,aAAO,IAAI,aAAa,EAAE,OAAO,WAAW,SAAS,SAAS,CAAC;AAAA,IACjE;AAAA,EACF;AACF;AA3BgB;;;AC5ChB,eAAsB,cACpB,QACA,MACA,MACA,WACA,QACkB;AAGlB,QAAM,cAAc,yBAAyB,IAAI;AAEjD,MAAI;AACJ,MAAI;AACF,eAAW,IAAI,SAAS,OAAO,QAAQ,MAAM,WAAW;AAAA,EAK1D,SAAS,KAAK;AACZ,UAAM,MAAM,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAC3D,UAAM,IAAI,MAAM,wBAAwB,GAAG,EAAE;AAAA,EAC/C;AAKA,QAAM,MAAM,iBAAiB,MAAM;AACnC,QAAM,iBAAiB,YAAY,SAAS,KAAK,MAAM,MAAS,GAAG;AAGnE,MAAI,iCAAQ,SAAS;AACnB,UAAM,IAAI,MAAM,gBAAgB;AAAA,EAClC;AAGA,QAAM,SAA6B,CAAC,aAAa;AACjD,MAAI;AACJ,MAAI;AACJ,QAAM,WAA2B,CAAC;AAElC,MAAI,YAAY,GAAG;AACjB,WAAO;AAAA,MACL,IAAI,QAAe,CAAC,GAAG,WAAW;AAChC,wBAAgB,WAAW,MAAM;AAC/B,iBAAO,IAAI,MAAM,wBAAwB,SAAS,IAAI,CAAC;AAAA,QACzD,GAAG,SAAS;AAAA,MACd,CAAC;AAAA,IACH;AACA,aAAS,KAAK,MAAM;AAClB,UAAI,cAAe,cAAa,aAAa;AAAA,IAC/C,CAAC;AAAA,EACH;AAEA,MAAI,QAAQ;AACV,WAAO;AAAA,MACL,IAAI,QAAe,CAAC,GAAG,WAAW;AAChC,uBAAe,6BAAM,OAAO,IAAI,MAAM,gBAAgB,CAAC,GAAxC;AACf,eAAO,iBAAiB,SAAS,cAAc,EAAE,MAAM,KAAK,CAAC;AAAA,MAC/D,CAAC;AAAA,IACH;AACA,aAAS,KAAK,MAAM;AAClB,UAAI,aAAc,QAAO,oBAAoB,SAAS,YAAY;AAAA,IACpE,CAAC;AAAA,EACH;AAEA,MAAI;AACF,WAAO,MAAM,QAAQ,KAAK,MAAM;AAAA,EAClC,UAAE;AACA,eAAW,WAAW,SAAU,SAAQ;AAAA,EAC1C;AACF;AAtEsB;;;ACxBtB,IAAM,wBAAwB;AAYvB,SAAS,uBAAuB,MAA+C;AACpF,QAAM,SAAS,IAAI,OAAO;AAM1B,SAAO,SAAS,CAAC,OAAO;AACtB,SAAK,EAAE,MAAM,SAAS,OAAO,mBAAmB,SAAS,GAAG,CAAoB;AAAA,EAClF,CAAC;AAED,SAAO,sCAAeC,UAAS,KAA6B;AAE1D,QAAI,QAAQ,QAAQ,OAAO,QAAQ,SAAU;AAC7C,UAAM,MAAM;AACZ,QAAI,IAAI,SAAS,UAAW;AAC5B,UAAM,MAAM;AAGZ,QAAI,IAAI,WAAW,uBAAuB;AACxC,UAAI;AACF,cAAM,CAAC,MAAM,MAAM,SAAS,IAAI,IAAI;AAKpC,cAAM,SAAS,MAAM,cAAc,QAAQ,MAAM,MAAM,SAAS;AAChE,aAAK,EAAE,MAAM,YAAY,IAAI,IAAI,IAAI,OAAO,CAAuB;AAAA,MACrE,SAAS,GAAG;AACV,aAAK,EAAE,MAAM,SAAS,IAAI,IAAI,IAAI,OAAO,eAAe,CAAC,EAAE,CAAoB;AAAA,MACjF;AACA;AAAA,IACF;AAEA,UAAM,UAAU,eAAe,IAAI,MAAsB;AACzD,QAAI,CAAC,SAAS;AACZ,WAAK;AAAA,QACH,MAAM;AAAA,QACN,IAAI,IAAI;AAAA,QACR,OAAO,EAAE,SAAS,0BAA0B,IAAI,MAAM,GAAG;AAAA,MAC3D,CAAoB;AACpB;AAAA,IACF;AAEA,QAAI;AACF,YAAM,SAAS,MAAM;AAAA,QACnB;AAAA,UACE;AAAA,UACA,YAAY,wBAAC,OAAO,QAAQ;AAC1B,iBAAK,EAAE,MAAM,YAAY,IAAI,IAAI,IAAI,OAAO,IAAI,CAAuB;AAAA,UACzE,GAFY;AAAA,QAGd;AAAA,QACA,IAAI;AAAA,MACN;AACA,WAAK,EAAE,MAAM,YAAY,IAAI,IAAI,IAAI,OAAO,CAAuB;AAAA,IACrE,SAAS,GAAG;AACV,WAAK,EAAE,MAAM,SAAS,IAAI,IAAI,IAAI,OAAO,eAAe,CAAC,EAAE,CAAoB;AAAA,IACjF;AAAA,EACF,GA/CO;AAgDT;AA3DgB;AA6DT,SAAS,eAAe,GAA+B;AAnG9D;AAoGE,MAAI,aAAa,WAAW;AAC1B,WAAO;AAAA,MACL,MAAM,EAAE;AAAA,MACR,SAAS,EAAE;AAAA,MACX,OAAO,EAAE;AAAA,MACT,SAAS,EAAE;AAAA,MACX,MAAM,EAAE;AAAA,IACV;AAAA,EACF;AACA,QAAM,MAAM;AACZ,SAAO;AAAA,IACL,UAAS,gCAAK,YAAL,YAAgB,OAAO,CAAC;AAAA,IACjC,MAAM,2BAAK;AAAA,IACX,OAAO,2BAAK;AAAA,EACd;AACF;AAhBgB;;;ACpFhB,IAAM,MAAM;AACZ,IAAI,OAAO,IAAI,gBAAgB,cAAc,OAAO,IAAI,qBAAqB,YAAY;AACvF,QAAM,IAAI,MAAM,0EAA0E;AAC5F;AAEA,IAAM,WAAW,uBAAuB,CAAC,SAAS;AAChD,MAAI,YAAY,IAAI;AACtB,CAAC;AAED,IAAI,iBAAiB,WAAW,CAAC,MAA0B;AACzD,OAAK,SAAS,EAAE,IAAI;AACtB,CAAC;","names":["parseXmlDocument","CONTENT_TYPES_PATH","CONTENT_TYPES_NS","CONTENT_TYPES_CTYPE","parseXmlDocument","parseXmlDocument","serializeToWellFormedString","CONTENT_TYPES_PATH","isXmlContentType","parseXmlDocument","serializeToWellFormedString","parseXmlDocument","serializeToWellFormedString","info","serializeToWellFormedString","snapshot","serializeToWellFormedString","RELS_NS","totalPages","slice","snapshot","firstDirectChild","findStoryForEl","firstDirectChild","snapshot","numAttr","value","table","snapshot","ctx","issue","paragraphText","firstDirectChildW","firstDirectChildW","ctx","firstDirectChildW","endOffset","ctx","parseXmlDocument","CONTENT_TYPES_PATH","CONTENT_TYPES_NS","ctx","isTextRange","requireParagraph","numAttr","parseXmlDocument","firstDirectChildW","createT","createW","COMMENTS_PART_PATH","ctx","firstDirectChildW","markStoryPartDirty","isRunEffectivelyEmpty","ctx","snapshot","createW","COMMENTS_PART_PATH","ctx","dropBookmarkByName","dropCommentById","markStoryPartDirty","isRunEffectivelyEmpty","doc","parseXmlDocument","CONTENT_TYPES_PATH","CONTENT_TYPES_NS","RELS_NS","parseXmlDocument","resolveRelTarget","RELS_NS","ctx","relsPathFor","snapshot","isRunEffectivelyEmpty","p","firstDirectChildW","resolveRelTarget","parseXmlDocument","RELS_NS","CONTENT_TYPES_PATH","CONTENT_TYPES_NS","IMAGE_RELATIONSHIP_TYPE","ctx","relsPathFor","parseXmlDocument","computeRelTarget","ctx","relsPathFor","reassignClonedParaIds","snapshot","ctx","ctx","relsPathFor","firstDirectChild","resolveRelTarget","RELS_NS","ctx","_a","partToBytes","isXmlContentType","parseXmlDocument","relsPathFor","serializeToWellFormedString","info","info","result","dispatch"]}